{"owner":"aws-amplify","repo":"amplify-js","hasSkills":true,"totalSkillsCount":34,"totalTokensCount":10897,"categories":["root-instruction","claude-rule","plugin-manifest","anthropic-skill"],"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md","CLAUDE.md","packages/adapter-nextjs/README.md","packages/analytics/README.md","packages/api-graphql/README.md","packages/api-rest/README.md","packages/api/README.md","packages/auth/README.md","packages/aws-amplify/README.md","packages/core/README.md","packages/core/__mocks__/configMocks/README.md","packages/datastore-storage-adapter/README.md","packages/datastore/README.md","packages/datastore/__tests__/helpers/README.md","packages/datastore/docs/conflict-resolution.md","packages/datastore/docs/contributing.md","packages/datastore/docs/datastore-lifecycle-events.md","packages/datastore/docs/getting-started.md","packages/datastore/docs/namespaces.md","packages/datastore/docs/observables.md","packages/datastore/docs/schema-changes.md","packages/datastore/docs/storage.md","packages/datastore/docs/sync-engine.md","packages/datastore/docs/workarounds.md","packages/geo/README.md","packages/interactions/README.md","packages/notifications/README.md","packages/predictions/README.md","packages/pubsub/README.md","packages/react-native/README.md","packages/react-native/example/README.md","packages/rtn-passkeys/README.md","packages/rtn-passkeys/example/README.md","packages/storage/README.md"],"skills":{"AGENTS.md":"# AGENTS.md\n\nGuidance for AI coding agents working in the **AWS Amplify JS** monorepo. Read this before making changes.\n\n## Repository Overview\n\nAmplify JS is a **Yarn + Turborepo** monorepo. Every package lives under `packages/<name>/`, each with its own `src/` and `package.json`. Packages are published under the `@aws-amplify/*` scope (plus the umbrella `aws-amplify` package).\n\nKey packages:\n\n| Package | Purpose |\n|---|---|\n| `@aws-amplify/core` | Shared runtime: config singleton, Hub, utils |\n| `@aws-amplify/auth` | Cognito authentication |\n| `@aws-amplify/storage` | S3 storage (client/utils + server/utils split) |\n| `@aws-amplify/api`, `api-graphql`, `api-rest` | API categories |\n| `@aws-amplify/analytics`, `geo`, `interactions`, `notifications`, `predictions`, `pubsub` | Feature categories |\n| `aws-amplify` | Umbrella package re-exporting category APIs |\n| `@aws-amplify/adapter-nextjs` | Next.js server adapter |\n\n## Environment\n\n| Requirement | Version |\n|---|---|\n| Node.js | 24 (pinned in CI; repo has no local `engines`/`.nvmrc`) |\n| Yarn | 1.22.x |\n\n## Build & Test Commands (MANDATORY: use `yarn`)\n\n**Always drive builds/tests/lint through `yarn`. NEVER invoke `tsc`, `eslint`, `jest`, `npx`, or `tsx` directly** — the workspace scripts wire up the correct config and dependency graph. Single-package targeting goes through Turbo's `--filter` (see below).\n\n```bash\n# Install\nyarn\n\n# Build\nyarn build                              # all packages\nyarn turbo run build --filter=@aws-amplify/auth   # single package (+ its deps)\n\n# Test\nyarn test                               # full suite (use before final confirmation)\nyarn turbo run test --filter=@aws-amplify/auth    # single package\n\n# Lint\nyarn lint                               # lint all packages\nyarn turbo run lint --filter=@aws-amplify/auth    # single package\n\n# Bundle size\nyarn test:size                          # size-limit check (only runs for packages that define it)\nyarn test:size --why                    # debug regression (Statoscope)\n\n# Watch mode for local dev\nyarn build:watch\nyarn link-all                           # make all packages linkable\n\n# Nuclear clean\ngit clean -xdf\n```\n\nRun `yarn` from the **monorepo root or a package root**. During implementation you may narrow with file/suite/test filters, but always run the full `test` / `lint` / `build` for final confirmation.\n\n> **Single-package targeting must go through Turbo directly** — `yarn turbo run <task> --filter=@aws-amplify/<pkg>`. Do **not** pass `--filter` to the top-level `yarn build` / `yarn test` scripts: they are compound (`&&`) scripts, so the flag is misrouted to the trailing command and Turbo still runs unfiltered. (`--scope` is a Lerna flag — not valid for Turbo 2.x at all.)\n\n## Testing Conventions\n\n- **Do NOT mock `getConfig` on the Amplify singleton.** Mock the actual underlying modules/functions instead (real Amplify config approach).\n- Write or update unit tests for any added/modified code. Be especially vigilant with shared code (race conditions).\n- Passing unit tests are required for any PR that changes functionality.\n- **Bundle-size (`size-limit`) checks only apply to packages that configure them.** Eight packages declare a `size-limit` key (`aws-amplify`, `core`, `datastore`, `geo`, `interactions`, `predictions`, `pubsub`, `api-graphql`), but `yarn test:size` only exercises the seven that also define a `test:size` script (all of the above except `api-graphql`). Filtering it to a package without size-limit configured (e.g. `auth`, `storage`) is a no-op.\n\n## Code Conventions\n\n- **License headers are required** on source files (enforced by the `license-test` CI check).\n- **Never commit `tsconfig.tsbuildinfo` files.** A stray `packages/*/tsconfig.tsbuildinfo` causes `license-test` failures (`License not found in ...`). Remove it if generated.\n- Preserve existing comments, JSDoc, and logging statements.\n- Follow existing formatting (Prettier + ESLint config are applied via `yarn` scripts).\n\n## Git Hooks (Husky)\n\nThe repo installs Husky hooks that run automatically — an agent committing or pushing will trigger them:\n\n- **`pre-commit`** — runs `lint-staged` (`eslint --fix` on staged `*.ts`/`*.tsx`). Do not bypass with `--no-verify`.\n- **`pre-push`** — runs a **git-secrets** scan and **blocks the push if git-secrets is not installed**. Install and register it before pushing:\n\n```bash\nbrew install git-secrets   # or: apt-get install git-secrets\ngit secrets --register-aws\n```\n\n## Changesets (required for functional changes)\n\n```bash\nyarn changeset\n```\n\nCreates a file in `.changeset/`:\n\n```markdown\n---\n'@aws-amplify/<package>': patch|minor|major\n---\n\n<type>(<scope>): description of the change.\n```\n\n**Skip a changeset** only for docs-only, formatting, or CI-only changes.\n\n## Branch Naming\n\n```\n<scope>/<type>/<description>\n```\n\n- **scope**: category or alias (e.g. `auth`, `storage`, `core`)\n- **type**: `feat` | `fix` | `docs` | `refactor` | `perf` | `test` | `build` | `ci` | `chore` | `revert`\n\nExamples: `auth/fix/refresh-token-race-condition`, `storage/feat/presigned-urls`\n\n## Commit / PR Flow\n\n1. Make changes in `packages/<category>/`.\n2. Add/update unit tests.\n3. Add a changeset (if functional).\n4. Validate: `yarn build` + `yarn test` (+ `yarn test:size` if bundle-sensitive).\n5. Commit with a conventional message: `<type>(<scope>): summary`.\n6. Push and open a PR filling out the template (description, linked issue, validation steps, checklist).\n\n## CI Checks (must pass before merge)\n\n| Check | Validates |\n|---|---|\n| `unit-tests` | Jest suites across packages |\n| `native-unit-tests` | React Native tests |\n| `bundle-size-tests` | Tree-shaken footprint (size-limit) |\n| `license-test` | License headers present |\n| `tsc-compliance-test` | TypeScript compilation |\n| `dependency-review` | No problematic dependencies |\n| `git-secrets-check` | No leaked AWS credentials |\n| `github-actions-test` | CI config validity |\n\nThe `ci - Unit and Bundle tests have passed` gate turns green only when all above pass.\n\n## Maintenance Branch: `v5-stable`\n\nThe `v5-stable` branch hosts Amplify JS v5 maintenance releases (security patches, critical fixes). **Do not apply this document's conventions there** — it uses different tooling (Lerna instead of Turborepo, no changesets, different setup and CI checks).\n\nWhen backporting a fix to v5: branch off `v5-stable`, target the PR at `v5-stable`, and follow the `AGENTS.md` **on that branch** for its specific conventions.\n\n## Do / Don't Summary\n\n**Do**\n- Use `yarn` for everything\n- Add tests + changesets\n- Keep license headers\n- Mock underlying modules, not `Amplify.getConfig`\n\n**Don't**\n- Run `tsc`/`jest`/`eslint`/`npx` directly\n- Commit `tsconfig.tsbuildinfo`\n- Strip existing comments or logging\n","CLAUDE.md":"# CLAUDE.md\n\nThis project's AI agent guidance lives in [AGENTS.md](./AGENTS.md).\n\nPlease read **[AGENTS.md](./AGENTS.md)** for repository structure, build/test commands, code conventions, changeset requirements, and CI checks.\n","packages/adapter-nextjs/README.md":"This package contains the AWS Amplify Next.js Adapter. For more information on using Next.js in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/javascript/build-a-backend/server-side-rendering/nextjs/).\n\n### Licensing Note\nAlthough this repository is released and licensed under the Apache License (see [LICENSE](./LICENSE)), its devDependencies transitively use the third party [sharp](https://sharp.pixelplumbing.com/) project.\n\nThe sharp projects prebuilt binaries' licensing includes [LGPL-2.1](https://opensource.org/license/LGPL-2.1) and [LGPL-3.0-or-later](https://opensource.org/license/LGPL-3.0) licenses","packages/analytics/README.md":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify Analytics category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","packages/api-graphql/README.md":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify API GraphQL category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","packages/api-rest/README.md":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify API REST category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","packages/api/README.md":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify API category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","packages/auth/README.md":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify Auth category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","packages/aws-amplify/README.md":"# AWS Amplify Package - aws-amplify\n\nAWS Amplify is a JavaScript library for frontend and mobile developers building cloud-enabled applications. The library is a declarative interface across different categories of operations in order to make common tasks easier to add into your application. The default implementation works with Amazon Web Services (AWS) resources but is designed to be open and pluggable for usage with other cloud services that wish to provide an implementation or custom backends.\n\nDocumentation is available [here](https://docs.amplify.aws/javascript/).\n","packages/core/README.md":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify core utilities and is intended for internal use only. To integrate Amplify into your app. Please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","packages/core/__mocks__/configMocks/README.md":"This directory contains equivalent Gen1 & Gen2 configurations which are used to validate interoperability between\ndifferent config versions/schemas. Make sure that any updates applied to one are applied to the other.\n","packages/datastore-storage-adapter/README.md":"This package contains the AWS Amplify DataStore storage adapter. For more information on using the DataStore storage adapter in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/react-native/build-a-backend/more-features/datastore/set-up-datastore/#setup-local-development-environment).\n","packages/datastore/README.md":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify DataStore category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n\n# AWS Amplify DataStore Docs\n\n[Amplify DataStore](https://docs.amplify.aws/lib/datastore/getting-started/q/platform/js/) provides a programming model for leveraging shared and distributed data without writing additional code for offline and online scenarios, which makes working with distributed, cross-user data just as simple as working with local-only data.\n\n---\n\n| package                | version                                                         | open issues                                                                                                                                                                                  | closed issues                                                                                                                                                                                 |\n| ---------------------- | --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| @aws-amplify/datastore | ![npm](https://img.shields.io/npm/v/@aws-amplify/datastore.svg) | [![Open Issues](https://img.shields.io/github/issues/aws-amplify/amplify-js/DataStore?color=red)](https://github.com/aws-amplify/amplify-js/issues?q=is%3Aissue+label%3ADataStore+is%3Aopen) | [![Closed Issues](https://img.shields.io/github/issues-closed/aws-amplify/amplify-js/DataStore)](https://github.com/aws-amplify/amplify-js/issues?q=is%3Aissue+label%3ADataStore+is%3Aclosed) |\n\n---\n\n## **👋 Note For Contributers: 👋**\n\n_**Please update these docs any time you find something that is incorrect or lacking. In particular, if a line in the docs prompts a question, take a moment to figure out the answer, then update the docs with the necessary detail.**_\n\n---\n\n## Getting Started\n\nBefore you start reading through these docs, take a moment to understand [how DataStore works at a high level](https://docs.amplify.aws/lib/datastore/how-it-works/q/platform/js/). Additionally, we recommend first reading through [docs.amplify.aws](https://docs.amplify.aws/lib/datastore/getting-started/q/platform/js/). The purpose of these docs is to dive deep into the codebase itself and understand the inner workings of DataStore for the purpose of contributing. Understanding these docs is **not** necessary for using DataStore. Lastly, before reading, take a look at [the diagrams below](#diagrams).\n\n---\n\n## Docs\n\n- [Conflict Resolution](docs/conflict-resolution.md)\n- [Contributing](docs/contributing.md)\n- [DataStore Lifecycle Events (\"Start\", \"Stop\", \"Clear\")](docs/datastore-lifecycle-events.md)\n  - This explains how DataStore fundementally works, and is a great place to start.\n- [Getting Started](docs/getting-started.md) (Running against a sample app, etc.)\n- [Namespaces](docs/namespaces.md)\n- [How DataStore uses Observables](docs/observables.md)\n- [Schema Changes](docs/schema-changes.md)\n- [Storage](docs/storage.md)\n- [Sync Engine](docs/sync-engine.md)\n- [\"Unsupported hacks\" / workarounds](docs/workarounds.md)\n\n---\n\n# Diagrams\n\n_Note: relationships with dotted lines are explained more in a separate diagram._\n\n## How the DataStore API and Storage Engine Interact\n\n```mermaid\nflowchart TD\n  %% API and Storage\n  api[[DS API]]-- observe -->storage{Storage Engine}\n  storage-- next -->adapter[[Adapter]]\n  adapter-->db[[Local DB]]\n  db-->api\n  sync[[Sync Engine*]]-.-storage\n  sync-.-appSync[(AppSync)]\n```\n\n# How the Sync Engine Observes Changes in Storage and AppSync\n\n_Note: All green nodes belong to the Sync Engine._\n\n\\* Merger first checks outbox\n\n\\*\\* Outbox sends outgoing messages to AppSync\n\n```mermaid\nflowchart TD\n\n  subgraph SyncEngine\n  index{index.ts}-- observe -->reach[Core reachability]\n\n  subgraph processors\n  mp[Mutation Processor]\n  sp[Subscription Processor]\n  syp[Sync Processor]\n  end\n\n  reach--next-->mp[Mutation Processor]\n  reach--next-->sp[Subscription Processor]\n  reach--next-->syp[Sync Processor]\n\n  subgraph outbox / merger\n  outbox[Outbox]\n  merger[Merger]\n  outbox---merger\n  end\n\n  end\n\n  api[DS API]-.->storage\n  mp-- 1. observe -->storage{Storage Engine}\n  storage-- 2. next -->merger[merger*]-- next -->storage\n\n\n  sp-- observe -->appsync[(AppSync)]\n  appsync-- next -->sp\n\n  syp---appsync\n\n  mp-->outbox[outbox**]\n\n  appsync<--->outbox\n  %% styling\n  classDef syncEngineClass fill:#8FB,stroke:#333,stroke-width:4px,color:#333;\n  class index,mp,sp,syp,merger,outbox syncEngineClass;\n```\n\n---\n\n# Project Structure\n\n<pre>\namplify-js/packages/datastore/src\n├── authModeStrategies\n│   └── defaultAuthStraegy.ts\n│   └── index.ts\n│   └── multiAuthStrategy.ts\n├── datastore\n│   └── datastore.ts # Entry point for DataStore\n├── predicates\n│   └── index.ts\n│   └── sort.ts\n├── ssr\n├── storage # Storage Engine\n│   └── adapter # Platform-specific Storage Adapters\n│      └── getDefaultAdapter\n│      └── AsyncStorageAdapter.ts\n│      └── AsyncStorageDatabase.ts\n│      └── index.ts\n│      └── IndexedDBAdapter.ts\n│      └── InMemoryStore.native.ts\n│      └── InMemoryStore.ts\n│   └── storage.ts # Entry point for Storage\n├── sync # Sync Engine\n│   └── dataStoreReachability\n│      └── index.native.ts\n│      └── index.ts\n│   └── processors # Sync Engine Processors\n│      └── mutation.ts\n│      └── subscription.ts\n│      └── sync.ts\n│   └── datastoreConnectivity.ts # Subscribe to reachability monitor\n│   └── index.ts # Entry point for Sync Engine\n│   └── merger.ts # <a href=\"https://github.com/aws-amplify/amplify-js/blob/datastore-docs/packages/datastore/docs/sync-engine.md#merger\" title=\"merger doc\">doc</a>\n│   └── outbox.ts # <a href=\"https://github.com/aws-amplify/amplify-js/blob/datastore-docs/packages/datastore/docs/sync-engine.md#outbox\" title=\"outbox doc\">doc</a>\n</pre>\n\n---\n\n## Other Resources:\n\n- [High-level overview of how DataStore works](https://docs.amplify.aws/lib/datastore/how-it-works/q/platform/js/)\n- [DataStore Docs](https://docs.amplify.aws/lib/datastore/getting-started/q/platform/js/)\n- [re:Invent talk](https://www.youtube.com/watch?v=KcYl6_We0EU)\n","packages/datastore/__tests__/helpers/README.md":"## Helper functions for DataStore testing\n\nPlease try to keep things clean.\n\nIn particular, let's try to to keep file sizes smaller and more \"categorical\" in order to:\n\n1. Make finding and discovering test utils easier\n2. Reduce excessive vertical scrolling\n3. Reduce complexity of merge conflicts\n4. _<< And other awesome benefits I haven't thought of! >>_\n\nIntended organization is as follows:\n\n|                       | Intent                                                                                                                |\n| --------------------- | --------------------------------------------------------------------------------------------------------------------- |\n| `fakes/*`             | Util classes to inject and/or observe datastore's interaction with its boundaries, like cloud/graphql storage.        |\n| `schemas/*`           | Schema JSON and model types (Plenty of room for further refactoring and reorganization here!)                         |\n| `datastoreFactory.ts` | Function(s) for creating clean, test-configured initializations of DataStore and deps to test against.                |\n| `util.ts`             | Miscellaneous, mostly-isolated utility functions to aid with testing. (To be further decomposed as-needed over time.) |\n\nThere's almost always room to clean things up and do better. If you encounter a merge conflict that would have benefitted from chunks of code living separately; submit a refactor-only PR to separate them. If you get \"lost\" vertically scrolling in a file, look for a semantically meaningful boundary to separate on. If you can't find what you're looking for, consider whether another folder/category to drill into would have helped.\n\nIf you have any ideas around taming the rather large test schemas, making it easier to add new models and corresponding JSON, submit a PR with your idea! Etc..\n\nThanks!\n","packages/datastore/docs/conflict-resolution.md":"# Conflict Resolution\n- **AppSync is the source of truth for conflict resolution**\n   1. In the event AppSync fails to resolve a conflict, the network response will contain an error message (`conflict unhandled`). This is how we give customers the chance to make an update, or try again.\n   2. We use jittered retry (10x).\n   - TODO: add more detail / links to how this retry logic occurs.\n- We err on the side of not deleting customer data when performing conflict resolution.\n- Auto-merge is the default resolution strategy. This relies on the version, and will attempt to merge fields that changed when possible.\n- For more, see [the AppSync docs](https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html)","packages/datastore/docs/contributing.md":"# Contributing\n\n## Formatting\n- We use Prettier to format our code. We recommend installing it within your IDE to prevent formatting code within other Amplify packages (as opposed to formatting from the Prettier CLI directly). Example [VS Code Extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)).\n\n## Testing DataStore changes locally\n- On first build:\n\t- Within **amplify-js**: `yarn && yarn build && yarn link-all && yarn build:watch`\n\t- Within sample app: `yarn && yarn link aws-amplify && yarn link @aws-amplify/datastore && yarn start`\n- On subsequent builds (useful if something isn't working):\n\t- Within **amplify-js**: `yarn clean && yarn build && yarn link-all && yarn build:watch`\n\t- Within sample app: `rm -rf node_modules && yarn && yarn link aws-amplify && yarn link @aws-amplify/datastore && yarn start`\n\n## Contributing to these docs\n- Do not link to specific lines of code, as these frequently change. Instead, do the opposite: link to the documentation within the code itself, as the docs are less likely to change.\n- Prefer small, self-contained sections over large, monolothic documents.\n- Do not use permalinks - instead, link to the most current files.","packages/datastore/docs/datastore-lifecycle-events.md":"# DataStore Lifecycle Events (\"Start\", \"Stop\", \"Clear\")\n\n# DataStore Initialization (\"Start\")\n\n**Understanding how DataStore starts is critical to understanding how DataStore fundamentally works.** At a high level, starting DataStore does the following things in order for each model:\n\n> 1.  Init Schema\n> 2.  Init the Storage Engine\n> 3.  Migrate schema changes\n> 4.  Sync Engine Operations\n> 5.  Empty the Outbox / processes the mutation queue\n> 6.  Begin processing the subscription buffer\n> 7.  DataStore is now in \"ready\" state\n\n- _We can eagerly start DataStore by calling `DataStore.start`. Otherwise, invoking a method (query, save, delete, observe) will start it up_\n- _When importing a model, DS consumes `schema.js`, and creates the IndexedDB store._\n\n## **How it works:**\n\n1.  ### **Init schema**\n    - **1.1** First we call `initSchema` [here](packages/datastore/src/datastore/datastore.ts)\n    - **1.2** Codegen then generates `schema.js` from the schema\n    - **1.3** DataStore consumes `schema.js`\n\n2.  ### **Init the storage engine**\n    - **2.1** The adapter is initialized\n    - **2.2** The local database gets created if it doesn’t exist already\n    - **2.3** The adapter [has a `setUp`](packages/datastore/src/storage/adapter/IndexedDBAdapter.ts#L82) method that then calls the database's `init` method\n    - **2.4** Relations are established\n    - _Nothing happens until the first interaction with DataStore_\n\n3.  ### **Migrate schema changes (if needed)**\n    - See [schema-changes.md](./schema-changes.md)\n    - If the user has updated the schema, we perform the migration here\n\n4.  ### **Sync Engine Operations**\n-  #### 4.1 Instantiate Sync Engine (`this.sync = new SyncEngine(`)\n    - The Sync Engine is only instantiated if there is a graphql endpoint (meaning we’ve already provisioned the backend). Otherwise, DataStore is in local-only mode. See [datastore.ts](packages/datastore/src/datastore/datastore.ts#L735)\n    - **Note: at this step, we do not yet process the buffer**\n    - There are three subscriptions per model: `create`, `update`, and `delete`\n\n- #### 4.2 Sync Engine is started (`syncSubscription = this.sync.start(`)\n    - **4.2.1 Subscribe to the Sync Engine**\n      - Messages from this subscription are emmited as Hub events for DataStore\n      - When ready, we call `initResolve`\n      - If unauthorized, DS keeps working, as we may have publicly readable models\n      - If a validation error occurs, DataStore Sync breaks entirely\n      - Without subscriptions, DataStore doesn’t work (when there is an endpoint present)\n      - Subscriptions are the only component that update the local store from remote\n      - If updates come in, they’re buffered to be processed after sync is complete\n      - Prepares the sync predicates (similar to adapter setup)\n\n    - **4.2.2 Subscribe to DataStore connectivity observable (notifications about network status)**\n        - `this.datastoreConnectivity.status().subscribe`\n        - Subscribe Amplify Core component that monitors network reachability\n        - We do this here because we need the ability to stop or start the sync process. When offline, we disconnect the websocket and stop syncing. Once online, we reconnect the websocket and start base / delta syncing\n        - Sync engine subscribes to the Storage Engine\n            - Every write may need to get translated to a mutation in the outbox\n            - Storage engine is local source of truth for DataStore, all other pieces are observing\n\n    - **4.2.3 Run the Sync Queries (when online)**\n        - _Note: We perform a topological sort of the data - we sync the children first, so when we query the parent, the children are already present We also use an optimisation to parallelize this process if possible (i.e. non-dependent models)_\n        - Sync queries are Graphql queries that are necessary to hydrate the local store initially\n        - The first time we run the app, we will perform a query to perform a scan or query of DynamoDB with up to 10k records per table. This populates the local store. With selective sync, we perform a query instead of a scan against DynamoDB.\n        - Subsequent changes after the initial sync query come in through subscriptions\n        - There are two mechanisms:\n            - Base sync - retrieve all records up to total sync value\n            - Delta sync - one table per model, one delta sync table per DS store\n        - AppSync makse the final decision regarding which sync (base vs delta) to perform\n            - The client sends the last sync param with the sync query, service then compares the diff\n            - There is a TTL on all delta sync table records\n            - To find the TTL within the AppSync Console, see \"Update Data Source\"\n\n5. ### **Empty the Outbox / processes the mutation queue**\n    - Example: when performing mutations offline, records are added to the queue. Once there is connectivity, we start sending these **ONE BY ONE**.\n    - **Note: No batch API is exposed to consumers**\n    - Mutation events have ids\n    - Syncs get applied before mutations are sent\n6. ### **Begin processing the subscription buffer**\n    - If we receive subscription messages any time in the process of initializing subscriptions, performing sync queries, or processing the mutation queue, we buffer the subscription messages until everything else is completed. Once we have completed processing the mutation queue, we then process the subscription buffer\n7. ### **DataStore is now in \"ready\" state**\n    - For additional reference, and how the above are published as Hub events, see [the docs](https://docs.amplify.aws/lib/datastore/datastore-events/q/platform/js/)\n\n## Stop\n- Stops the DataStore sync process. This will close the real-time subscription connection when your app is no longer interested in updates. You will typically call DataStore.stop() just before your application is closed. You can also force your DataStore sync expressions to be re-evaluated at runtime by calling stop(), followed by start()\n\n## Clear\n- Clears local data from DataStore. DataStore will now require a full sync (not a delta sync) to populate the local store with data\n","packages/datastore/docs/getting-started.md":"# Onboarding with DataStore\n\n## Understand the primary DataStore events\n- Read the [DataStore lifecycle events doc](docs/datastore-lifecycle-events.md)\n\n## Building a sample app with DataStore to understand how it works\n1. Build a basic DataStore sample app (no @auth, just 1-2 models).\n2. Build a similar sample app with the API category.\n3. Add @auth rules to the DataStore app:\n    1. `amplify update api`\n    2. Modify schema according to auth rules docs (https://docs.amplify.aws/lib/datastore/setup-auth-rules/q/platform/js).\n    3. `amplify push`\n    4. `amplify codegen models`\n4. Add [selective sync](https://docs.amplify.aws/lib/datastore/sync/q/platform/js#selectively-syncing-a-subset-of-your-data).\n5. Enable [real-time changes](https://docs.amplify.aws/lib/datastore/real-time/q/platform/js).\n6. While interacting with your app, examine the IndexedDB tables (Application > IndexedDB within Chrome dev tools):\n    1. Check out the different stores in IDB that get created for your schema. Note the internal stores prefixed with sync_, and the stores corresponding to your models prefixed with user_.\n    2. Familiarize yourself with how actions taken in the UI affect the data stored in IDB. This may be easier to do while throttling the network connection. You'll be able to see how outgoing mutations first get persisted into the corresponding store, then added to the mutation queue / outbox (sync_MutationEvent), and then updated in the store with data from AppSync.\n7. Turn on DEBUG logging (`ConsoleLogger.LOG_LEVEL = \"DEBUG\";`) at the root of your project, and inspect the logs in the console while using your app. Additionally, [enable hub events](https://docs.amplify.aws/lib/datastore/datastore-events/q/platform/js#usage) for DataStore.\n8. The best way to understand DataStore events is to place several debuggers or breakpoints throughout DataStore.\n    - With logging / Hub events enabled, you can see what operations DataStore is performing (i.e. start, sync, etc.) as you step through with the debugger.\n9. Testing offline scenerios / concurrent user sessions is a useful way to test the full functionality of DataStore, and to fully understand how the sync process actually works.\n10. Next steps:\n    - Create a React Native example (uses a different storage type)\n    - Try more complex schema types\n    - Observe changes in records within DynamoDB (for instance, soft deletion).","packages/datastore/docs/namespaces.md":"# Namespaces\n- `datastore`\n\t- Settings\n- `user` \n\t- Models that came from user schema\n- `sync` \n\t- Metadata (last time ran query, etc.)\n- `storage` \n\t- Deprecated\n# Local database examples:\n\n- *Note: Anything prepended with `sync_` is an internal table.*\n\n- ## datastore_Setting\n    - Used for schema versioning\n    - See the [schema changes doc](docs/schema-changes.md)\n    ```\n\t{\n\t\tid: \"01FYABF3DMBZZJ46W1CC214NH2\"\n\t\tkey: \"schemaVersion\"\n\t\tvalue: \"\\\"4401034582a70c60713e1f7f9da3b752\\\"\"\n\t}\n\t```\n- ## sync_ModelMetadata\n    - Sync Engine metadata\n\t- Includes information about the last time we synced a model\n\t```\n\t{\n\t\tfullSyncInterval: 86400000\n\t\tid: \"01FYABF3DMBZZJ46W1CC214NH3\"\n\t\tlastFullSync: 1647467532307\n\t\tlastSync: 1647467532307\n\t\tlastSyncPredicate: null\n\t\tmodel: \"Todo\"\n\t\tnamespace: \"user\"\n\t}\n\t```\n- ## sync_MutationEvent\n- ## user_[Model Name]\n    - The actual records themselves.\n\t```\n\t{\n\t\tcreatedAt: \"2022-03-16T21:52:07.718Z\"\n\t\tdescription: null\n\t\tid: \"6f69055b-b081-4225-8fc4-1d6d52732660\"\n\t\tname: \"name 1647467527489\"\n\t\tupdatedAt: \"2022-03-16T21:52:07.718Z\"\n\t\t_deleted: null\n\t\t_lastChangedAt: 1647467527754\n\t\t_version: 1\n\t}\n\t```","packages/datastore/docs/observables.md":"# How DataStore uses Observables\n- All of DataStore internally uses event driven methods (observables) to handle everything from the sync process, to observing online connectivity. **This makes the Storage Engine the single source of truth for DataStore.**\n- Examples:\n\t- The Sync Engine observes DataStore Connectivity \n\t- The Sync Engine observes the Storage Engine \n    - The client observes DataStore with `observe` and `observeQuery`:\n\t\t- https://docs.amplify.aws/lib/datastore/real-time/q/platform/js/\n\n## Understanding Observables\n- DataStore uses [`zen-observable`](https://github.com/zenparsing/zen-observable)\n- [The RXJS docs](https://rxjs.dev/guide/observable) do a good job of describing observables in more detail.","packages/datastore/docs/schema-changes.md":"# What happens when a user changes their schema?\n   - The `schema.js` file that exists within an Amplify project (located at `src/models/schema.js`) contains a version hash. \n   - This hash is compared against the hash stored in the `Settings` table of the local database. Example:\n       ```\n           {\n               id: \"01FYABF3DMBZZJ46W1CC214NH2\"\n               key: \"schemaVersion\"\n               value: \"\\\"4401034582a70c60713e1f7f9da3b752\\\"\"\n           }\n       ```\n   - The process of checking the schema version (`checkSchemaVersion`) occurs when DataStore starts, after the Storage Engine has been initialized, and before the Sync Engine is initialized.\n   - If the schema version has changed, we clear local storage, and perform a full sync","packages/datastore/docs/storage.md":"# Storage\n## Adapters:\n- Web\n   - [IndexedDB](../src/storage/adapter/IndexedDBAdapter.ts)\n- Mobile\n   - React Native\n      - [Async Storage](../src/storage/adapter/AsyncStorageAdapter.ts) (can opt in to use SQLite)\n- SSR\n   - [InMemoryStore](../src/storage/adapter/InMemoryStore.ts)\n\n## How we determine which adapter to use\n\nWe determine the storage adapter [here](../src/storage/adapter/getDefaultAdapter/index.ts). \n\n\n## [The Storage class](../src/storage/storage.ts)\n- The Storage class is what interacts with the adapters.\n\n## [Storage Adapters](../src/storage/adapter)\n   1. There is one adapter per database type we support (i.e. three adapters).\n   2. Each adapter provides a unified API for the storage engine to interact with.\n   3. The SQLite adapter lives [in it’s own package](https://github.com/aws-amplify/amplify-js/tree/main/packages/datastore-storage-adapter).\n   4. **ExclusiveStorage wraps public storage methods (e.g. `Storage.runExclusive`)**\n      1. Guarantees consistency\n      2. Makes the storage class transactional\n      3. **Provides concurrency control**\n\n## How DataStore finds records locally:\n- Varies by storage adapter\n- [SQLiteAdapter](https://github.com/aws-amplify/amplify-js/tree/main/packages/datastore-storage-adapter): DataStore constructs a query. \n- [Async Storage](../src/storage/adapter/AsyncStorageAdapter.ts): DataStore scans and filters. \n- [IndexedDB](../src/storage/adapter/IndexedDBAdapter.ts): if the query is by primary key, DataStore queries against the index, otherwise it scans and filters.\n   - *Note: The lazy loading branch includes an improvement to the IndexedDB adapter that will check if any search criteria can leverage an index (there is no preference for low cardinality; the first identified index is used.) If so, the base result is sourced from the index and the remaining criteria will be applied as a filter.*\n\n## Understanding the difference between Save and Batch Save\n- As the names imply, `save` accepts a single record and persists it, while `batchSave` accepts a page of records and persists them all. `batchSave`, however, is *only used within the sync processor*, and will filter out deleted records from the sync page results, and then delete them from the local db.","packages/datastore/docs/sync-engine.md":"# Sync Engine\n\nSee [the sync class](packages/datastore/src/sync/index.ts)\n\n## High-level overview:\n- The first time DataStore is started on a new client, a full sync is performed. Subsequent reloads of the app (including browser refresh, or a new browser session) are delta syncs.\n- If it has been greater than the `fullSyncInterval` (configurable) since the client has performed a full sync, this operation occurs as a full sync.\n- The Sync Engine is well documented in the [DataStore Lifecycle Events doc](./datastore-lifecycle-events.md). The purpose of this doc is to explain anything about the sync process that is not already documented there.\n\n\n## Types of Syncs\n### Full Sync\n- All records are fetched from AppSync.\n\n### Delta Sync\n- All the records that changed after a given time stamp are fetched.\n\n## How it works\n\n### [Merger](../src/sync/merger.ts)\n- A helper class for merging subscription records with the outbox (checks IDs).\n- The Sync Engine uses merge in two places:\n\t- 1. https://github.com/aws-amplify/amplify-js/blob/main/packages/datastore/src/sync/index.ts#L289\n\t\t- Triggered by the mutation response. It gets called after the client that authored the change receives the network response of the mutation request they generated.\n\t- 2. https://github.com/aws-amplify/amplify-js/blob/main/packages/datastore/src/sync/index.ts#L326\n\t\t- Triggered by an AppSync real-time subscription event, which is how all clients get notified of the change. In the case of the mutation author, this notification is redundant, but it’s necessary for all other active users of the application. This is why there will always be multiple snapshot returned by `observe` and `observeQuery` in the case of the mutation author.\n\n- The function of [the Merger class](../src/sync/merger.ts) is to filter out any incoming records that have corresponding pending changes in that client’s mutation queue / outbox, and is done to maintain data consistency. We wouldn’t want to write over data that the client has deliberately changed, and essentially undo whatever changes were performed on that client - even temporarily. Thus, each time a change comes in via a mutation response, AppSync subscription, or sync query, **Merger will only persist that change to the local database when there is not a pending mutation for that same record**.\n- If there is a pending change in the outbox - we discard the incoming model we were working with inside the merge call (by not saving it). Later, when the record from the Outbox gets processed by AppSync (and conflict resolution rules are applied as appropriate), we will persist the response of the mutation (assuming we don’t change the record again in the interim)\n- If there is not a pending change in the outbox - we persist the model to the local store via `Storage.save` within `merge`.\n- _Note: We maintain a single instance of a mutation when we are offline (i.e. if we perform multiple updates on the same record, we merge them into a single event). Once we are online, but other mutations are processing, we'll still attempt to merge outgoing events into an existing one if they are not already in flight_\n- Merger Example:\n\t- User A updates record 1\n\t- The update to record 1 is persisted locally, and enters the mutation queue for persistence to Appsync\n\t- User B has not yet received the update to record 1, and updates record 1\n\t- User A receives User B's update to record 1, but has not yet sent the mutation to AppSync\n\t- If Merger did not first check the mutation queue prior to applying the change from User B, User A would see their update, then user B's update, then, depending on how the conflict is handled by AppSync, could then see their update again. Instead, User A sees their update, and rejects User B's update. Once the conflict is handled by AppSync, any changes that are received are then applied.\n- *How to locally test / step through Merger:* \n\t- Create a few records and make sure the records go out successfully and are persisted. Then, delete local data in IndexedDB (either by clicking the `clear` button in a sample, or through dev tools), then reload the page, or perform a query.\n- **Note: AppSync expects us to send only updated fields in order for merge to work correctly.**\n\n### [Outbox]((../src/sync/outbox.ts))\n- A mutation event outbox\n- Holds all local changes (even if you close the app). \n- Peek returns the next mutation event to be sent to AppSync, but does not remove it from the outbox.\n\n## [Processors](../src/sync/processors)\n- Sync Engine uses processors depending on the type of operation\n- All processors utilize observables\n- Where retry happens\n\n### Mutation Processor (Local changes)\n- Online or offline changes that were optimistically made to the Storage Engine (processed in mutation queue **one by one**).\n- Observes Storage Engine for new changes.\n\n### Subscription Processor (Remote changes)\n- Real-time subscription messages (such as another client performing a change).\n- Uses the Amplify API Graphql package (which then uses PubSub).\n### Sync Processor\n- When the client goes online, fetch all changes that were performed in AppSync (could be full or delta sync).\n\n## Misc:\n- AppSync records are soft-deleted and have a TTL. \n- TODO: special configurations around sync intervals","packages/datastore/docs/workarounds.md":"# TODO: \"Unsupported hacks\" / Workarounds","packages/geo/README.md":"This package contains the AWS Amplify Geo category. For more information on using Geo in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/javascript/build-a-backend/more-features/geo/).\n","packages/interactions/README.md":"This package contains the AWS Amplify Interactions category. For more information on using Interactions in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/javascript/build-a-backend/more-features/interactions/).\n","packages/notifications/README.md":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify Notifications category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","packages/predictions/README.md":"This package contains the AWS Amplify Predictions category. For more information on using Predictions in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/javascript/build-a-backend/more-features/predictions/).\n\n","packages/pubsub/README.md":"This package contains the AWS Amplify PubSub category. For more information on using PubSub in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/javascript/build-a-backend/more-features/pubsub/).\n\n","packages/react-native/README.md":"> INTERNAL USE ONLY\n\nThis package contains AWS Amplify React Native utilities and is intended for internal use only. Please ensure this package is installed alongside [aws-amplify](https://www.npmjs.com/package/aws-amplify). We do not advise using any exports from this package directly.\n","packages/react-native/example/README.md":"This is an example app for developing and testing the react-native modules located at `../`.\n\n# Getting Started\n\n> **Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till \"Creating a new application\" step, before proceeding.\n\n## Step 1: Start the Metro Server\n\nFirst, you will need to start **Metro**, the JavaScript _bundler_ that ships _with_ React Native.\n\nTo start Metro, run the following command from the _root_ of your React Native project:\n\n```bash\n# using npm\nnpm start\n\n# OR using Yarn\nyarn start\n```\n\n## Step 2: Start your Application\n\nLet Metro Bundler run in its _own_ terminal. Open a _new_ terminal from the _root_ of your React Native project. Run the following command to start your _Android_ or _iOS_ app:\n\n### For Android\n\n```bash\n# using npm\nnpm run android\n\n# OR using Yarn\nyarn android\n```\n\n### For iOS\n\n```bash\n# using npm\nnpm run ios\n\n# OR using Yarn\nyarn ios\n```\n\nIf everything is set up _correctly_, you should see your new app running in your _Android Emulator_ or _iOS Simulator_ shortly provided you have set up your emulator/simulator correctly.\n\nThis is one way to run your app — you can also run it directly from within Android Studio and Xcode respectively.\n","packages/rtn-passkeys/README.md":"> INTERNAL USE ONLY\n\nThis package contains AWS Amplify React Native utilities and is intended for internal use only. Please ensure this package is installed alongside [aws-amplify](https://www.npmjs.com/package/aws-amplify) and [@aws-amplify/react-native](https://www.npmjs.com/package/@aws-amplify/react-native). We do not advise using any exports from this package directly.\n","packages/rtn-passkeys/example/README.md":"This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli).\n\n# Getting Started\n\n> **Note**: Make sure you have completed the [Set Up Your Environment](https://reactnative.dev/docs/set-up-your-environment) guide before proceeding.\n\n## Step 1: Start Metro\n\nFirst, you will need to run **Metro**, the JavaScript build tool for React Native.\n\nTo start the Metro dev server, run the following command from the root of your React Native project:\n\n```sh\n# Using npm\nnpm start\n\n# OR using Yarn\nyarn start\n```\n\n## Step 2: Build and run your app\n\nWith Metro running, open a new terminal window/pane from the root of your React Native project, and use one of the following commands to build and run your Android or iOS app:\n\n### Android\n\n```sh\n# Using npm\nnpm run android\n\n# OR using Yarn\nyarn android\n```\n\n### iOS\n\nFor iOS, remember to install CocoaPods dependencies (this only needs to be run on first clone or after updating native deps).\n\nThe first time you create a new project, run the Ruby bundler to install CocoaPods itself:\n\n```sh\nbundle install\n```\n\nThen, and every time you update your native dependencies, run:\n\n```sh\nbundle exec pod install\n```\n\nFor more information, please visit [CocoaPods Getting Started guide](https://guides.cocoapods.org/using/getting-started.html).\n\n```sh\n# Using npm\nnpm run ios\n\n# OR using Yarn\nyarn ios\n```\n\nIf everything is set up correctly, you should see your new app running in the Android Emulator, iOS Simulator, or your connected device.\n\nThis is one way to run your app — you can also build it directly from Android Studio or Xcode.\n\n## Step 3: Modify your app\n\nNow that you have successfully run the app, let's make changes!\n\nOpen `App.tsx` in your text editor of choice and make some changes. When you save, your app will automatically update and reflect these changes — this is powered by [Fast Refresh](https://reactnative.dev/docs/fast-refresh).\n\nWhen you want to forcefully reload, for example to reset the state of your app, you can perform a full reload:\n\n- **Android**: Press the <kbd>R</kbd> key twice or select **\"Reload\"** from the **Dev Menu**, accessed via <kbd>Ctrl</kbd> + <kbd>M</kbd> (Windows/Linux) or <kbd>Cmd ⌘</kbd> + <kbd>M</kbd> (macOS).\n- **iOS**: Press <kbd>R</kbd> in iOS Simulator.\n\n## Congratulations! :tada:\n\nYou've successfully run and modified your React Native App. :partying_face:\n\n### Now what?\n\n- If you want to add this new React Native code to an existing application, check out the [Integration guide](https://reactnative.dev/docs/integration-with-existing-apps).\n- If you're curious to learn more about React Native, check out the [docs](https://reactnative.dev/docs/getting-started).\n\n# Troubleshooting\n\nIf you're having issues getting the above steps to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page.\n\n# Learn More\n\nTo learn more about React Native, take a look at the following resources:\n\n- [React Native Website](https://reactnative.dev) - learn more about React Native.\n- [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how setup your environment.\n- [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**.\n- [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts.\n- [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native.\n","packages/storage/README.md":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify Storage category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n"},"files":{"AGENTS.md":"# AGENTS.md\n\nGuidance for AI coding agents working in the **AWS Amplify JS** monorepo. Read this before making changes.\n\n## Repository Overview\n\nAmplify JS is a **Yarn + Turborepo** monorepo. Every package lives under `packages/<name>/`, each with its own `src/` and `package.json`. Packages are published under the `@aws-amplify/*` scope (plus the umbrella `aws-amplify` package).\n\nKey packages:\n\n| Package | Purpose |\n|---|---|\n| `@aws-amplify/core` | Shared runtime: config singleton, Hub, utils |\n| `@aws-amplify/auth` | Cognito authentication |\n| `@aws-amplify/storage` | S3 storage (client/utils + server/utils split) |\n| `@aws-amplify/api`, `api-graphql`, `api-rest` | API categories |\n| `@aws-amplify/analytics`, `geo`, `interactions`, `notifications`, `predictions`, `pubsub` | Feature categories |\n| `aws-amplify` | Umbrella package re-exporting category APIs |\n| `@aws-amplify/adapter-nextjs` | Next.js server adapter |\n\n## Environment\n\n| Requirement | Version |\n|---|---|\n| Node.js | 24 (pinned in CI; repo has no local `engines`/`.nvmrc`) |\n| Yarn | 1.22.x |\n\n## Build & Test Commands (MANDATORY: use `yarn`)\n\n**Always drive builds/tests/lint through `yarn`. NEVER invoke `tsc`, `eslint`, `jest`, `npx`, or `tsx` directly** — the workspace scripts wire up the correct config and dependency graph. Single-package targeting goes through Turbo's `--filter` (see below).\n\n```bash\n# Install\nyarn\n\n# Build\nyarn build                              # all packages\nyarn turbo run build --filter=@aws-amplify/auth   # single package (+ its deps)\n\n# Test\nyarn test                               # full suite (use before final confirmation)\nyarn turbo run test --filter=@aws-amplify/auth    # single package\n\n# Lint\nyarn lint                               # lint all packages\nyarn turbo run lint --filter=@aws-amplify/auth    # single package\n\n# Bundle size\nyarn test:size                          # size-limit check (only runs for packages that define it)\nyarn test:size --why                    # debug regression (Statoscope)\n\n# Watch mode for local dev\nyarn build:watch\nyarn link-all                           # make all packages linkable\n\n# Nuclear clean\ngit clean -xdf\n```\n\nRun `yarn` from the **monorepo root or a package root**. During implementation you may narrow with file/suite/test filters, but always run the full `test` / `lint` / `build` for final confirmation.\n\n> **Single-package targeting must go through Turbo directly** — `yarn turbo run <task> --filter=@aws-amplify/<pkg>`. Do **not** pass `--filter` to the top-level `yarn build` / `yarn test` scripts: they are compound (`&&`) scripts, so the flag is misrouted to the trailing command and Turbo still runs unfiltered. (`--scope` is a Lerna flag — not valid for Turbo 2.x at all.)\n\n## Testing Conventions\n\n- **Do NOT mock `getConfig` on the Amplify singleton.** Mock the actual underlying modules/functions instead (real Amplify config approach).\n- Write or update unit tests for any added/modified code. Be especially vigilant with shared code (race conditions).\n- Passing unit tests are required for any PR that changes functionality.\n- **Bundle-size (`size-limit`) checks only apply to packages that configure them.** Eight packages declare a `size-limit` key (`aws-amplify`, `core`, `datastore`, `geo`, `interactions`, `predictions`, `pubsub`, `api-graphql`), but `yarn test:size` only exercises the seven that also define a `test:size` script (all of the above except `api-graphql`). Filtering it to a package without size-limit configured (e.g. `auth`, `storage`) is a no-op.\n\n## Code Conventions\n\n- **License headers are required** on source files (enforced by the `license-test` CI check).\n- **Never commit `tsconfig.tsbuildinfo` files.** A stray `packages/*/tsconfig.tsbuildinfo` causes `license-test` failures (`License not found in ...`). Remove it if generated.\n- Preserve existing comments, JSDoc, and logging statements.\n- Follow existing formatting (Prettier + ESLint config are applied via `yarn` scripts).\n\n## Git Hooks (Husky)\n\nThe repo installs Husky hooks that run automatically — an agent committing or pushing will trigger them:\n\n- **`pre-commit`** — runs `lint-staged` (`eslint --fix` on staged `*.ts`/`*.tsx`). Do not bypass with `--no-verify`.\n- **`pre-push`** — runs a **git-secrets** scan and **blocks the push if git-secrets is not installed**. Install and register it before pushing:\n\n```bash\nbrew install git-secrets   # or: apt-get install git-secrets\ngit secrets --register-aws\n```\n\n## Changesets (required for functional changes)\n\n```bash\nyarn changeset\n```\n\nCreates a file in `.changeset/`:\n\n```markdown\n---\n'@aws-amplify/<package>': patch|minor|major\n---\n\n<type>(<scope>): description of the change.\n```\n\n**Skip a changeset** only for docs-only, formatting, or CI-only changes.\n\n## Branch Naming\n\n```\n<scope>/<type>/<description>\n```\n\n- **scope**: category or alias (e.g. `auth`, `storage`, `core`)\n- **type**: `feat` | `fix` | `docs` | `refactor` | `perf` | `test` | `build` | `ci` | `chore` | `revert`\n\nExamples: `auth/fix/refresh-token-race-condition`, `storage/feat/presigned-urls`\n\n## Commit / PR Flow\n\n1. Make changes in `packages/<category>/`.\n2. Add/update unit tests.\n3. Add a changeset (if functional).\n4. Validate: `yarn build` + `yarn test` (+ `yarn test:size` if bundle-sensitive).\n5. Commit with a conventional message: `<type>(<scope>): summary`.\n6. Push and open a PR filling out the template (description, linked issue, validation steps, checklist).\n\n## CI Checks (must pass before merge)\n\n| Check | Validates |\n|---|---|\n| `unit-tests` | Jest suites across packages |\n| `native-unit-tests` | React Native tests |\n| `bundle-size-tests` | Tree-shaken footprint (size-limit) |\n| `license-test` | License headers present |\n| `tsc-compliance-test` | TypeScript compilation |\n| `dependency-review` | No problematic dependencies |\n| `git-secrets-check` | No leaked AWS credentials |\n| `github-actions-test` | CI config validity |\n\nThe `ci - Unit and Bundle tests have passed` gate turns green only when all above pass.\n\n## Maintenance Branch: `v5-stable`\n\nThe `v5-stable` branch hosts Amplify JS v5 maintenance releases (security patches, critical fixes). **Do not apply this document's conventions there** — it uses different tooling (Lerna instead of Turborepo, no changesets, different setup and CI checks).\n\nWhen backporting a fix to v5: branch off `v5-stable`, target the PR at `v5-stable`, and follow the `AGENTS.md` **on that branch** for its specific conventions.\n\n## Do / Don't Summary\n\n**Do**\n- Use `yarn` for everything\n- Add tests + changesets\n- Keep license headers\n- Mock underlying modules, not `Amplify.getConfig`\n\n**Don't**\n- Run `tsc`/`jest`/`eslint`/`npx` directly\n- Commit `tsconfig.tsbuildinfo`\n- Strip existing comments or logging\n","CLAUDE.md":"# CLAUDE.md\n\nThis project's AI agent guidance lives in [AGENTS.md](./AGENTS.md).\n\nPlease read **[AGENTS.md](./AGENTS.md)** for repository structure, build/test commands, code conventions, changeset requirements, and CI checks.\n","packages/adapter-nextjs/README.md":"This package contains the AWS Amplify Next.js Adapter. For more information on using Next.js in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/javascript/build-a-backend/server-side-rendering/nextjs/).\n\n### Licensing Note\nAlthough this repository is released and licensed under the Apache License (see [LICENSE](./LICENSE)), its devDependencies transitively use the third party [sharp](https://sharp.pixelplumbing.com/) project.\n\nThe sharp projects prebuilt binaries' licensing includes [LGPL-2.1](https://opensource.org/license/LGPL-2.1) and [LGPL-3.0-or-later](https://opensource.org/license/LGPL-3.0) licenses","packages/analytics/README.md":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify Analytics category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","packages/api-graphql/README.md":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify API GraphQL category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","packages/api-rest/README.md":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify API REST category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","packages/api/README.md":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify API category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","packages/auth/README.md":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify Auth category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","packages/aws-amplify/README.md":"# AWS Amplify Package - aws-amplify\n\nAWS Amplify is a JavaScript library for frontend and mobile developers building cloud-enabled applications. The library is a declarative interface across different categories of operations in order to make common tasks easier to add into your application. The default implementation works with Amazon Web Services (AWS) resources but is designed to be open and pluggable for usage with other cloud services that wish to provide an implementation or custom backends.\n\nDocumentation is available [here](https://docs.amplify.aws/javascript/).\n","packages/core/README.md":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify core utilities and is intended for internal use only. To integrate Amplify into your app. Please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","packages/core/__mocks__/configMocks/README.md":"This directory contains equivalent Gen1 & Gen2 configurations which are used to validate interoperability between\ndifferent config versions/schemas. Make sure that any updates applied to one are applied to the other.\n","packages/datastore-storage-adapter/README.md":"This package contains the AWS Amplify DataStore storage adapter. For more information on using the DataStore storage adapter in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/react-native/build-a-backend/more-features/datastore/set-up-datastore/#setup-local-development-environment).\n","packages/datastore/README.md":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify DataStore category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n\n# AWS Amplify DataStore Docs\n\n[Amplify DataStore](https://docs.amplify.aws/lib/datastore/getting-started/q/platform/js/) provides a programming model for leveraging shared and distributed data without writing additional code for offline and online scenarios, which makes working with distributed, cross-user data just as simple as working with local-only data.\n\n---\n\n| package                | version                                                         | open issues                                                                                                                                                                                  | closed issues                                                                                                                                                                                 |\n| ---------------------- | --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| @aws-amplify/datastore | ![npm](https://img.shields.io/npm/v/@aws-amplify/datastore.svg) | [![Open Issues](https://img.shields.io/github/issues/aws-amplify/amplify-js/DataStore?color=red)](https://github.com/aws-amplify/amplify-js/issues?q=is%3Aissue+label%3ADataStore+is%3Aopen) | [![Closed Issues](https://img.shields.io/github/issues-closed/aws-amplify/amplify-js/DataStore)](https://github.com/aws-amplify/amplify-js/issues?q=is%3Aissue+label%3ADataStore+is%3Aclosed) |\n\n---\n\n## **👋 Note For Contributers: 👋**\n\n_**Please update these docs any time you find something that is incorrect or lacking. In particular, if a line in the docs prompts a question, take a moment to figure out the answer, then update the docs with the necessary detail.**_\n\n---\n\n## Getting Started\n\nBefore you start reading through these docs, take a moment to understand [how DataStore works at a high level](https://docs.amplify.aws/lib/datastore/how-it-works/q/platform/js/). Additionally, we recommend first reading through [docs.amplify.aws](https://docs.amplify.aws/lib/datastore/getting-started/q/platform/js/). The purpose of these docs is to dive deep into the codebase itself and understand the inner workings of DataStore for the purpose of contributing. Understanding these docs is **not** necessary for using DataStore. Lastly, before reading, take a look at [the diagrams below](#diagrams).\n\n---\n\n## Docs\n\n- [Conflict Resolution](docs/conflict-resolution.md)\n- [Contributing](docs/contributing.md)\n- [DataStore Lifecycle Events (\"Start\", \"Stop\", \"Clear\")](docs/datastore-lifecycle-events.md)\n  - This explains how DataStore fundementally works, and is a great place to start.\n- [Getting Started](docs/getting-started.md) (Running against a sample app, etc.)\n- [Namespaces](docs/namespaces.md)\n- [How DataStore uses Observables](docs/observables.md)\n- [Schema Changes](docs/schema-changes.md)\n- [Storage](docs/storage.md)\n- [Sync Engine](docs/sync-engine.md)\n- [\"Unsupported hacks\" / workarounds](docs/workarounds.md)\n\n---\n\n# Diagrams\n\n_Note: relationships with dotted lines are explained more in a separate diagram._\n\n## How the DataStore API and Storage Engine Interact\n\n```mermaid\nflowchart TD\n  %% API and Storage\n  api[[DS API]]-- observe -->storage{Storage Engine}\n  storage-- next -->adapter[[Adapter]]\n  adapter-->db[[Local DB]]\n  db-->api\n  sync[[Sync Engine*]]-.-storage\n  sync-.-appSync[(AppSync)]\n```\n\n# How the Sync Engine Observes Changes in Storage and AppSync\n\n_Note: All green nodes belong to the Sync Engine._\n\n\\* Merger first checks outbox\n\n\\*\\* Outbox sends outgoing messages to AppSync\n\n```mermaid\nflowchart TD\n\n  subgraph SyncEngine\n  index{index.ts}-- observe -->reach[Core reachability]\n\n  subgraph processors\n  mp[Mutation Processor]\n  sp[Subscription Processor]\n  syp[Sync Processor]\n  end\n\n  reach--next-->mp[Mutation Processor]\n  reach--next-->sp[Subscription Processor]\n  reach--next-->syp[Sync Processor]\n\n  subgraph outbox / merger\n  outbox[Outbox]\n  merger[Merger]\n  outbox---merger\n  end\n\n  end\n\n  api[DS API]-.->storage\n  mp-- 1. observe -->storage{Storage Engine}\n  storage-- 2. next -->merger[merger*]-- next -->storage\n\n\n  sp-- observe -->appsync[(AppSync)]\n  appsync-- next -->sp\n\n  syp---appsync\n\n  mp-->outbox[outbox**]\n\n  appsync<--->outbox\n  %% styling\n  classDef syncEngineClass fill:#8FB,stroke:#333,stroke-width:4px,color:#333;\n  class index,mp,sp,syp,merger,outbox syncEngineClass;\n```\n\n---\n\n# Project Structure\n\n<pre>\namplify-js/packages/datastore/src\n├── authModeStrategies\n│   └── defaultAuthStraegy.ts\n│   └── index.ts\n│   └── multiAuthStrategy.ts\n├── datastore\n│   └── datastore.ts # Entry point for DataStore\n├── predicates\n│   └── index.ts\n│   └── sort.ts\n├── ssr\n├── storage # Storage Engine\n│   └── adapter # Platform-specific Storage Adapters\n│      └── getDefaultAdapter\n│      └── AsyncStorageAdapter.ts\n│      └── AsyncStorageDatabase.ts\n│      └── index.ts\n│      └── IndexedDBAdapter.ts\n│      └── InMemoryStore.native.ts\n│      └── InMemoryStore.ts\n│   └── storage.ts # Entry point for Storage\n├── sync # Sync Engine\n│   └── dataStoreReachability\n│      └── index.native.ts\n│      └── index.ts\n│   └── processors # Sync Engine Processors\n│      └── mutation.ts\n│      └── subscription.ts\n│      └── sync.ts\n│   └── datastoreConnectivity.ts # Subscribe to reachability monitor\n│   └── index.ts # Entry point for Sync Engine\n│   └── merger.ts # <a href=\"https://github.com/aws-amplify/amplify-js/blob/datastore-docs/packages/datastore/docs/sync-engine.md#merger\" title=\"merger doc\">doc</a>\n│   └── outbox.ts # <a href=\"https://github.com/aws-amplify/amplify-js/blob/datastore-docs/packages/datastore/docs/sync-engine.md#outbox\" title=\"outbox doc\">doc</a>\n</pre>\n\n---\n\n## Other Resources:\n\n- [High-level overview of how DataStore works](https://docs.amplify.aws/lib/datastore/how-it-works/q/platform/js/)\n- [DataStore Docs](https://docs.amplify.aws/lib/datastore/getting-started/q/platform/js/)\n- [re:Invent talk](https://www.youtube.com/watch?v=KcYl6_We0EU)\n","packages/datastore/__tests__/helpers/README.md":"## Helper functions for DataStore testing\n\nPlease try to keep things clean.\n\nIn particular, let's try to to keep file sizes smaller and more \"categorical\" in order to:\n\n1. Make finding and discovering test utils easier\n2. Reduce excessive vertical scrolling\n3. Reduce complexity of merge conflicts\n4. _<< And other awesome benefits I haven't thought of! >>_\n\nIntended organization is as follows:\n\n|                       | Intent                                                                                                                |\n| --------------------- | --------------------------------------------------------------------------------------------------------------------- |\n| `fakes/*`             | Util classes to inject and/or observe datastore's interaction with its boundaries, like cloud/graphql storage.        |\n| `schemas/*`           | Schema JSON and model types (Plenty of room for further refactoring and reorganization here!)                         |\n| `datastoreFactory.ts` | Function(s) for creating clean, test-configured initializations of DataStore and deps to test against.                |\n| `util.ts`             | Miscellaneous, mostly-isolated utility functions to aid with testing. (To be further decomposed as-needed over time.) |\n\nThere's almost always room to clean things up and do better. If you encounter a merge conflict that would have benefitted from chunks of code living separately; submit a refactor-only PR to separate them. If you get \"lost\" vertically scrolling in a file, look for a semantically meaningful boundary to separate on. If you can't find what you're looking for, consider whether another folder/category to drill into would have helped.\n\nIf you have any ideas around taming the rather large test schemas, making it easier to add new models and corresponding JSON, submit a PR with your idea! Etc..\n\nThanks!\n","packages/datastore/docs/conflict-resolution.md":"# Conflict Resolution\n- **AppSync is the source of truth for conflict resolution**\n   1. In the event AppSync fails to resolve a conflict, the network response will contain an error message (`conflict unhandled`). This is how we give customers the chance to make an update, or try again.\n   2. We use jittered retry (10x).\n   - TODO: add more detail / links to how this retry logic occurs.\n- We err on the side of not deleting customer data when performing conflict resolution.\n- Auto-merge is the default resolution strategy. This relies on the version, and will attempt to merge fields that changed when possible.\n- For more, see [the AppSync docs](https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html)","packages/datastore/docs/contributing.md":"# Contributing\n\n## Formatting\n- We use Prettier to format our code. We recommend installing it within your IDE to prevent formatting code within other Amplify packages (as opposed to formatting from the Prettier CLI directly). Example [VS Code Extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)).\n\n## Testing DataStore changes locally\n- On first build:\n\t- Within **amplify-js**: `yarn && yarn build && yarn link-all && yarn build:watch`\n\t- Within sample app: `yarn && yarn link aws-amplify && yarn link @aws-amplify/datastore && yarn start`\n- On subsequent builds (useful if something isn't working):\n\t- Within **amplify-js**: `yarn clean && yarn build && yarn link-all && yarn build:watch`\n\t- Within sample app: `rm -rf node_modules && yarn && yarn link aws-amplify && yarn link @aws-amplify/datastore && yarn start`\n\n## Contributing to these docs\n- Do not link to specific lines of code, as these frequently change. Instead, do the opposite: link to the documentation within the code itself, as the docs are less likely to change.\n- Prefer small, self-contained sections over large, monolothic documents.\n- Do not use permalinks - instead, link to the most current files.","packages/datastore/docs/datastore-lifecycle-events.md":"# DataStore Lifecycle Events (\"Start\", \"Stop\", \"Clear\")\n\n# DataStore Initialization (\"Start\")\n\n**Understanding how DataStore starts is critical to understanding how DataStore fundamentally works.** At a high level, starting DataStore does the following things in order for each model:\n\n> 1.  Init Schema\n> 2.  Init the Storage Engine\n> 3.  Migrate schema changes\n> 4.  Sync Engine Operations\n> 5.  Empty the Outbox / processes the mutation queue\n> 6.  Begin processing the subscription buffer\n> 7.  DataStore is now in \"ready\" state\n\n- _We can eagerly start DataStore by calling `DataStore.start`. Otherwise, invoking a method (query, save, delete, observe) will start it up_\n- _When importing a model, DS consumes `schema.js`, and creates the IndexedDB store._\n\n## **How it works:**\n\n1.  ### **Init schema**\n    - **1.1** First we call `initSchema` [here](packages/datastore/src/datastore/datastore.ts)\n    - **1.2** Codegen then generates `schema.js` from the schema\n    - **1.3** DataStore consumes `schema.js`\n\n2.  ### **Init the storage engine**\n    - **2.1** The adapter is initialized\n    - **2.2** The local database gets created if it doesn’t exist already\n    - **2.3** The adapter [has a `setUp`](packages/datastore/src/storage/adapter/IndexedDBAdapter.ts#L82) method that then calls the database's `init` method\n    - **2.4** Relations are established\n    - _Nothing happens until the first interaction with DataStore_\n\n3.  ### **Migrate schema changes (if needed)**\n    - See [schema-changes.md](./schema-changes.md)\n    - If the user has updated the schema, we perform the migration here\n\n4.  ### **Sync Engine Operations**\n-  #### 4.1 Instantiate Sync Engine (`this.sync = new SyncEngine(`)\n    - The Sync Engine is only instantiated if there is a graphql endpoint (meaning we’ve already provisioned the backend). Otherwise, DataStore is in local-only mode. See [datastore.ts](packages/datastore/src/datastore/datastore.ts#L735)\n    - **Note: at this step, we do not yet process the buffer**\n    - There are three subscriptions per model: `create`, `update`, and `delete`\n\n- #### 4.2 Sync Engine is started (`syncSubscription = this.sync.start(`)\n    - **4.2.1 Subscribe to the Sync Engine**\n      - Messages from this subscription are emmited as Hub events for DataStore\n      - When ready, we call `initResolve`\n      - If unauthorized, DS keeps working, as we may have publicly readable models\n      - If a validation error occurs, DataStore Sync breaks entirely\n      - Without subscriptions, DataStore doesn’t work (when there is an endpoint present)\n      - Subscriptions are the only component that update the local store from remote\n      - If updates come in, they’re buffered to be processed after sync is complete\n      - Prepares the sync predicates (similar to adapter setup)\n\n    - **4.2.2 Subscribe to DataStore connectivity observable (notifications about network status)**\n        - `this.datastoreConnectivity.status().subscribe`\n        - Subscribe Amplify Core component that monitors network reachability\n        - We do this here because we need the ability to stop or start the sync process. When offline, we disconnect the websocket and stop syncing. Once online, we reconnect the websocket and start base / delta syncing\n        - Sync engine subscribes to the Storage Engine\n            - Every write may need to get translated to a mutation in the outbox\n            - Storage engine is local source of truth for DataStore, all other pieces are observing\n\n    - **4.2.3 Run the Sync Queries (when online)**\n        - _Note: We perform a topological sort of the data - we sync the children first, so when we query the parent, the children are already present We also use an optimisation to parallelize this process if possible (i.e. non-dependent models)_\n        - Sync queries are Graphql queries that are necessary to hydrate the local store initially\n        - The first time we run the app, we will perform a query to perform a scan or query of DynamoDB with up to 10k records per table. This populates the local store. With selective sync, we perform a query instead of a scan against DynamoDB.\n        - Subsequent changes after the initial sync query come in through subscriptions\n        - There are two mechanisms:\n            - Base sync - retrieve all records up to total sync value\n            - Delta sync - one table per model, one delta sync table per DS store\n        - AppSync makse the final decision regarding which sync (base vs delta) to perform\n            - The client sends the last sync param with the sync query, service then compares the diff\n            - There is a TTL on all delta sync table records\n            - To find the TTL within the AppSync Console, see \"Update Data Source\"\n\n5. ### **Empty the Outbox / processes the mutation queue**\n    - Example: when performing mutations offline, records are added to the queue. Once there is connectivity, we start sending these **ONE BY ONE**.\n    - **Note: No batch API is exposed to consumers**\n    - Mutation events have ids\n    - Syncs get applied before mutations are sent\n6. ### **Begin processing the subscription buffer**\n    - If we receive subscription messages any time in the process of initializing subscriptions, performing sync queries, or processing the mutation queue, we buffer the subscription messages until everything else is completed. Once we have completed processing the mutation queue, we then process the subscription buffer\n7. ### **DataStore is now in \"ready\" state**\n    - For additional reference, and how the above are published as Hub events, see [the docs](https://docs.amplify.aws/lib/datastore/datastore-events/q/platform/js/)\n\n## Stop\n- Stops the DataStore sync process. This will close the real-time subscription connection when your app is no longer interested in updates. You will typically call DataStore.stop() just before your application is closed. You can also force your DataStore sync expressions to be re-evaluated at runtime by calling stop(), followed by start()\n\n## Clear\n- Clears local data from DataStore. DataStore will now require a full sync (not a delta sync) to populate the local store with data\n","packages/datastore/docs/getting-started.md":"# Onboarding with DataStore\n\n## Understand the primary DataStore events\n- Read the [DataStore lifecycle events doc](docs/datastore-lifecycle-events.md)\n\n## Building a sample app with DataStore to understand how it works\n1. Build a basic DataStore sample app (no @auth, just 1-2 models).\n2. Build a similar sample app with the API category.\n3. Add @auth rules to the DataStore app:\n    1. `amplify update api`\n    2. Modify schema according to auth rules docs (https://docs.amplify.aws/lib/datastore/setup-auth-rules/q/platform/js).\n    3. `amplify push`\n    4. `amplify codegen models`\n4. Add [selective sync](https://docs.amplify.aws/lib/datastore/sync/q/platform/js#selectively-syncing-a-subset-of-your-data).\n5. Enable [real-time changes](https://docs.amplify.aws/lib/datastore/real-time/q/platform/js).\n6. While interacting with your app, examine the IndexedDB tables (Application > IndexedDB within Chrome dev tools):\n    1. Check out the different stores in IDB that get created for your schema. Note the internal stores prefixed with sync_, and the stores corresponding to your models prefixed with user_.\n    2. Familiarize yourself with how actions taken in the UI affect the data stored in IDB. This may be easier to do while throttling the network connection. You'll be able to see how outgoing mutations first get persisted into the corresponding store, then added to the mutation queue / outbox (sync_MutationEvent), and then updated in the store with data from AppSync.\n7. Turn on DEBUG logging (`ConsoleLogger.LOG_LEVEL = \"DEBUG\";`) at the root of your project, and inspect the logs in the console while using your app. Additionally, [enable hub events](https://docs.amplify.aws/lib/datastore/datastore-events/q/platform/js#usage) for DataStore.\n8. The best way to understand DataStore events is to place several debuggers or breakpoints throughout DataStore.\n    - With logging / Hub events enabled, you can see what operations DataStore is performing (i.e. start, sync, etc.) as you step through with the debugger.\n9. Testing offline scenerios / concurrent user sessions is a useful way to test the full functionality of DataStore, and to fully understand how the sync process actually works.\n10. Next steps:\n    - Create a React Native example (uses a different storage type)\n    - Try more complex schema types\n    - Observe changes in records within DynamoDB (for instance, soft deletion).","packages/datastore/docs/namespaces.md":"# Namespaces\n- `datastore`\n\t- Settings\n- `user` \n\t- Models that came from user schema\n- `sync` \n\t- Metadata (last time ran query, etc.)\n- `storage` \n\t- Deprecated\n# Local database examples:\n\n- *Note: Anything prepended with `sync_` is an internal table.*\n\n- ## datastore_Setting\n    - Used for schema versioning\n    - See the [schema changes doc](docs/schema-changes.md)\n    ```\n\t{\n\t\tid: \"01FYABF3DMBZZJ46W1CC214NH2\"\n\t\tkey: \"schemaVersion\"\n\t\tvalue: \"\\\"4401034582a70c60713e1f7f9da3b752\\\"\"\n\t}\n\t```\n- ## sync_ModelMetadata\n    - Sync Engine metadata\n\t- Includes information about the last time we synced a model\n\t```\n\t{\n\t\tfullSyncInterval: 86400000\n\t\tid: \"01FYABF3DMBZZJ46W1CC214NH3\"\n\t\tlastFullSync: 1647467532307\n\t\tlastSync: 1647467532307\n\t\tlastSyncPredicate: null\n\t\tmodel: \"Todo\"\n\t\tnamespace: \"user\"\n\t}\n\t```\n- ## sync_MutationEvent\n- ## user_[Model Name]\n    - The actual records themselves.\n\t```\n\t{\n\t\tcreatedAt: \"2022-03-16T21:52:07.718Z\"\n\t\tdescription: null\n\t\tid: \"6f69055b-b081-4225-8fc4-1d6d52732660\"\n\t\tname: \"name 1647467527489\"\n\t\tupdatedAt: \"2022-03-16T21:52:07.718Z\"\n\t\t_deleted: null\n\t\t_lastChangedAt: 1647467527754\n\t\t_version: 1\n\t}\n\t```","packages/datastore/docs/observables.md":"# How DataStore uses Observables\n- All of DataStore internally uses event driven methods (observables) to handle everything from the sync process, to observing online connectivity. **This makes the Storage Engine the single source of truth for DataStore.**\n- Examples:\n\t- The Sync Engine observes DataStore Connectivity \n\t- The Sync Engine observes the Storage Engine \n    - The client observes DataStore with `observe` and `observeQuery`:\n\t\t- https://docs.amplify.aws/lib/datastore/real-time/q/platform/js/\n\n## Understanding Observables\n- DataStore uses [`zen-observable`](https://github.com/zenparsing/zen-observable)\n- [The RXJS docs](https://rxjs.dev/guide/observable) do a good job of describing observables in more detail.","packages/datastore/docs/schema-changes.md":"# What happens when a user changes their schema?\n   - The `schema.js` file that exists within an Amplify project (located at `src/models/schema.js`) contains a version hash. \n   - This hash is compared against the hash stored in the `Settings` table of the local database. Example:\n       ```\n           {\n               id: \"01FYABF3DMBZZJ46W1CC214NH2\"\n               key: \"schemaVersion\"\n               value: \"\\\"4401034582a70c60713e1f7f9da3b752\\\"\"\n           }\n       ```\n   - The process of checking the schema version (`checkSchemaVersion`) occurs when DataStore starts, after the Storage Engine has been initialized, and before the Sync Engine is initialized.\n   - If the schema version has changed, we clear local storage, and perform a full sync","packages/datastore/docs/storage.md":"# Storage\n## Adapters:\n- Web\n   - [IndexedDB](../src/storage/adapter/IndexedDBAdapter.ts)\n- Mobile\n   - React Native\n      - [Async Storage](../src/storage/adapter/AsyncStorageAdapter.ts) (can opt in to use SQLite)\n- SSR\n   - [InMemoryStore](../src/storage/adapter/InMemoryStore.ts)\n\n## How we determine which adapter to use\n\nWe determine the storage adapter [here](../src/storage/adapter/getDefaultAdapter/index.ts). \n\n\n## [The Storage class](../src/storage/storage.ts)\n- The Storage class is what interacts with the adapters.\n\n## [Storage Adapters](../src/storage/adapter)\n   1. There is one adapter per database type we support (i.e. three adapters).\n   2. Each adapter provides a unified API for the storage engine to interact with.\n   3. The SQLite adapter lives [in it’s own package](https://github.com/aws-amplify/amplify-js/tree/main/packages/datastore-storage-adapter).\n   4. **ExclusiveStorage wraps public storage methods (e.g. `Storage.runExclusive`)**\n      1. Guarantees consistency\n      2. Makes the storage class transactional\n      3. **Provides concurrency control**\n\n## How DataStore finds records locally:\n- Varies by storage adapter\n- [SQLiteAdapter](https://github.com/aws-amplify/amplify-js/tree/main/packages/datastore-storage-adapter): DataStore constructs a query. \n- [Async Storage](../src/storage/adapter/AsyncStorageAdapter.ts): DataStore scans and filters. \n- [IndexedDB](../src/storage/adapter/IndexedDBAdapter.ts): if the query is by primary key, DataStore queries against the index, otherwise it scans and filters.\n   - *Note: The lazy loading branch includes an improvement to the IndexedDB adapter that will check if any search criteria can leverage an index (there is no preference for low cardinality; the first identified index is used.) If so, the base result is sourced from the index and the remaining criteria will be applied as a filter.*\n\n## Understanding the difference between Save and Batch Save\n- As the names imply, `save` accepts a single record and persists it, while `batchSave` accepts a page of records and persists them all. `batchSave`, however, is *only used within the sync processor*, and will filter out deleted records from the sync page results, and then delete them from the local db.","packages/datastore/docs/sync-engine.md":"# Sync Engine\n\nSee [the sync class](packages/datastore/src/sync/index.ts)\n\n## High-level overview:\n- The first time DataStore is started on a new client, a full sync is performed. Subsequent reloads of the app (including browser refresh, or a new browser session) are delta syncs.\n- If it has been greater than the `fullSyncInterval` (configurable) since the client has performed a full sync, this operation occurs as a full sync.\n- The Sync Engine is well documented in the [DataStore Lifecycle Events doc](./datastore-lifecycle-events.md). The purpose of this doc is to explain anything about the sync process that is not already documented there.\n\n\n## Types of Syncs\n### Full Sync\n- All records are fetched from AppSync.\n\n### Delta Sync\n- All the records that changed after a given time stamp are fetched.\n\n## How it works\n\n### [Merger](../src/sync/merger.ts)\n- A helper class for merging subscription records with the outbox (checks IDs).\n- The Sync Engine uses merge in two places:\n\t- 1. https://github.com/aws-amplify/amplify-js/blob/main/packages/datastore/src/sync/index.ts#L289\n\t\t- Triggered by the mutation response. It gets called after the client that authored the change receives the network response of the mutation request they generated.\n\t- 2. https://github.com/aws-amplify/amplify-js/blob/main/packages/datastore/src/sync/index.ts#L326\n\t\t- Triggered by an AppSync real-time subscription event, which is how all clients get notified of the change. In the case of the mutation author, this notification is redundant, but it’s necessary for all other active users of the application. This is why there will always be multiple snapshot returned by `observe` and `observeQuery` in the case of the mutation author.\n\n- The function of [the Merger class](../src/sync/merger.ts) is to filter out any incoming records that have corresponding pending changes in that client’s mutation queue / outbox, and is done to maintain data consistency. We wouldn’t want to write over data that the client has deliberately changed, and essentially undo whatever changes were performed on that client - even temporarily. Thus, each time a change comes in via a mutation response, AppSync subscription, or sync query, **Merger will only persist that change to the local database when there is not a pending mutation for that same record**.\n- If there is a pending change in the outbox - we discard the incoming model we were working with inside the merge call (by not saving it). Later, when the record from the Outbox gets processed by AppSync (and conflict resolution rules are applied as appropriate), we will persist the response of the mutation (assuming we don’t change the record again in the interim)\n- If there is not a pending change in the outbox - we persist the model to the local store via `Storage.save` within `merge`.\n- _Note: We maintain a single instance of a mutation when we are offline (i.e. if we perform multiple updates on the same record, we merge them into a single event). Once we are online, but other mutations are processing, we'll still attempt to merge outgoing events into an existing one if they are not already in flight_\n- Merger Example:\n\t- User A updates record 1\n\t- The update to record 1 is persisted locally, and enters the mutation queue for persistence to Appsync\n\t- User B has not yet received the update to record 1, and updates record 1\n\t- User A receives User B's update to record 1, but has not yet sent the mutation to AppSync\n\t- If Merger did not first check the mutation queue prior to applying the change from User B, User A would see their update, then user B's update, then, depending on how the conflict is handled by AppSync, could then see their update again. Instead, User A sees their update, and rejects User B's update. Once the conflict is handled by AppSync, any changes that are received are then applied.\n- *How to locally test / step through Merger:* \n\t- Create a few records and make sure the records go out successfully and are persisted. Then, delete local data in IndexedDB (either by clicking the `clear` button in a sample, or through dev tools), then reload the page, or perform a query.\n- **Note: AppSync expects us to send only updated fields in order for merge to work correctly.**\n\n### [Outbox]((../src/sync/outbox.ts))\n- A mutation event outbox\n- Holds all local changes (even if you close the app). \n- Peek returns the next mutation event to be sent to AppSync, but does not remove it from the outbox.\n\n## [Processors](../src/sync/processors)\n- Sync Engine uses processors depending on the type of operation\n- All processors utilize observables\n- Where retry happens\n\n### Mutation Processor (Local changes)\n- Online or offline changes that were optimistically made to the Storage Engine (processed in mutation queue **one by one**).\n- Observes Storage Engine for new changes.\n\n### Subscription Processor (Remote changes)\n- Real-time subscription messages (such as another client performing a change).\n- Uses the Amplify API Graphql package (which then uses PubSub).\n### Sync Processor\n- When the client goes online, fetch all changes that were performed in AppSync (could be full or delta sync).\n\n## Misc:\n- AppSync records are soft-deleted and have a TTL. \n- TODO: special configurations around sync intervals","packages/datastore/docs/workarounds.md":"# TODO: \"Unsupported hacks\" / Workarounds","packages/geo/README.md":"This package contains the AWS Amplify Geo category. For more information on using Geo in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/javascript/build-a-backend/more-features/geo/).\n","packages/interactions/README.md":"This package contains the AWS Amplify Interactions category. For more information on using Interactions in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/javascript/build-a-backend/more-features/interactions/).\n","packages/notifications/README.md":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify Notifications category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","packages/predictions/README.md":"This package contains the AWS Amplify Predictions category. For more information on using Predictions in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/javascript/build-a-backend/more-features/predictions/).\n\n","packages/pubsub/README.md":"This package contains the AWS Amplify PubSub category. For more information on using PubSub in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/javascript/build-a-backend/more-features/pubsub/).\n\n","packages/react-native/README.md":"> INTERNAL USE ONLY\n\nThis package contains AWS Amplify React Native utilities and is intended for internal use only. Please ensure this package is installed alongside [aws-amplify](https://www.npmjs.com/package/aws-amplify). We do not advise using any exports from this package directly.\n","packages/react-native/example/README.md":"This is an example app for developing and testing the react-native modules located at `../`.\n\n# Getting Started\n\n> **Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till \"Creating a new application\" step, before proceeding.\n\n## Step 1: Start the Metro Server\n\nFirst, you will need to start **Metro**, the JavaScript _bundler_ that ships _with_ React Native.\n\nTo start Metro, run the following command from the _root_ of your React Native project:\n\n```bash\n# using npm\nnpm start\n\n# OR using Yarn\nyarn start\n```\n\n## Step 2: Start your Application\n\nLet Metro Bundler run in its _own_ terminal. Open a _new_ terminal from the _root_ of your React Native project. Run the following command to start your _Android_ or _iOS_ app:\n\n### For Android\n\n```bash\n# using npm\nnpm run android\n\n# OR using Yarn\nyarn android\n```\n\n### For iOS\n\n```bash\n# using npm\nnpm run ios\n\n# OR using Yarn\nyarn ios\n```\n\nIf everything is set up _correctly_, you should see your new app running in your _Android Emulator_ or _iOS Simulator_ shortly provided you have set up your emulator/simulator correctly.\n\nThis is one way to run your app — you can also run it directly from within Android Studio and Xcode respectively.\n","packages/rtn-passkeys/README.md":"> INTERNAL USE ONLY\n\nThis package contains AWS Amplify React Native utilities and is intended for internal use only. Please ensure this package is installed alongside [aws-amplify](https://www.npmjs.com/package/aws-amplify) and [@aws-amplify/react-native](https://www.npmjs.com/package/@aws-amplify/react-native). We do not advise using any exports from this package directly.\n","packages/rtn-passkeys/example/README.md":"This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli).\n\n# Getting Started\n\n> **Note**: Make sure you have completed the [Set Up Your Environment](https://reactnative.dev/docs/set-up-your-environment) guide before proceeding.\n\n## Step 1: Start Metro\n\nFirst, you will need to run **Metro**, the JavaScript build tool for React Native.\n\nTo start the Metro dev server, run the following command from the root of your React Native project:\n\n```sh\n# Using npm\nnpm start\n\n# OR using Yarn\nyarn start\n```\n\n## Step 2: Build and run your app\n\nWith Metro running, open a new terminal window/pane from the root of your React Native project, and use one of the following commands to build and run your Android or iOS app:\n\n### Android\n\n```sh\n# Using npm\nnpm run android\n\n# OR using Yarn\nyarn android\n```\n\n### iOS\n\nFor iOS, remember to install CocoaPods dependencies (this only needs to be run on first clone or after updating native deps).\n\nThe first time you create a new project, run the Ruby bundler to install CocoaPods itself:\n\n```sh\nbundle install\n```\n\nThen, and every time you update your native dependencies, run:\n\n```sh\nbundle exec pod install\n```\n\nFor more information, please visit [CocoaPods Getting Started guide](https://guides.cocoapods.org/using/getting-started.html).\n\n```sh\n# Using npm\nnpm run ios\n\n# OR using Yarn\nyarn ios\n```\n\nIf everything is set up correctly, you should see your new app running in the Android Emulator, iOS Simulator, or your connected device.\n\nThis is one way to run your app — you can also build it directly from Android Studio or Xcode.\n\n## Step 3: Modify your app\n\nNow that you have successfully run the app, let's make changes!\n\nOpen `App.tsx` in your text editor of choice and make some changes. When you save, your app will automatically update and reflect these changes — this is powered by [Fast Refresh](https://reactnative.dev/docs/fast-refresh).\n\nWhen you want to forcefully reload, for example to reset the state of your app, you can perform a full reload:\n\n- **Android**: Press the <kbd>R</kbd> key twice or select **\"Reload\"** from the **Dev Menu**, accessed via <kbd>Ctrl</kbd> + <kbd>M</kbd> (Windows/Linux) or <kbd>Cmd ⌘</kbd> + <kbd>M</kbd> (macOS).\n- **iOS**: Press <kbd>R</kbd> in iOS Simulator.\n\n## Congratulations! :tada:\n\nYou've successfully run and modified your React Native App. :partying_face:\n\n### Now what?\n\n- If you want to add this new React Native code to an existing application, check out the [Integration guide](https://reactnative.dev/docs/integration-with-existing-apps).\n- If you're curious to learn more about React Native, check out the [docs](https://reactnative.dev/docs/getting-started).\n\n# Troubleshooting\n\nIf you're having issues getting the above steps to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page.\n\n# Learn More\n\nTo learn more about React Native, take a look at the following resources:\n\n- [React Native Website](https://reactnative.dev) - learn more about React Native.\n- [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how setup your environment.\n- [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**.\n- [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts.\n- [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native.\n","packages/storage/README.md":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify Storage category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# AGENTS.md\n\nGuidance for AI coding agents working in the **AWS Amplify JS** monorepo. Read this before making changes.\n\n## Repository Overview\n\nAmplify JS is a **Yarn + Turborepo** monorepo. Every package lives under `packages/<name>/`, each with its own `src/` and `package.json`. Packages are published under the `@aws-amplify/*` scope (plus the umbrella `aws-amplify` package).\n\nKey packages:\n\n| Package | Purpose |\n|---|---|\n| `@aws-amplify/core` | Shared runtime: config singleton, Hub, utils |\n| `@aws-amplify/auth` | Cognito authentication |\n| `@aws-amplify/storage` | S3 storage (client/utils + server/utils split) |\n| `@aws-amplify/api`, `api-graphql`, `api-rest` | API categories |\n| `@aws-amplify/analytics`, `geo`, `interactions`, `notifications`, `predictions`, `pubsub` | Feature categories |\n| `aws-amplify` | Umbrella package re-exporting category APIs |\n| `@aws-amplify/adapter-nextjs` | Next.js server adapter |\n\n## Environment\n\n| Requirement | Version |\n|---|---|\n| Node.js | 24 (pinned in CI; repo has no local `engines`/`.nvmrc`) |\n| Yarn | 1.22.x |\n\n## Build & Test Commands (MANDATORY: use `yarn`)\n\n**Always drive builds/tests/lint through `yarn`. NEVER invoke `tsc`, `eslint`, `jest`, `npx`, or `tsx` directly** — the workspace scripts wire up the correct config and dependency graph. Single-package targeting goes through Turbo's `--filter` (see below).\n\n```bash\n# Install\nyarn\n\n# Build\nyarn build                              # all packages\nyarn turbo run build --filter=@aws-amplify/auth   # single package (+ its deps)\n\n# Test\nyarn test                               # full suite (use before final confirmation)\nyarn turbo run test --filter=@aws-amplify/auth    # single package\n\n# Lint\nyarn lint                               # lint all packages\nyarn turbo run lint --filter=@aws-amplify/auth    # single package\n\n# Bundle size\nyarn test:size                          # size-limit check (only runs for packages that define it)\nyarn test:size --why                    # debug regression (Statoscope)\n\n# Watch mode for local dev\nyarn build:watch\nyarn link-all                           # make all packages linkable\n\n# Nuclear clean\ngit clean -xdf\n```\n\nRun `yarn` from the **monorepo root or a package root**. During implementation you may narrow with file/suite/test filters, but always run the full `test` / `lint` / `build` for final confirmation.\n\n> **Single-package targeting must go through Turbo directly** — `yarn turbo run <task> --filter=@aws-amplify/<pkg>`. Do **not** pass `--filter` to the top-level `yarn build` / `yarn test` scripts: they are compound (`&&`) scripts, so the flag is misrouted to the trailing command and Turbo still runs unfiltered. (`--scope` is a Lerna flag — not valid for Turbo 2.x at all.)\n\n## Testing Conventions\n\n- **Do NOT mock `getConfig` on the Amplify singleton.** Mock the actual underlying modules/functions instead (real Amplify config approach).\n- Write or update unit tests for any added/modified code. Be especially vigilant with shared code (race conditions).\n- Passing unit tests are required for any PR that changes functionality.\n- **Bundle-size (`size-limit`) checks only apply to packages that configure them.** Eight packages declare a `size-limit` key (`aws-amplify`, `core`, `datastore`, `geo`, `interactions`, `predictions`, `pubsub`, `api-graphql`), but `yarn test:size` only exercises the seven that also define a `test:size` script (all of the above except `api-graphql`). Filtering it to a package without size-limit configured (e.g. `auth`, `storage`) is a no-op.\n\n## Code Conventions\n\n- **License headers are required** on source files (enforced by the `license-test` CI check).\n- **Never commit `tsconfig.tsbuildinfo` files.** A stray `packages/*/tsconfig.tsbuildinfo` causes `license-test` failures (`License not found in ...`). Remove it if generated.\n- Preserve existing comments, JSDoc, and logging statements.\n- Follow existing formatting (Prettier + ESLint config are applied via `yarn` scripts).\n\n## Git Hooks (Husky)\n\nThe repo installs Husky hooks that run automatically — an agent committing or pushing will trigger them:\n\n- **`pre-commit`** — runs `lint-staged` (`eslint --fix` on staged `*.ts`/`*.tsx`). Do not bypass with `--no-verify`.\n- **`pre-push`** — runs a **git-secrets** scan and **blocks the push if git-secrets is not installed**. Install and register it before pushing:\n\n```bash\nbrew install git-secrets   # or: apt-get install git-secrets\ngit secrets --register-aws\n```\n\n## Changesets (required for functional changes)\n\n```bash\nyarn changeset\n```\n\nCreates a file in `.changeset/`:\n\n```markdown\n---\n'@aws-amplify/<package>': patch|minor|major\n---\n\n<type>(<scope>): description of the change.\n```\n\n**Skip a changeset** only for docs-only, formatting, or CI-only changes.\n\n## Branch Naming\n\n```\n<scope>/<type>/<description>\n```\n\n- **scope**: category or alias (e.g. `auth`, `storage`, `core`)\n- **type**: `feat` | `fix` | `docs` | `refactor` | `perf` | `test` | `build` | `ci` | `chore` | `revert`\n\nExamples: `auth/fix/refresh-token-race-condition`, `storage/feat/presigned-urls`\n\n## Commit / PR Flow\n\n1. Make changes in `packages/<category>/`.\n2. Add/update unit tests.\n3. Add a changeset (if functional).\n4. Validate: `yarn build` + `yarn test` (+ `yarn test:size` if bundle-sensitive).\n5. Commit with a conventional message: `<type>(<scope>): summary`.\n6. Push and open a PR filling out the template (description, linked issue, validation steps, checklist).\n\n## CI Checks (must pass before merge)\n\n| Check | Validates |\n|---|---|\n| `unit-tests` | Jest suites across packages |\n| `native-unit-tests` | React Native tests |\n| `bundle-size-tests` | Tree-shaken footprint (size-limit) |\n| `license-test` | License headers present |\n| `tsc-compliance-test` | TypeScript compilation |\n| `dependency-review` | No problematic dependencies |\n| `git-secrets-check` | No leaked AWS credentials |\n| `github-actions-test` | CI config validity |\n\nThe `ci - Unit and Bundle tests have passed` gate turns green only when all above pass.\n\n## Maintenance Branch: `v5-stable`\n\nThe `v5-stable` branch hosts Amplify JS v5 maintenance releases (security patches, critical fixes). **Do not apply this document's conventions there** — it uses different tooling (Lerna instead of Turborepo, no changesets, different setup and CI checks).\n\nWhen backporting a fix to v5: branch off `v5-stable`, target the PR at `v5-stable`, and follow the `AGENTS.md` **on that branch** for its specific conventions.\n\n## Do / Don't Summary\n\n**Do**\n- Use `yarn` for everything\n- Add tests + changesets\n- Keep license headers\n- Mock underlying modules, not `Amplify.getConfig`\n\n**Don't**\n- Run `tsc`/`jest`/`eslint`/`npx` directly\n- Commit `tsconfig.tsbuildinfo`\n- Strip existing comments or logging\n","isInternal":false,"tokens":1754,"sizeBytes":6786},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# CLAUDE.md\n\nThis project's AI agent guidance lives in [AGENTS.md](./AGENTS.md).\n\nPlease read **[AGENTS.md](./AGENTS.md)** for repository structure, build/test commands, code conventions, changeset requirements, and CI checks.\n","isInternal":false,"tokens":56,"sizeBytes":227},{"name":"conflict-resolution.md","path":"packages/datastore/docs/conflict-resolution.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/datastore/docs/conflict-resolution.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Conflict Resolution\n- **AppSync is the source of truth for conflict resolution**\n   1. In the event AppSync fails to resolve a conflict, the network response will contain an error message (`conflict unhandled`). This is how we give customers the chance to make an update, or try again.\n   2. We use jittered retry (10x).\n   - TODO: add more detail / links to how this retry logic occurs.\n- We err on the side of not deleting customer data when performing conflict resolution.\n- Auto-merge is the default resolution strategy. This relies on the version, and will attempt to merge fields that changed when possible.\n- For more, see [the AppSync docs](https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html)","isInternal":false,"tokens":165,"sizeBytes":736},{"name":"contributing.md","path":"packages/datastore/docs/contributing.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/datastore/docs/contributing.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Contributing\n\n## Formatting\n- We use Prettier to format our code. We recommend installing it within your IDE to prevent formatting code within other Amplify packages (as opposed to formatting from the Prettier CLI directly). Example [VS Code Extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)).\n\n## Testing DataStore changes locally\n- On first build:\n\t- Within **amplify-js**: `yarn && yarn build && yarn link-all && yarn build:watch`\n\t- Within sample app: `yarn && yarn link aws-amplify && yarn link @aws-amplify/datastore && yarn start`\n- On subsequent builds (useful if something isn't working):\n\t- Within **amplify-js**: `yarn clean && yarn build && yarn link-all && yarn build:watch`\n\t- Within sample app: `rm -rf node_modules && yarn && yarn link aws-amplify && yarn link @aws-amplify/datastore && yarn start`\n\n## Contributing to these docs\n- Do not link to specific lines of code, as these frequently change. Instead, do the opposite: link to the documentation within the code itself, as the docs are less likely to change.\n- Prefer small, self-contained sections over large, monolothic documents.\n- Do not use permalinks - instead, link to the most current files.","isInternal":false,"tokens":294,"sizeBytes":1209},{"name":"datastore-lifecycle-events.md","path":"packages/datastore/docs/datastore-lifecycle-events.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/datastore/docs/datastore-lifecycle-events.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# DataStore Lifecycle Events (\"Start\", \"Stop\", \"Clear\")\n\n# DataStore Initialization (\"Start\")\n\n**Understanding how DataStore starts is critical to understanding how DataStore fundamentally works.** At a high level, starting DataStore does the following things in order for each model:\n\n> 1.  Init Schema\n> 2.  Init the Storage Engine\n> 3.  Migrate schema changes\n> 4.  Sync Engine Operations\n> 5.  Empty the Outbox / processes the mutation queue\n> 6.  Begin processing the subscription buffer\n> 7.  DataStore is now in \"ready\" state\n\n- _We can eagerly start DataStore by calling `DataStore.start`. Otherwise, invoking a method (query, save, delete, observe) will start it up_\n- _When importing a model, DS consumes `schema.js`, and creates the IndexedDB store._\n\n## **How it works:**\n\n1.  ### **Init schema**\n    - **1.1** First we call `initSchema` [here](packages/datastore/src/datastore/datastore.ts)\n    - **1.2** Codegen then generates `schema.js` from the schema\n    - **1.3** DataStore consumes `schema.js`\n\n2.  ### **Init the storage engine**\n    - **2.1** The adapter is initialized\n    - **2.2** The local database gets created if it doesn’t exist already\n    - **2.3** The adapter [has a `setUp`](packages/datastore/src/storage/adapter/IndexedDBAdapter.ts#L82) method that then calls the database's `init` method\n    - **2.4** Relations are established\n    - _Nothing happens until the first interaction with DataStore_\n\n3.  ### **Migrate schema changes (if needed)**\n    - See [schema-changes.md](./schema-changes.md)\n    - If the user has updated the schema, we perform the migration here\n\n4.  ### **Sync Engine Operations**\n-  #### 4.1 Instantiate Sync Engine (`this.sync = new SyncEngine(`)\n    - The Sync Engine is only instantiated if there is a graphql endpoint (meaning we’ve already provisioned the backend). Otherwise, DataStore is in local-only mode. See [datastore.ts](packages/datastore/src/datastore/datastore.ts#L735)\n    - **Note: at this step, we do not yet process the buffer**\n    - There are three subscriptions per model: `create`, `update`, and `delete`\n\n- #### 4.2 Sync Engine is started (`syncSubscription = this.sync.start(`)\n    - **4.2.1 Subscribe to the Sync Engine**\n      - Messages from this subscription are emmited as Hub events for DataStore\n      - When ready, we call `initResolve`\n      - If unauthorized, DS keeps working, as we may have publicly readable models\n      - If a validation error occurs, DataStore Sync breaks entirely\n      - Without subscriptions, DataStore doesn’t work (when there is an endpoint present)\n      - Subscriptions are the only component that update the local store from remote\n      - If updates come in, they’re buffered to be processed after sync is complete\n      - Prepares the sync predicates (similar to adapter setup)\n\n    - **4.2.2 Subscribe to DataStore connectivity observable (notifications about network status)**\n        - `this.datastoreConnectivity.status().subscribe`\n        - Subscribe Amplify Core component that monitors network reachability\n        - We do this here because we need the ability to stop or start the sync process. When offline, we disconnect the websocket and stop syncing. Once online, we reconnect the websocket and start base / delta syncing\n        - Sync engine subscribes to the Storage Engine\n            - Every write may need to get translated to a mutation in the outbox\n            - Storage engine is local source of truth for DataStore, all other pieces are observing\n\n    - **4.2.3 Run the Sync Queries (when online)**\n        - _Note: We perform a topological sort of the data - we sync the children first, so when we query the parent, the children are already present We also use an optimisation to parallelize this process if possible (i.e. non-dependent models)_\n        - Sync queries are Graphql queries that are necessary to hydrate the local store initially\n        - The first time we run the app, we will perform a query to perform a scan or query of DynamoDB with up to 10k records per table. This populates the local store. With selective sync, we perform a query instead of a scan against DynamoDB.\n        - Subsequent changes after the initial sync query come in through subscriptions\n        - There are two mechanisms:\n            - Base sync - retrieve all records up to total sync value\n            - Delta sync - one table per model, one delta sync table per DS store\n        - AppSync makse the final decision regarding which sync (base vs delta) to perform\n            - The client sends the last sync param with the sync query, service then compares the diff\n            - There is a TTL on all delta sync table records\n            - To find the TTL within the AppSync Console, see \"Update Data Source\"\n\n5. ### **Empty the Outbox / processes the mutation queue**\n    - Example: when performing mutations offline, records are added to the queue. Once there is connectivity, we start sending these **ONE BY ONE**.\n    - **Note: No batch API is exposed to consumers**\n    - Mutation events have ids\n    - Syncs get applied before mutations are sent\n6. ### **Begin processing the subscription buffer**\n    - If we receive subscription messages any time in the process of initializing subscriptions, performing sync queries, or processing the mutation queue, we buffer the subscription messages until everything else is completed. Once we have completed processing the mutation queue, we then process the subscription buffer\n7. ### **DataStore is now in \"ready\" state**\n    - For additional reference, and how the above are published as Hub events, see [the docs](https://docs.amplify.aws/lib/datastore/datastore-events/q/platform/js/)\n\n## Stop\n- Stops the DataStore sync process. This will close the real-time subscription connection when your app is no longer interested in updates. You will typically call DataStore.stop() just before your application is closed. You can also force your DataStore sync expressions to be re-evaluated at runtime by calling stop(), followed by start()\n\n## Clear\n- Clears local data from DataStore. DataStore will now require a full sync (not a delta sync) to populate the local store with data\n","isInternal":false,"tokens":1394,"sizeBytes":6184},{"name":"getting-started.md","path":"packages/datastore/docs/getting-started.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/datastore/docs/getting-started.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Onboarding with DataStore\n\n## Understand the primary DataStore events\n- Read the [DataStore lifecycle events doc](docs/datastore-lifecycle-events.md)\n\n## Building a sample app with DataStore to understand how it works\n1. Build a basic DataStore sample app (no @auth, just 1-2 models).\n2. Build a similar sample app with the API category.\n3. Add @auth rules to the DataStore app:\n    1. `amplify update api`\n    2. Modify schema according to auth rules docs (https://docs.amplify.aws/lib/datastore/setup-auth-rules/q/platform/js).\n    3. `amplify push`\n    4. `amplify codegen models`\n4. Add [selective sync](https://docs.amplify.aws/lib/datastore/sync/q/platform/js#selectively-syncing-a-subset-of-your-data).\n5. Enable [real-time changes](https://docs.amplify.aws/lib/datastore/real-time/q/platform/js).\n6. While interacting with your app, examine the IndexedDB tables (Application > IndexedDB within Chrome dev tools):\n    1. Check out the different stores in IDB that get created for your schema. Note the internal stores prefixed with sync_, and the stores corresponding to your models prefixed with user_.\n    2. Familiarize yourself with how actions taken in the UI affect the data stored in IDB. This may be easier to do while throttling the network connection. You'll be able to see how outgoing mutations first get persisted into the corresponding store, then added to the mutation queue / outbox (sync_MutationEvent), and then updated in the store with data from AppSync.\n7. Turn on DEBUG logging (`ConsoleLogger.LOG_LEVEL = \"DEBUG\";`) at the root of your project, and inspect the logs in the console while using your app. Additionally, [enable hub events](https://docs.amplify.aws/lib/datastore/datastore-events/q/platform/js#usage) for DataStore.\n8. The best way to understand DataStore events is to place several debuggers or breakpoints throughout DataStore.\n    - With logging / Hub events enabled, you can see what operations DataStore is performing (i.e. start, sync, etc.) as you step through with the debugger.\n9. Testing offline scenerios / concurrent user sessions is a useful way to test the full functionality of DataStore, and to fully understand how the sync process actually works.\n10. Next steps:\n    - Create a React Native example (uses a different storage type)\n    - Try more complex schema types\n    - Observe changes in records within DynamoDB (for instance, soft deletion).","isInternal":false,"tokens":559,"sizeBytes":2409},{"name":"namespaces.md","path":"packages/datastore/docs/namespaces.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/datastore/docs/namespaces.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Namespaces\n- `datastore`\n\t- Settings\n- `user` \n\t- Models that came from user schema\n- `sync` \n\t- Metadata (last time ran query, etc.)\n- `storage` \n\t- Deprecated\n# Local database examples:\n\n- *Note: Anything prepended with `sync_` is an internal table.*\n\n- ## datastore_Setting\n    - Used for schema versioning\n    - See the [schema changes doc](docs/schema-changes.md)\n    ```\n\t{\n\t\tid: \"01FYABF3DMBZZJ46W1CC214NH2\"\n\t\tkey: \"schemaVersion\"\n\t\tvalue: \"\\\"4401034582a70c60713e1f7f9da3b752\\\"\"\n\t}\n\t```\n- ## sync_ModelMetadata\n    - Sync Engine metadata\n\t- Includes information about the last time we synced a model\n\t```\n\t{\n\t\tfullSyncInterval: 86400000\n\t\tid: \"01FYABF3DMBZZJ46W1CC214NH3\"\n\t\tlastFullSync: 1647467532307\n\t\tlastSync: 1647467532307\n\t\tlastSyncPredicate: null\n\t\tmodel: \"Todo\"\n\t\tnamespace: \"user\"\n\t}\n\t```\n- ## sync_MutationEvent\n- ## user_[Model Name]\n    - The actual records themselves.\n\t```\n\t{\n\t\tcreatedAt: \"2022-03-16T21:52:07.718Z\"\n\t\tdescription: null\n\t\tid: \"6f69055b-b081-4225-8fc4-1d6d52732660\"\n\t\tname: \"name 1647467527489\"\n\t\tupdatedAt: \"2022-03-16T21:52:07.718Z\"\n\t\t_deleted: null\n\t\t_lastChangedAt: 1647467527754\n\t\t_version: 1\n\t}\n\t```","isInternal":false,"tokens":415,"sizeBytes":1143},{"name":"observables.md","path":"packages/datastore/docs/observables.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/datastore/docs/observables.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# How DataStore uses Observables\n- All of DataStore internally uses event driven methods (observables) to handle everything from the sync process, to observing online connectivity. **This makes the Storage Engine the single source of truth for DataStore.**\n- Examples:\n\t- The Sync Engine observes DataStore Connectivity \n\t- The Sync Engine observes the Storage Engine \n    - The client observes DataStore with `observe` and `observeQuery`:\n\t\t- https://docs.amplify.aws/lib/datastore/real-time/q/platform/js/\n\n## Understanding Observables\n- DataStore uses [`zen-observable`](https://github.com/zenparsing/zen-observable)\n- [The RXJS docs](https://rxjs.dev/guide/observable) do a good job of describing observables in more detail.","isInternal":false,"tokens":166,"sizeBytes":728},{"name":"schema-changes.md","path":"packages/datastore/docs/schema-changes.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/datastore/docs/schema-changes.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# What happens when a user changes their schema?\n   - The `schema.js` file that exists within an Amplify project (located at `src/models/schema.js`) contains a version hash. \n   - This hash is compared against the hash stored in the `Settings` table of the local database. Example:\n       ```\n           {\n               id: \"01FYABF3DMBZZJ46W1CC214NH2\"\n               key: \"schemaVersion\"\n               value: \"\\\"4401034582a70c60713e1f7f9da3b752\\\"\"\n           }\n       ```\n   - The process of checking the schema version (`checkSchemaVersion`) occurs when DataStore starts, after the Storage Engine has been initialized, and before the Sync Engine is initialized.\n   - If the schema version has changed, we clear local storage, and perform a full sync","isInternal":false,"tokens":179,"sizeBytes":753},{"name":"storage.md","path":"packages/datastore/docs/storage.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/datastore/docs/storage.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Storage\n## Adapters:\n- Web\n   - [IndexedDB](../src/storage/adapter/IndexedDBAdapter.ts)\n- Mobile\n   - React Native\n      - [Async Storage](../src/storage/adapter/AsyncStorageAdapter.ts) (can opt in to use SQLite)\n- SSR\n   - [InMemoryStore](../src/storage/adapter/InMemoryStore.ts)\n\n## How we determine which adapter to use\n\nWe determine the storage adapter [here](../src/storage/adapter/getDefaultAdapter/index.ts). \n\n\n## [The Storage class](../src/storage/storage.ts)\n- The Storage class is what interacts with the adapters.\n\n## [Storage Adapters](../src/storage/adapter)\n   1. There is one adapter per database type we support (i.e. three adapters).\n   2. Each adapter provides a unified API for the storage engine to interact with.\n   3. The SQLite adapter lives [in it’s own package](https://github.com/aws-amplify/amplify-js/tree/main/packages/datastore-storage-adapter).\n   4. **ExclusiveStorage wraps public storage methods (e.g. `Storage.runExclusive`)**\n      1. Guarantees consistency\n      2. Makes the storage class transactional\n      3. **Provides concurrency control**\n\n## How DataStore finds records locally:\n- Varies by storage adapter\n- [SQLiteAdapter](https://github.com/aws-amplify/amplify-js/tree/main/packages/datastore-storage-adapter): DataStore constructs a query. \n- [Async Storage](../src/storage/adapter/AsyncStorageAdapter.ts): DataStore scans and filters. \n- [IndexedDB](../src/storage/adapter/IndexedDBAdapter.ts): if the query is by primary key, DataStore queries against the index, otherwise it scans and filters.\n   - *Note: The lazy loading branch includes an improvement to the IndexedDB adapter that will check if any search criteria can leverage an index (there is no preference for low cardinality; the first identified index is used.) If so, the base result is sourced from the index and the remaining criteria will be applied as a filter.*\n\n## Understanding the difference between Save and Batch Save\n- As the names imply, `save` accepts a single record and persists it, while `batchSave` accepts a page of records and persists them all. `batchSave`, however, is *only used within the sync processor*, and will filter out deleted records from the sync page results, and then delete them from the local db.","isInternal":false,"tokens":522,"sizeBytes":2250},{"name":"sync-engine.md","path":"packages/datastore/docs/sync-engine.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/datastore/docs/sync-engine.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Sync Engine\n\nSee [the sync class](packages/datastore/src/sync/index.ts)\n\n## High-level overview:\n- The first time DataStore is started on a new client, a full sync is performed. Subsequent reloads of the app (including browser refresh, or a new browser session) are delta syncs.\n- If it has been greater than the `fullSyncInterval` (configurable) since the client has performed a full sync, this operation occurs as a full sync.\n- The Sync Engine is well documented in the [DataStore Lifecycle Events doc](./datastore-lifecycle-events.md). The purpose of this doc is to explain anything about the sync process that is not already documented there.\n\n\n## Types of Syncs\n### Full Sync\n- All records are fetched from AppSync.\n\n### Delta Sync\n- All the records that changed after a given time stamp are fetched.\n\n## How it works\n\n### [Merger](../src/sync/merger.ts)\n- A helper class for merging subscription records with the outbox (checks IDs).\n- The Sync Engine uses merge in two places:\n\t- 1. https://github.com/aws-amplify/amplify-js/blob/main/packages/datastore/src/sync/index.ts#L289\n\t\t- Triggered by the mutation response. It gets called after the client that authored the change receives the network response of the mutation request they generated.\n\t- 2. https://github.com/aws-amplify/amplify-js/blob/main/packages/datastore/src/sync/index.ts#L326\n\t\t- Triggered by an AppSync real-time subscription event, which is how all clients get notified of the change. In the case of the mutation author, this notification is redundant, but it’s necessary for all other active users of the application. This is why there will always be multiple snapshot returned by `observe` and `observeQuery` in the case of the mutation author.\n\n- The function of [the Merger class](../src/sync/merger.ts) is to filter out any incoming records that have corresponding pending changes in that client’s mutation queue / outbox, and is done to maintain data consistency. We wouldn’t want to write over data that the client has deliberately changed, and essentially undo whatever changes were performed on that client - even temporarily. Thus, each time a change comes in via a mutation response, AppSync subscription, or sync query, **Merger will only persist that change to the local database when there is not a pending mutation for that same record**.\n- If there is a pending change in the outbox - we discard the incoming model we were working with inside the merge call (by not saving it). Later, when the record from the Outbox gets processed by AppSync (and conflict resolution rules are applied as appropriate), we will persist the response of the mutation (assuming we don’t change the record again in the interim)\n- If there is not a pending change in the outbox - we persist the model to the local store via `Storage.save` within `merge`.\n- _Note: We maintain a single instance of a mutation when we are offline (i.e. if we perform multiple updates on the same record, we merge them into a single event). Once we are online, but other mutations are processing, we'll still attempt to merge outgoing events into an existing one if they are not already in flight_\n- Merger Example:\n\t- User A updates record 1\n\t- The update to record 1 is persisted locally, and enters the mutation queue for persistence to Appsync\n\t- User B has not yet received the update to record 1, and updates record 1\n\t- User A receives User B's update to record 1, but has not yet sent the mutation to AppSync\n\t- If Merger did not first check the mutation queue prior to applying the change from User B, User A would see their update, then user B's update, then, depending on how the conflict is handled by AppSync, could then see their update again. Instead, User A sees their update, and rejects User B's update. Once the conflict is handled by AppSync, any changes that are received are then applied.\n- *How to locally test / step through Merger:* \n\t- Create a few records and make sure the records go out successfully and are persisted. Then, delete local data in IndexedDB (either by clicking the `clear` button in a sample, or through dev tools), then reload the page, or perform a query.\n- **Note: AppSync expects us to send only updated fields in order for merge to work correctly.**\n\n### [Outbox]((../src/sync/outbox.ts))\n- A mutation event outbox\n- Holds all local changes (even if you close the app). \n- Peek returns the next mutation event to be sent to AppSync, but does not remove it from the outbox.\n\n## [Processors](../src/sync/processors)\n- Sync Engine uses processors depending on the type of operation\n- All processors utilize observables\n- Where retry happens\n\n### Mutation Processor (Local changes)\n- Online or offline changes that were optimistically made to the Storage Engine (processed in mutation queue **one by one**).\n- Observes Storage Engine for new changes.\n\n### Subscription Processor (Remote changes)\n- Real-time subscription messages (such as another client performing a change).\n- Uses the Amplify API Graphql package (which then uses PubSub).\n### Sync Processor\n- When the client goes online, fetch all changes that were performed in AppSync (could be full or delta sync).\n\n## Misc:\n- AppSync records are soft-deleted and have a TTL. \n- TODO: special configurations around sync intervals","isInternal":false,"tokens":1181,"sizeBytes":5292},{"name":"workarounds.md","path":"packages/datastore/docs/workarounds.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/datastore/docs/workarounds.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# TODO: \"Unsupported hacks\" / Workarounds","isInternal":false,"tokens":11,"sizeBytes":41},{"name":"README.md","path":"packages/adapter-nextjs/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/adapter-nextjs/README.md","title":"adapter-nextjs Documentation","category":"plugin-manifest","format":"markdown","content":"This package contains the AWS Amplify Next.js Adapter. For more information on using Next.js in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/javascript/build-a-backend/server-side-rendering/nextjs/).\n\n### Licensing Note\nAlthough this repository is released and licensed under the Apache License (see [LICENSE](./LICENSE)), its devDependencies transitively use the third party [sharp](https://sharp.pixelplumbing.com/) project.\n\nThe sharp projects prebuilt binaries' licensing includes [LGPL-2.1](https://opensource.org/license/LGPL-2.1) and [LGPL-3.0-or-later](https://opensource.org/license/LGPL-3.0) licenses","isInternal":false,"tokens":150,"sizeBytes":649},{"name":"README.md","path":"packages/analytics/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/analytics/README.md","title":"analytics Documentation","category":"plugin-manifest","format":"markdown","content":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify Analytics category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","isInternal":false,"tokens":51,"sizeBytes":222},{"name":"README.md","path":"packages/api-graphql/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/api-graphql/README.md","title":"api-graphql Documentation","category":"plugin-manifest","format":"markdown","content":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify API GraphQL category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","isInternal":false,"tokens":52,"sizeBytes":224},{"name":"README.md","path":"packages/api-rest/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/api-rest/README.md","title":"api-rest Documentation","category":"plugin-manifest","format":"markdown","content":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify API REST category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","isInternal":false,"tokens":52,"sizeBytes":221},{"name":"README.md","path":"packages/api/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/api/README.md","title":"api Documentation","category":"plugin-manifest","format":"markdown","content":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify API category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","isInternal":false,"tokens":51,"sizeBytes":216},{"name":"README.md","path":"packages/auth/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/auth/README.md","title":"auth Documentation","category":"plugin-manifest","format":"markdown","content":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify Auth category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","isInternal":false,"tokens":51,"sizeBytes":217},{"name":"README.md","path":"packages/aws-amplify/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/aws-amplify/README.md","title":"aws-amplify Documentation","category":"plugin-manifest","format":"markdown","content":"# AWS Amplify Package - aws-amplify\n\nAWS Amplify is a JavaScript library for frontend and mobile developers building cloud-enabled applications. The library is a declarative interface across different categories of operations in order to make common tasks easier to add into your application. The default implementation works with Amazon Web Services (AWS) resources but is designed to be open and pluggable for usage with other cloud services that wish to provide an implementation or custom backends.\n\nDocumentation is available [here](https://docs.amplify.aws/javascript/).\n","isInternal":false,"tokens":108,"sizeBytes":577},{"name":"README.md","path":"packages/core/__mocks__/configMocks/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/core/__mocks__/configMocks/README.md","title":"configMocks Documentation","category":"plugin-manifest","format":"markdown","content":"This directory contains equivalent Gen1 & Gen2 configurations which are used to validate interoperability between\ndifferent config versions/schemas. Make sure that any updates applied to one are applied to the other.\n","isInternal":false,"tokens":39,"sizeBytes":217},{"name":"README.md","path":"packages/core/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/core/README.md","title":"core Documentation","category":"plugin-manifest","format":"markdown","content":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify core utilities and is intended for internal use only. To integrate Amplify into your app. Please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","isInternal":false,"tokens":51,"sizeBytes":218},{"name":"README.md","path":"packages/datastore-storage-adapter/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/datastore-storage-adapter/README.md","title":"datastore-storage-adapter Documentation","category":"plugin-manifest","format":"markdown","content":"This package contains the AWS Amplify DataStore storage adapter. For more information on using the DataStore storage adapter in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/react-native/build-a-backend/more-features/datastore/set-up-datastore/#setup-local-development-environment).\n","isInternal":false,"tokens":64,"sizeBytes":321},{"name":"README.md","path":"packages/datastore/__tests__/helpers/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/datastore/__tests__/helpers/README.md","title":"helpers Documentation","category":"plugin-manifest","format":"markdown","content":"## Helper functions for DataStore testing\n\nPlease try to keep things clean.\n\nIn particular, let's try to to keep file sizes smaller and more \"categorical\" in order to:\n\n1. Make finding and discovering test utils easier\n2. Reduce excessive vertical scrolling\n3. Reduce complexity of merge conflicts\n4. _<< And other awesome benefits I haven't thought of! >>_\n\nIntended organization is as follows:\n\n|                       | Intent                                                                                                                |\n| --------------------- | --------------------------------------------------------------------------------------------------------------------- |\n| `fakes/*`             | Util classes to inject and/or observe datastore's interaction with its boundaries, like cloud/graphql storage.        |\n| `schemas/*`           | Schema JSON and model types (Plenty of room for further refactoring and reorganization here!)                         |\n| `datastoreFactory.ts` | Function(s) for creating clean, test-configured initializations of DataStore and deps to test against.                |\n| `util.ts`             | Miscellaneous, mostly-isolated utility functions to aid with testing. (To be further decomposed as-needed over time.) |\n\nThere's almost always room to clean things up and do better. If you encounter a merge conflict that would have benefitted from chunks of code living separately; submit a refactor-only PR to separate them. If you get \"lost\" vertically scrolling in a file, look for a semantically meaningful boundary to separate on. If you can't find what you're looking for, consider whether another folder/category to drill into would have helped.\n\nIf you have any ideas around taming the rather large test schemas, making it easier to add new models and corresponding JSON, submit a PR with your idea! Etc..\n\nThanks!\n","isInternal":false,"tokens":341,"sizeBytes":1876},{"name":"README.md","path":"packages/datastore/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/datastore/README.md","title":"datastore Documentation","category":"plugin-manifest","format":"markdown","content":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify DataStore category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n\n# AWS Amplify DataStore Docs\n\n[Amplify DataStore](https://docs.amplify.aws/lib/datastore/getting-started/q/platform/js/) provides a programming model for leveraging shared and distributed data without writing additional code for offline and online scenarios, which makes working with distributed, cross-user data just as simple as working with local-only data.\n\n---\n\n| package                | version                                                         | open issues                                                                                                                                                                                  | closed issues                                                                                                                                                                                 |\n| ---------------------- | --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| @aws-amplify/datastore | ![npm](https://img.shields.io/npm/v/@aws-amplify/datastore.svg) | [![Open Issues](https://img.shields.io/github/issues/aws-amplify/amplify-js/DataStore?color=red)](https://github.com/aws-amplify/amplify-js/issues?q=is%3Aissue+label%3ADataStore+is%3Aopen) | [![Closed Issues](https://img.shields.io/github/issues-closed/aws-amplify/amplify-js/DataStore)](https://github.com/aws-amplify/amplify-js/issues?q=is%3Aissue+label%3ADataStore+is%3Aclosed) |\n\n---\n\n## **👋 Note For Contributers: 👋**\n\n_**Please update these docs any time you find something that is incorrect or lacking. In particular, if a line in the docs prompts a question, take a moment to figure out the answer, then update the docs with the necessary detail.**_\n\n---\n\n## Getting Started\n\nBefore you start reading through these docs, take a moment to understand [how DataStore works at a high level](https://docs.amplify.aws/lib/datastore/how-it-works/q/platform/js/). Additionally, we recommend first reading through [docs.amplify.aws](https://docs.amplify.aws/lib/datastore/getting-started/q/platform/js/). The purpose of these docs is to dive deep into the codebase itself and understand the inner workings of DataStore for the purpose of contributing. Understanding these docs is **not** necessary for using DataStore. Lastly, before reading, take a look at [the diagrams below](#diagrams).\n\n---\n\n## Docs\n\n- [Conflict Resolution](docs/conflict-resolution.md)\n- [Contributing](docs/contributing.md)\n- [DataStore Lifecycle Events (\"Start\", \"Stop\", \"Clear\")](docs/datastore-lifecycle-events.md)\n  - This explains how DataStore fundementally works, and is a great place to start.\n- [Getting Started](docs/getting-started.md) (Running against a sample app, etc.)\n- [Namespaces](docs/namespaces.md)\n- [How DataStore uses Observables](docs/observables.md)\n- [Schema Changes](docs/schema-changes.md)\n- [Storage](docs/storage.md)\n- [Sync Engine](docs/sync-engine.md)\n- [\"Unsupported hacks\" / workarounds](docs/workarounds.md)\n\n---\n\n# Diagrams\n\n_Note: relationships with dotted lines are explained more in a separate diagram._\n\n## How the DataStore API and Storage Engine Interact\n\n```mermaid\nflowchart TD\n  %% API and Storage\n  api[[DS API]]-- observe -->storage{Storage Engine}\n  storage-- next -->adapter[[Adapter]]\n  adapter-->db[[Local DB]]\n  db-->api\n  sync[[Sync Engine*]]-.-storage\n  sync-.-appSync[(AppSync)]\n```\n\n# How the Sync Engine Observes Changes in Storage and AppSync\n\n_Note: All green nodes belong to the Sync Engine._\n\n\\* Merger first checks outbox\n\n\\*\\* Outbox sends outgoing messages to AppSync\n\n```mermaid\nflowchart TD\n\n  subgraph SyncEngine\n  index{index.ts}-- observe -->reach[Core reachability]\n\n  subgraph processors\n  mp[Mutation Processor]\n  sp[Subscription Processor]\n  syp[Sync Processor]\n  end\n\n  reach--next-->mp[Mutation Processor]\n  reach--next-->sp[Subscription Processor]\n  reach--next-->syp[Sync Processor]\n\n  subgraph outbox / merger\n  outbox[Outbox]\n  merger[Merger]\n  outbox---merger\n  end\n\n  end\n\n  api[DS API]-.->storage\n  mp-- 1. observe -->storage{Storage Engine}\n  storage-- 2. next -->merger[merger*]-- next -->storage\n\n\n  sp-- observe -->appsync[(AppSync)]\n  appsync-- next -->sp\n\n  syp---appsync\n\n  mp-->outbox[outbox**]\n\n  appsync<--->outbox\n  %% styling\n  classDef syncEngineClass fill:#8FB,stroke:#333,stroke-width:4px,color:#333;\n  class index,mp,sp,syp,merger,outbox syncEngineClass;\n```\n\n---\n\n# Project Structure\n\n<pre>\namplify-js/packages/datastore/src\n├── authModeStrategies\n│   └── defaultAuthStraegy.ts\n│   └── index.ts\n│   └── multiAuthStrategy.ts\n├── datastore\n│   └── datastore.ts # Entry point for DataStore\n├── predicates\n│   └── index.ts\n│   └── sort.ts\n├── ssr\n├── storage # Storage Engine\n│   └── adapter # Platform-specific Storage Adapters\n│      └── getDefaultAdapter\n│      └── AsyncStorageAdapter.ts\n│      └── AsyncStorageDatabase.ts\n│      └── index.ts\n│      └── IndexedDBAdapter.ts\n│      └── InMemoryStore.native.ts\n│      └── InMemoryStore.ts\n│   └── storage.ts # Entry point for Storage\n├── sync # Sync Engine\n│   └── dataStoreReachability\n│      └── index.native.ts\n│      └── index.ts\n│   └── processors # Sync Engine Processors\n│      └── mutation.ts\n│      └── subscription.ts\n│      └── sync.ts\n│   └── datastoreConnectivity.ts # Subscribe to reachability monitor\n│   └── index.ts # Entry point for Sync Engine\n│   └── merger.ts # <a href=\"https://github.com/aws-amplify/amplify-js/blob/datastore-docs/packages/datastore/docs/sync-engine.md#merger\" title=\"merger doc\">doc</a>\n│   └── outbox.ts # <a href=\"https://github.com/aws-amplify/amplify-js/blob/datastore-docs/packages/datastore/docs/sync-engine.md#outbox\" title=\"outbox doc\">doc</a>\n</pre>\n\n---\n\n## Other Resources:\n\n- [High-level overview of how DataStore works](https://docs.amplify.aws/lib/datastore/how-it-works/q/platform/js/)\n- [DataStore Docs](https://docs.amplify.aws/lib/datastore/getting-started/q/platform/js/)\n- [re:Invent talk](https://www.youtube.com/watch?v=KcYl6_We0EU)\n","isInternal":false,"tokens":1577,"sizeBytes":6801},{"name":"README.md","path":"packages/geo/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/geo/README.md","title":"geo Documentation","category":"plugin-manifest","format":"markdown","content":"This package contains the AWS Amplify Geo category. For more information on using Geo in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/javascript/build-a-backend/more-features/geo/).\n","isInternal":false,"tokens":48,"sizeBytes":221},{"name":"README.md","path":"packages/interactions/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/interactions/README.md","title":"interactions Documentation","category":"plugin-manifest","format":"markdown","content":"This package contains the AWS Amplify Interactions category. For more information on using Interactions in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/javascript/build-a-backend/more-features/interactions/).\n","isInternal":false,"tokens":51,"sizeBytes":248},{"name":"README.md","path":"packages/notifications/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/notifications/README.md","title":"notifications Documentation","category":"plugin-manifest","format":"markdown","content":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify Notifications category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","isInternal":false,"tokens":51,"sizeBytes":226},{"name":"README.md","path":"packages/predictions/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/predictions/README.md","title":"predictions Documentation","category":"plugin-manifest","format":"markdown","content":"This package contains the AWS Amplify Predictions category. For more information on using Predictions in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/javascript/build-a-backend/more-features/predictions/).\n\n","isInternal":false,"tokens":51,"sizeBytes":246},{"name":"README.md","path":"packages/pubsub/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/pubsub/README.md","title":"pubsub Documentation","category":"plugin-manifest","format":"markdown","content":"This package contains the AWS Amplify PubSub category. For more information on using PubSub in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/javascript/build-a-backend/more-features/pubsub/).\n\n","isInternal":false,"tokens":50,"sizeBytes":231},{"name":"README.md","path":"packages/react-native/example/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/react-native/example/README.md","title":"example Documentation","category":"plugin-manifest","format":"markdown","content":"This is an example app for developing and testing the react-native modules located at `../`.\n\n# Getting Started\n\n> **Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till \"Creating a new application\" step, before proceeding.\n\n## Step 1: Start the Metro Server\n\nFirst, you will need to start **Metro**, the JavaScript _bundler_ that ships _with_ React Native.\n\nTo start Metro, run the following command from the _root_ of your React Native project:\n\n```bash\n# using npm\nnpm start\n\n# OR using Yarn\nyarn start\n```\n\n## Step 2: Start your Application\n\nLet Metro Bundler run in its _own_ terminal. Open a _new_ terminal from the _root_ of your React Native project. Run the following command to start your _Android_ or _iOS_ app:\n\n### For Android\n\n```bash\n# using npm\nnpm run android\n\n# OR using Yarn\nyarn android\n```\n\n### For iOS\n\n```bash\n# using npm\nnpm run ios\n\n# OR using Yarn\nyarn ios\n```\n\nIf everything is set up _correctly_, you should see your new app running in your _Android Emulator_ or _iOS Simulator_ shortly provided you have set up your emulator/simulator correctly.\n\nThis is one way to run your app — you can also run it directly from within Android Studio and Xcode respectively.\n","isInternal":false,"tokens":308,"sizeBytes":1281},{"name":"README.md","path":"packages/react-native/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/react-native/README.md","title":"react-native Documentation","category":"plugin-manifest","format":"markdown","content":"> INTERNAL USE ONLY\n\nThis package contains AWS Amplify React Native utilities and is intended for internal use only. Please ensure this package is installed alongside [aws-amplify](https://www.npmjs.com/package/aws-amplify). We do not advise using any exports from this package directly.\n","isInternal":false,"tokens":60,"sizeBytes":288},{"name":"README.md","path":"packages/rtn-passkeys/example/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/rtn-passkeys/example/README.md","title":"example Documentation","category":"plugin-manifest","format":"markdown","content":"This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli).\n\n# Getting Started\n\n> **Note**: Make sure you have completed the [Set Up Your Environment](https://reactnative.dev/docs/set-up-your-environment) guide before proceeding.\n\n## Step 1: Start Metro\n\nFirst, you will need to run **Metro**, the JavaScript build tool for React Native.\n\nTo start the Metro dev server, run the following command from the root of your React Native project:\n\n```sh\n# Using npm\nnpm start\n\n# OR using Yarn\nyarn start\n```\n\n## Step 2: Build and run your app\n\nWith Metro running, open a new terminal window/pane from the root of your React Native project, and use one of the following commands to build and run your Android or iOS app:\n\n### Android\n\n```sh\n# Using npm\nnpm run android\n\n# OR using Yarn\nyarn android\n```\n\n### iOS\n\nFor iOS, remember to install CocoaPods dependencies (this only needs to be run on first clone or after updating native deps).\n\nThe first time you create a new project, run the Ruby bundler to install CocoaPods itself:\n\n```sh\nbundle install\n```\n\nThen, and every time you update your native dependencies, run:\n\n```sh\nbundle exec pod install\n```\n\nFor more information, please visit [CocoaPods Getting Started guide](https://guides.cocoapods.org/using/getting-started.html).\n\n```sh\n# Using npm\nnpm run ios\n\n# OR using Yarn\nyarn ios\n```\n\nIf everything is set up correctly, you should see your new app running in the Android Emulator, iOS Simulator, or your connected device.\n\nThis is one way to run your app — you can also build it directly from Android Studio or Xcode.\n\n## Step 3: Modify your app\n\nNow that you have successfully run the app, let's make changes!\n\nOpen `App.tsx` in your text editor of choice and make some changes. When you save, your app will automatically update and reflect these changes — this is powered by [Fast Refresh](https://reactnative.dev/docs/fast-refresh).\n\nWhen you want to forcefully reload, for example to reset the state of your app, you can perform a full reload:\n\n- **Android**: Press the <kbd>R</kbd> key twice or select **\"Reload\"** from the **Dev Menu**, accessed via <kbd>Ctrl</kbd> + <kbd>M</kbd> (Windows/Linux) or <kbd>Cmd ⌘</kbd> + <kbd>M</kbd> (macOS).\n- **iOS**: Press <kbd>R</kbd> in iOS Simulator.\n\n## Congratulations! :tada:\n\nYou've successfully run and modified your React Native App. :partying_face:\n\n### Now what?\n\n- If you want to add this new React Native code to an existing application, check out the [Integration guide](https://reactnative.dev/docs/integration-with-existing-apps).\n- If you're curious to learn more about React Native, check out the [docs](https://reactnative.dev/docs/getting-started).\n\n# Troubleshooting\n\nIf you're having issues getting the above steps to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page.\n\n# Learn More\n\nTo learn more about React Native, take a look at the following resources:\n\n- [React Native Website](https://reactnative.dev) - learn more about React Native.\n- [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how setup your environment.\n- [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**.\n- [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts.\n- [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native.\n","isInternal":false,"tokens":859,"sizeBytes":3582},{"name":"README.md","path":"packages/rtn-passkeys/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/rtn-passkeys/README.md","title":"rtn-passkeys Documentation","category":"plugin-manifest","format":"markdown","content":"> INTERNAL USE ONLY\n\nThis package contains AWS Amplify React Native utilities and is intended for internal use only. Please ensure this package is installed alongside [aws-amplify](https://www.npmjs.com/package/aws-amplify) and [@aws-amplify/react-native](https://www.npmjs.com/package/@aws-amplify/react-native). We do not advise using any exports from this package directly.\n","isInternal":false,"tokens":85,"sizeBytes":377},{"name":"README.md","path":"packages/storage/README.md","rawUrl":"https://raw.githubusercontent.com/aws-amplify/amplify-js/HEAD/packages/storage/README.md","title":"storage Documentation","category":"plugin-manifest","format":"markdown","content":"> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify Storage category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n","isInternal":false,"tokens":51,"sizeBytes":220}],"systemPromptSnippet":"<yakaai_skills repo=\"aws-amplify/amplify-js\">\n<!-- File: AGENTS.md (Tokens: ~1754 | Category: root-instruction) -->\n# AGENTS.md\n\nGuidance for AI coding agents working in the **AWS Amplify JS** monorepo. Read this before making changes.\n\n## Repository Overview\n\nAmplify JS is a **Yarn + Turborepo** monorepo. Every package lives under `packages/<name>/`, each with its own `src/` and `package.json`. Packages are published under the `@aws-amplify/*` scope (plus the umbrella `aws-amplify` package).\n\nKey packages:\n\n| Package | Purpose |\n|---|---|\n| `@aws-amplify/core` | Shared runtime: config singleton, Hub, utils |\n| `@aws-amplify/auth` | Cognito authentication |\n| `@aws-amplify/storage` | S3 storage (client/utils + server/utils split) |\n| `@aws-amplify/api`, `api-graphql`, `api-rest` | API categories |\n| `@aws-amplify/analytics`, `geo`, `interactions`, `notifications`, `predictions`, `pubsub` | Feature categories |\n| `aws-amplify` | Umbrella package re-exporting category APIs |\n| `@aws-amplify/adapter-nextjs` | Next.js server adapter |\n\n## Environment\n\n| Requirement | Version |\n|---|---|\n| Node.js | 24 (pinned in CI; repo has no local `engines`/`.nvmrc`) |\n| Yarn | 1.22.x |\n\n## Build & Test Commands (MANDATORY: use `yarn`)\n\n**Always drive builds/tests/lint through `yarn`. NEVER invoke `tsc`, `eslint`, `jest`, `npx`, or `tsx` directly** — the workspace scripts wire up the correct config and dependency graph. Single-package targeting goes through Turbo's `--filter` (see below).\n\n```bash\n# Install\nyarn\n\n# Build\nyarn build                              # all packages\nyarn turbo run build --filter=@aws-amplify/auth   # single package (+ its deps)\n\n# Test\nyarn test                               # full suite (use before final confirmation)\nyarn turbo run test --filter=@aws-amplify/auth    # single package\n\n# Lint\nyarn lint                               # lint all packages\nyarn turbo run lint --filter=@aws-amplify/auth    # single package\n\n# Bundle size\nyarn test:size                          # size-limit check (only runs for packages that define it)\nyarn test:size --why                    # debug regression (Statoscope)\n\n# Watch mode for local dev\nyarn build:watch\nyarn link-all                           # make all packages linkable\n\n# Nuclear clean\ngit clean -xdf\n```\n\nRun `yarn` from the **monorepo root or a package root**. During implementation you may narrow with file/suite/test filters, but always run the full `test` / `lint` / `build` for final confirmation.\n\n> **Single-package targeting must go through Turbo directly** — `yarn turbo run <task> --filter=@aws-amplify/<pkg>`. Do **not** pass `--filter` to the top-level `yarn build` / `yarn test` scripts: they are compound (`&&`) scripts, so the flag is misrouted to the trailing command and Turbo still runs unfiltered. (`--scope` is a Lerna flag — not valid for Turbo 2.x at all.)\n\n## Testing Conventions\n\n- **Do NOT mock `getConfig` on the Amplify singleton.** Mock the actual underlying modules/functions instead (real Amplify config approach).\n- Write or update unit tests for any added/modified code. Be especially vigilant with shared code (race conditions).\n- Passing unit tests are required for any PR that changes functionality.\n- **Bundle-size (`size-limit`) checks only apply to packages that configure them.** Eight packages declare a `size-limit` key (`aws-amplify`, `core`, `datastore`, `geo`, `interactions`, `predictions`, `pubsub`, `api-graphql`), but `yarn test:size` only exercises the seven that also define a `test:size` script (all of the above except `api-graphql`). Filtering it to a package without size-limit configured (e.g. `auth`, `storage`) is a no-op.\n\n## Code Conventions\n\n- **License headers are required** on source files (enforced by the `license-test` CI check).\n- **Never commit `tsconfig.tsbuildinfo` files.** A stray `packages/*/tsconfig.tsbuildinfo` causes `license-test` failures (`License not found in ...`). Remove it if generated.\n- Preserve existing comments, JSDoc, and logging statements.\n- Follow existing formatting (Prettier + ESLint config are applied via `yarn` scripts).\n\n## Git Hooks (Husky)\n\nThe repo installs Husky hooks that run automatically — an agent committing or pushing will trigger them:\n\n- **`pre-commit`** — runs `lint-staged` (`eslint --fix` on staged `*.ts`/`*.tsx`). Do not bypass with `--no-verify`.\n- **`pre-push`** — runs a **git-secrets** scan and **blocks the push if git-secrets is not installed**. Install and register it before pushing:\n\n```bash\nbrew install git-secrets   # or: apt-get install git-secrets\ngit secrets --register-aws\n```\n\n## Changesets (required for functional changes)\n\n```bash\nyarn changeset\n```\n\nCreates a file in `.changeset/`:\n\n```markdown\n---\n'@aws-amplify/<package>': patch|minor|major\n---\n\n<type>(<scope>): description of the change.\n```\n\n**Skip a changeset** only for docs-only, formatting, or CI-only changes.\n\n## Branch Naming\n\n```\n<scope>/<type>/<description>\n```\n\n- **scope**: category or alias (e.g. `auth`, `storage`, `core`)\n- **type**: `feat` | `fix` | `docs` | `refactor` | `perf` | `test` | `build` | `ci` | `chore` | `revert`\n\nExamples: `auth/fix/refresh-token-race-condition`, `storage/feat/presigned-urls`\n\n## Commit / PR Flow\n\n1. Make changes in `packages/<category>/`.\n2. Add/update unit tests.\n3. Add a changeset (if functional).\n4. Validate: `yarn build` + `yarn test` (+ `yarn test:size` if bundle-sensitive).\n5. Commit with a conventional message: `<type>(<scope>): summary`.\n6. Push and open a PR filling out the template (description, linked issue, validation steps, checklist).\n\n## CI Checks (must pass before merge)\n\n| Check | Validates |\n|---|---|\n| `unit-tests` | Jest suites across packages |\n| `native-unit-tests` | React Native tests |\n| `bundle-size-tests` | Tree-shaken footprint (size-limit) |\n| `license-test` | License headers present |\n| `tsc-compliance-test` | TypeScript compilation |\n| `dependency-review` | No problematic dependencies |\n| `git-secrets-check` | No leaked AWS credentials |\n| `github-actions-test` | CI config validity |\n\nThe `ci - Unit and Bundle tests have passed` gate turns green only when all above pass.\n\n## Maintenance Branch: `v5-stable`\n\nThe `v5-stable` branch hosts Amplify JS v5 maintenance releases (security patches, critical fixes). **Do not apply this document's conventions there** — it uses different tooling (Lerna instead of Turborepo, no changesets, different setup and CI checks).\n\nWhen backporting a fix to v5: branch off `v5-stable`, target the PR at `v5-stable`, and follow the `AGENTS.md` **on that branch** for its specific conventions.\n\n## Do / Don't Summary\n\n**Do**\n- Use `yarn` for everything\n- Add tests + changesets\n- Keep license headers\n- Mock underlying modules, not `Amplify.getConfig`\n\n**Don't**\n- Run `tsc`/`jest`/`eslint`/`npx` directly\n- Commit `tsconfig.tsbuildinfo`\n- Strip existing comments or logging\n\n<!-- File: CLAUDE.md (Tokens: ~56 | Category: claude-rule) -->\n# CLAUDE.md\n\nThis project's AI agent guidance lives in [AGENTS.md](./AGENTS.md).\n\nPlease read **[AGENTS.md](./AGENTS.md)** for repository structure, build/test commands, code conventions, changeset requirements, and CI checks.\n\n<!-- File: packages/datastore/docs/conflict-resolution.md (Tokens: ~165 | Category: anthropic-skill) -->\n# Conflict Resolution\n- **AppSync is the source of truth for conflict resolution**\n   1. In the event AppSync fails to resolve a conflict, the network response will contain an error message (`conflict unhandled`). This is how we give customers the chance to make an update, or try again.\n   2. We use jittered retry (10x).\n   - TODO: add more detail / links to how this retry logic occurs.\n- We err on the side of not deleting customer data when performing conflict resolution.\n- Auto-merge is the default resolution strategy. This relies on the version, and will attempt to merge fields that changed when possible.\n- For more, see [the AppSync docs](https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html)\n\n<!-- File: packages/datastore/docs/contributing.md (Tokens: ~294 | Category: anthropic-skill) -->\n# Contributing\n\n## Formatting\n- We use Prettier to format our code. We recommend installing it within your IDE to prevent formatting code within other Amplify packages (as opposed to formatting from the Prettier CLI directly). Example [VS Code Extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)).\n\n## Testing DataStore changes locally\n- On first build:\n\t- Within **amplify-js**: `yarn && yarn build && yarn link-all && yarn build:watch`\n\t- Within sample app: `yarn && yarn link aws-amplify && yarn link @aws-amplify/datastore && yarn start`\n- On subsequent builds (useful if something isn't working):\n\t- Within **amplify-js**: `yarn clean && yarn build && yarn link-all && yarn build:watch`\n\t- Within sample app: `rm -rf node_modules && yarn && yarn link aws-amplify && yarn link @aws-amplify/datastore && yarn start`\n\n## Contributing to these docs\n- Do not link to specific lines of code, as these frequently change. Instead, do the opposite: link to the documentation within the code itself, as the docs are less likely to change.\n- Prefer small, self-contained sections over large, monolothic documents.\n- Do not use permalinks - instead, link to the most current files.\n\n<!-- File: packages/datastore/docs/datastore-lifecycle-events.md (Tokens: ~1394 | Category: anthropic-skill) -->\n# DataStore Lifecycle Events (\"Start\", \"Stop\", \"Clear\")\n\n# DataStore Initialization (\"Start\")\n\n**Understanding how DataStore starts is critical to understanding how DataStore fundamentally works.** At a high level, starting DataStore does the following things in order for each model:\n\n> 1.  Init Schema\n> 2.  Init the Storage Engine\n> 3.  Migrate schema changes\n> 4.  Sync Engine Operations\n> 5.  Empty the Outbox / processes the mutation queue\n> 6.  Begin processing the subscription buffer\n> 7.  DataStore is now in \"ready\" state\n\n- _We can eagerly start DataStore by calling `DataStore.start`. Otherwise, invoking a method (query, save, delete, observe) will start it up_\n- _When importing a model, DS consumes `schema.js`, and creates the IndexedDB store._\n\n## **How it works:**\n\n1.  ### **Init schema**\n    - **1.1** First we call `initSchema` [here](packages/datastore/src/datastore/datastore.ts)\n    - **1.2** Codegen then generates `schema.js` from the schema\n    - **1.3** DataStore consumes `schema.js`\n\n2.  ### **Init the storage engine**\n    - **2.1** The adapter is initialized\n    - **2.2** The local database gets created if it doesn’t exist already\n    - **2.3** The adapter [has a `setUp`](packages/datastore/src/storage/adapter/IndexedDBAdapter.ts#L82) method that then calls the database's `init` method\n    - **2.4** Relations are established\n    - _Nothing happens until the first interaction with DataStore_\n\n3.  ### **Migrate schema changes (if needed)**\n    - See [schema-changes.md](./schema-changes.md)\n    - If the user has updated the schema, we perform the migration here\n\n4.  ### **Sync Engine Operations**\n-  #### 4.1 Instantiate Sync Engine (`this.sync = new SyncEngine(`)\n    - The Sync Engine is only instantiated if there is a graphql endpoint (meaning we’ve already provisioned the backend). Otherwise, DataStore is in local-only mode. See [datastore.ts](packages/datastore/src/datastore/datastore.ts#L735)\n    - **Note: at this step, we do not yet process the buffer**\n    - There are three subscriptions per model: `create`, `update`, and `delete`\n\n- #### 4.2 Sync Engine is started (`syncSubscription = this.sync.start(`)\n    - **4.2.1 Subscribe to the Sync Engine**\n      - Messages from this subscription are emmited as Hub events for DataStore\n      - When ready, we call `initResolve`\n      - If unauthorized, DS keeps working, as we may have publicly readable models\n      - If a validation error occurs, DataStore Sync breaks entirely\n      - Without subscriptions, DataStore doesn’t work (when there is an endpoint present)\n      - Subscriptions are the only component that update the local store from remote\n      - If updates come in, they’re buffered to be processed after sync is complete\n      - Prepares the sync predicates (similar to adapter setup)\n\n    - **4.2.2 Subscribe to DataStore connectivity observable (notifications about network status)**\n        - `this.datastoreConnectivity.status().subscribe`\n        - Subscribe Amplify Core component that monitors network reachability\n        - We do this here because we need the ability to stop or start the sync process. When offline, we disconnect the websocket and stop syncing. Once online, we reconnect the websocket and start base / delta syncing\n        - Sync engine subscribes to the Storage Engine\n            - Every write may need to get translated to a mutation in the outbox\n            - Storage engine is local source of truth for DataStore, all other pieces are observing\n\n    - **4.2.3 Run the Sync Queries (when online)**\n        - _Note: We perform a topological sort of the data - we sync the children first, so when we query the parent, the children are already present We also use an optimisation to parallelize this process if possible (i.e. non-dependent models)_\n        - Sync queries are Graphql queries that are necessary to hydrate the local store initially\n        - The first time we run the app, we will perform a query to perform a scan or query of DynamoDB with up to 10k records per table. This populates the local store. With selective sync, we perform a query instead of a scan against DynamoDB.\n        - Subsequent changes after the initial sync query come in through subscriptions\n        - There are two mechanisms:\n            - Base sync - retrieve all records up to total sync value\n            - Delta sync - one table per model, one delta sync table per DS store\n        - AppSync makse the final decision regarding which sync (base vs delta) to perform\n            - The client sends the last sync param with the sync query, service then compares the diff\n            - There is a TTL on all delta sync table records\n            - To find the TTL within the AppSync Console, see \"Update Data Source\"\n\n5. ### **Empty the Outbox / processes the mutation queue**\n    - Example: when performing mutations offline, records are added to the queue. Once there is connectivity, we start sending these **ONE BY ONE**.\n    - **Note: No batch API is exposed to consumers**\n    - Mutation events have ids\n    - Syncs get applied before mutations are sent\n6. ### **Begin processing the subscription buffer**\n    - If we receive subscription messages any time in the process of initializing subscriptions, performing sync queries, or processing the mutation queue, we buffer the subscription messages until everything else is completed. Once we have completed processing the mutation queue, we then process the subscription buffer\n7. ### **DataStore is now in \"ready\" state**\n    - For additional reference, and how the above are published as Hub events, see [the docs](https://docs.amplify.aws/lib/datastore/datastore-events/q/platform/js/)\n\n## Stop\n- Stops the DataStore sync process. This will close the real-time subscription connection when your app is no longer interested in updates. You will typically call DataStore.stop() just before your application is closed. You can also force your DataStore sync expressions to be re-evaluated at runtime by calling stop(), followed by start()\n\n## Clear\n- Clears local data from DataStore. DataStore will now require a full sync (not a delta sync) to populate the local store with data\n\n<!-- File: packages/datastore/docs/getting-started.md (Tokens: ~559 | Category: anthropic-skill) -->\n# Onboarding with DataStore\n\n## Understand the primary DataStore events\n- Read the [DataStore lifecycle events doc](docs/datastore-lifecycle-events.md)\n\n## Building a sample app with DataStore to understand how it works\n1. Build a basic DataStore sample app (no @auth, just 1-2 models).\n2. Build a similar sample app with the API category.\n3. Add @auth rules to the DataStore app:\n    1. `amplify update api`\n    2. Modify schema according to auth rules docs (https://docs.amplify.aws/lib/datastore/setup-auth-rules/q/platform/js).\n    3. `amplify push`\n    4. `amplify codegen models`\n4. Add [selective sync](https://docs.amplify.aws/lib/datastore/sync/q/platform/js#selectively-syncing-a-subset-of-your-data).\n5. Enable [real-time changes](https://docs.amplify.aws/lib/datastore/real-time/q/platform/js).\n6. While interacting with your app, examine the IndexedDB tables (Application > IndexedDB within Chrome dev tools):\n    1. Check out the different stores in IDB that get created for your schema. Note the internal stores prefixed with sync_, and the stores corresponding to your models prefixed with user_.\n    2. Familiarize yourself with how actions taken in the UI affect the data stored in IDB. This may be easier to do while throttling the network connection. You'll be able to see how outgoing mutations first get persisted into the corresponding store, then added to the mutation queue / outbox (sync_MutationEvent), and then updated in the store with data from AppSync.\n7. Turn on DEBUG logging (`ConsoleLogger.LOG_LEVEL = \"DEBUG\";`) at the root of your project, and inspect the logs in the console while using your app. Additionally, [enable hub events](https://docs.amplify.aws/lib/datastore/datastore-events/q/platform/js#usage) for DataStore.\n8. The best way to understand DataStore events is to place several debuggers or breakpoints throughout DataStore.\n    - With logging / Hub events enabled, you can see what operations DataStore is performing (i.e. start, sync, etc.) as you step through with the debugger.\n9. Testing offline scenerios / concurrent user sessions is a useful way to test the full functionality of DataStore, and to fully understand how the sync process actually works.\n10. Next steps:\n    - Create a React Native example (uses a different storage type)\n    - Try more complex schema types\n    - Observe changes in records within DynamoDB (for instance, soft deletion).\n\n<!-- File: packages/datastore/docs/namespaces.md (Tokens: ~415 | Category: anthropic-skill) -->\n# Namespaces\n- `datastore`\n\t- Settings\n- `user` \n\t- Models that came from user schema\n- `sync` \n\t- Metadata (last time ran query, etc.)\n- `storage` \n\t- Deprecated\n# Local database examples:\n\n- *Note: Anything prepended with `sync_` is an internal table.*\n\n- ## datastore_Setting\n    - Used for schema versioning\n    - See the [schema changes doc](docs/schema-changes.md)\n    ```\n\t{\n\t\tid: \"01FYABF3DMBZZJ46W1CC214NH2\"\n\t\tkey: \"schemaVersion\"\n\t\tvalue: \"\\\"4401034582a70c60713e1f7f9da3b752\\\"\"\n\t}\n\t```\n- ## sync_ModelMetadata\n    - Sync Engine metadata\n\t- Includes information about the last time we synced a model\n\t```\n\t{\n\t\tfullSyncInterval: 86400000\n\t\tid: \"01FYABF3DMBZZJ46W1CC214NH3\"\n\t\tlastFullSync: 1647467532307\n\t\tlastSync: 1647467532307\n\t\tlastSyncPredicate: null\n\t\tmodel: \"Todo\"\n\t\tnamespace: \"user\"\n\t}\n\t```\n- ## sync_MutationEvent\n- ## user_[Model Name]\n    - The actual records themselves.\n\t```\n\t{\n\t\tcreatedAt: \"2022-03-16T21:52:07.718Z\"\n\t\tdescription: null\n\t\tid: \"6f69055b-b081-4225-8fc4-1d6d52732660\"\n\t\tname: \"name 1647467527489\"\n\t\tupdatedAt: \"2022-03-16T21:52:07.718Z\"\n\t\t_deleted: null\n\t\t_lastChangedAt: 1647467527754\n\t\t_version: 1\n\t}\n\t```\n\n<!-- File: packages/datastore/docs/observables.md (Tokens: ~166 | Category: anthropic-skill) -->\n# How DataStore uses Observables\n- All of DataStore internally uses event driven methods (observables) to handle everything from the sync process, to observing online connectivity. **This makes the Storage Engine the single source of truth for DataStore.**\n- Examples:\n\t- The Sync Engine observes DataStore Connectivity \n\t- The Sync Engine observes the Storage Engine \n    - The client observes DataStore with `observe` and `observeQuery`:\n\t\t- https://docs.amplify.aws/lib/datastore/real-time/q/platform/js/\n\n## Understanding Observables\n- DataStore uses [`zen-observable`](https://github.com/zenparsing/zen-observable)\n- [The RXJS docs](https://rxjs.dev/guide/observable) do a good job of describing observables in more detail.\n\n<!-- File: packages/datastore/docs/schema-changes.md (Tokens: ~179 | Category: anthropic-skill) -->\n# What happens when a user changes their schema?\n   - The `schema.js` file that exists within an Amplify project (located at `src/models/schema.js`) contains a version hash. \n   - This hash is compared against the hash stored in the `Settings` table of the local database. Example:\n       ```\n           {\n               id: \"01FYABF3DMBZZJ46W1CC214NH2\"\n               key: \"schemaVersion\"\n               value: \"\\\"4401034582a70c60713e1f7f9da3b752\\\"\"\n           }\n       ```\n   - The process of checking the schema version (`checkSchemaVersion`) occurs when DataStore starts, after the Storage Engine has been initialized, and before the Sync Engine is initialized.\n   - If the schema version has changed, we clear local storage, and perform a full sync\n\n<!-- File: packages/datastore/docs/storage.md (Tokens: ~522 | Category: anthropic-skill) -->\n# Storage\n## Adapters:\n- Web\n   - [IndexedDB](../src/storage/adapter/IndexedDBAdapter.ts)\n- Mobile\n   - React Native\n      - [Async Storage](../src/storage/adapter/AsyncStorageAdapter.ts) (can opt in to use SQLite)\n- SSR\n   - [InMemoryStore](../src/storage/adapter/InMemoryStore.ts)\n\n## How we determine which adapter to use\n\nWe determine the storage adapter [here](../src/storage/adapter/getDefaultAdapter/index.ts). \n\n\n## [The Storage class](../src/storage/storage.ts)\n- The Storage class is what interacts with the adapters.\n\n## [Storage Adapters](../src/storage/adapter)\n   1. There is one adapter per database type we support (i.e. three adapters).\n   2. Each adapter provides a unified API for the storage engine to interact with.\n   3. The SQLite adapter lives [in it’s own package](https://github.com/aws-amplify/amplify-js/tree/main/packages/datastore-storage-adapter).\n   4. **ExclusiveStorage wraps public storage methods (e.g. `Storage.runExclusive`)**\n      1. Guarantees consistency\n      2. Makes the storage class transactional\n      3. **Provides concurrency control**\n\n## How DataStore finds records locally:\n- Varies by storage adapter\n- [SQLiteAdapter](https://github.com/aws-amplify/amplify-js/tree/main/packages/datastore-storage-adapter): DataStore constructs a query. \n- [Async Storage](../src/storage/adapter/AsyncStorageAdapter.ts): DataStore scans and filters. \n- [IndexedDB](../src/storage/adapter/IndexedDBAdapter.ts): if the query is by primary key, DataStore queries against the index, otherwise it scans and filters.\n   - *Note: The lazy loading branch includes an improvement to the IndexedDB adapter that will check if any search criteria can leverage an index (there is no preference for low cardinality; the first identified index is used.) If so, the base result is sourced from the index and the remaining criteria will be applied as a filter.*\n\n## Understanding the difference between Save and Batch Save\n- As the names imply, `save` accepts a single record and persists it, while `batchSave` accepts a page of records and persists them all. `batchSave`, however, is *only used within the sync processor*, and will filter out deleted records from the sync page results, and then delete them from the local db.\n\n<!-- File: packages/datastore/docs/sync-engine.md (Tokens: ~1181 | Category: anthropic-skill) -->\n# Sync Engine\n\nSee [the sync class](packages/datastore/src/sync/index.ts)\n\n## High-level overview:\n- The first time DataStore is started on a new client, a full sync is performed. Subsequent reloads of the app (including browser refresh, or a new browser session) are delta syncs.\n- If it has been greater than the `fullSyncInterval` (configurable) since the client has performed a full sync, this operation occurs as a full sync.\n- The Sync Engine is well documented in the [DataStore Lifecycle Events doc](./datastore-lifecycle-events.md). The purpose of this doc is to explain anything about the sync process that is not already documented there.\n\n\n## Types of Syncs\n### Full Sync\n- All records are fetched from AppSync.\n\n### Delta Sync\n- All the records that changed after a given time stamp are fetched.\n\n## How it works\n\n### [Merger](../src/sync/merger.ts)\n- A helper class for merging subscription records with the outbox (checks IDs).\n- The Sync Engine uses merge in two places:\n\t- 1. https://github.com/aws-amplify/amplify-js/blob/main/packages/datastore/src/sync/index.ts#L289\n\t\t- Triggered by the mutation response. It gets called after the client that authored the change receives the network response of the mutation request they generated.\n\t- 2. https://github.com/aws-amplify/amplify-js/blob/main/packages/datastore/src/sync/index.ts#L326\n\t\t- Triggered by an AppSync real-time subscription event, which is how all clients get notified of the change. In the case of the mutation author, this notification is redundant, but it’s necessary for all other active users of the application. This is why there will always be multiple snapshot returned by `observe` and `observeQuery` in the case of the mutation author.\n\n- The function of [the Merger class](../src/sync/merger.ts) is to filter out any incoming records that have corresponding pending changes in that client’s mutation queue / outbox, and is done to maintain data consistency. We wouldn’t want to write over data that the client has deliberately changed, and essentially undo whatever changes were performed on that client - even temporarily. Thus, each time a change comes in via a mutation response, AppSync subscription, or sync query, **Merger will only persist that change to the local database when there is not a pending mutation for that same record**.\n- If there is a pending change in the outbox - we discard the incoming model we were working with inside the merge call (by not saving it). Later, when the record from the Outbox gets processed by AppSync (and conflict resolution rules are applied as appropriate), we will persist the response of the mutation (assuming we don’t change the record again in the interim)\n- If there is not a pending change in the outbox - we persist the model to the local store via `Storage.save` within `merge`.\n- _Note: We maintain a single instance of a mutation when we are offline (i.e. if we perform multiple updates on the same record, we merge them into a single event). Once we are online, but other mutations are processing, we'll still attempt to merge outgoing events into an existing one if they are not already in flight_\n- Merger Example:\n\t- User A updates record 1\n\t- The update to record 1 is persisted locally, and enters the mutation queue for persistence to Appsync\n\t- User B has not yet received the update to record 1, and updates record 1\n\t- User A receives User B's update to record 1, but has not yet sent the mutation to AppSync\n\t- If Merger did not first check the mutation queue prior to applying the change from User B, User A would see their update, then user B's update, then, depending on how the conflict is handled by AppSync, could then see their update again. Instead, User A sees their update, and rejects User B's update. Once the conflict is handled by AppSync, any changes that are received are then applied.\n- *How to locally test / step through Merger:* \n\t- Create a few records and make sure the records go out successfully and are persisted. Then, delete local data in IndexedDB (either by clicking the `clear` button in a sample, or through dev tools), then reload the page, or perform a query.\n- **Note: AppSync expects us to send only updated fields in order for merge to work correctly.**\n\n### [Outbox]((../src/sync/outbox.ts))\n- A mutation event outbox\n- Holds all local changes (even if you close the app). \n- Peek returns the next mutation event to be sent to AppSync, but does not remove it from the outbox.\n\n## [Processors](../src/sync/processors)\n- Sync Engine uses processors depending on the type of operation\n- All processors utilize observables\n- Where retry happens\n\n### Mutation Processor (Local changes)\n- Online or offline changes that were optimistically made to the Storage Engine (processed in mutation queue **one by one**).\n- Observes Storage Engine for new changes.\n\n### Subscription Processor (Remote changes)\n- Real-time subscription messages (such as another client performing a change).\n- Uses the Amplify API Graphql package (which then uses PubSub).\n### Sync Processor\n- When the client goes online, fetch all changes that were performed in AppSync (could be full or delta sync).\n\n## Misc:\n- AppSync records are soft-deleted and have a TTL. \n- TODO: special configurations around sync intervals\n\n<!-- File: packages/datastore/docs/workarounds.md (Tokens: ~11 | Category: anthropic-skill) -->\n# TODO: \"Unsupported hacks\" / Workarounds\n\n<!-- File: packages/adapter-nextjs/README.md (Tokens: ~150 | Category: plugin-manifest) -->\nThis package contains the AWS Amplify Next.js Adapter. For more information on using Next.js in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/javascript/build-a-backend/server-side-rendering/nextjs/).\n\n### Licensing Note\nAlthough this repository is released and licensed under the Apache License (see [LICENSE](./LICENSE)), its devDependencies transitively use the third party [sharp](https://sharp.pixelplumbing.com/) project.\n\nThe sharp projects prebuilt binaries' licensing includes [LGPL-2.1](https://opensource.org/license/LGPL-2.1) and [LGPL-3.0-or-later](https://opensource.org/license/LGPL-3.0) licenses\n\n<!-- File: packages/analytics/README.md (Tokens: ~51 | Category: plugin-manifest) -->\n> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify Analytics category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n\n<!-- File: packages/api-graphql/README.md (Tokens: ~52 | Category: plugin-manifest) -->\n> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify API GraphQL category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n\n<!-- File: packages/api-rest/README.md (Tokens: ~52 | Category: plugin-manifest) -->\n> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify API REST category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n\n<!-- File: packages/api/README.md (Tokens: ~51 | Category: plugin-manifest) -->\n> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify API category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n\n<!-- File: packages/auth/README.md (Tokens: ~51 | Category: plugin-manifest) -->\n> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify Auth category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n\n<!-- File: packages/aws-amplify/README.md (Tokens: ~108 | Category: plugin-manifest) -->\n# AWS Amplify Package - aws-amplify\n\nAWS Amplify is a JavaScript library for frontend and mobile developers building cloud-enabled applications. The library is a declarative interface across different categories of operations in order to make common tasks easier to add into your application. The default implementation works with Amazon Web Services (AWS) resources but is designed to be open and pluggable for usage with other cloud services that wish to provide an implementation or custom backends.\n\nDocumentation is available [here](https://docs.amplify.aws/javascript/).\n\n<!-- File: packages/core/__mocks__/configMocks/README.md (Tokens: ~39 | Category: plugin-manifest) -->\nThis directory contains equivalent Gen1 & Gen2 configurations which are used to validate interoperability between\ndifferent config versions/schemas. Make sure that any updates applied to one are applied to the other.\n\n<!-- File: packages/core/README.md (Tokens: ~51 | Category: plugin-manifest) -->\n> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify core utilities and is intended for internal use only. To integrate Amplify into your app. Please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n\n<!-- File: packages/datastore-storage-adapter/README.md (Tokens: ~64 | Category: plugin-manifest) -->\nThis package contains the AWS Amplify DataStore storage adapter. For more information on using the DataStore storage adapter in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/react-native/build-a-backend/more-features/datastore/set-up-datastore/#setup-local-development-environment).\n\n<!-- File: packages/datastore/__tests__/helpers/README.md (Tokens: ~341 | Category: plugin-manifest) -->\n## Helper functions for DataStore testing\n\nPlease try to keep things clean.\n\nIn particular, let's try to to keep file sizes smaller and more \"categorical\" in order to:\n\n1. Make finding and discovering test utils easier\n2. Reduce excessive vertical scrolling\n3. Reduce complexity of merge conflicts\n4. _<< And other awesome benefits I haven't thought of! >>_\n\nIntended organization is as follows:\n\n|                       | Intent                                                                                                                |\n| --------------------- | --------------------------------------------------------------------------------------------------------------------- |\n| `fakes/*`             | Util classes to inject and/or observe datastore's interaction with its boundaries, like cloud/graphql storage.        |\n| `schemas/*`           | Schema JSON and model types (Plenty of room for further refactoring and reorganization here!)                         |\n| `datastoreFactory.ts` | Function(s) for creating clean, test-configured initializations of DataStore and deps to test against.                |\n| `util.ts`             | Miscellaneous, mostly-isolated utility functions to aid with testing. (To be further decomposed as-needed over time.) |\n\nThere's almost always room to clean things up and do better. If you encounter a merge conflict that would have benefitted from chunks of code living separately; submit a refactor-only PR to separate them. If you get \"lost\" vertically scrolling in a file, look for a semantically meaningful boundary to separate on. If you can't find what you're looking for, consider whether another folder/category to drill into would have helped.\n\nIf you have any ideas around taming the rather large test schemas, making it easier to add new models and corresponding JSON, submit a PR with your idea! Etc..\n\nThanks!\n\n<!-- File: packages/datastore/README.md (Tokens: ~1577 | Category: plugin-manifest) -->\n> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify DataStore category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n\n# AWS Amplify DataStore Docs\n\n[Amplify DataStore](https://docs.amplify.aws/lib/datastore/getting-started/q/platform/js/) provides a programming model for leveraging shared and distributed data without writing additional code for offline and online scenarios, which makes working with distributed, cross-user data just as simple as working with local-only data.\n\n---\n\n| package                | version                                                         | open issues                                                                                                                                                                                  | closed issues                                                                                                                                                                                 |\n| ---------------------- | --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| @aws-amplify/datastore | ![npm](https://img.shields.io/npm/v/@aws-amplify/datastore.svg) | [![Open Issues](https://img.shields.io/github/issues/aws-amplify/amplify-js/DataStore?color=red)](https://github.com/aws-amplify/amplify-js/issues?q=is%3Aissue+label%3ADataStore+is%3Aopen) | [![Closed Issues](https://img.shields.io/github/issues-closed/aws-amplify/amplify-js/DataStore)](https://github.com/aws-amplify/amplify-js/issues?q=is%3Aissue+label%3ADataStore+is%3Aclosed) |\n\n---\n\n## **👋 Note For Contributers: 👋**\n\n_**Please update these docs any time you find something that is incorrect or lacking. In particular, if a line in the docs prompts a question, take a moment to figure out the answer, then update the docs with the necessary detail.**_\n\n---\n\n## Getting Started\n\nBefore you start reading through these docs, take a moment to understand [how DataStore works at a high level](https://docs.amplify.aws/lib/datastore/how-it-works/q/platform/js/). Additionally, we recommend first reading through [docs.amplify.aws](https://docs.amplify.aws/lib/datastore/getting-started/q/platform/js/). The purpose of these docs is to dive deep into the codebase itself and understand the inner workings of DataStore for the purpose of contributing. Understanding these docs is **not** necessary for using DataStore. Lastly, before reading, take a look at [the diagrams below](#diagrams).\n\n---\n\n## Docs\n\n- [Conflict Resolution](docs/conflict-resolution.md)\n- [Contributing](docs/contributing.md)\n- [DataStore Lifecycle Events (\"Start\", \"Stop\", \"Clear\")](docs/datastore-lifecycle-events.md)\n  - This explains how DataStore fundementally works, and is a great place to start.\n- [Getting Started](docs/getting-started.md) (Running against a sample app, etc.)\n- [Namespaces](docs/namespaces.md)\n- [How DataStore uses Observables](docs/observables.md)\n- [Schema Changes](docs/schema-changes.md)\n- [Storage](docs/storage.md)\n- [Sync Engine](docs/sync-engine.md)\n- [\"Unsupported hacks\" / workarounds](docs/workarounds.md)\n\n---\n\n# Diagrams\n\n_Note: relationships with dotted lines are explained more in a separate diagram._\n\n## How the DataStore API and Storage Engine Interact\n\n```mermaid\nflowchart TD\n  %% API and Storage\n  api[[DS API]]-- observe -->storage{Storage Engine}\n  storage-- next -->adapter[[Adapter]]\n  adapter-->db[[Local DB]]\n  db-->api\n  sync[[Sync Engine*]]-.-storage\n  sync-.-appSync[(AppSync)]\n```\n\n# How the Sync Engine Observes Changes in Storage and AppSync\n\n_Note: All green nodes belong to the Sync Engine._\n\n\\* Merger first checks outbox\n\n\\*\\* Outbox sends outgoing messages to AppSync\n\n```mermaid\nflowchart TD\n\n  subgraph SyncEngine\n  index{index.ts}-- observe -->reach[Core reachability]\n\n  subgraph processors\n  mp[Mutation Processor]\n  sp[Subscription Processor]\n  syp[Sync Processor]\n  end\n\n  reach--next-->mp[Mutation Processor]\n  reach--next-->sp[Subscription Processor]\n  reach--next-->syp[Sync Processor]\n\n  subgraph outbox / merger\n  outbox[Outbox]\n  merger[Merger]\n  outbox---merger\n  end\n\n  end\n\n  api[DS API]-.->storage\n  mp-- 1. observe -->storage{Storage Engine}\n  storage-- 2. next -->merger[merger*]-- next -->storage\n\n\n  sp-- observe -->appsync[(AppSync)]\n  appsync-- next -->sp\n\n  syp---appsync\n\n  mp-->outbox[outbox**]\n\n  appsync<--->outbox\n  %% styling\n  classDef syncEngineClass fill:#8FB,stroke:#333,stroke-width:4px,color:#333;\n  class index,mp,sp,syp,merger,outbox syncEngineClass;\n```\n\n---\n\n# Project Structure\n\n<pre>\namplify-js/packages/datastore/src\n├── authModeStrategies\n│   └── defaultAuthStraegy.ts\n│   └── index.ts\n│   └── multiAuthStrategy.ts\n├── datastore\n│   └── datastore.ts # Entry point for DataStore\n├── predicates\n│   └── index.ts\n│   └── sort.ts\n├── ssr\n├── storage # Storage Engine\n│   └── adapter # Platform-specific Storage Adapters\n│      └── getDefaultAdapter\n│      └── AsyncStorageAdapter.ts\n│      └── AsyncStorageDatabase.ts\n│      └── index.ts\n│      └── IndexedDBAdapter.ts\n│      └── InMemoryStore.native.ts\n│      └── InMemoryStore.ts\n│   └── storage.ts # Entry point for Storage\n├── sync # Sync Engine\n│   └── dataStoreReachability\n│      └── index.native.ts\n│      └── index.ts\n│   └── processors # Sync Engine Processors\n│      └── mutation.ts\n│      └── subscription.ts\n│      └── sync.ts\n│   └── datastoreConnectivity.ts # Subscribe to reachability monitor\n│   └── index.ts # Entry point for Sync Engine\n│   └── merger.ts # <a href=\"https://github.com/aws-amplify/amplify-js/blob/datastore-docs/packages/datastore/docs/sync-engine.md#merger\" title=\"merger doc\">doc</a>\n│   └── outbox.ts # <a href=\"https://github.com/aws-amplify/amplify-js/blob/datastore-docs/packages/datastore/docs/sync-engine.md#outbox\" title=\"outbox doc\">doc</a>\n</pre>\n\n---\n\n## Other Resources:\n\n- [High-level overview of how DataStore works](https://docs.amplify.aws/lib/datastore/how-it-works/q/platform/js/)\n- [DataStore Docs](https://docs.amplify.aws/lib/datastore/getting-started/q/platform/js/)\n- [re:Invent talk](https://www.youtube.com/watch?v=KcYl6_We0EU)\n\n<!-- File: packages/geo/README.md (Tokens: ~48 | Category: plugin-manifest) -->\nThis package contains the AWS Amplify Geo category. For more information on using Geo in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/javascript/build-a-backend/more-features/geo/).\n\n<!-- File: packages/interactions/README.md (Tokens: ~51 | Category: plugin-manifest) -->\nThis package contains the AWS Amplify Interactions category. For more information on using Interactions in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/javascript/build-a-backend/more-features/interactions/).\n\n<!-- File: packages/notifications/README.md (Tokens: ~51 | Category: plugin-manifest) -->\n> INTERNAL USE ONLY\n\nThis package contains the AWS Amplify Notifications category and is intended for internal use only. To integrate Amplify into your app, please use [aws-amplify](https://www.npmjs.com/package/aws-amplify).\n\n<!-- File: packages/predictions/README.md (Tokens: ~51 | Category: plugin-manifest) -->\nThis package contains the AWS Amplify Predictions category. For more information on using Predictions in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/javascript/build-a-backend/more-features/predictions/).\n\n<!-- File: packages/pubsub/README.md (Tokens: ~50 | Category: plugin-manifest) -->\nThis package contains the AWS Amplify PubSub category. For more information on using PubSub in your application please reference the [Amplify Dev Center](https://docs.amplify.aws/javascript/build-a-backend/more-features/pubsub/).\n\n<!-- File: packages/react-native/example/README.md (Tokens: ~308 | Category: plugin-manifest) -->\nThis is an example app for developing and testing the react-native modules located at `../`.\n\n# Getting Started\n\n> **Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till \"Creating a new application\" step, before proceeding.\n\n## Step 1: Start the Metro Server\n\nFirst, you will need to start **Metro**, the JavaScript _bundler_ that ships _with_ React Native.\n\nTo start Metro, run the following command from the _root_ of your React Native project:\n\n```bash\n# using npm\nnpm start\n\n# OR using Yarn\nyarn start\n```\n\n## Step 2: Start your Application\n\nLet Metro Bundler run in its _own_ terminal. Open a _new_ terminal from the _root_ of your React Native project. Run the following command to start your _Android_ or _iOS_ app:\n\n### For Android\n\n```bash\n# using npm\nnpm run android\n\n# OR using Yarn\nyarn android\n```\n\n### For iOS\n\n```bash\n# using npm\nnpm run ios\n\n# OR using Yarn\nyarn ios\n```\n\nIf everything is set up _correctly_, you should see your new app running in your _Android Emulator_ or _iOS Simulator_ shortly provided you have set up your emulator/simulator correctly.\n\nThis is one way to run your app — you can also run it directly from within Android Studio and Xcode respectively.\n\n<!-- ... +4 more modular skills available via /api/skills/aws-amplify/amplify-js?path={path} -->\n</yakaai_skills>"}