From e12c886144538d7816c3fb8d97e6d66792841127 Mon Sep 17 00:00:00 2001 From: Katie Goines <30757403+katiegoines@users.noreply.github.com> Date: Fri, 19 Apr 2024 15:40:21 -0700 Subject: [PATCH] chore: merge `main` into `next-release/main` (#7260) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Minor edits to Vite + React quickstart (#6926) * Updates to Vite + React quickstart * Update src/fragments/gen2/quickstart/build-a-backend.mdx Co-authored-by: Kevin Old * Update build-a-backend.mdx * Update build-a-backend.mdx * Update build-a-backend.mdx --------- Co-authored-by: Kevin Old * fix: Fix incorrect auth import path in migration guide. (#6934) * fix: Update incorrect `updateMFAPreference` parameter in JS v6 migration guide. (#6935) * Amplify Android Release 2.14.11 (#6933) * chore: refactor .layout-header into separate component (#6826) * platform typed as optional * refactor init * remove commented code * remove angry useEffect * fix typing * added layoutcontext so mobile menu closes on navigation * move import --------- Co-authored-by: katiegoines * fix: Nesting of auth cli templates (#6932) * fix: change config variable name (#6923) * Guide to support Amplify v2 with AWS Android SDK (#6927) * Update puppeteer (#6949) * Update index.mdx (#6950) * Update CODEOWNERS with correct PM alignment (#6951) * fix(flutter, js): scope "connect existing cdk" guide to respective platform (#6947) Co-authored-by: Tim Nguyen <54393192+timngyn@users.noreply.github.com> * Revert "fix(flutter, js): scope "connect existing cdk" guide to respective pl…" (#6955) This reverts commit 5998b22f18cada98ba7c6d1f35c3f6b378637476. * chore: remove duplicated logic between Layout and LayoutHeader (#6954) * chore: more layout refactoring * remove unused prop, alphabetize props * improve oauth docs (#6961) * fixed gen 2 getting started guide (#6968) * Update redirects for deleted hidden pages (#6944) * Update manual installation to point to @beta tag (#6972) * include usage for multi-page apps (#6964) * include usage for multi-page apps * improve multi-page app docs * use Hub syntax * update imports in examples * chore: Clean up broken Amplify JS API reference links (#6976) * chore: Clean up broken Amplify JS API reference links. * Cleaned up language. * Update build image instructions for Gen 2 (#6978) * update build image settings for Gen 2 * remove callout and add fragment to vite guide * chore: add unit test for YoutubeEmbed component (#6983) * chore: add unit test for YoutubeEmbed component * add code coverage stats --------- Co-authored-by: katiegoines * chore: add unit tests for Accordion component (#6981) * chore: add unit tests for Accordion component * issue with window properties * fixed tracking test * working on animation issue * accordion tests * fix testing errors * added test for closing accordion * add code coverage stats --------- Co-authored-by: katiegoines * Update index.mdx (#6986) * Add env variables for algolia (#6957) * Add algolia env vars to next.config * Remove extra code string * fix(data): update REST API docs to document correct error response type (#6989) * fix(data): update React Native minimum iOS deployment target guidance; add build step to docs (#6970) * fix(data): update React Native minimum iOS deployment target; add build step to docs * address PR feedback * remove deployment target guidance * add React Native version deployment target callout * fix unrecognized syntax * replace callout with accordion * move 'upgrading' callout * Clarify behavior of forgetDevice() API regarding device tracking (#6985) * Clarify behavior of forgetDevice() API regarding device tracking This commit updates the documentation to clarify that using the forgetDevice() API results in the device being neither remembered nor tracked. Previously, the documentation suggested that forgotten devices might still be tracked, leading to confusion about the API's behavior. The revised wording aligns with the detailed description under the "Forgotten" section, ensuring consistency and eliminating ambiguity about how forgotten devices are handled. * Clarify behavior of forgetDevice() API regarding device tracking * Support for enum value listing (#6885) * Support for enum value listing * Update src/pages/gen2/build-a-backend/data/data-modeling/add-fields/index.mdx * CDK updates v2 (#6990) * Add padding to bottom of nav menu (#6991) * Adding secondary index to Gen 2 (#6996) * Adding secondary index docs * fixed some formatting for custom query fields * extend config to show addOuput (#6963) * extend config * modify wording * modify example * improve wording * Update index.mdx (#6995) * Update index.mdx * add guest access support to docs * chore: add unit tests for NextPrevious component (#7003) Co-authored-by: katiegoines * chore: add unit tests for LinkCards and LinkCard components (#7006) Co-authored-by: katiegoines * chore: add unit tests for GetStartedPopover component (#7005) Co-authored-by: katiegoines * fix: [Storage] Configure Access (#6948) Co-authored-by: Tim Nguyen <54393192+timngyn@users.noreply.github.com> * fix(Swift): update data use policy info's tracking to false (#6938) * fix(Swift): update data use policy info's tracking to false * Update data-information.mdx * chore: add callouts and troubleshooting guide for configuration (#6967) * fix: resolve in-content broken links (#7011) * re-platforming * remove reference to mocking and testing for android & swift * remove reference to mocking and testing for android & swift * filtered out reference to optimistic ui for react native --------- Co-authored-by: katiegoines * update gen2 storage and function docs (#7009) * update gen2 storage and function docs * add resource access links and example * revisions, update code snippet titles * Update CODEOWNERS (#7014) * updated steps for extending components in code (#6827) Co-authored-by: Aditya Shahani * Custom business logic support as of March @beta (#7019) * Enhanced custom business logic DX * addressed tim's comments * Added custom subscription configuration worfklow * removed in-development areas * added titles * added links for deep dive material * Update src/pages/gen2/build-a-backend/data/custom-business-logic/index.mdx Co-authored-by: josef * Update src/pages/gen2/build-a-backend/data/custom-business-logic/index.mdx Co-authored-by: josef * Update src/pages/gen2/build-a-backend/data/custom-business-logic/index.mdx Co-authored-by: Kethan sai * Update src/pages/gen2/build-a-backend/data/custom-business-logic/index.mdx Co-authored-by: Kethan sai * Update src/pages/gen2/build-a-backend/data/custom-business-logic/index.mdx Co-authored-by: josef * Update src/pages/gen2/build-a-backend/data/custom-business-logic/index.mdx * added client method for clarity. * Update src/pages/gen2/build-a-backend/data/custom-business-logic/index.mdx Co-authored-by: Kethan sai * Apply suggestions from code review Co-authored-by: josef --------- Co-authored-by: josef Co-authored-by: Kethan sai * add storage trigger docs (#7020) * storage trigger docs * Apply suggestions from code review Co-authored-by: josef * add storage access actions --------- Co-authored-by: josef * update link checker to wait for each call to complete before making t… (#6993) * update link checker to wait for each call to complete before making the next and remove # from urls being checked * update logging to show how many links found on each page * Update tasks/link-checker.js --------- Co-authored-by: Jacob Logan Co-authored-by: katiegoines Co-authored-by: Scott Rees <6165315+reesscot@users.noreply.github.com> * custom examples (#6979) * custom examples * fix: broken link, missing / at start (#7026) Co-authored-by: katiegoines * validate and fix code snippets in Data section (#6975) * Update sandbox --dir-to-watch description (#7031) * Update index.mdx (#7035) * Fix link (#7028) * add docs to auth resource access pattern (#7032) * fix: type platform as optional in Breadcrumbs component & add unit tests (#6912) * platform typed as optional * chore: add unit tests for Breadcrumbs * testing to include platform optional * fix: type platform as optional * add tests for override values --------- Co-authored-by: katiegoines * fix: proper variable naming conventions for storage (#7033) fix: proper variable naming conventions for storage * remove explicit file extension from gen2 imports (#6946) Co-authored-by: Tim Nguyen <54393192+timngyn@users.noreply.github.com> * fix: Update diff code blocks to TypeScript with code highlights (#6905) * add docs on granting defineFunction access to defineData (#7029) * standardize Gen 2 wording (#7036) * Update index.mdx (#6906) * Modify_Amplify_resources (#7018) * fix code snippets on read data page * code snippet updates * updated the code snippets * updated code snippets. * custom business page rollback * Update maplibre links (#7040) * chore: add unit tests for PlatformNavigator (#6980) * chore: add unit tests for PlatformNavigator * add code coverage * simplify * simplify --------- Co-authored-by: katiegoines * Update links to expo docs (#7044) * Update links to expo docs * Update src/pages/[platform]/prev/build-a-backend/auth/add-social-provider/index.mdx Co-authored-by: josef * Update src/pages/[platform]/prev/build-a-backend/auth/add-social-provider/index.mdx Co-authored-by: josef --------- Co-authored-by: josef * chore: add unit tests for InternalLinkButton (#7000) Co-authored-by: katiegoines * chore: add addtl unit test for Block component (#6982) * chore: add addtl unit test for Block component * add code coverage stats * remove superfluous Block component --------- Co-authored-by: katiegoines * chore: add unit tests for TOC (#6984) * chore: add unit tests for TOC * add code coverage * hardcode expected hash --------- Co-authored-by: katiegoines * chore: add unit tests for ExternalLink (#6915) * chore: add unit tests for ExternalLink * fixing tracking test --------- Co-authored-by: katiegoines * chore: add unit tests for ExternalLinkButton (#6914) * chore: add unit tests for ExternalLinkButton * Update ExternalLinkButton.test.tsx triggering checks --------- Co-authored-by: katiegoines * chore: add unit tests for Footer component (#6999) Co-authored-by: katiegoines * chore: add unit tests for MigrationAlert component (#7004) * chore: add unit tests for MigrationAlert component * chore: add unit tests for MigrationAlert component --------- Co-authored-by: katiegoines * chore: add unit test for Overview component (#7002) Co-authored-by: katiegoines * chore: upgrade docsearch/react to 3.6 (#7046) * added utility type content (#7047) * chore: add unit tests for PageLastUpdated (#7001) Co-authored-by: katiegoines * chore: add unit tests for Commands and Columns (#6916) * chore: add unit test for CLICommands * chore: add unit test for Columns * Update Command.test.tsx triggering checks --------- Co-authored-by: katiegoines * Update resolution for follow-redirects (#7055) * Update relative urls (#7048) * Update relative urls * Update url * Updating link checker (#7052) * Updating link checker to account for duplicate urls from different pages and link text * Update slack formatting * Remove console.log * Add comments to function * Remove extra console.logs() * chore: update redirects list (#6969) * update redirects * updated redirects --------- Co-authored-by: katiegoines * remove allowlist role names for appsync console access page (#7081) * Add JavaScript resolver code sample to Gen 1 (#7087) * fix(JS): Update v5 JS libraries installation guides. (#7090) * fix(v5): update aws-amplify v5 dependency * chore: remove extra '0' number from versions * chore: remove vue2 block * chore: update version reference * Cbonif/field-level-auth-support-for-sql (#7091) * chore(gen2-data): update .secondaryIndexes example to match the latest interface (#7095) * update setup auth client example with correct props (#7106) * update auth with correct props * Change generated function env package name (#7096) * Update typo in url for localhost (#7110) * update next config to use a static build Id (#7102) Co-authored-by: Jacob Logan * chore: Add callout on Analytics buffer persistence in Amplify JS (#7115) * chore: Add callout on Analytics buffer persistence in Amplify JS. * PR feedback. * Custom subscription docs to Gen 2 (#7120) * Add playsInline to videos (#7125) * autoSignIn position correction in v6 migration docs (#7059) * fix(next-release/main): update home page h1 and code block font size (#7117) (#7126) * update font sizes * add text-size-adjust * add webkit prefix, add comment * update text-size-adjust fix --------- Co-authored-by: Tim Nguyen <54393192+timngyn@users.noreply.github.com> * remove parenthesis from "Amplify (Gen 2)" (#7113) * change "NPM" to "npm" (#7112) * remove explicit ".js" extension from gen2 resource imports (#7134) * remove leading slash from storage access paths (#7116) * remove unnecessary "Angular" mention in auth getting started (#7139) Removed 'Angular' from the app description. It is not necessarily an angular app. * Gen 2 Quickstart: Fix amplify console link (#7141) * fix amplify console link * fix text from AWS Console to Amplify Console * updated alt text for Amplify console * Update src/fragments/gen2/quickstart/deploy-and-host.mdx Co-authored-by: Scott Rees <6165315+reesscot@users.noreply.github.com> * Update src/pages/gen2/deploy-and-host/fullstack-branching/branch-deployments/index.mdx Co-authored-by: Scott Rees <6165315+reesscot@users.noreply.github.com> --------- Co-authored-by: Scott Rees <6165315+reesscot@users.noreply.github.com> * Add Favicon and apple-touch icons to root (#7137) * add 96x96 favicons * add favicon and apple-touch to root * updated icons --------- Co-authored-by: Jacob Logan * docs(migration): fixes mislabeling notification enable snippet (#7135) the v5 snippet was labeled as v6 and the v6 was labeled as v5 Co-authored-by: derrik.fleming * edits to custom business logic (#7129) * remove console.log (#7147) * fix: copied code no longer includes markdown comments (#7146) * fix: copied code no longer includes markdown comments * minor cleanup * splite prepareCopyText to it's own export for easier testing * fix MDXCode mock * chore(react-native): Add callouts for dropped Expo Go support (#7160) * Update index.mdx (#7165) * Update github link to maplibre repo (#7162) * Cbonif/add-sql-support-for-secrets-manager (#7104) * add image example for secrets manager key/value * add documentation for creating secrets in secrets manager and configuring db details on the construct * adjust order of paragraphs, moving relevant text closer to image and make alt text more descriptive * Fixed typo in amplifyconfiguration.json for predictions (#7185) * fix swift docs to use the `.update` call (#7191) * Update index.mdx (#7164) * Added documentation on updated IAM behavior (#7056) * Added documentation on updated IAM behavior * Update src/pages/[platform]/tools/cli/migration/iam-auth-updates-for-cdk-construct/index.mdx Co-authored-by: Kamil Sobol * Update src/pages/[platform]/build-a-backend/graphqlapi/customize-authorization-rules/index.mdx Co-authored-by: Kamil Sobol * Update src/pages/[platform]/build-a-backend/graphqlapi/customize-authorization-rules/index.mdx * Update src/pages/[platform]/tools/cli/migration/iam-auth-updates-for-cdk-construct/index.mdx * Update src/pages/[platform]/tools/cli/migration/iam-auth-updates-for-cdk-construct/index.mdx Co-authored-by: Tim Schmelter * addressed comments * Updated to reflect changes to Gen 2 content * Update src/pages/[platform]/build-a-backend/graphqlapi/customize-authorization-rules/index.mdx --------- Co-authored-by: Kamil Sobol Co-authored-by: Tim Schmelter * Added Metadata section in Storage (#7152) * Cbonif/edits-to-secondary-indexes-page (#7179) * edits to custom business logic * update secondary index code examples * Add client examples of accessing models with specific auth modes (#7080) * add client side code for public access * add client side code for signed in user access * add client side code for multi user access * add client side code for per user/owner access * add client side code for custom id & group claims * add client side code for custom access * add client side code for user pool group access * add client side code for oidc access * Update src/pages/gen2/build-a-backend/data/customize-authz/signed-in-user-data-access/index.mdx Co-authored-by: Rene Brandel <4989523+renebrandel@users.noreply.github.com> * add info callout and configuration code to public/private iam examples * move callout up * remove "**note**" from callouts --------- Co-authored-by: Rene Brandel <4989523+renebrandel@users.noreply.github.com> * Updated Gen 2 relationship behavior (#7222) * Added new relationship behavior doc * fixed typos * fix(predictions): fix wrong reference of swfit/android predictions use aws sdk page (#7220) * fix(predictions): fix wrong reference of swfit/android predictions use aws sdk page * fix(predictions): update Use AWS SDK description * Update amplify/data/increment-like.js syntax (#7229) The correct DynamoDB syntax requires semicolon in both expression and expressionValues * Graphql generate client code (#7176) * updated generate-client-code section * updated graphql-client-code section * updated the description * removed workflow * Update src/pages/gen2/reference/cli-commands/index.mdx Co-authored-by: Rene Brandel <4989523+renebrandel@users.noreply.github.com> * Update src/pages/gen2/reference/cli-commands/index.mdx Co-authored-by: Rene Brandel <4989523+renebrandel@users.noreply.github.com> * added Supported GraphQL client code combinations * fixed the spell * fixed the format * fixed the syntax * Update src/pages/gen2/reference/cli-commands/index.mdx Co-authored-by: josef * Update src/pages/gen2/reference/cli-commands/index.mdx Co-authored-by: josef * Update src/pages/gen2/reference/cli-commands/index.mdx Co-authored-by: josef * Update src/pages/gen2/reference/cli-commands/index.mdx Co-authored-by: josef * updated the stack name --------- Co-authored-by: Rene Brandel <4989523+renebrandel@users.noreply.github.com> Co-authored-by: josef * use latest tag for Gen2 apps (#7256) * Updated Data Gen 2 authorization rules to use the new syntax (#7252) * Updated authorization rules to use the new syntax * Update src/pages/gen2/build-a-backend/data/customize-authz/signed-in-user-data-access/index.mdx Co-authored-by: Hui Zhao <10602282+HuiSF@users.noreply.github.com> --------- Co-authored-by: Hui Zhao <10602282+HuiSF@users.noreply.github.com> --------- Co-authored-by: Jim Eagan <84857865+hibler13@users.noreply.github.com> Co-authored-by: Kevin Old Co-authored-by: Jim Blanchard Co-authored-by: Ankit Shah <22114629+ankpshah@users.noreply.github.com> Co-authored-by: katiegoines Co-authored-by: Dan Kiuna Co-authored-by: Kihara, Takuya Co-authored-by: Tyler Roach Co-authored-by: Tim Nguyen <54393192+timngyn@users.noreply.github.com> Co-authored-by: Rene Brandel <4989523+renebrandel@users.noreply.github.com> Co-authored-by: Elijah Quartey Co-authored-by: Heather Buchel Co-authored-by: John Corser Co-authored-by: Heather Pundt <119376175+heatheramz@users.noreply.github.com> Co-authored-by: Nikhil Swaminathan <2429410+swaminator@users.noreply.github.com> Co-authored-by: Jay Raval Co-authored-by: David McAfee Co-authored-by: Kethan sai Co-authored-by: Michael Law <1365977+lawmicha@users.noreply.github.com> Co-authored-by: erinleigh90 <106691284+erinleigh90@users.noreply.github.com> Co-authored-by: Edward Foyle Co-authored-by: Adi <34354177+the1adi@users.noreply.github.com> Co-authored-by: Aditya Shahani Co-authored-by: josef Co-authored-by: jacoblogan Co-authored-by: Jacob Logan Co-authored-by: Scott Rees <6165315+reesscot@users.noreply.github.com> Co-authored-by: Chris Bonifacio Co-authored-by: Roshane Pascual Co-authored-by: Charles Shin Co-authored-by: Ujjwol Shrestha Co-authored-by: Gen Tamura Co-authored-by: dwittle <72715628+dwittle@users.noreply.github.com> Co-authored-by: Anil Maktala Co-authored-by: israx <70438514+israx@users.noreply.github.com> Co-authored-by: Hui Zhao <10602282+HuiSF@users.noreply.github.com> Co-authored-by: Nairi Areg <51801223+NairiAreg@users.noreply.github.com> Co-authored-by: spivakov83 Co-authored-by: Harshita Daddala Co-authored-by: derrik Co-authored-by: derrik.fleming Co-authored-by: Chris F <5827964+cshfang@users.noreply.github.com> Co-authored-by: Kamil Sobol Co-authored-by: Tim Schmelter Co-authored-by: yuhengshs <94558971+yuhengshs@users.noreply.github.com> Co-authored-by: Di Wu Co-authored-by: Guy Pavlov --- .../gen2/quickstart/build-a-backend.mdx | 10 +- .../gen2/quickstart/create-amplify.mdx | 2 +- .../data/connect-existing-data/index.mdx | 6 +- .../data/custom-business-logic/index.mdx | 30 +- .../data/custom-subscription/index.mdx | 16 +- .../index.mdx | 6 +- .../custom-data-access-patterns/index.mdx | 2 +- .../index.mdx | 8 +- .../data/customize-authz/index.mdx | 34 +- .../multi-user-data-access/index.mdx | 10 +- .../per-user-per-owner-data-access/index.mdx | 10 +- .../public-data-access/index.mdx | 4 +- .../signed-in-user-data-access/index.mdx | 4 +- .../user-group-based-data-access/index.mdx | 10 +- .../index.mdx | 10 +- .../data/data-modeling/identifiers/index.mdx | 4 +- .../data/data-modeling/index.mdx | 2 +- .../data-modeling/relationships/index.mdx | 306 ++++++++++-------- .../data-modeling/secondary-index/index.mdx | 8 +- .../data/set-up-data/index.mdx | 6 +- .../mono-and-multi-repos/index.mdx | 2 +- .../reference/cli-commands/index.mdx | 76 ++++- .../reference/project-structure/index.mdx | 2 +- .../start/manual-installation/index.mdx | 4 +- .../[platform]/start/mobile-support/index.mdx | 12 +- .../more-features/predictions/sdk/index.mdx | 6 +- .../more-features/predictions/sdk/index.mdx | 2 +- 27 files changed, 347 insertions(+), 245 deletions(-) diff --git a/src/fragments/gen2/quickstart/build-a-backend.mdx b/src/fragments/gen2/quickstart/build-a-backend.mdx index 9660802085a..f30fae92ac5 100644 --- a/src/fragments/gen2/quickstart/build-a-backend.mdx +++ b/src/fragments/gen2/quickstart/build-a-backend.mdx @@ -27,7 +27,7 @@ const schema = a.schema({ .model({ content: a.string() }) - .authorization([a.allow.owner(), a.allow.public().to(['read'])]) + .authorization(allow => [allow.owner(), allow.publicApiKey().to(['read'])]) }); export type Schema = ClientSchema; @@ -36,7 +36,7 @@ export const data = defineData({ schema, authorizationModes: { defaultAuthorizationMode: 'apiKey', - // API Key is used for a.allow.public() rules + // API Key is used for allow.publicApiKey() rules apiKeyAuthorizationMode: { expiresInDays: 30 } @@ -99,7 +99,7 @@ const schema = a.schema({ priority: a.enum(['low', 'medium', 'high']) // highlight-end }) - .authorization([a.allow.owner(), a.allow.public().to(['read'])]), + .authorization(allow => [allow.owner(), allow.publicApiKey().to(['read'])]), }); // ... @@ -114,12 +114,12 @@ The `Todo` data model is defined with authorization rules to allow the person wh **Note:** These authorization rules can be modified using a chain of methods as defined by default. For example, we could remove the `.to(['read'])` and allow all visitors to perform all actions on data or add permissions for signed-in users or users who belong to user groups such as `Admin`. You can learn more about all options for authorization in the [Customize your auth rules](/[platform]/build-a-backend/data/customize-authz/) section of the docs. -Step 2: Remove public access by deleting the `a.allow.public().to(['read'])` authorization rule. Your authorization rule will look like the code below: +Step 2: Remove public access by deleting the `allow.publicApiKey().to(['read'])` authorization rule. Your authorization rule will look like the code below: ```js title="amplify/data/resource.ts" // ... -.authorization([a.allow.owner()]), +.authorization(allow => [allow.owner()]), // ... ``` diff --git a/src/fragments/gen2/quickstart/create-amplify.mdx b/src/fragments/gen2/quickstart/create-amplify.mdx index bbb764ccc8e..0fe5dadd7be 100644 --- a/src/fragments/gen2/quickstart/create-amplify.mdx +++ b/src/fragments/gen2/quickstart/create-amplify.mdx @@ -2,7 +2,7 @@ The easiest way to get started with AWS Amplify is through npm with `create-amplify`. ```bash showLineNumbers={false} -npm create amplify@beta +npm create amplify@latest ``` ```console showLineNumbers={false} diff --git a/src/pages/[platform]/build-a-backend/data/connect-existing-data/index.mdx b/src/pages/[platform]/build-a-backend/data/connect-existing-data/index.mdx index c90ac4ae8ed..a8dec9951d3 100644 --- a/src/pages/[platform]/build-a-backend/data/connect-existing-data/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/connect-existing-data/index.mdx @@ -109,7 +109,7 @@ import { schema as rdsSchema } from './schema.rds.ts' // Add an authorization rule to the schema // highlight-next-line -rdsSchema.models.Todo.authorization([a.allow.public()]) +rdsSchema.models.Todo.authorization(allow => [allow.publicApiKey()]) const schema = a.schema({ Todo: a.model({ @@ -146,7 +146,7 @@ const schema = a.schema({ content: a.string() isDone: a.boolean() }) -}).authorization([a.allow.public()]) +}).authorization(allow => [allow.publicApiKey()]) const combinedSchema = a.schema.combine([ schema, @@ -183,7 +183,7 @@ rdsSchema.addQueries({ ST_MakePoint(:lat, :long) ) <= :radiusInMeters `) - .authorization([a.allow.public()]) + .authorization(allow => [allow.publicApiKey()]) }) // highlight-end diff --git a/src/pages/[platform]/build-a-backend/data/custom-business-logic/index.mdx b/src/pages/[platform]/build-a-backend/data/custom-business-logic/index.mdx index f719db5ca8d..5b9fe809327 100644 --- a/src/pages/[platform]/build-a-backend/data/custom-business-logic/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/custom-business-logic/index.mdx @@ -70,7 +70,7 @@ const schema = a.schema({ // return type of the query .returns(a.ref('EchoResponse')) // only allow signed-in users to call this API - .authorization([a.allow.private()]) + .authorization(allow => [allow.authenticated()]) }); export type Schema = ClientSchema; @@ -105,7 +105,7 @@ const schema = a.schema({ // return type of the query .returns(a.ref('Post')) // only allow signed-in users to call this API - .authorization([a.allow.private()]) + .authorization(allow => [allow.authenticated()]) }); export type Schema = ClientSchema; @@ -166,7 +166,7 @@ const schema = a.schema({ .query() .arguments({ content: a.string() }) .returns(a.ref('EchoResponse')) - .authorization([a.allow.public()]) + .authorization(allow => [allow.publicApiKey()]) // 3. set the function has the handler .handler(a.handler.function(echoHandler)) }); @@ -202,17 +202,17 @@ const schema = a.schema({ Post: a.model({ content: a.string(), likes: a.integer() - .authorization([a.allow.private().to(['read'])]) - }).authorization([ - a.allow.owner(), - a.allow.private().to(['read']) + .authorization(allow => [allow.authenticated().to(['read'])]) + }).authorization(allow => [ + allow.owner(), + allow.authenticated().to(['read']) ]), likePost: a .mutation() .arguments({ postId: a.id() }) .returns(a.ref('Post')) - .authorization([a.allow.private()]) + .authorization(allow => [allow.authenticated()]) .handler(a.handler.custom({ dataSource: a.ref('Post'), entry: './increment-like.js' @@ -224,7 +224,7 @@ export type Schema = ClientSchema; export const data = defineData({ schema, authorizationModes: { - defaultAuthorizationMode: 'userPool', + defaultAuthorizationMode: 'apiKey', apiKeyAuthorizationMode: { expiresInDays: 30 } @@ -239,7 +239,7 @@ export function request(ctx) { key: util.dynamodb.toMapValues({ id: ctx.args.postId}), update: { expression: 'ADD likes :plusOne', - expressionValues: { 'plusOne': { N: 1 } }, + expressionValues: { ':plusOne': { N: 1 } }, } } } @@ -295,17 +295,17 @@ const schema = a.schema({ Post: a.model({ content: a.string(), likes: a.integer() - .authorization([a.allow.private().to(['read'])]) - }).authorization([ - a.allow.owner(), - a.allow.private().to(['read']) + .authorization(allow => [allow.authenticated().to(['read'])]) + }).authorization(allow => [ + allow.owner(), + allow.authenticated().to(['read']) ]), likePost: a .mutation() .arguments({ postId: a.id() }) .returns(a.ref('Post')) - .authorization([a.allow.private()]) + .authorization(allow => [allow.authenticated()]) .handler(a.handler.custom({ // highlight-next-line dataSource: "ExternalTableDataSource", diff --git a/src/pages/[platform]/build-a-backend/data/custom-subscription/index.mdx b/src/pages/[platform]/build-a-backend/data/custom-subscription/index.mdx index 2bc5cf2ff36..f0c3fb39193 100644 --- a/src/pages/[platform]/build-a-backend/data/custom-subscription/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/custom-subscription/index.mdx @@ -60,7 +60,7 @@ const schema = a.schema({ }) .returns(a.ref('Message')) .handler(a.handler.custom({ entry: './publish.js' })) - .authorization([a.allow.public()]), + .authorization(allow => [allow.publicApiKey()]), // highlight-start // Subscribe to incoming messages @@ -72,13 +72,13 @@ const schema = a.schema({ // subscription handler to set custom filters .handler(a.handler.custom({entry: './receive.js'})) // authorization rules as to who can subscribe to the data - .authorization([a.allow.public()]), + .authorization(allow => [allow.publicApiKey()]), // highlight-end // A data model to manage channels Channel: a.model({ name: a.string(), - }).authorization([a.allow.public()]), + }).authorization(allow => [allow.publicApiKey()]), }); export type Schema = ClientSchema; @@ -179,14 +179,14 @@ const schema = a.schema({ .handler(a.handler.custom({ entry: "./publish.js" })) - .authorization([a.allow.private()]), + .authorization(allow => [allow.authenticated()]), // Subscribe to all events from the "publish" mutation receive: a.subscription(['publish']) // highlight-next-line .arguments({ name: a.string() }) .returns(a.ref('Channel')) - .authorization([a.allow.public()]) + .authorization(allow => [allow.publicApiKey()]) }); export type Schema = ClientSchema; export const data = defineData({ @@ -203,7 +203,7 @@ import { type ClientSchema, a, defineData } from '@aws-amplify/backend'; const schema = a.schema({ Channel: a.model({ name: a.string(), - }).authorization([a.allow.public()]), + }).authorization(allow => [allow.publicApiKey()]), Message: a.customType({ content: a.string().required(), @@ -217,7 +217,7 @@ const schema = a.schema({ }) .returns(a.ref('Message')) .handler(a.handler.custom({ entry: './publish.js' })) - .authorization([a.allow.public()]), + .authorization(allow => [allow.publicApiKey()]), receive: a.subscription() .for(a.ref('publish')) @@ -225,7 +225,7 @@ const schema = a.schema({ .arguments({ namePrefix: a.string() }) .returns(a.ref('Message')) .handler(a.handler.custom({entry: './receive.js'})) - .authorization([a.allow.public()]) + .authorization(allow => [allow.publicApiKey()]) }); export type Schema = ClientSchema; diff --git a/src/pages/[platform]/build-a-backend/data/customize-authz/configure-custom-identity-and-group-claim/index.mdx b/src/pages/[platform]/build-a-backend/data/customize-authz/configure-custom-identity-and-group-claim/index.mdx index b7c5a16a72b..abf61c6881d 100644 --- a/src/pages/[platform]/build-a-backend/data/customize-authz/configure-custom-identity-and-group-claim/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/customize-authz/configure-custom-identity-and-group-claim/index.mdx @@ -43,9 +43,9 @@ const schema = a.schema({ postname: a.string(), content: a.string(), }) - .authorization([ - a.allow.owner().identityClaim('user_id'), - a.allow.specificGroups(['Moderator']).withClaimIn('user_groups'), + .authorization(allow => [ + allow.owner().identityClaim('user_id'), + allow.groups(['Moderator']).withClaimIn('user_groups'), ]), }); diff --git a/src/pages/[platform]/build-a-backend/data/customize-authz/custom-data-access-patterns/index.mdx b/src/pages/[platform]/build-a-backend/data/customize-authz/custom-data-access-patterns/index.mdx index 2722fbc0846..5b9875d67a4 100644 --- a/src/pages/[platform]/build-a-backend/data/customize-authz/custom-data-access-patterns/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/customize-authz/custom-data-access-patterns/index.mdx @@ -45,7 +45,7 @@ const schema = a.schema({ }) // STEP 1 // Indicate which models / fields should use a custom authorization rule - .authorization([a.allow.custom()]), + .authorization(allow => [allow.custom()]), }); export type Schema = ClientSchema; diff --git a/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx b/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx index f5e821ec6c3..471beabe8ec 100644 --- a/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/index.mdx @@ -50,7 +50,7 @@ const schema = a }) }) // highlight-next-line - .authorization([a.allow.resource(functionWithDataAccess)]); + .authorization(allow => [allow.resource(functionWithDataAccess)]); export type Schema = ClientSchema; @@ -59,7 +59,7 @@ export const data = defineData({ }); ``` -The object returned from `defineFunction` can be passed directly to `a.allow.resource()` in the schema authorization rules. This will grant the function the ability to execute Query, Mutation, and Subscription operations against the GraphQL API. Use the `.to()` method to narrow down access to one or more operations. +The object returned from `defineFunction` can be passed directly to `allow.resource()` in the schema authorization rules. This will grant the function the ability to execute Query, Mutation, and Subscription operations against the GraphQL API. Use the `.to()` method to narrow down access to one or more operations. ```ts const schema = a @@ -70,8 +70,8 @@ const schema = a }) }) // highlight-start - .authorization([ - a.allow.resource(functionWithDataAccess).to(['query', 'listen']) + .authorization(allow => [ + allow.resource(functionWithDataAccess).to(['query', 'listen']) ]); // allow query and subscription operations but not mutations // highlight-end ``` diff --git a/src/pages/[platform]/build-a-backend/data/customize-authz/index.mdx b/src/pages/[platform]/build-a-backend/data/customize-authz/index.mdx index aace23f453f..cecb2ef4846 100644 --- a/src/pages/[platform]/build-a-backend/data/customize-authz/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/customize-authz/index.mdx @@ -39,12 +39,12 @@ Use the `.authorization()` modifier to configure authorization rules for public, const schema = a.schema({ Post: a.model({ content: a.string() - }).authorization([ + }).authorization(allow => [ // Allow anyone auth'd with an API key to read everyone's posts. - a.allow.public().to(['read']), + allow.publicApiKey().to(['read']), // Allow signed-in user to create, read, update, // and delete their __OWN__ posts. - a.allow.owner(), + allow.owner(), ]) }) ``` @@ -75,7 +75,7 @@ If there are multiple authorization rules present, they will be logically OR'ed. To help you get started, you can define an authorization rule on the data schema that will be applied to all data models that **do not** have a model-level authorization rule. Instead of having a global authorization rule for all production environments, we recommend creating specific authorization rules for each model or field. -The global authorization rule below uses `a.allow.public()`. This example allows anyone to create, read, update, and delete and is applied to every data model. +The global authorization rule below uses `allow.publicApiKey()`. This example allows anyone to create, read, update, and delete and is applied to every data model. ```ts const schema = a.schema({ @@ -89,11 +89,11 @@ const schema = a.schema({ Notes: a.model({ content: a.string() // [Model-level authorization rule] - }).authorization([a.allow.public().to(['read'])]) + }).authorization(allow => [allow.publicApiKey().to(['read'])]) // [Global authorization rule] -}).authorization([ - a.allow.public() +}).authorization(allow => [ + allow.publicApiKey() ]) ``` @@ -109,9 +109,9 @@ const schema = a.schema({ // [Model-level authorization rule] // All fields (content, createdBy) will be protected by // this authorization rule - }).authorization([ - a.allow.public().to(['read']), - a.allow.owner(), + }).authorization(allow => [ + allow.publicApiKey().to(['read']), + allow.owner(), ]) }) ``` @@ -133,13 +133,13 @@ const schema = a.schema({ // [Field-level authorization rule] // This auth rule will be used for the "ssn" field // All other fields will use the model-level auth rule - ssn: a.string().authorization([a.allow.owner()]), + ssn: a.string().authorization(allow => [allow.owner()]), }) // [Model-level authorization rule] - .authorization([ - a.allow.private().to(["read"]), - a.allow.owner() + .authorization(allow => [ + allow.authenticated().to(["read"]), + allow.owner() ]), }); ``` @@ -155,9 +155,9 @@ const schema = a.schema({ Post: a.model({ title: a.string(), content: a.string() - }).authorization([ - a.allow.public("identityPool").to(["read"]), - a.allow.owner() + }).authorization(allow => [ + allow.guest().to(["read"]), + allow.owner() ]) }) ``` diff --git a/src/pages/[platform]/build-a-backend/data/customize-authz/multi-user-data-access/index.mdx b/src/pages/[platform]/build-a-backend/data/customize-authz/multi-user-data-access/index.mdx index 67ec3d8e3b6..172e3bd589f 100644 --- a/src/pages/[platform]/build-a-backend/data/customize-authz/multi-user-data-access/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/customize-authz/multi-user-data-access/index.mdx @@ -2,7 +2,7 @@ import { getCustomStaticPath } from '@/utils/getCustomStaticPath'; export const meta = { title: 'Multi-user data access', - description: "The `multipleOwners` rule grants a set of users access to a record by automatically creating an `owners` field to store the allowed record owners. You can override the default owners field name by specifying `inField` with the desired field name to store the owner information. You can dynamically manage which users can access a record by updating the owner field.", + description: "The `ownersDefinedIn` rule grants a set of users access to a record by automatically creating an `owners` field to store the allowed record owners. You can override the default owners field name by specifying `inField` with the desired field name to store the owner information. You can dynamically manage which users can access a record by updating the owner field.", platforms: [ 'android', 'angular', @@ -29,11 +29,11 @@ export function getStaticProps(context) { }; } -The `multipleOwners` rule grants a set of users access to a record by automatically creating an `owners` field to store the allowed record owners. You can override the default owners field name by specifying `inField` with the desired field name to store the owner information. You can dynamically manage which users can access a record by updating the owner field. +The `ownersDefinedIn` rule grants a set of users access to a record by automatically creating an `owners` field to store the allowed record owners. You can override the default owners field name by specifying `inField` with the desired field name to store the owner information. You can dynamically manage which users can access a record by updating the owner field. ## Add multi-user authorization rule -If you want to grant a set of users access to a record, you use the `multipleOwners` rule. This automatically creates a `owner: a.string().array()` field to store the allowed owners. +If you want to grant a set of users access to a record, you use the `ownersDefinedIn` rule. This automatically creates a `owner: a.string().array()` field to store the allowed owners. ```ts title="amplify/data/resource.ts" const schema = a.schema({ @@ -41,7 +41,7 @@ const schema = a.schema({ .model({ content: a.string(), }) - .authorization([a.allow.multipleOwners()]), + .authorization(allow => [allow.ownersDefinedIn('owners')]), }); ``` @@ -91,6 +91,6 @@ const schema = a.schema({ content: a.string(), authors: a.string().array(), // record owner information now stored in "authors" field }) - .authorization([a.allow.multipleOwners().inField('authors')]), + .authorization(allow => [allow.ownersDefinedIn('authors')]), }); ``` diff --git a/src/pages/[platform]/build-a-backend/data/customize-authz/per-user-per-owner-data-access/index.mdx b/src/pages/[platform]/build-a-backend/data/customize-authz/per-user-per-owner-data-access/index.mdx index 3942e0c53f5..8f9f680f974 100644 --- a/src/pages/[platform]/build-a-backend/data/customize-authz/per-user-per-owner-data-access/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/customize-authz/per-user-per-owner-data-access/index.mdx @@ -43,7 +43,7 @@ const schema = a.schema({ .model({ content: a.string(), }) - .authorization([a.allow.owner()]), + .authorization(allow => [allow.owner()]), }); ``` @@ -55,7 +55,7 @@ const schema = a.schema({ .model({ content: a.string(), }) - .authorization([a.allow.owner().to(['create', 'read', 'update'])]), + .authorization(allow => [allow.owner().to(['create', 'read', 'update'])]), }); ``` @@ -94,9 +94,9 @@ const schema = a.schema({ Todo: a .model({ content: a.string(), - owner: a.string().authorization([a.allow.owner().to(['read', 'delete'])]), + owner: a.string().authorization(allow => [allow.owner().to(['read', 'delete'])]), }) - .authorization([a.allow.owner()]), + .authorization(allow => [allow.owner()]), }); ``` @@ -113,6 +113,6 @@ const schema = a.schema({ content: a.string(), author: a.string(), // record owner information now stored in "author" field }) - .authorization([a.allow.owner().inField('author')]), + .authorization(allow => [allow.ownerDefinedIn('author')]), }); ``` diff --git a/src/pages/[platform]/build-a-backend/data/customize-authz/public-data-access/index.mdx b/src/pages/[platform]/build-a-backend/data/customize-authz/public-data-access/index.mdx index 7f95293923f..3071f716115 100644 --- a/src/pages/[platform]/build-a-backend/data/customize-authz/public-data-access/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/customize-authz/public-data-access/index.mdx @@ -40,7 +40,7 @@ const schema = a.schema({ .model({ content: a.string(), }) - .authorization([a.allow.public()]), + .authorization(allow => [allow.publicApiKey()]), }); ``` @@ -74,7 +74,7 @@ const schema = a.schema({ .model({ content: a.string(), }) - .authorization([a.allow.public('identityPool')]), + .authorization(allow => [allow.guest()]), }); ``` diff --git a/src/pages/[platform]/build-a-backend/data/customize-authz/signed-in-user-data-access/index.mdx b/src/pages/[platform]/build-a-backend/data/customize-authz/signed-in-user-data-access/index.mdx index ef01b0f9a79..2a987fcaaf6 100644 --- a/src/pages/[platform]/build-a-backend/data/customize-authz/signed-in-user-data-access/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/customize-authz/signed-in-user-data-access/index.mdx @@ -46,7 +46,7 @@ const schema = a.schema({ .model({ content: a.string(), }) - .authorization([a.allow.private()]), + .authorization(allow => [allow.authenticated()]), }); ``` @@ -81,7 +81,7 @@ const schema = a.schema({ .model({ content: a.string(), }) - .authorization([a.allow.private('identityPool')]), + .authorization(allow => [allow.authenticated('iam')]), }); ``` diff --git a/src/pages/[platform]/build-a-backend/data/customize-authz/user-group-based-data-access/index.mdx b/src/pages/[platform]/build-a-backend/data/customize-authz/user-group-based-data-access/index.mdx index 9241f16729b..347f8b3f92c 100644 --- a/src/pages/[platform]/build-a-backend/data/customize-authz/user-group-based-data-access/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/customize-authz/user-group-based-data-access/index.mdx @@ -42,7 +42,7 @@ const schema = a.schema({ wage: a.float(), currency: a.string(), }) - .authorization([a.allow.specificGroup('Admin')]), + .authorization(allow => [allow.group('Admin')]), }); ``` @@ -78,7 +78,7 @@ const schema = a.schema({ wage: a.float(), currency: a.string(), }) - .authorization([a.allow.specificGroups(['Admin', 'Leadership'])]), + .authorization(allow => [allow.groups(['Admin', 'Leadership'])]), }); ``` @@ -94,7 +94,7 @@ const schema = a.schema({ title: a.string(), groups: a.string().array(), }) - .authorization([a.allow.groupsDefinedIn('groups')]), + .authorization(allow => [allow.groupsDefinedIn('groups')]), }); ``` @@ -104,9 +104,9 @@ const schema = a.schema({ Post: a .model({ title: a.string(), - groups: a.string(), + group: a.string(), }) - .authorization([a.allow.groupDefinedIn('groups')]), + .authorization(allow => [allow.groupDefinedIn('group')]), }); ``` diff --git a/src/pages/[platform]/build-a-backend/data/customize-authz/using-oidc-authorization-provider/index.mdx b/src/pages/[platform]/build-a-backend/data/customize-authz/using-oidc-authorization-provider/index.mdx index 4f32e5e2ef6..90dedbc62a7 100644 --- a/src/pages/[platform]/build-a-backend/data/customize-authz/using-oidc-authorization-provider/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/customize-authz/using-oidc-authorization-provider/index.mdx @@ -41,11 +41,11 @@ const schema = a.schema({ .model({ content: a.string(), }) - .authorization([ - a.allow.owner('oidc').identityClaim('user_id'), - a.allow.private('oidc'), - a.allow - .specificGroups(['testGroupName'], 'oidc') + .authorization(allow => [ + allow.owner('oidc').identityClaim('user_id'), + allow.authenticated('oidc'), + allow + .groups(['testGroupName'], 'oidc') .withClaimIn('user_groups'), ]), }); diff --git a/src/pages/[platform]/build-a-backend/data/data-modeling/identifiers/index.mdx b/src/pages/[platform]/build-a-backend/data/data-modeling/identifiers/index.mdx index 971d0809165..ff1ac2c2350 100644 --- a/src/pages/[platform]/build-a-backend/data/data-modeling/identifiers/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/data-modeling/identifiers/index.mdx @@ -62,7 +62,7 @@ const schema = a.schema({ title: a.string(), completed: a.boolean(), }).identifier(['todoId']) - .authorization([a.allow.public()]), + .authorization(allow => [allow.publicApiKey()]), }); const client = generateClient(); @@ -86,7 +86,7 @@ const schema = a.schema({ zipCode: a.string(), streetAddress: a.string(), }).identifier(['tenantId', 'name']) - .authorization([a.allow.public()]), + .authorization(allow => [allow.publicApiKey()]), }); const client = generateClient(); diff --git a/src/pages/[platform]/build-a-backend/data/data-modeling/index.mdx b/src/pages/[platform]/build-a-backend/data/data-modeling/index.mdx index 05ca68bebd0..c05a7aab259 100644 --- a/src/pages/[platform]/build-a-backend/data/data-modeling/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/data-modeling/index.mdx @@ -63,7 +63,7 @@ const schema = a.schema({ }).secondaryIndexes(index => [ a.index('representativeId') ]), -}).authorization([a.allow.owner()]) +}).authorization(allow => [allow.owner()]) ``` diff --git a/src/pages/[platform]/build-a-backend/data/data-modeling/relationships/index.mdx b/src/pages/[platform]/build-a-backend/data/data-modeling/relationships/index.mdx index a2160ffa966..78cc75245b2 100644 --- a/src/pages/[platform]/build-a-backend/data/data-modeling/relationships/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/data-modeling/relationships/index.mdx @@ -29,34 +29,42 @@ export function getStaticProps(context) { }; } -Applications that work with data need well-defined entities to represent that data. Typically, entities are stored across different tables in a database, and items in a given table need to be **uniquely identified**. This is achieved by defining a field (or a combination of fields) that will hold a value (or values) to unambiguously refer to the item. When modeling applications, you often need to **establish relationships** between entities. This is done by adding a field that holds the value of the unique identifier of the related entity. - -Retrieving an entity's related data can be expensive, so Amplify Data offers a way to specify lazy or eager loading of relationships. This is done through "custom selection sets." With eager loading, related data is retrieved immediately when the entity is loaded. With lazy loading, related data is only retrieved when explicitly requested. Custom selection sets give you control over when and how an entity's relationships are populated. +When modeling application data, you often need to establish relationships between different data models. In Amplify Data, you can create one-to-many, one-to-one, and many-to-many relationships in your Data schema. On the client-side, Amplify Data allows you to lazy or eager load of related data. ## Types of relationships -|Relationship|Description| -|------------|--------| -|`a.hasMany()`|Creates a one-directional, one-to-many relationship between two models. For example, a **Post** has many **Comments**. This allows you to query all the comments from the post record.| -|`a.manyToMany()`| Creates a bidirectional relationship. Must be defined on both related models. For example, a **Blog** has many **Tags** and a **Tag** has many **Blogs**.| -|`a.hasOne()`|Creates a one-directional, one-to-one relationship between two models. For example, a **Project** has one **Team**. This allows you to query the team from the project record.| -|`a.belongsTo()`|Makes a "has one" or "has many" relationship bidirectional so you can read from both sides of the relationship. For example, a **Project** has one **Team** and a Team belongs to a Project. This allows you to reference the team from the project record and the other way around.| +|Relationship|Code|Description|Example| +|-|-|-|-| +|one to many|`a.hasMany(...)` & `a.belongsTo(...)`|Creates a one-to-many relationship between two models.|A **Team** has many **Members**. A **Member** belongs to a **Team**.| +|one to one|`a.hasOne(...)` & `a.belongsTo(...)`|Creates a one-to-one relationship between two models.|A **Customer** has one **Cart**. A **Cart** belongs to one **Customer**.| +|many to many| Two `a.hasMany(...)` & `a.belongsTo(...)` on join tables|Create two one-to-many relationships between the related models in a join table.|A **Post** has many **Tags**. A **Tag** has many **Posts**.| + +## Model one-to-many relationships -## Model a "Has Many" relationship +Create a one-to-many relationship between two models using the `hasMany()` and `belongsTo()` method. In the example below, a Team has many Members and a Member belongs to exactly one Team. -Create a bidirectional, one-to-many relationship between two models using the `hasMany()` method. In the example below, a Team has many Members and the parent Team may be looked up from a given member. +1. Create a **reference field** called `teamId` on the **Member** model. This reference field's type **MUST** match the type of **Team**'s identifier. In this case, it's an auto-generated `id: a.id().required()` field. +2. Add a **relationship field** called `team` that references the `teamId` field. This allows you to query for the team information from the **Member** model. +3. Add a **relationship field** called `members` that references the `teamId` field on the **Member** model. ```typescript const schema = a.schema({ + Member: a.model({ + name: a.string().required(), + // 1. Create a reference field + teamId: a.id(), + // 2. Create a belongsTo relationship with the reference field + team: a.belongsTo('Team', 'teamId'), + }) + .authorization(allow => [allow.publicApiKey()]), + Team: a.model({ mantra: a.string().required(), - members: a.hasMany('Member'), + // 3. Create a hasMany relationship with the reference field + // from the `Member`s model. + members: a.hasMany('Member', 'teamId'), }) - .authorization([a.allow.public()]), - Member: a.model({ - team: a.belongsTo('Team'), - }) - .authorization([a.allow.public()]), + .authorization(allow => [allow.publicApiKey()]), }); ``` @@ -64,11 +72,11 @@ const schema = a.schema({ ```ts const { data: team } = await client.models.Team.create({ - mantra: 'Hello', + mantra: 'Go Frontend!', }); -await client.models.Member.update({ - id: 'SOME_MEMBER_ID', +const { data: member } = await client.models.Member.create({ + name: "Tim", team, }); ``` @@ -76,18 +84,24 @@ await client.models.Member.update({ ### Update a "Has Many" relationship between records ```ts +const { data: newTeam } = await client.models.Team.create({ + mantra: 'Go Fullstack', +}); + await client.models.Member.update({ - id: 'SOME_MEMBER_ID', + id: member.id, team, }); ``` ### Delete a "Has Many" relationship between records +If your reference field is not required, then you can "delete" a one-to-many relationship by setting the relationship value to `null`. + ```ts await client.models.Member.update({ id: 'SOME_MEMBER_ID', - team: undefined, + team: null, }); ``` @@ -112,35 +126,28 @@ const { data: teamWithMembers } = await client.models.Team.get( teamWithMembers.members.forEach(member => console.log(member.id)); ``` -## Model a "many-to-many" relationship -Create a many-to-many relationship between two models with the `manyToMany()` method. Provide a common `relationName` on both models to join them in a many-to-many relationship. - -```typescript -const schema = a.schema({ - Post: a.model({ - title: a.string(), - content: a.string(), - tags: a.manyToMany('Tag', { relationName: 'PostTags'}), - }), - Tag: a.model({ - name: a.string(), - posts: a.manyToMany('Post', { relationName: 'PostTags'}), - }), -}); -``` +## Model a "one-to-one" relationship -## Model a "Has One" relationship +Create a one-to-one relationship between two models using the `hasOne()` and `belongsTo()` methods. In the example below, a **Customer** has a **Cart** and a *Cart* belongs to a **Customer**. -Create a one-directional, one-to-one relationship between two models using the `hasOne()` method. In the example below, a Project has a Team. By using `hasOne` this way, it will automatically generate a field to hold the identifier of the related model. +1. Create a **reference field** called `customerId` on the **Cart** model. This reference field's type **MUST** match the type of **Customer**'s identifier. In this case, it's an auto-generated `id: a.id().required()` field. +2. Add a **relationship field** called `customer` that references the `customerId` field. This allows you to query for the customer information from the **Cart** model. +3. Add a **relationship field** called `activeCart` that references the `customerId` field on the **Cart** model. ```typescript const schema = a.schema({ - Project: a.model({ - name: a.string(), - team: a.hasOne('Team'), + Cart: a.model({ + items: a.string().required().array(), + // 1. Create reference field + customerId: a.id(), + // 2. Create relationship field with the reference field + customer: a.belongsTo('Customer', 'customerId'), }), - Team: a.model({ + Customer: a.model({ name: a.string(), + // 3. Create relationship field with the reference field + // from the Cart model + activeCart: a.hasOne('Cart', 'customerId') }), }); ``` @@ -150,167 +157,190 @@ const schema = a.schema({ To create a "has one" relationship between records, first create the parent item and then create the child item and assign the parent. ```ts -const { data: team } = await client.models.Team.create({ - name: 'My Team', +const { data: customer } = await client.models.Customer.create({ + name: 'Rene', }); -const { data: project } = await client.models.Project.create({ - name: 'My Project', - team, +const { data: cart } = await client.models.Cart.create({ + items: ['Tomato', 'Ice', 'Mint'], + customer, }); ``` ### Update a "Has One" relationship between records -To update a "Has One" relationship between records, you first retrieve the child item and then update the reference to the parent to another parent. For example, to move a Project to a new Team: +To update a "Has One" relationship between records, you first retrieve the child item and then update the reference to the parent to another parent. For example, to reassign a Cart to another Customer: ```ts -const { data: newTeam } = await client.models.Team.create({ - name: 'New Team', +const { data: newCustomer } = await client.models.Customer.create({ + name: 'Ian', }); -await client.models.Project.update({ - id: project.id, - team: newTeam, +await client.models.Cart.update({ + id: cart.id, + customer: newCustomer, }); ``` ### Delete a "Has One" relationship between records -You can update the relationship field to delete a "Has One" relationship between records. +You can the relationship field to `null` to delete a "Has One" relationship between records. ```ts -await client.models.Project.update({ +await client.models.Cart.update({ id: project.id, - team: undefined, + customer: null, }); ``` ### Lazy load a "Has One" relationship ```ts -const { data: project } = await client.models.Project.get({ id: "MY_PROJECT_ID"}); -const { data: team } = await project.team(); +const { data: cart } = await client.models.Cart.get({ id: "MY_CART_ID"}); +const { data: customer } = await cart.customer(); ``` ### Eagerly load a "Has One" relationship ```ts -const { data: project } = await client.models.Project.get( - { id: "MY_PROJECT_ID" }, - { selectionSet: ['id', 'team.*'] }, +const { data: cart } = await client.models.Cart.get( + { id: "MY_CART_ID" }, + { selectionSet: ['id', 'customer.*'] }, ); + +console.log(cart.customer.id) ``` -### Model multiple relationships between two models +## Model a "many-to-many" relationship +Create a many-to-many relationship between two models, you have to create a model that serves as a "join table". This "join table" should contain two one-to-many relationships between the two related entity. For example, to model a **Post** has many **Tags** and a **Tag** has many **Posts**, you'll need to create a new **PostTag** model that represents the relationship between these two entities. ```typescript const schema = a.schema({ - Employee: a.model({ - firstName: a.string(), - lastName: a.string(), + PostTag: a.model({ + // 1. Create reference fields to both ends of + // the many-to-many relationship + // highlight-start + postId: a.id().required(), + tagId: a.id().required(), + // highlight-end + // 2. Create relationship fields to both ends of + // the many-to-many relationship using their + // respective reference fields + // highlight-start + post: a.belongsTo('Post', 'postId'), + tag: a.belongsTo('Tag', 'tagId'), + // highlight-end + }), + Post: a.model({ + title: a.string(), + content: a.string(), + // 3. Add relationship field to the join model + // with the reference of `postId` + // highlight-next-line + tags: a.hasMany('PostTag', 'postId'), }), - Organization: a.model({ + Tag: a.model({ name: a.string(), - individualContributors: a.hasMany('Employee'), - managers: a.hasMany('Employee'), + // 4. Add relationship field to the join model + // with the reference of `tagId` + // highlight-next-line + posts: a.hasMany('PostTag', 'tagId'), }), -}); -``` - -```ts -const client = generateClient(); - -const { data: org } = await client.models.Organization.get({ id: 'AE6191BF-FEB4-4D8B-867D-898A7DA33101' }); - -const { data: ics } = await org.individualContributors(); -const { data: managers } = await org.managers(); +}).authorization(allow => [allow.publicApiKey()]); ``` -## Model a bidirectional relationship - -You can make a "has one" or "has many" relationship bidirectional with the `belongsTo()` method. Using the bidirectionality of `belongsTo()`, you can query the related item from both sides of the relationship. +## Model multiple relationships between two models - -**Note:** The `belongsTo()` method requires that a `hasOne()` or `hasMany()` relationship already exists from parent to the related model. - - -### Create a bidirectional "Has One" relationship +Relationships are defined uniquely by their reference fields. For example, a Post can have two relationships to a Person model for `author` and `editor`. ```typescript const schema = a.schema({ - Project: a.model({ - name: a.string(), - team: a.hasOne('Team'), + Post: a.model({ + title: a.string().required(), + content: a.string().required(), + // highlight-start + authorId: a.id(), + author: a.belongsTo('Person', 'authorId'), + editorId: a.id(), + editor: a.belongsTo('Person', 'editorId'), + // highlight-end }), - Team: a.model({ + Person: a.model({ name: a.string(), - project: a.belongsTo('Project'), + // highlight-start + editedPosts: a.hasMany('Post', 'editorId'), + authoredPosts: a.hasMany('Post', 'authorId'), + // highlight-end }), -}); +}).authorization(allow => [allow.publicApiKey()]); ``` +On the client-side, you can fetch the related data with the following code: + ```ts const client = generateClient(); -const { data: team } = await client.models.Team.get({ id: 'FABF27EE-25D2-4851-AE1C-09BCA1604C77' }); - -console.log((await team.project()).data?.name); // There is a 'project' field in the team +const { data: post } = await client.models.Post.get({ id: 'SOME_POST_ID' }); -const { data: teamProject } = await team.project(); -const { data: teamProjectRelatedTeam } = await teamProject.team(); -// teamProjectRelatedTeam is equivalent to original team +const { data: authors } = await post.authors(); +const { data: editors } = await post.editors(); ``` - -"Belongs to" relationships **do not** allow you to update both sides of a "has one" and "belongs to" relationship in a transactional manner. - +## Model relationships for models with sort keys in their identifier -### Create a bidirectional "Has Many" relationship +In case your data model uses sort keys in the identifier, you need to also add in reference fields store the sort key fields in the related data model: -```typescript +```ts const schema = a.schema({ Post: a.model({ - title: a.string(), - comments: a.hasMany('Comment'), - }), - Comment: a.model({ - content: a.string(), - post: a.belongsTo('Post'), + title: a.string().required(), + content: a.string().required(), + // Reference fields must correspond to identifier fields. + // highlight-start + authorName: a.string(), + authorDoB: a.date(), + // Must pass references in the same order as identifiers. + author: a.belongsTo('Person', ['authorName', 'authorDoB']), + // highlight-end }), -}); + Person: a.model({ + name: a.string().required(), + dateOfBirth: a.date().required(), + // Must reference all reference fields corresponding to the + // identifier of this model. + authoredPosts: a.hasMany('Post', ['authorName', 'authorDoB']), + // highlight-next-line + }).identifier(['name', 'dateOfBirth']), +}).authorization(allow => [allow.publicApiKey()]); ``` -```ts -const client = generateClient(); - -const { data: post } = await client.models.Post.get({ id: 'FABF27EE-25D2-4851-AE1C-09BCA1604C77' }); +## Make relationships required or optional -const { data: postComments } = await post.comments(); -const firstComment = postComments[0]; -const { data: firstCommentRelatedPost } = await firstComment.post(); -// firstCommentRelatedPost should be equivalent to post -``` +Amplify Data's relationship uses the reference fields to determine if a relationship is required or not. If you mark a reference field as required, then you can't "delete" a relationship between two models. You'd have to delete the related record as a whole. -## Retrieve related models - -```typescript +```ts const schema = a.schema({ - Project: a.model({ - name: a.string(), - team: a.hasOne('Team'), + Post: a.model({ + + title: a.string().required(), + content: a.string().required(), + // You must supply an author when creating the post + // Author can't be set to `null`. + // highlight-next-line + authorId: a.id().required(), + author: a.belongsTo('Person', 'authorId'), + // You can optionally supply an editor when creating the post. + // Editor can also be set to `null`. + // highlight-next-line + editorId: a.id(), + editor: a.belongsTo('Person', 'editorId'), }), - Team: a.model({ + Person: a.model({ name: a.string(), + // highlight-start + editedPosts: a.hasMany('Post', 'editorId'), + authoredPosts: a.hasMany('Post', 'authorId'), + // highlight-end }), -}); - -const client = generateClient(); - -const { data: project } = await client.models.Project.get({ id: '1234' }); -const projectName = project.name; -const lazyTeamName = (await project.team()).data?.name; // project.team is typed as `Lazy` and can be awaited - -const projectWithTeam = await client.models.Project.get({ id: '1234' }, { selectionSet: ['team.*'] }); -const eagerTeamName = project.team.name // All team attributes were requested, so no need to await, it was eagerly loaded +}) ``` diff --git a/src/pages/[platform]/build-a-backend/data/data-modeling/secondary-index/index.mdx b/src/pages/[platform]/build-a-backend/data/data-modeling/secondary-index/index.mdx index 86001fa817a..2742ca88c55 100644 --- a/src/pages/[platform]/build-a-backend/data/data-modeling/secondary-index/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/data-modeling/secondary-index/index.mdx @@ -43,7 +43,7 @@ export const schema = a.schema({ }) // highlight-next-line .secondaryIndexes((index) => [index("accountRepresentativeId")]) - .authorization([a.allow.public()]), + .authorization(allow => [allow.publicApiKey()]), }); ``` @@ -88,7 +88,7 @@ export const schema = a.schema({ // highlight-next-line .sortKeys(["name"]), ]) - .authorization([a.allow.owner()]), + .authorization(allow => [allow.owner()]), }); ``` @@ -125,7 +125,7 @@ const schema = a.schema({ // highlight-next-line .queryField("listByRep"), ]) - .authorization([a.allow.owner()]), + .authorization(allow => [allow.owner()]), }); ``` @@ -158,6 +158,6 @@ const schema = a.schema({ // highlight-next-line .name("MyCustomIndexName"), ]) - .authorization([a.allow.owner()]), + .authorization(allow => [allow.owner()]), }); ``` diff --git a/src/pages/[platform]/build-a-backend/data/set-up-data/index.mdx b/src/pages/[platform]/build-a-backend/data/set-up-data/index.mdx index 3462d9b1be0..fe209a72acc 100644 --- a/src/pages/[platform]/build-a-backend/data/set-up-data/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/set-up-data/index.mdx @@ -42,7 +42,7 @@ With Amplify Data, you can build a secure, real-time API backed by a database in ## Building your data backend -If you've run `npm create amplify@beta` already, you should see an `amplify/data/resource.ts` file, which is the central location to configure your data backend. The most important element is the `schema` object, which defines your backend data models (`a.model()`) and custom queries (`a.query()`), mutations (`a.mutation()`), and subscriptions (`a.subscription()`). +If you've run `npm create amplify@latest` already, you should see an `amplify/data/resource.ts` file, which is the central location to configure your data backend. The most important element is the `schema` object, which defines your backend data models (`a.model()`) and custom queries (`a.query()`), mutations (`a.mutation()`), and subscriptions (`a.subscription()`). ```ts title="amplify/data/resource.ts" import { a, defineData, type ClientSchema } from '@aws-amplify/backend'; @@ -52,7 +52,7 @@ const schema = a.schema({ content: a.string(), isDone: a.boolean() }) - .authorization([a.allow.public()]) + .authorization(allow => [allow.publicApiKey()]) }); // Used for code completion / highlighting when making requests from frontend @@ -74,7 +74,7 @@ Every `a.model()` automatically creates the following resources in the cloud: - query and mutation APIs to create, read (list/get), update, and delete records - real-time APIs to subscribe for create, update, and delete events of records -The `a.allow.public()` rule designates that anyone authenticated using an API key can create, read, update, and delete todos. +The `allow.publicApiKey()` rule designates that anyone authenticated using an API key can create, read, update, and delete todos. To deploy these resources to your cloud sandbox, run the following CLI command in your terminal: diff --git a/src/pages/[platform]/deploy-and-host/fullstack-branching/mono-and-multi-repos/index.mdx b/src/pages/[platform]/deploy-and-host/fullstack-branching/mono-and-multi-repos/index.mdx index f8192acca95..440ebada9b4 100644 --- a/src/pages/[platform]/deploy-and-host/fullstack-branching/mono-and-multi-repos/index.mdx +++ b/src/pages/[platform]/deploy-and-host/fullstack-branching/mono-and-multi-repos/index.mdx @@ -34,7 +34,7 @@ You might have different frontend and backend teams that maintain their own repo ## Deploy the backend app -1. Run `mkdir backend-app && cd backend-app && npm create amplify@beta` to set up a backend-only Amplify project. Commit the code to a Git provider of your choice. +1. Run `mkdir backend-app && cd backend-app && npm create amplify@latest` to set up a backend-only Amplify project. Commit the code to a Git provider of your choice. 1. Connect the `backend-app` in the new console. Navigate to the Amplify console and select **New app > Build an app (Gen 2)**. diff --git a/src/pages/[platform]/reference/cli-commands/index.mdx b/src/pages/[platform]/reference/cli-commands/index.mdx index dd1cfddc00e..d532be4070c 100644 --- a/src/pages/[platform]/reference/cli-commands/index.mdx +++ b/src/pages/[platform]/reference/cli-commands/index.mdx @@ -231,9 +231,81 @@ npx amplify generate config --stack amplify-nextamplifygen2-josef-sandbox-ca85e1 ## npx amplify generate graphql-client-code -Generate GraphQL statements for your frontend application to consume. +Generate GraphQL statements and types for your frontend application to consume. + +Options + +The available parameters for `npx amplify generate graphql-client-code` are: + +Required parameters: +- Stack identifier + - `--stack`(_string_) - A stack name that contains an Amplify backend. +- Project identifier + - `--app-id`(_string_) - The Amplify App ID of the project. + - `--branch`(_string_) - A git branch of the Amplify project. + +Optional parameters: +- `--out`(_string_) - Specifies the path to the directory where the config is written. If not provided, defaults to the current process working directory. +- `--format`(_string_) (choices: `modelgen`, `graphql-codegen`, `introspection`) - Specifies the format of the GraphQL client code to be generated. +- `--model-target` (_string_) (choices: `java`, `swift`, `javascript`, `typescript`, `dart`) - Specifies the modelgen export target. Only applies when the --format parameter is set to modelgen. +- `--statement-target`(_string_) (choices: `javascript`, `graphql`, `flow`, `typescript`, `angular`) - Specifies the graphql-codegen statement export target. Only applies when the --format parameter is set to graphql-codegen. +- `--type-target`(_string_) (choices: `json`, `swift`, `typescript`, `flow`, `scala`, `flow-modern`, `angular`) - Specifies the optional graphql-codegen type export target. Only applies when the --format parameter is set to graphql-codegen. +- `--all`(_boolean_)- Shows hidden options. +- `--profile`(_string_) - Specifies an AWS profile name. +- `--debug` (_boolean_) - Print debug logs to the console. +- `--help`(_boolean_) - Displays help information about the command. +Usage + + +### Generate GraphQL client code using the Amplify App ID and branch. +```bash title="Terminal" showLineNumbers={false} +npx amplify generate graphql-client-code --app-id --branch staging +``` +### Generate GraphQL client code for a branch that is connected in the Amplify service +Sometimes you want to test your latest local changes with the backend of another deployed branch. If you want to generate the GraphQL client code file(s) for the latest deployment of another branch, then you can run the following command: + +```bash title="Terminal" showLineNumbers={false} +npx amplify generate graphql-client-code --branch staging +``` +### Generate codegen for CDK app using a joint "AmplifyBackendStack" construct +Assume you have deployed your Amplify project with the CDK construct. You will need to remember your app's project name (designated as the second parameter in your CDK construct) and stack name (designated as part of your `npx cdk deploy` context) + +```ts title="lib/stack.ts" showLineNumbers={false} +import { Construct } from 'constructs'; +import { App, Backend } from 'aws-cdk-lib/aws-amplify'; + +export class MyAmplifyStack extends cdk.Stack { + constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + new Backend(this, "Backend", { /* ... */ }); + } +} +``` +### Deployment command for CDK project +```bash title="Terminal" showLineNumbers={false} +npx cdk deploy +``` +Run Amplify codegen command to generate GraphQL codegen: +```bash title="Terminal" showLineNumbers={false} +npx amplify generate graphql-client-code --stack Backend --platform ts --out ./src +``` +### Generate codegen in specific language and format + +```bash title="Terminal" showLineNumbers={false} +npx amplify generate graphql-client-code --format modelgen --type-target angular +``` +### Supported GraphQL client code combinations: + +| Format | Platform | Codegen command in Amplify CLI | Command in Amplify Gen2 | Default generated file/path | +| -------| -------- | ------------------------------ | ----------------------- | --------------------------- | +| Introspection schema | Amplify Javascript | N/A | `npx amplify generate graphql-client-code --format introspection` | `/` | +| GraphQL codegen | Amplify Javascript | `amplify codegen` | `npx amplify generate graphql-client-code --format graphql-codegen --statement-target javascript --out /src/graphql/` | `/src/graphql/` | +| Modelgen | Amplify Javascript | `amplify codegen model` | `npx amplify generate graphql-client-code --format modelgen --model-target javascript --out /src/models/` | `/src/models/` | +| Modelgen | Amplify Android | `amplify codegen model` | `npx amplify generate graphql-client-code --format modelgen --model-target java --out ` | `/src/main/java/com/amplifyframework/datastore/generated/model` | +| Modelgen | Amplify Swift | `amplify codegen model` | `npx amplify generate graphql-client-code --format modelgen --model-target swift --out /AmplifyModels` | `/AmplifyModels` | +| Modelgen | Amplify Flutter | `amplify codegen model` | `npx amplify generate graphql-client-code --format modelgen --model-target dart --out /AmplifyModels` | `/AmplifyModels` | -{/* @TODO */} ## npx amplify generate forms diff --git a/src/pages/[platform]/reference/project-structure/index.mdx b/src/pages/[platform]/reference/project-structure/index.mdx index a86b753487c..e3d6e62c420 100644 --- a/src/pages/[platform]/reference/project-structure/index.mdx +++ b/src/pages/[platform]/reference/project-structure/index.mdx @@ -30,7 +30,7 @@ export function getStaticProps(context) { Amplify Gen 2 backends are defined using TypeScript, and enable you to collocate resources depending on their function. For example, you can author a [post confirmation trigger for Amazon Cognito](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-post-confirmation.html) right next to your auth's resource file. -When you create your first Amplify project using `npm create amplify@beta`, it will automatically set up the scaffolding for Data and Authentication resources: +When you create your first Amplify project using `npm create amplify@latest`, it will automatically set up the scaffolding for Data and Authentication resources: ```text ├── amplify/ diff --git a/src/pages/[platform]/start/manual-installation/index.mdx b/src/pages/[platform]/start/manual-installation/index.mdx index db3a40b6e3e..109f6a0d7fa 100644 --- a/src/pages/[platform]/start/manual-installation/index.mdx +++ b/src/pages/[platform]/start/manual-installation/index.mdx @@ -35,7 +35,7 @@ The easiest way to get started with AWS Amplify is through [npm](https://npmjs.c First, if your frontend framework of choice doesn't have it already, create your project's `package.json` with `npm init -y`. Then, install the Amplify dependencies for building a backend: ```bash -npm add --save-dev @aws-amplify/backend@beta @aws-amplify/backend-cli@beta typescript +npm add --save-dev @aws-amplify/backend@latest @aws-amplify/backend-cli@latest typescript ``` @@ -115,7 +115,7 @@ defineBackend({ You can also update an existing frontend app. To upgrade existing Amplify code-first DX (Gen 2) apps, use your Node.js package manager (for example, `npm`) to update relevant backend packages: ```bash -npm update @aws-amplify/backend@beta @aws-amplify/backend-cli@beta +npm update @aws-amplify/backend@latest @aws-amplify/backend-cli@latest ``` ## Next steps diff --git a/src/pages/[platform]/start/mobile-support/index.mdx b/src/pages/[platform]/start/mobile-support/index.mdx index 5a0aaa1811a..f33a0c131f6 100644 --- a/src/pages/[platform]/start/mobile-support/index.mdx +++ b/src/pages/[platform]/start/mobile-support/index.mdx @@ -78,7 +78,7 @@ In **Select a Project Template**, select **Empty Activity** or **Empty Compose A The easiest way to get started with AWS Amplify is through npm with `create-amplify` command. You can run it from your base project directory. ```bash -npm create amplify@beta +npm create amplify@latest ? Where should we create your project? (.) # press enter ``` @@ -242,7 +242,7 @@ const schema = a.schema({ content: a.string(), isDone: a.boolean() }) - .authorization([a.allow.owner()]) + .authorization(allow => [allow.owner()]) }); export type Schema = ClientSchema; @@ -515,7 +515,7 @@ For publishing the changes to cloud, you need to create a remote git repository. The easiest way to get started with AWS Amplify is through npm with `create-amplify` command. You can run it from your base project directory. ```bash -npm create amplify@beta +npm create amplify@latest ? Where should we create your project? (.) # press enter ``` @@ -656,7 +656,7 @@ const schema = a.schema({ content: a.string(), isDone: a.boolean() }) - .authorization([a.allow.owner()]) + .authorization(allow => [allow.owner()]) }); export type Schema = ClientSchema; @@ -898,7 +898,7 @@ Now you should have your project created. The easiest way to get started with AWS Amplify is through npm with `create-amplify` command. You can run it from your base project directory. ```bash -npm create amplify@beta +npm create amplify@latest ? Where should we create your project? (.) # press enter ``` @@ -1036,7 +1036,7 @@ const schema = a.schema({ content: a.string(), isDone: a.boolean() }) - .authorization([a.allow.owner()]) + .authorization(allow => [allow.owner()]) }); export type Schema = ClientSchema; diff --git a/src/pages/gen1/[platform]/build-a-backend/more-features/predictions/sdk/index.mdx b/src/pages/gen1/[platform]/build-a-backend/more-features/predictions/sdk/index.mdx index 6c0a7ea9270..0da3631f085 100644 --- a/src/pages/gen1/[platform]/build-a-backend/more-features/predictions/sdk/index.mdx +++ b/src/pages/gen1/[platform]/build-a-backend/more-features/predictions/sdk/index.mdx @@ -2,7 +2,7 @@ import { getCustomStaticPath } from '@/utils/getCustomStaticPath'; export const meta = { title: 'Use AWS SDK', - description: 'For advanced use cases where Amplify does not provide the functionality, you can retrieve the escape hatch to access the AWSPinpoint instance.', + description: 'For advanced use cases where Amplify does not provide the functionality, you can retrieve the escape hatch to access the AWSRekognition instance.', platforms: [ 'swift', 'android' @@ -31,10 +31,10 @@ export function getStaticProps(context) { }; } -import ios0 from '/src/fragments/lib/analytics/ios/escapehatch.mdx'; +import ios0 from '/src/fragments/lib/predictions/ios/escapehatch.mdx'; -import android1 from '/src/fragments/lib/analytics/android/escapehatch.mdx'; +import android1 from '/src/fragments/lib/predictions/android/escapehatch.mdx'; diff --git a/src/pages/gen1/[platform]/prev/build-a-backend/more-features/predictions/sdk/index.mdx b/src/pages/gen1/[platform]/prev/build-a-backend/more-features/predictions/sdk/index.mdx index 8a7979aa9bb..1309c603782 100644 --- a/src/pages/gen1/[platform]/prev/build-a-backend/more-features/predictions/sdk/index.mdx +++ b/src/pages/gen1/[platform]/prev/build-a-backend/more-features/predictions/sdk/index.mdx @@ -3,7 +3,7 @@ import { getCustomStaticPath } from '@/utils/getCustomStaticPath'; export const meta = { title: 'Use AWS SDK', description: - 'For advanced use cases where Amplify does not provide the functionality, you can retrieve the escape hatch to access the AWSPinpoint instance.', + 'For advanced use cases where Amplify does not provide the functionality, you can retrieve the escape hatch to access the AWSRekognition instance.', platforms: ['swift', 'android'] };