{"owner":"supabase","repo":"supabase-js","hasSkills":true,"totalSkillsCount":37,"totalTokensCount":53739,"categories":["anthropic-skill","claude-rule","mcp-config","root-instruction","plugin-manifest"],"hasMcp":true,"mcpConfig":{"mcpServers":{}},"found":[".agents/skills/link-workspace-packages/SKILL.md",".agents/skills/nx-generate/SKILL.md",".agents/skills/nx-import/SKILL.md",".agents/skills/nx-import/references/ESLINT.md",".agents/skills/nx-import/references/JEST.md",".agents/skills/nx-import/references/VITE.md",".agents/skills/nx-plugins/SKILL.md",".agents/skills/nx-run-tasks/SKILL.md",".agents/skills/nx-workspace/SKILL.md",".agents/skills/nx-workspace/references/AFFECTED.md",".claude/CLAUDE.md",".cursor/mcp.json","AGENTS.md","packages/core/auth-js/AGENTS.md","packages/core/auth-js/README.md","packages/core/auth-js/example/react/README.md","packages/core/auth-js/migrations/README.md","packages/core/auth-js/test/README.md","packages/core/functions-js/AGENTS.md","packages/core/functions-js/README.md","packages/core/functions-js/migrations/README.md","packages/core/postgrest-js/AGENTS.md","packages/core/postgrest-js/README.md","packages/core/postgrest-js/migrations/README.md","packages/core/realtime-js/AGENTS.md","packages/core/realtime-js/README.md","packages/core/realtime-js/example/README.md","packages/core/realtime-js/migrations/README.md","packages/core/storage-js/AGENTS.md","packages/core/storage-js/README.md","packages/core/storage-js/migrations/README.md","packages/core/supabase-js/AGENTS.md","packages/core/supabase-js/README.md","packages/core/supabase-js/migrations/README.md","packages/core/supabase-js/test/integration/expo/README.md","packages/core/supabase-js/test/integration/next/README.md","packages/shared/tracing/README.md"],"skills":{".agents/skills/link-workspace-packages/SKILL.md":"---\nname: link-workspace-packages\ndescription: 'Link workspace packages in monorepos (npm, yarn, pnpm, bun). USE WHEN: (1) you just created or generated new packages and need to wire up their dependencies, (2) user imports from a sibling package and needs to add it as a dependency, (3) you get resolution errors for workspace packages (@org/*) like \"cannot find module\", \"failed to resolve import\", \"TS2307\", or \"cannot resolve\". DO NOT patch around with tsconfig paths or manual package.json edits - use the package manager''s workspace commands to fix actual linking.'\n---\n\n# Link Workspace Packages\n\nAdd dependencies between packages in a monorepo. All package managers support workspaces but with different syntax.\n\n## Detect Package Manager\n\nCheck whether there's a `packageManager` field in the root-level `package.json`.\n\nAlternatively check lockfile in repo root:\n\n- `pnpm-lock.yaml` → pnpm\n- `yarn.lock` → yarn\n- `bun.lock` / `bun.lockb` → bun\n- `package-lock.json` → npm\n\n## Workflow\n\n1. Identify consumer package (the one importing)\n2. Identify provider package(s) (being imported)\n3. Add dependency using package manager's workspace syntax\n4. Verify symlinks created in consumer's `node_modules/`\n\n---\n\n## pnpm\n\nUses `workspace:` protocol - symlinks only created when explicitly declared.\n\n```bash\n# From consumer directory\npnpm add @org/ui --workspace\n\n# Or with --filter from anywhere\npnpm add @org/ui --filter @org/app --workspace\n```\n\nResult in `package.json`:\n\n```json\n{ \"dependencies\": { \"@org/ui\": \"workspace:*\" } }\n```\n\n---\n\n## yarn (v2+/berry)\n\nAlso uses `workspace:` protocol.\n\n```bash\nyarn workspace @org/app add @org/ui\n```\n\nResult in `package.json`:\n\n```json\n{ \"dependencies\": { \"@org/ui\": \"workspace:^\" } }\n```\n\n---\n\n## npm\n\nNo `workspace:` protocol. npm auto-symlinks workspace packages.\n\n```bash\nnpm install @org/ui --workspace @org/app\n```\n\nResult in `package.json`:\n\n```json\n{ \"dependencies\": { \"@org/ui\": \"*\" } }\n```\n\nnpm resolves to local workspace automatically during install.\n\n---\n\n## bun\n\nSupports `workspace:` protocol (pnpm-compatible).\n\n```bash\ncd packages/app && bun add @org/ui\n```\n\nResult in `package.json`:\n\n```json\n{ \"dependencies\": { \"@org/ui\": \"workspace:*\" } }\n```\n\n---\n\n## Examples\n\n**Example 1: pnpm - link ui lib to app**\n\n```bash\npnpm add @org/ui --filter @org/app --workspace\n```\n\n**Example 2: npm - link multiple packages**\n\n```bash\nnpm install @org/data-access @org/ui --workspace @org/dashboard\n```\n\n**Example 3: Debug \"Cannot find module\"**\n\n1. Check if dependency is declared in consumer's `package.json`\n2. If not, add it using appropriate command above\n3. Run install (`pnpm install`, `npm install`, etc.)\n\n## Notes\n\n- Symlinks appear in `<consumer>/node_modules/@org/<package>`\n- **Hoisting differs by manager:**\n  - npm/bun: hoist shared deps to root `node_modules`\n  - pnpm: no hoisting (strict isolation, prevents phantom deps)\n  - yarn berry: uses Plug'n'Play by default (no `node_modules`)\n- Root `package.json` should have `\"private\": true` to prevent accidental publish\n",".agents/skills/nx-generate/SKILL.md":"---\nname: nx-generate\ndescription: Generate code using nx generators. INVOKE IMMEDIATELY when user mentions scaffolding, setup, structure, creating apps/libs, or setting up project structure. Trigger words - scaffold, setup, create a ... app, create a ... lib, project structure, generate, add a new project. ALWAYS use this BEFORE calling nx_docs or exploring - this skill handles discovery internally.\nsubagent: general-purpose\ncontext: fork\n---\n\n# Run Nx Generator\n\nNx generators are powerful tools that scaffold projects, make automated code migrations or automate repetitive tasks in a monorepo. They ensure consistency across the codebase and reduce boilerplate work.\n\nThis skill applies when the user wants to:\n\n- Create new projects like libraries or applications\n- Scaffold features or boilerplate code\n- Run workspace-specific or custom generators\n- Do anything else that an nx generator exists for\n\n## Key Principles\n\n1. **Always use `--no-interactive`** - Prevents prompts that would hang execution\n2. **Read the generator source code** - The schema alone is not enough; understand what the generator actually does\n3. **Match existing repo patterns** - Study similar artifacts in the repo and follow their conventions\n4. **Verify with lint/test/build/typecheck etc.** - Generated code must pass verification. The listed targets are just an example, use what's appropriate for this workspace.\n\n## Steps\n\n### 1. Discover Available Generators\n\nUse the Nx CLI to discover available generators:\n\n- List all generators for a plugin: `npx nx list @nx/react`\n- View available plugins: `npx nx list`\n\nThis includes plugin generators (e.g., `@nx/react:library`) and local workspace generators.\n\n### 2. Match Generator to User Request\n\nIdentify which generator(s) could fulfill the user's needs. Consider what artifact type they want, which framework is relevant, and any specific generator names mentioned.\n\n**IMPORTANT**: When both a local workspace generator and an external plugin generator could satisfy the request, **always prefer the local workspace generator**. Local generators are customized for the specific repo's patterns.\n\nIf no suitable generator exists, you can stop using this skill. However, the burden of proof is high—carefully consider all available generators before deciding none apply.\n\n### 3. Get Generator Options\n\nUse the `--help` flag to understand available options:\n\n```bash\nnpx nx g @nx/react:library --help\n```\n\nPay attention to required options, defaults that might need overriding, and options relevant to the user's request.\n\n### Library Buildability\n\n**Default to non-buildable libraries** unless there's a specific reason for buildable.\n\n| Type                        | When to use                                                       | Generator flags                     |\n| --------------------------- | ----------------------------------------------------------------- | ----------------------------------- |\n| **Non-buildable** (default) | Internal monorepo libs consumed by apps                           | No `--bundler` flag                 |\n| **Buildable**               | Publishing to npm, cross-repo sharing, stable libs for cache hits | `--bundler=vite` or `--bundler=swc` |\n\nNon-buildable libs:\n\n- Export `.ts`/`.tsx` source directly\n- Consumer's bundler compiles them\n- Faster dev experience, less config\n\nBuildable libs:\n\n- Have their own build target\n- Useful for stable libs that rarely change (cache hits)\n- Required for npm publishing\n\n**If unclear, ask the user:** \"Should this library be buildable (own build step, better caching) or non-buildable (source consumed directly, simpler setup)?\"\n\n### 4. Read Generator Source Code\n\n**This step is critical.** The schema alone does not tell you everything. Reading the source code helps you:\n\n- Know exactly what files will be created/modified and where\n- Understand side effects (updating configs, installing deps, etc.)\n- Identify behaviors and options not obvious from the schema\n- Understand how options interact with each other\n\nTo find generator source code:\n\n- For plugin generators: Use `node -e \"console.log(require.resolve('@nx/<plugin>/generators.json'));\"` to find the generators.json, then locate the source from there\n- If that fails, read directly from `node_modules/<plugin>/generators.json`\n- For local generators: Typically in `tools/generators/` or a local plugin directory. Search the repo for the generator name.\n\nAfter reading the source, reconsider: Is this the right generator? If not, go back to step 2.\n\n> **⚠️ `--directory` flag behavior can be misleading.**\n> It should specify the full path of the generated library or component, not the parent path that it will be generated in.\n>\n> ```bash\n> # ✅ Correct - directory is the full path for the library\n> nx g @nx/react:library --directory=libs/my-lib\n> # generates libs/my-lib/package.json and more\n>\n> # ❌ Wrong - this will create files at libs and libs/src/...\n> nx g @nx/react:library --name=my-lib --directory=libs\n> # generates libs/package.json and more\n> ```\n\n### 5. Examine Existing Patterns\n\nBefore generating, examine the target area of the codebase:\n\n- Look at similar existing artifacts (other libraries, applications, etc.)\n- Identify naming conventions, file structures, and configuration patterns\n- Note which test runners, build tools, and linters are used\n- Configure the generator to match these patterns\n\n### 6. Dry-Run to Verify File Placement\n\n**Always run with `--dry-run` first** to verify files will be created in the correct location:\n\n```bash\nnpx nx g @nx/react:library --name=my-lib --dry-run --no-interactive\n```\n\nReview the output carefully. If files would be created in the wrong location, adjust your options based on what you learned from the generator source code.\n\nNote: Some generators don't support dry-run (e.g., if they install npm packages). If dry-run fails for this reason, proceed to running the generator for real.\n\n### 7. Run the Generator\n\nExecute the generator:\n\n```bash\nnx generate <generator-name> <options> --no-interactive\n```\n\n> **Tip:** New packages often need workspace dependencies wired up (e.g., importing shared types, being consumed by apps). The `link-workspace-packages` skill can help add these correctly.\n\n### 8. Modify Generated Code (If Needed)\n\nGenerators provide a starting point. Modify the output as needed to:\n\n- Add or modify functionality as requested\n- Adjust imports, exports, or configurations\n- Integrate with existing code patterns\n\n**Important:** If you replace or delete generated test files (e.g., `*.spec.ts`), either write meaningful replacement tests or remove the `test` target from the project configuration. Empty test suites will cause `nx test` to fail.\n\n### 9. Format and Verify\n\nFormat all generated/modified files:\n\n```bash\nnx format --fix\n```\n\nThis example is for built-in nx formatting with prettier. There might be other formatting tools for this workspace, use these when appropriate.\n\nThen verify the generated code works. Keep in mind that the changes you make with a generator or subsequent modifications might impact various projects so it's usually not enough to only run targets for the artifact you just created.\n\n```bash\n# these targets are just an example!\nnx run-many -t build,lint,test,typecheck\n```\n\nThese targets are common examples used across many workspaces. You should do research into other targets available for this workspace and its projects. CI configuration is usually a good guide for what the critical targets are that have to pass.\n\nIf verification fails with manageable issues (a few lint errors, minor type issues), fix them. If issues are extensive, attempt obvious fixes first, then escalate to the user with details about what was generated, what's failing, and what you've attempted.\n",".agents/skills/nx-import/SKILL.md":"---\nname: nx-import\ndescription: Import, merge, or combine repositories into an Nx workspace using nx import. USE WHEN the user asks to adopt Nx across repos, move projects into a monorepo, or bring code/history from another repository.\n---\n\n## Quick Start\n\n- `nx import` brings code from a source repository or folder into the current workspace, preserving commit history.\n- After nx `22.6.0`, `nx import` responds with .ndjson outputs and follow-up questions. For earlier versions, always run with `--no-interactive` and specify all flags directly.\n- Run `nx import --help` for available options.\n- Make sure the destination directory is empty before importing.\n  EXAMPLE: target has `libs/utils` and `libs/models`; source has `libs/ui` and `libs/data-access` — you cannot import `libs/` into `libs/` directly. Import each source library individually.\n\nPrimary docs:\n\n- https://nx.dev/docs/guides/adopting-nx/import-project\n- https://nx.dev/docs/guides/adopting-nx/preserving-git-histories\n\nRead the nx docs if you have the tools for it.\n\n## Import Strategy\n\n**Subdirectory-at-a-time** (`nx import <source> apps --source=apps`):\n\n- **Recommended for monorepo sources** — files land at top level, no redundant config\n- Caveats: multiple import commands (separate merge commits each); dest must not have conflicting directories; root configs (deps, plugins, targetDefaults) not imported\n- **Directory conflicts**: Import into alternate-named dir (e.g. `imported-apps/`), then rename\n\n**Whole repo** (`nx import <source> imported --source=.`):\n\n- **Only for non-monorepo sources** (single-project repos)\n- For monorepos, creates messy nested config (`imported/nx.json`, `imported/tsconfig.base.json`, etc.)\n- If you must: keep imported `tsconfig.base.json` (projects extend it), prefix workspace globs and executor paths\n\n### Directory Conventions\n\n- **Always prefer the destination's existing conventions.** Source uses `libs/`but dest uses `packages/`? Import into `packages/` (`nx import <source> packages/foo --source=libs/foo`).\n- If dest has no convention (empty workspace), ask the user.\n\n### Application vs Library Detection\n\nBefore importing, identify whether the source is an **application** or a **library**:\n\n- **Applications**: Deployable end products. Common indicators:\n  - _Frontend_: `next.config.*`, `vite.config.*` with a build entry point, framework-specific app scaffolding (CRA, Angular CLI app, etc.)\n  - _Backend (Node.js)_: Express/Fastify/NestJS server entrypoint, no `\"exports\"` field in `package.json`\n  - _JVM_: Maven `pom.xml` with `<packaging>jar</packaging>` or `<packaging>war</packaging>` and a `main` class; Gradle `application` plugin or `mainClass` setting\n  - _.NET_: `.csproj`/`.fsproj` with `<OutputType>Exe</OutputType>` or `<OutputType>WinExe</OutputType>`\n  - _General_: Dockerfile, a runnable entrypoint, no public API surface intended for import by other projects\n- **Libraries**: Reusable packages consumed by other projects. Common indicators: `\"main\"`/`\"exports\"` in `package.json`, Maven/Gradle packaging as a library jar, .NET `<OutputType>Library</OutputType>`, named exports intended for import by other packages.\n\n**Destination directory rules**:\n\n- Applications → `apps/<name>`. Check workspace globs (e.g. `pnpm-workspace.yaml`, `workspaces` in root `package.json`) for an existing `apps/*` entry.\n  - If `apps/*` is **not** present, add it before importing: update the workspace glob config and commit (or stage) the change.\n  - Example: `nx import <source> apps/my-app --source=packages/my-app`\n- Libraries → follow the dest's existing convention (`packages/`, `libs/`, etc.).\n\n## Common Issues\n\n### pnpm Workspace Globs (Critical)\n\n`nx import` adds the imported directory itself (e.g. `apps`) to `pnpm-workspace.yaml`, **NOT** glob patterns for packages within it. Cross-package imports will fail with `Cannot find module`.\n\n**Fix**: Replace with proper globs from the source config (e.g. `apps/*`, `libs/shared/*`), then `pnpm install`.\n\n### Root Dependencies and Config Not Imported (Critical)\n\n`nx import` does **NOT** merge from the source's root:\n\n- `dependencies`/`devDependencies` from `package.json`\n- `targetDefaults` from `nx.json` (e.g. `\"@nx/esbuild:esbuild\": { \"dependsOn\": [\"^build\"] }` — critical for build ordering)\n- `namedInputs` from `nx.json` (e.g. `production` exclusion patterns for test files)\n- Plugin configurations from `nx.json`\n\n**Fix**: Diff source and dest `package.json` + `nx.json`. Add missing deps, merge relevant `targetDefaults` and `namedInputs`.\n\n### TypeScript Project References\n\nAfter import, run `nx sync --yes`. If it reports nothing but typecheck still fails, `nx reset` first, then `nx sync --yes` again.\n\n### Explicit Executor Path Fixups\n\nInferred targets (via Nx plugins) resolve config relative to project root — no changes needed. Explicit executor targets (e.g. `@nx/esbuild:esbuild`) have workspace-root-relative paths (`main`, `outputPath`, `tsConfig`, `assets`, `sourceRoot`) that must be prefixed with the import destination directory.\n\n### Plugin Detection\n\n- **Whole-repo import**: `nx import` detects and offers to install plugins. Accept them.\n- **Subdirectory import**: Plugins NOT auto-detected. Manually add with `npx nx add @nx/PLUGIN`. Check `include`/`exclude` patterns — defaults won't match alternate directories (e.g. `apps-beta/`).\n- Run `npx nx reset` after any plugin config changes.\n\n### Redundant Root Files (Whole-Repo Only)\n\nWhole-repo import brings ALL source root files into the dest subdirectory. Clean up:\n\n- `pnpm-lock.yaml` — stale; dest has its own lockfile\n- `pnpm-workspace.yaml` — source workspace config; conflicts with dest\n- `node_modules/` — stale symlinks pointing to source filesystem\n- `.gitignore` — redundant with dest root `.gitignore`\n- `nx.json` — source Nx config; dest has its own\n- `README.md` — optional; keep or remove\n\n**Don't blindly delete** `tsconfig.base.json` — imported projects may extend it via relative paths.\n\n### Root ESLint Config Missing (Subdirectory Import)\n\nSubdirectory import doesn't bring the source's root `eslint.config.mjs`, but project configs reference `../../eslint.config.mjs`.\n\n**Fix order**:\n\n1. Install ESLint deps first: `pnpm add -wD eslint@^9 @nx/eslint-plugin typescript-eslint` (plus framework-specific plugins)\n2. Create root `eslint.config.mjs` (copy from source or create with `@nx/eslint-plugin` base rules)\n3. Then `npx nx add @nx/eslint` to register the plugin in `nx.json`\n\nInstall `typescript-eslint` explicitly — pnpm's strict hoisting won't auto-resolve this transitive dep of `@nx/eslint-plugin`.\n\n### ESLint Version Pinning (Critical)\n\n**Pin ESLint to v9** (`eslint@^9.0.0`). ESLint 10 breaks `@nx/eslint` and many plugins with cryptic errors like `Cannot read properties of undefined (reading 'version')`.\n\n`@nx/eslint` may peer-depend on ESLint 8, causing the wrong version to resolve. If lint fails with `Cannot read properties of undefined (reading 'allow')`, add `pnpm.overrides`:\n\n```json\n{ \"pnpm\": { \"overrides\": { \"eslint\": \"^9.0.0\" } } }\n```\n\n### Dependency Version Conflicts\n\nAfter import, compare key deps (`typescript`, `eslint`, framework-specific). If dest uses newer versions, upgrade imported packages to match (usually safe). If source is newer, may need to upgrade dest first. Use `pnpm.overrides` to enforce single-version policy if desired.\n\n### Module Boundaries\n\nImported projects may lack `tags`. Add tags or update `@nx/enforce-module-boundaries` rules.\n\n### Project Name Collisions (Multi-Import)\n\nSame `name` in `package.json` across source and dest causes `MultipleProjectsWithSameNameError`. **Fix**: Rename conflicting names (e.g. `@org/api` → `@org/teama-api`), update all dep references and import statements, `pnpm install`. The root `package.json` of each imported repo also becomes a project — rename those too.\n\n### Workspace Dep Import Ordering\n\n`pnpm install` fails during `nx import` if a `\"workspace:*\"` dependency hasn't been imported yet. File operations still succeed. **Fix**: Import all projects first, then `pnpm install --no-frozen-lockfile`.\n\n### `.gitkeep` Blocking Subdirectory Import\n\nThe TS preset creates `packages/.gitkeep`. Remove it and commit before importing.\n\n### Frontend tsconfig Base Settings (Critical)\n\nThe TS preset defaults (`module: \"nodenext\"`, `moduleResolution: \"nodenext\"`, `lib: [\"es2022\"]`) are incompatible with frontend frameworks (React, Next.js, Vue, Vite). After importing frontend projects, verify the dest root `tsconfig.base.json`:\n\n- **`moduleResolution`**: Must be `\"bundler\"` (not `\"nodenext\"`)\n- **`module`**: Must be `\"esnext\"` (not `\"nodenext\"`)\n- **`lib`**: Must include `\"dom\"` and `\"dom.iterable\"` (frontend projects need these)\n- **`jsx`**: `\"react-jsx\"` for React-only workspaces, per-project for mixed frameworks\n\nFor **subdirectory imports**, the dest root tsconfig is authoritative — update it. For **whole-repo imports**, imported projects may extend their own nested `tsconfig.base.json`, making this less critical.\n\nIf the dest also has backend projects needing `nodenext`, use per-project overrides instead of changing the root.\n\n**Gotcha**: TypeScript does NOT merge `lib` arrays — a project-level override **replaces** the base array entirely. Always include all needed entries (e.g. `es2022`, `dom`, `dom.iterable`) in any project-level `lib`.\n\n### `@nx/react` Typings for Libraries\n\nReact libraries generated with `@nx/react:library` reference `@nx/react/typings/cssmodule.d.ts` and `@nx/react/typings/image.d.ts` in their tsconfig `types`. These fail with `Cannot find type definition file` unless `@nx/react` is installed in the dest workspace.\n\n**Fix**: `pnpm add -wD @nx/react`\n\n### Jest Preset Missing (Subdirectory Import)\n\nNx presets create `jest.preset.js` at the workspace root, and project jest configs reference it (e.g. `../../jest.preset.js`). Subdirectory import does NOT bring this file.\n\n**Fix**:\n\n1. Run `npx nx add @nx/jest` — registers `@nx/jest/plugin` in `nx.json` and updates `namedInputs`\n2. Create `jest.preset.js` at workspace root (see `references/JEST.md` for content) — `nx add` only creates this when a generator runs, not on bare `nx add`\n3. Install test runner deps: `pnpm add -wD jest jest-environment-jsdom ts-jest @types/jest`\n4. Install framework-specific test deps as needed (see `references/JEST.md`)\n\nFor deeper Jest issues (tsconfig.spec.json, Babel transforms, CI atomization, Jest vs Vitest coexistence), see `references/JEST.md`.\n\n### Target Name Prefixing (Whole-Repo Import)\n\nWhen importing a project with existing npm scripts (`build`, `dev`, `start`, `lint`), Nx plugins auto-prefix inferred target names to avoid conflicts: e.g. `next:build`, `vite:build`, `eslint:lint`.\n\n**Fix**: Remove the Nx-rewritten npm scripts from the imported `package.json`, then either:\n\n- Accept the prefixed names (e.g. `nx run app:next:build`)\n- Rename plugin target names in `nx.json` to use unprefixed names\n\n## Non-Nx Source Issues\n\nWhen the source is a plain pnpm/npm workspace without `nx.json`.\n\n### npm Script Rewriting (Critical)\n\nNx rewrites `package.json` scripts during init, creating broken commands (e.g. `vitest run` → `nx test run`). **Fix**: Remove all rewritten scripts — Nx plugins infer targets from config files.\n\n### `noEmit` → `composite` + `emitDeclarationOnly` (Critical)\n\nPlain TS projects use `\"noEmit\": true`, incompatible with Nx project references.\n\n**Symptoms**: \"typecheck target is disabled because one or more project references set 'noEmit: true'\" or TS6310.\n\n**Fix** in **all** imported tsconfigs:\n\n1. Remove `\"noEmit\": true`. If inherited via extends chain, set `\"noEmit\": false` explicitly.\n2. Add `\"composite\": true`, `\"emitDeclarationOnly\": true`, `\"declarationMap\": true`\n3. Add `\"outDir\": \"dist\"` and `\"tsBuildInfoFile\": \"dist/tsconfig.tsbuildinfo\"`\n4. Add `\"extends\": \"../../tsconfig.base.json\"` if missing. Remove settings now inherited from base.\n\n### Stale node_modules and Lockfiles\n\n`nx import` may bring `node_modules/` (pnpm symlinks pointing to the source filesystem) and `pnpm-lock.yaml` from the source. Both are stale.\n\n**Fix**: `rm -rf imported/node_modules imported/pnpm-lock.yaml imported/pnpm-workspace.yaml imported/.gitignore`, then `pnpm install`.\n\n### ESLint Config Handling\n\n- **Legacy `.eslintrc.json` (ESLint 8)**: Delete all `.eslintrc.*`, remove v8 deps, create flat `eslint.config.mjs`.\n- **Flat config (`eslint.config.js`)**: Self-contained configs can often be left as-is.\n- **No ESLint**: Create both root and project-level configs from scratch.\n\n### TypeScript `paths` Aliases\n\nNx uses `package.json` `\"exports\"` + pnpm workspace linking instead of tsconfig `\"paths\"`. If packages have proper `\"exports\"`, paths are redundant. Otherwise, update paths for the new directory structure.\n\n## Technology-specific Guidance\n\nIdentify technologies in the source repo, then read and apply the matching reference file(s).\n\nAvailable references:\n\n- `references/ESLINT.md` — ESLint projects: duplicate `lint`/`eslint:lint` targets, legacy `.eslintrc.*` linting generated files, flat config `.cjs` self-linting, `typescript-eslint` v7/v9 peer dep conflict, mixed ESLint v8+v9 in one workspace.\n- `references/GRADLE.md`\n- `references/JEST.md` — Jest testing: `@nx/jest/plugin` setup, jest.preset.js, testing deps by framework, tsconfig.spec.json, Jest vs Vitest coexistence, Babel transforms, CI atomization.\n- `references/NEXT.md` — Next.js projects: `@nx/next/plugin` targets, `withNx`, Next.js TS config (`noEmit`, `jsx: \"preserve\"`), auto-installing deps via wrong PM, non-Nx `create-next-app` imports, mixed Next.js+Vite coexistence.\n- `references/TURBOREPO.md`\n- `references/VITE.md` — Vite projects (React, Vue, or both): `@nx/vite/plugin` typecheck target, `resolve.alias`/`__dirname` fixes, framework deps, Vue-specific setup, mixed React+Vue coexistence.\n",".agents/skills/nx-import/references/ESLINT.md":"## ESLint\n\nESLint-specific guidance for `nx import`. For generic import issues (root deps, pnpm globs, project references), see `SKILL.md`.\n\n---\n\n### How `@nx/eslint/plugin` Works\n\n`@nx/eslint/plugin` scans for ESLint config files and creates a lint target for each project. It detects **both** flat config files (`eslint.config.{js,mjs,cjs,ts,mts,cts}`) and legacy config files (`.eslintrc.{json,js,cjs,mjs,yml,yaml}`).\n\n**Plugin options (set during `nx add @nx/eslint`):**\n\n```json\n{\n  \"plugin\": \"@nx/eslint/plugin\",\n  \"options\": {\n    \"targetName\": \"eslint:lint\"\n  }\n}\n```\n\n**Auto-installation**: `nx import` auto-detects ESLint config files and offers to install `@nx/eslint`. Accept the offer — it registers the plugin and updates `namedInputs.production` to exclude ESLint config files.\n\n---\n\n### Duplicate `lint` and `eslint:lint` Targets\n\nAfter import, projects will have **two** lint-related targets if the source `package.json` has a `\"lint\"` npm script:\n\n- `eslint:lint` — inferred by `@nx/eslint/plugin`; has proper caching and input/output tracking\n- `lint` — created by Nx from the npm script via `nx:run-script`; no caching intelligence, just wraps `npm run lint`\n\n**Fix**: Remove the `\"lint\"` script from each project's `package.json`. Keep `\"lint:fix\"` if present — there is no plugin-inferred equivalent for auto-fixing.\n\n---\n\n### Legacy `.eslintrc.*` Configs Linting Generated Files\n\nWhen `@nx/eslint/plugin` runs `eslint .` on a project with a legacy `.eslintrc.*` config that uses `parserOptions.project`, it tries to lint **all** files in the project directory including:\n\n- Generated `dist/**/*.d.ts` files (not in tsconfig `include`)\n- The `.eslintrc.js` config file itself (not in tsconfig `include`)\n\nThis causes `Parsing error: ESLint was configured to run on X using parserOptions.project, however that TSConfig does not include this file`.\n\n**Fix**: Add `ignorePatterns` to the `.eslintrc.*` config:\n\n```json\n// .eslintrc.json\n{\n  \"ignorePatterns\": [\"dist/**\"]\n}\n```\n\n```js\n// .eslintrc.js — also ignore the config file itself since module.exports isn't in tsconfig\nmodule.exports = {\n  ignorePatterns: ['dist/**', '.eslintrc.js'],\n  // ...\n}\n```\n\n---\n\n### Flat Config `.cjs` Files Self-Linting\n\nWhen a project uses `eslint.config.cjs` (CJS flat config), `eslint .` lints the config file itself. The `require()` call on line 1 triggers `@typescript-eslint/no-require-imports`.\n\n**Fix**: Add the config filename to the top-level `ignores` array:\n\n```js\nmodule.exports = tseslint.config(\n  {\n    ignores: ['dist/**', 'node_modules/**', 'eslint.config.cjs'],\n  }\n  // ...\n)\n```\n\nThe same applies to `eslint.config.js` in a CJS project (no `\"type\": \"module\"`) if it uses `require()`.\n\n---\n\n### `typescript-eslint` Version Conflict With ESLint 9\n\n`typescript-eslint@7.x` declares `peerDependencies: { \"eslint\": \"^8.56.0\" }`, but it is commonly used alongside `\"eslint\": \"^9.0.0\"`. npm treats this as a hard peer dep conflict and refuses to install.\n\n**Root cause**: `@nx/eslint` init adds `eslint@~8.57.0` at the workspace root (for its own peer deps). Workspace packages that request `eslint@^9.0.0` + `typescript-eslint@^7.0.0` trigger the conflict when npm resolves their deps.\n\n**Fix**: Upgrade `typescript-eslint` from `^7.0.0` to `^8.0.0` directly in the affected workspace package's `package.json`. The `tseslint.config()` API and `tseslint.configs.recommended` are identical between v7 and v8 — no config changes needed.\n\n```json\n// packages/my-package/package.json\n{\n  \"devDependencies\": {\n    \"typescript-eslint\": \"^8.0.0\"\n  }\n}\n```\n\n**Note**: npm's root-level `\"overrides\"` field does not force versions for workspace packages' direct dependencies — update each package.json individually.\n\n---\n\n### Mixed ESLint v8 and v9 in One Workspace\n\nLegacy v8 and flat-config v9 packages can coexist in the same workspace. Each package resolves its own `eslint` version. The root `eslint@~8.57.0` (added by `@nx/eslint` init) is used by legacy v8 packages; v9 packages get their own hoisted `eslint@9`.\n\n`@nx/eslint/plugin` infers `eslint:lint` targets for **both** config formats. Legacy packages run ESLint v8 with `.eslintrc.*`; flat-config packages run ESLint v9 with `eslint.config.*`. No special nx.json configuration is needed to support both simultaneously.\n",".agents/skills/nx-import/references/JEST.md":"## Jest\n\nJest-specific guidance for `nx import`. For the basic \"Jest Preset Missing\" fix (create `jest.preset.js`, install deps), see `SKILL.md`. This file covers deeper Jest integration issues.\n\n---\n\n### How `@nx/jest` Works\n\n`@nx/jest/plugin` scans for `jest.config.{ts,js,cjs,mjs,cts,mts}` and creates a `test` target for each project.\n\n**Plugin options:**\n\n```json\n{\n  \"plugin\": \"@nx/jest/plugin\",\n  \"options\": {\n    \"targetName\": \"test\"\n  }\n}\n```\n\n`npx nx add @nx/jest` does two things:\n\n1. **Registers `@nx/jest/plugin` in `nx.json`** — without this, no `test` targets are inferred\n2. Updates `namedInputs.production` to exclude test files\n\n**Gotcha**: `nx add @nx/jest` does NOT create `jest.preset.js` — that file is only generated when you run a generator (e.g. `@nx/jest:configuration`). For imports, you must create it manually (see \"Jest Preset\" section below).\n\n**Other gotcha**: If you create `jest.preset.js` manually but skip `npx nx add @nx/jest`, the plugin won't be registered and `nx run PROJECT:test` will fail with \"Cannot find target 'test'\". You need both.\n\n---\n\n### Jest Preset\n\nThe preset provides shared Jest configuration (test patterns, ts-jest transform, resolver, jsdom environment).\n\n**Root `jest.preset.js`:**\n\n```js\nconst nxPreset = require('@nx/jest/preset').default\nmodule.exports = { ...nxPreset }\n```\n\n**Project `jest.config.ts`:**\n\n```ts\nexport default {\n  displayName: 'my-lib',\n  preset: '../../jest.preset.js',\n  // project-specific overrides\n}\n```\n\nThe `preset` path is relative from the project root to the workspace root. Subdirectory imports preserve the original relative path (e.g. `../../jest.preset.js`), which resolves correctly if the import destination matches the source directory depth.\n\n---\n\n### Testing Dependencies\n\n#### Core (always needed)\n\n```\npnpm add -wD jest ts-jest @types/jest @nx/jest\n```\n\n#### Environment-specific\n\n- **DOM testing** (React, Vue, browser libs): `jest-environment-jsdom`\n- **Node testing** (APIs, CLIs): no extra deps (Jest defaults to `node` env, but Nx preset defaults to `jsdom`)\n\n#### React testing\n\n```\npnpm add -wD @testing-library/react @testing-library/jest-dom\n```\n\n#### React with Babel (non-ts-jest transform)\n\nSome React projects use Babel instead of ts-jest for JSX transformation:\n\n```\npnpm add -wD babel-jest @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript\n```\n\n**When**: Project `jest.config` has `transform` using `babel-jest` instead of `ts-jest`. Common in older Nx workspaces and CRA migrations.\n\n#### Vue testing\n\n```\npnpm add -wD @vue/test-utils\n```\n\nVue projects typically use Vitest (not Jest) — see VITE.md.\n\n---\n\n### `tsconfig.spec.json`\n\nJest projects need a `tsconfig.spec.json` that includes test files:\n\n```json\n{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../../dist/out-tsc\",\n    \"module\": \"commonjs\",\n    \"types\": [\"jest\", \"node\"]\n  },\n  \"include\": [\"jest.config.ts\", \"src/**/*.test.ts\", \"src/**/*.spec.ts\", \"src/**/*.d.ts\"]\n}\n```\n\n**Common issues after import:**\n\n- Missing `\"types\": [\"jest\", \"node\"]` — causes `describe`/`it`/`expect` to be unrecognized\n- Missing `\"module\": \"commonjs\"` — Jest doesn't support ESM by default (ts-jest transpiles to CJS)\n- `include` array missing test patterns — TypeScript won't check test files\n\n---\n\n### Jest vs Vitest Coexistence\n\nWorkspaces can have both:\n\n- **Jest**: Next.js apps, older React libs, Node libraries\n- **Vitest**: Vite-based React/Vue apps and libs\n\nBoth `@nx/jest/plugin` and `@nx/vite/plugin` (which infers Vitest targets) coexist without conflicts — they detect different config files (`jest.config.*` vs `vite.config.*`).\n\n**Target naming**: Both default to `test`. If a project somehow has both config files, rename one:\n\n```json\n{\n  \"plugin\": \"@nx/jest/plugin\",\n  \"options\": { \"targetName\": \"jest-test\" }\n}\n```\n\n---\n\n### `@testing-library/jest-dom` — Jest vs Vitest\n\nProjects migrating from Jest to Vitest (or workspaces with both) need different imports:\n\n**Jest** (in `test-setup.ts`):\n\n```ts\nimport '@testing-library/jest-dom'\n```\n\n**Vitest** (in `test-setup.ts`):\n\n```ts\nimport '@testing-library/jest-dom/vitest'\n```\n\nIf the source used Jest but the dest workspace uses Vitest for that project type, update the import path. Also add `@testing-library/jest-dom` to tsconfig `types` array.\n\n---\n\n### Non-Nx Source: Test Script Rewriting\n\nNx rewrites `package.json` scripts during init. Test scripts get broken:\n\n- `\"test\": \"jest\"` → `\"test\": \"nx test\"` (circular if no executor configured)\n- `\"test\": \"vitest run\"` → `\"test\": \"nx test run\"` (broken — `run` becomes an argument)\n\n**Fix**: Remove all rewritten test scripts. `@nx/jest/plugin` and `@nx/vite/plugin` infer test targets from config files.\n\n---\n\n### CI Atomization\n\n`@nx/jest/plugin` supports splitting tests per-file for CI parallelism:\n\n```json\n{\n  \"plugin\": \"@nx/jest/plugin\",\n  \"options\": {\n    \"targetName\": \"test\",\n    \"ciTargetName\": \"test-ci\"\n  }\n}\n```\n\nThis creates `test-ci--src/lib/foo.spec.ts` targets for each test file, enabling Nx Cloud distribution. Not relevant during import, but useful for post-import CI setup.\n\n---\n\n### Common Post-Import Issues\n\n1. **\"Cannot find target 'test'\"**: `@nx/jest/plugin` not registered in `nx.json`. Run `npx nx add @nx/jest` or manually add the plugin entry.\n\n2. **\"Cannot find module 'jest-preset'\"**: `jest.preset.js` missing at workspace root. Create it (see SKILL.md).\n\n3. **\"Cannot find type definition file for 'jest'\"**: Missing `@types/jest` or `tsconfig.spec.json` doesn't have `\"types\": [\"jest\", \"node\"]`.\n\n4. **Tests fail with \"Cannot use import statement outside a module\"**: `ts-jest` not installed or not configured as transform. Check `jest.config.ts` transform section.\n\n5. **Snapshot path mismatches**: After import, `__snapshots__` directories may have paths baked in. Run tests once with `--updateSnapshot` to regenerate.\n\n---\n\n## Fix Order\n\n### Subdirectory Import (Nx Source)\n\n1. `npx nx add @nx/jest` — registers plugin in `nx.json` (does NOT create `jest.preset.js`)\n2. Create `jest.preset.js` manually (see \"Jest Preset\" section above)\n3. Install deps: `pnpm add -wD jest jest-environment-jsdom ts-jest @types/jest`\n4. Install framework test deps: `@testing-library/react @testing-library/jest-dom` (React), `@vue/test-utils` (Vue)\n5. Verify `tsconfig.spec.json` has `\"types\": [\"jest\", \"node\"]`\n6. `nx run-many -t test`\n\n### Whole-Repo Import (Non-Nx Source)\n\n1. Remove rewritten test scripts from `package.json`\n2. `npx nx add @nx/jest` — registers plugin (does NOT create preset)\n3. Create `jest.preset.js` manually\n4. Install deps (same as above)\n5. Verify/fix `jest.config.*` — ensure `preset` path points to root `jest.preset.js`\n6. Verify/fix `tsconfig.spec.json` — add `types`, `module`, `include` if missing\n7. `nx run-many -t test`\n",".agents/skills/nx-import/references/VITE.md":"## Vite\n\nVite-specific guidance for `nx import`. For generic import issues (pnpm globs, root deps, project references, name collisions, ESLint, frontend tsconfig base settings, `@nx/react` typings, Jest preset, non-Nx source handling), see `SKILL.md`.\n\n---\n\n### `@nx/vite/plugin` Typecheck Target\n\n`@nx/vite/plugin` defaults `typecheckTargetName` to `\"vite:typecheck\"`. If the workspace expects `\"typecheck\"`, set it explicitly in `nx.json`. If `@nx/js/typescript` is also registered, rename one target to avoid conflicts (e.g. `\"tsc-typecheck\"` for the JS plugin).\n\nKeep both plugins only if the workspace has non-Vite pure TS libraries — `@nx/js/typescript` handles those while `@nx/vite/plugin` handles Vite projects.\n\n### @nx/vite Plugin Install Failure\n\nPlugin init loads `vite.config.ts` before deps are available. **Fix**: `pnpm add -wD vite @vitejs/plugin-react` (or `@vitejs/plugin-vue`) first, then `pnpm exec nx add @nx/vite`.\n\n### Vite `resolve.alias` and `__dirname` (Non-Nx Sources)\n\n**`__dirname` undefined** (CJS-only): Replace with `fileURLToPath(new URL('./src', import.meta.url))` from `'node:url'`.\n\n**`@/` path alias**: Vite's `resolve.alias` works at runtime but TS needs matching `\"paths\"`. Set `\"baseUrl\": \".\"` in project tsconfig.\n\n**PostCSS/Tailwind**: Verify `content` globs resolve correctly after import.\n\n### Missing TypeScript `types` (Non-Nx Sources)\n\nNon-Nx tsconfigs may not declare all needed types. Ensure Vite projects include `\"types\": [\"node\", \"vite/client\"]` in their tsconfig.\n\n### `noEmit` Fix: Vite-Specific Notes\n\nSee SKILL.md for the generic noEmit→composite fix. Vite-specific additions:\n\n- Non-Nx Vite projects often have **both** `tsconfig.app.json` and `tsconfig.node.json` with `noEmit` — fix both\n- Solution-style tsconfigs (`\"files\": [], \"references\": [...]`) may lack `extends`. Add `extends` pointing to the dest root `tsconfig.base.json` so base settings (`moduleResolution`, `lib`) apply.\n- This is safe — Vite/Vitest ignore TypeScript emit settings.\n\n### Dependency Version Conflicts\n\n**Shared Vite deps (both frameworks):** `vite`, `vitest`, `jsdom`, `@types/node`, `typescript` (dev)\n\n**Vite 6→7**: Typecheck fails (`Plugin<any>` type mismatch); build/serve still works. Fix: align versions.\n**Vitest 3→4**: Usually works; type conflicts may surface in shared test utils.\n\n---\n\n## React Router 7 (Vite-Based)\n\nReact Router 7 (`@react-router/dev`) uses Vite under the hood with a `vite.config.ts` and a `react-router.config.ts`. The `@nx/vite/plugin` detects `vite.config.ts` and creates inferred targets.\n\n### Targets\n\n`@nx/vite/plugin` creates `build`, `dev`, `serve` targets. The `build` target invokes the script defined in `package.json` (usually `react-router build`), not `vite build` directly.\n\n**No separate typecheck target from `@nx/vite/plugin`** — React Router 7 typegen is run as part of `typecheck` (e.g. `react-router typegen && tsc`). The `typecheck` target is inferred from the tsconfig. Keep the `typecheck` script in `package.json` if present; it is not rewritten.\n\n### tsconfig Notes\n\nReact Router 7 uses a single `tsconfig.json` (no `tsconfig.app.json`/`tsconfig.node.json` split). It includes:\n\n- `\"rootDirs\": [\".\", \"./.react-router/types\"]` — for generated type files; keep as-is\n- `\"paths\": { \"~/*\": [\"./app/*\"] }` — self-referential alias; keep as-is\n- `\"noEmit\": true` — replace with composite settings per SKILL.md\n\n### Build Output\n\nReact Router 7 outputs to `build/` (not `dist/`). Add `build` to the dest root `.gitignore`.\n\n### Generated Types Directory\n\nReact Router 7 generates `.react-router/` at the project root for route type generation. Add `.react-router` to the dest root `.gitignore`.\n\n---\n\n## TanStack Start (Vite-Based)\n\nTanStack Start uses Vinxi under the hood, which wraps Vite. Projects have a standard `vite.config.ts` that `@nx/vite/plugin` detects normally.\n\n### Targets\n\n`@nx/vite/plugin` creates `build`, `dev`, `preview`, `serve-static`, `typecheck` targets. The `build` target runs `vite build` which invokes the TanStack Start Vinxi pipeline (produces both client and SSR bundles).\n\n### tsconfig Notes\n\nTanStack Start uses a single `tsconfig.json` with `\"allowImportingTsExtensions\": true` and `\"noEmit\": true`. Apply the standard noEmit → composite fix. `allowImportingTsExtensions` is compatible with `emitDeclarationOnly: true` — no change needed.\n\n### `paths` Aliases\n\nTanStack Start commonly uses `\"#/*\": [\"./src/*\"]` and `\"@/*\": [\"./src/*\"]`. These are self-referential — keep as-is for a single-project app.\n\n### Uncommitted Source Repo\n\n`create-tan-stack` initializes a git repo but does NOT make an initial commit. Before importing, commit first:\n\n```bash\ngit -C /path/to/source add . && git -C /path/to/source commit -m \"Initial commit\"\n```\n\n### Generated and Build Directories\n\nTanStack Start / Vinxi / Nitro generate several directories that must be added to the dest root `.gitignore`:\n\n- `.vinxi` — Vinxi build cache\n- `.tanstack` — TanStack generated files\n- `.nitro` — Nitro build artifacts\n- `.output` — server-side build output (SSR/edge)\n\nThese are not covered by `dist` or `build`.\n\n---\n\n## React-Specific\n\n### React Dependencies\n\n**Production:** `react`, `react-dom`\n**Dev:** `@types/react`, `@types/react-dom`, `@vitejs/plugin-react`, `@testing-library/react`, `@testing-library/jest-dom`, `jsdom`\n**ESLint (Nx sources):** `eslint-plugin-import`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`, `eslint-plugin-react-hooks`\n**ESLint (`create-vite`):** `eslint-plugin-react-refresh`, `eslint-plugin-react-hooks` — self-contained flat configs can be left as-is\n**Nx plugins:** `@nx/react` (generators), `@nx/vite`, `@nx/vitest`, `@nx/eslint`\n\n### React TypeScript Configuration\n\nAdd `\"jsx\": \"react-jsx\"` — in `tsconfig.base.json` for single-framework workspaces, per-project for mixed (see Mixed section).\n\n### React ESLint Config\n\n```js\nimport nx from '@nx/eslint-plugin'\nimport baseConfig from '../../eslint.config.mjs'\nexport default [\n  ...baseConfig,\n  ...nx.configs['flat/react'],\n  { files: ['**/*.ts', '**/*.tsx'], rules: {} },\n]\n```\n\n### React Version Conflicts\n\nReact 18 (source) + React 19 (dest): pnpm may hoist mismatched `react-dom`, causing `TypeError: Cannot read properties of undefined (reading 'S')`. **Fix**: Align versions with `pnpm.overrides`.\n\n### `@testing-library/jest-dom` with Vitest\n\nIf source used Jest: change import to `@testing-library/jest-dom/vitest` in test-setup.ts, add to tsconfig `types`.\n\n---\n\n## Vue-Specific\n\n### Vue Dependencies\n\n**Production:** `vue` (plus `vue-router`, `pinia` if used)\n**Dev:** `@vitejs/plugin-vue`, `vue-tsc`, `@vue/test-utils`, `jsdom`\n**ESLint:** `eslint-plugin-vue`, `vue-eslint-parser`, `@vue/eslint-config-typescript`, `@vue/eslint-config-prettier`\n**Nx plugins:** `@nx/vue` (generators), `@nx/vite`, `@nx/vitest`, `@nx/eslint` (install AFTER deps — see below)\n\n### Vue TypeScript Configuration\n\nAdd to `tsconfig.base.json` (single-framework) or per-project (mixed):\n\n```json\n{ \"jsx\": \"preserve\", \"jsxImportSource\": \"vue\", \"resolveJsonModule\": true }\n```\n\n### `vue-shims.d.ts`\n\nVue SFC files need a type declaration. Usually exists in each project's `src/` and imports cleanly. If missing:\n\n```ts\ndeclare module '*.vue' {\n  import { defineComponent } from 'vue'\n  const component: ReturnType<typeof defineComponent>\n  export default component\n}\n```\n\n### `vue-tsc` Auto-Detection\n\nBoth `@nx/js/typescript` and `@nx/vite/plugin` auto-detect `vue-tsc` when installed — no manual config needed. Remove source scripts like `\"typecheck\": \"vue-tsc --noEmit\"`.\n\n### ESLint Plugin Installation Order (Critical)\n\n`@nx/eslint` init **crashes** if Vue ESLint deps aren't installed first (it loads all config files).\n\n**Correct order:**\n\n1. `pnpm add -wD eslint@^9 eslint-plugin-vue vue-eslint-parser @vue/eslint-config-typescript @typescript-eslint/parser @nx/eslint-plugin typescript-eslint`\n2. Create root `eslint.config.mjs`\n3. Then `npx nx add @nx/eslint`\n\n### Vue ESLint Config Pattern\n\n```js\nimport vue from 'eslint-plugin-vue'\nimport vueParser from 'vue-eslint-parser'\nimport tsParser from '@typescript-eslint/parser'\nimport baseConfig from '../../eslint.config.mjs'\nexport default [\n  ...baseConfig,\n  ...vue.configs['flat/recommended'],\n  {\n    files: ['**/*.vue'],\n    languageOptions: { parser: vueParser, parserOptions: { parser: tsParser } },\n  },\n  {\n    files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.vue'],\n    rules: { 'vue/multi-word-component-names': 'off' },\n  },\n]\n```\n\n**Important**: `vue-eslint-parser` override must come **AFTER** base config — `flat/typescript` sets the TS parser globally without a `files` filter, breaking `.vue` parsing.\n\n`vue-eslint-parser` must be an explicit pnpm dependency (strict resolution prevents transitive import).\n\n**Known issue**: Some generated Vue ESLint configs omit `vue-eslint-parser`. Use the pattern above instead.\n\n---\n\n## Mixed React + Vue\n\nWhen both frameworks coexist, several settings become per-project.\n\n### tsconfig `jsx` — Per-Project Only\n\n- React: `\"jsx\": \"react-jsx\"` in project tsconfig\n- Vue: `\"jsx\": \"preserve\"`, `\"jsxImportSource\": \"vue\"` in project tsconfig\n- Root: **NO** `jsx` setting\n\n### Typecheck — Auto-Detects Framework\n\n`@nx/vite/plugin` uses `vue-tsc` for Vue projects and `tsc` for React automatically.\n\n```json\n{\n  \"plugins\": [\n    { \"plugin\": \"@nx/eslint/plugin\", \"options\": { \"targetName\": \"lint\" } },\n    {\n      \"plugin\": \"@nx/vite/plugin\",\n      \"options\": {\n        \"buildTargetName\": \"build\",\n        \"typecheckTargetName\": \"typecheck\",\n        \"testTargetName\": \"test\"\n      }\n    }\n  ]\n}\n```\n\nRemove `@nx/js/typescript` if all projects use Vite. Keep it (renamed to `\"tsc-typecheck\"`) only for non-Vite pure TS libs.\n\n### ESLint — Three-Tier Config\n\n1. **Root**: Base rules only, no framework-specific rules\n2. **React projects**: Extend root + `nx.configs['flat/react']`\n3. **Vue projects**: Extend root + `vue.configs['flat/recommended']` + `vue-eslint-parser`\n\n**Required packages**: Shared (`eslint@^9`, `@nx/eslint-plugin`, `typescript-eslint`, `@typescript-eslint/parser`), React (`eslint-plugin-import`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`, `eslint-plugin-react-hooks`), Vue (`eslint-plugin-vue`, `vue-eslint-parser`)\n\n`@nx/react`/`@nx/vue` are for generators only — no target conflicts.\n\n---\n\n## Redundant npm Scripts After Import\n\n`nx import` copies `package.json` verbatim, so npm scripts come along. For Vite-based projects `@nx/vite/plugin` already infers the same targets from `vite.config.ts` — the npm scripts just shadow the plugin with weaker `nx:run-script` wrappers (no first-class caching inputs/outputs). Remove them after import.\n\n### Standalone Vite App (`create-vite`)\n\nRemove the following scripts — every one is redundant:\n\n| Script                        | Plugin replacement                                                           |\n| ----------------------------- | ---------------------------------------------------------------------------- |\n| `dev: vite`                   | `@nx/vite/plugin` → `dev`                                                    |\n| `build: tsc -b && vite build` | `@nx/vite/plugin` → `build`; `typecheck` via `@nx/js/typescript` handles tsc |\n| `preview: vite preview`       | `@nx/vite/plugin` → `preview`                                                |\n| `lint: eslint .`              | `@nx/eslint/plugin` → `eslint:lint`                                          |\n\n### TanStack Start\n\nRemove `build`, `dev`, `preview`, and `test` scripts, but move any hardcoded `--port` flag to `vite.config.ts` first:\n\n```ts\n// vite.config.ts\nexport default defineConfig({\n  server: { port: 3000 },  // replaces `vite dev --port 3000`\n  ...\n})\n```\n\n### React Router 7 — Keep ALL scripts\n\nDo **not** remove React Router 7 scripts. They use the framework CLI (`react-router build`, `react-router dev`, `react-router-serve`) which is not interchangeable with plain `vite`:\n\n- `typecheck` runs `react-router typegen && tsc` — typegen must precede `tsc` or it fails on missing route types\n- `start` serves the SSR bundle — no plugin equivalent\n\n---\n\n## Fix Orders\n\n### Nx Source\n\n1. Generic fixes from SKILL.md (pnpm globs, root deps, executor paths, frontend tsconfig base settings, `@nx/react` typings)\n2. Configure `@nx/vite/plugin` typecheck target\n3. **React**: `jsx: \"react-jsx\"` (root or per-project)\n4. **Vue**: `jsx: \"preserve\"` + `jsxImportSource: \"vue\"`; verify `vue-shims.d.ts`; install ESLint deps before `@nx/eslint`\n5. **Mixed**: `jsx` per-project; remove/rename `@nx/js/typescript`\n6. `nx sync --yes && nx reset && nx run-many -t typecheck,build,test,lint`\n\n### Non-Nx Source (additional steps)\n\n0. Import into `apps/<name>` (see SKILL.md: \"Application vs Library Detection\")\n1. Generic fixes from SKILL.md (stale files cleanup, pnpm globs, rewritten scripts, target name prefixing, noEmit→composite, ESLint handling)\n2. Fix `noEmit` in **all** tsconfigs (app, node, etc. — non-Nx projects often have multiple)\n3. Add `extends` to solution-style tsconfigs so root settings apply\n4. Fix `resolve.alias` / `__dirname` / `baseUrl`\n5. Ensure `types` include `vite/client` and `node`\n6. Install `@nx/vite` manually if it failed during import\n7. Remove redundant npm scripts so `@nx/vite/plugin` infers them natively (see \"Redundant npm Scripts\" section)\n8. **Vue**: Add `outDir` + `**/*.vue.d.ts` to ESLint ignores\n9. Full verification\n\n### Multiple-Source Imports\n\nSee SKILL.md for generic multi-import (name collisions, dep refs). Vite-specific: fix tsconfig `references` paths for alternate directories (`../../libs/` → `../../libs-beta/`).\n\n### Non-Nx Source: React Router 7\n\n1. Ensure source has at least one commit (see SKILL.md: \"Source Repo Has No Commits\")\n2. `nx import` whole-repo into `apps/<name>` (see SKILL.md: \"Application vs Library Detection\") → auto-installs `@nx/vite`, `@nx/react`\n3. Stale file cleanup: `node_modules/`, `package-lock.json`, `.gitignore`\n4. Fix `tsconfig.json`: `noEmit` → `composite + emitDeclarationOnly + outDir + tsBuildInfoFile`\n5. Add `build` and `.react-router` to dest root `.gitignore`\n6. **Keep all npm scripts** — React Router 7 uses framework CLI (`react-router build/dev`), not plain vite (see \"Redundant npm Scripts\" above)\n7. `npm install && nx reset && nx sync --yes`\n\n### Non-Nx Source: TanStack Start\n\n1. Ensure source has at least one commit — `create-tan-stack` does NOT auto-commit (see SKILL.md)\n2. `nx import` whole-repo into `apps/<name>` (see SKILL.md: \"Application vs Library Detection\") → auto-installs `@nx/vite`, `@nx/vitest`\n3. Stale file cleanup: `node_modules/`, `package-lock.json`, `.gitignore`\n4. Fix `tsconfig.json`: `noEmit` → `composite + emitDeclarationOnly + outDir + tsBuildInfoFile`\n5. Keep `allowImportingTsExtensions` — compatible with `emitDeclarationOnly: true`\n6. Add `.vinxi`, `.tanstack`, `.nitro`, `.output` to dest root `.gitignore`\n7. Move hardcoded `--port` from `dev` script into `vite.config.ts` (`server: { port: N }`)\n8. Remove redundant npm scripts — `@nx/vite/plugin` infers `build`, `dev`, `preview`, `test` (see \"Redundant npm Scripts\" above)\n9. `npm install && nx reset && nx sync --yes`\n\n### Quick Reference: React vs Vue\n\n| Aspect        | React                    | Vue                                       |\n| ------------- | ------------------------ | ----------------------------------------- |\n| Vite plugin   | `@vitejs/plugin-react`   | `@vitejs/plugin-vue`                      |\n| Type checker  | `tsc`                    | `vue-tsc` (auto-detected)                 |\n| SFC support   | N/A                      | `vue-shims.d.ts` needed                   |\n| tsconfig jsx  | `\"react-jsx\"`            | `\"preserve\"` + `\"jsxImportSource\": \"vue\"` |\n| ESLint parser | Standard TS              | `vue-eslint-parser` + TS sub-parser       |\n| ESLint setup  | Straightforward          | Must install deps before `@nx/eslint`     |\n| Test utils    | `@testing-library/react` | `@vue/test-utils`                         |\n\n### Quick Reference: Vite-Based React Frameworks\n\n| Aspect             | Vite (standalone) | React Router 7          | TanStack Start           |\n| ------------------ | ----------------- | ----------------------- | ------------------------ |\n| Build config       | `vite.config.ts`  | `vite.config.ts`        | `vite.config.ts`         |\n| Build output       | `dist/`           | `build/`                | `dist/`                  |\n| SSR bundle         | No                | Yes (`build/server/`)   | Yes (`dist/server/`)     |\n| tsconfig layout    | app + node split  | Single tsconfig         | Single tsconfig          |\n| Auto-committed     | Depends on tool   | Usually yes             | **No — commit first**    |\n| `nx import` plugin | `@nx/vite`        | `@nx/vite`, `@nx/react` | `@nx/vite`, `@nx/vitest` |\n\n---\n\n## Iteration Log\n\n### Scenario 6: Multiple non-Nx React apps (CRA, Next.js, React Router 7, TanStack Start, Vite) → TS preset (PASS)\n\n- Sources: 5 standalone non-Nx repos with different build tools\n- Dest: CNW ts preset (Nx 22.5.1), npm workspaces, `packages/*`\n- Import: whole-repo for each, sequential into `packages/<name>`\n- Pre-import fixes:\n  1. Removed `packages/.gitkeep` and committed\n  2. `git init && git add . && git commit` in Vite app (no git at all)\n  3. `git add . && git commit` in TanStack app (git init'd but no commits)\n- Import: `npm exec nx -- import <source> packages/<name> --source=. --ref=main --no-interactive`\n  - Next.js import auto-installed `@nx/eslint`, `@nx/next`\n  - React Router 7 import auto-installed `@nx/vite`, `@nx/react`, `@nx/docker` (Dockerfile present)\n  - TanStack import auto-installed `@nx/vitest`\n- Post-import fixes:\n  1. Removed stale `node_modules/`, `package-lock.json`, `.gitignore` from each package\n  2. Removed Nx-rewritten scripts from `board-games-nextjs/package.json` (had `\"build\": \"nx next:build\"`, etc.)\n  3. Updated root `tsconfig.base.json`: `nodenext` → `bundler`, added `dom`/`dom.iterable` to lib, added `jsx: react-jsx`\n  4. Added `build` to dest root `.gitignore` (CRA and React Router 7 output there)\n  5. Fixed `noEmit` → `composite + emitDeclarationOnly` in: `board-games-vite/tsconfig.app.json`, `board-games-vite/tsconfig.node.json`, `board-games-react-router/tsconfig.json`, `board-games-tanstack/tsconfig.json`\n  6. Fixed `tsBuildInfoFile` paths from `./node_modules/.tmp/...` to `./dist/...`\n  7. Installed root `@types/react`, `@types/react-dom`, `@types/node`\n- All targets green: `build` for all 5 projects; `typecheck` for Vite/React Router/TanStack; `next:build` for Next.js\n",".agents/skills/nx-plugins/SKILL.md":"---\nname: nx-plugins\ndescription: Find and add Nx plugins. USE WHEN user wants to discover available plugins, install a new plugin, or add support for a specific framework or technology to the workspace.\n---\n\n## Finding and Installing new plugins\n\n- List plugins: `pnpm nx list`\n- Install plugins `pnpm nx add <plugin>`. Example: `pnpm nx add @nx/react`.\n",".agents/skills/nx-run-tasks/SKILL.md":"---\nname: nx-run-tasks\ndescription: Helps with running tasks in an Nx workspace. USE WHEN the user wants to execute build, test, lint, serve, or run any other tasks defined in the workspace.\n---\n\nYou can run tasks with Nx in the following way.\n\nKeep in mind that you might have to prefix things with npx/pnpx/yarn if the user doesn't have nx installed globally. Look at the package.json or lockfile to determine which package manager is in use.\n\nFor more details on any command, run it with `--help` (e.g. `nx run-many --help`, `nx affected --help`).\n\n## Understand which tasks can be run\n\nYou can check those via `nx show project <projectname> --json`, for example `nx show project myapp --json`. It contains a `targets` section which has information about targets that can be run. You can also just look at the `package.json` scripts or `project.json` targets, but you might miss out on inferred tasks by Nx plugins.\n\n## Run a single task\n\n```\nnx run <project>:<task>\n```\n\nwhere `project` is the project name defined in `package.json` or `project.json` (if present).\n\n## Run multiple tasks\n\n```\nnx run-many -t build test lint typecheck\n```\n\nYou can pass a `-p` flag to filter to specific projects, otherwise it runs on all projects. You can also use `--exclude` to exclude projects, and `--parallel` to control the number of parallel processes (default is 3).\n\nExamples:\n\n- `nx run-many -t test -p proj1 proj2` — test specific projects\n- `nx run-many -t test --projects=*-app --exclude=excluded-app` — test projects matching a pattern\n- `nx run-many -t test --projects=tag:api-*` — test projects by tag\n\n## Run tasks for affected projects\n\nUse `nx affected` to only run tasks on projects that have been changed and projects that depend on changed projects. This is especially useful in CI and for large workspaces.\n\n```\nnx affected -t build test lint\n```\n\nBy default it compares against the base branch. You can customize this:\n\n- `nx affected -t test --base=main --head=HEAD` — compare against a specific base and head\n- `nx affected -t test --files=libs/mylib/src/index.ts` — specify changed files directly\n\n## Useful flags\n\nThese flags work with `run`, `run-many`, and `affected`:\n\n- `--skipNxCache` — rerun tasks even when results are cached\n- `--verbose` — print additional information such as stack traces\n- `--nxBail` — stop execution after the first failed task\n- `--configuration=<name>` — use a specific configuration (e.g. `production`)\n",".agents/skills/nx-workspace/SKILL.md":"---\nname: nx-workspace\ndescription: \"Explore and understand Nx workspaces. USE WHEN answering questions about the workspace, projects, or tasks. ALSO USE WHEN an nx command fails or you need to check available targets/configuration before running a task. EXAMPLES: 'What projects are in this workspace?', 'How is project X configured?', 'What depends on library Y?', 'What targets can I run?', 'Cannot find configuration for task', 'debug nx task failure'.\"\n---\n\n# Nx Workspace Exploration\n\nThis skill provides read-only exploration of Nx workspaces. Use it to understand workspace structure, project configuration, available targets, and dependencies.\n\nKeep in mind that you might have to prefix commands with `npx`/`pnpx`/`yarn` if nx isn't installed globally. Check the lockfile to determine the package manager in use.\n\n## Listing Projects\n\nUse `nx show projects` to list projects in the workspace.\n\nThe project filtering syntax (`-p`/`--projects`) works across many Nx commands including `nx run-many`, `nx release`, `nx show projects`, and more. Filters support explicit names, glob patterns, tag references (e.g. `tag:name`), directories, and negation (e.g. `!project-name`).\n\n```bash\n# List all projects\nnx show projects\n\n# Filter by pattern (glob)\nnx show projects --projects \"apps/*\"\nnx show projects --projects \"shared-*\"\n\n# Filter by tag\nnx show projects --projects \"tag:publishable\"\nnx show projects -p 'tag:publishable,!tag:internal'\n\n# Filter by target (projects that have a specific target)\nnx show projects --withTarget build\n\n# Combine filters\nnx show projects --type lib --withTarget test\nnx show projects --affected --exclude=\"*-e2e\"\nnx show projects -p \"tag:scope:client,packages/*\"\n\n# Negate patterns\nnx show projects -p '!tag:private'\nnx show projects -p '!*-e2e'\n\n# Output as JSON\nnx show projects --json\n```\n\n## Project Configuration\n\nUse `nx show project <name> --json` to get the full resolved configuration for a project.\n\n**Important**: Do NOT read `project.json` directly - it only contains partial configuration. The `nx show project --json` command returns the full resolved config including inferred targets from plugins.\n\nYou can read the full project schema at `node_modules/nx/schemas/project-schema.json` to understand nx project configuration options.\n\n```bash\n# Get full project configuration\nnx show project my-app --json\n\n# Extract specific parts from the JSON\nnx show project my-app --json | jq '.targets'\nnx show project my-app --json | jq '.targets.build'\nnx show project my-app --json | jq '.targets | keys'\n\n# Check project metadata\nnx show project my-app --json | jq '{name, root, sourceRoot, projectType, tags}'\n```\n\n## Target Information\n\nTargets define what tasks can be run on a project.\n\n```bash\n# List all targets for a project\nnx show project my-app --json | jq '.targets | keys'\n\n# Get full target configuration\nnx show project my-app --json | jq '.targets.build'\n\n# Check target executor/command\nnx show project my-app --json | jq '.targets.build.executor'\nnx show project my-app --json | jq '.targets.build.command'\n\n# View target options\nnx show project my-app --json | jq '.targets.build.options'\n\n# Check target inputs/outputs (for caching)\nnx show project my-app --json | jq '.targets.build.inputs'\nnx show project my-app --json | jq '.targets.build.outputs'\n\n# Find projects with a specific target\nnx show projects --withTarget serve\nnx show projects --withTarget e2e\n```\n\n## Workspace Configuration\n\nRead `nx.json` directly for workspace-level configuration.\nYou can read the full project schema at `node_modules/nx/schemas/nx-schema.json` to understand nx project configuration options.\n\n```bash\n# Read the full nx.json\ncat nx.json\n\n# Or use jq for specific sections\ncat nx.json | jq '.targetDefaults'\ncat nx.json | jq '.namedInputs'\ncat nx.json | jq '.plugins'\ncat nx.json | jq '.generators'\n```\n\nKey nx.json sections:\n\n- `targetDefaults` - Default configuration applied to all targets of a given name\n- `namedInputs` - Reusable input definitions for caching\n- `plugins` - Nx plugins and their configuration\n- ...and much more, read the schema or nx.json for details\n\n## Affected Projects\n\nIf the user is asking about affected projects, read the [affected projects reference](references/AFFECTED.md) for detailed commands and examples.\n\n## Common Exploration Patterns\n\n### \"What's in this workspace?\"\n\n```bash\nnx show projects\nnx show projects --type app\nnx show projects --type lib\n```\n\n### \"How do I build/test/lint project X?\"\n\n```bash\nnx show project X --json | jq '.targets | keys'\nnx show project X --json | jq '.targets.build'\n```\n\n### \"What depends on library Y?\"\n\n```bash\n# Use the project graph to find dependents\nnx graph --print | jq '.graph.dependencies | to_entries[] | select(.value[].target == \"Y\") | .key'\n```\n\n## Programmatic Answers\n\nWhen processing nx CLI results, use command-line tools to compute the answer programmatically rather than counting or parsing output manually. Always use `--json` flags to get structured output that can be processed with `jq`, `grep`, or other tools you have installed locally.\n\n### Listing Projects\n\n```bash\nnx show projects --json\n```\n\nExample output:\n\n```json\n[\"my-app\", \"my-app-e2e\", \"shared-ui\", \"shared-utils\", \"api\"]\n```\n\nCommon operations:\n\n```bash\n# Count projects\nnx show projects --json | jq 'length'\n\n# Filter by pattern\nnx show projects --json | jq '.[] | select(startswith(\"shared-\"))'\n\n# Get affected projects as array\nnx show projects --affected --json | jq '.'\n```\n\n### Project Details\n\n```bash\nnx show project my-app --json\n```\n\nExample output:\n\n```json\n{\n  \"root\": \"apps/my-app\",\n  \"name\": \"my-app\",\n  \"sourceRoot\": \"apps/my-app/src\",\n  \"projectType\": \"application\",\n  \"tags\": [\"type:app\", \"scope:client\"],\n  \"targets\": {\n    \"build\": {\n      \"executor\": \"@nx/vite:build\",\n      \"options\": { \"outputPath\": \"dist/apps/my-app\" }\n    },\n    \"serve\": {\n      \"executor\": \"@nx/vite:dev-server\",\n      \"options\": { \"buildTarget\": \"my-app:build\" }\n    },\n    \"test\": {\n      \"executor\": \"@nx/vite:test\",\n      \"options\": {}\n    }\n  },\n  \"implicitDependencies\": []\n}\n```\n\nCommon operations:\n\n```bash\n# Get target names\nnx show project my-app --json | jq '.targets | keys'\n\n# Get specific target config\nnx show project my-app --json | jq '.targets.build'\n\n# Get tags\nnx show project my-app --json | jq '.tags'\n\n# Get project root\nnx show project my-app --json | jq -r '.root'\n```\n\n### Project Graph\n\n```bash\nnx graph --print\n```\n\nExample output:\n\n```json\n{\n  \"graph\": {\n    \"nodes\": {\n      \"my-app\": {\n        \"name\": \"my-app\",\n        \"type\": \"app\",\n        \"data\": { \"root\": \"apps/my-app\", \"tags\": [\"type:app\"] }\n      },\n      \"shared-ui\": {\n        \"name\": \"shared-ui\",\n        \"type\": \"lib\",\n        \"data\": { \"root\": \"libs/shared-ui\", \"tags\": [\"type:ui\"] }\n      }\n    },\n    \"dependencies\": {\n      \"my-app\": [{ \"source\": \"my-app\", \"target\": \"shared-ui\", \"type\": \"static\" }],\n      \"shared-ui\": []\n    }\n  }\n}\n```\n\nCommon operations:\n\n```bash\n# Get all project names from graph\nnx graph --print | jq '.graph.nodes | keys'\n\n# Find dependencies of a project\nnx graph --print | jq '.graph.dependencies[\"my-app\"]'\n\n# Find projects that depend on a library\nnx graph --print | jq '.graph.dependencies | to_entries[] | select(.value[].target == \"shared-ui\") | .key'\n```\n\n## Troubleshooting\n\n### \"Cannot find configuration for task X:target\"\n\n```bash\n# Check what targets exist on the project\nnx show project X --json | jq '.targets | keys'\n\n# Check if any projects have that target\nnx show projects --withTarget target\n```\n\n### \"The workspace is out of sync\"\n\n```bash\nnx sync\nnx reset  # if sync doesn't fix stale cache\n```\n",".agents/skills/nx-workspace/references/AFFECTED.md":"## Affected Projects\n\nFind projects affected by changes in the current branch.\n\n```bash\n# Affected since base branch (auto-detected)\nnx show projects --affected\n\n# Affected with explicit base\nnx show projects --affected --base=main\nnx show projects --affected --base=origin/main\n\n# Affected between two commits\nnx show projects --affected --base=abc123 --head=def456\n\n# Affected apps only\nnx show projects --affected --type app\n\n# Affected excluding e2e projects\nnx show projects --affected --exclude=\"*-e2e\"\n\n# Affected by uncommitted changes\nnx show projects --affected --uncommitted\n\n# Affected by untracked files\nnx show projects --affected --untracked\n```\n",".claude/CLAUDE.md":"# Claude AI Instructions for Supabase JS Libraries Monorepo\n\nYou are assisting with development in a unified Nx monorepo that consolidates all Supabase JavaScript SDKs, built with Nx for optimal developer experience and maintainability. This strategic migration from 6 separate repositories addresses critical maintenance overhead, dependency duplication, and release coordination challenges while maintaining **zero breaking changes** for consumers.\n\n> **📚 Essential Documentation**: Always refer to these guides for detailed information:\n>\n> - **[CONTRIBUTING.md](../CONTRIBUTING.md)** - Development guidelines, commit format, PR process\n> - **[TESTING.md](../docs/TESTING.md)** - Complete testing guide with Docker requirements\n> - **[RELEASE.md](../docs/RELEASE.md)** - Release workflows and versioning strategy\n> - **[MIGRATION.md](../docs/MIGRATION.md)** - Cross-cutting migration notes (one H2 per theme). Per-package migrations live at `packages/core/<package>/migrations/`.\n> - **[Security Policy](https://github.com/supabase/supabase-js/security/policy)** - Security policies and responsible disclosure\n\n## Repository Architecture\n\n### Monorepo Structure\n\n```text\nsupabase-js/\n├── packages/core/\n│   ├── supabase-js/      # @supabase/supabase-js - Main isomorphic client for Supabase\n│   ├── auth-js/          # @supabase/auth-js - Authentication client\n│   ├── postgrest-js/     # @supabase/postgrest-js - PostgREST client for database operations\n│   ├── realtime-js/      # @supabase/realtime-js - Real-time subscriptions client\n│   ├── storage-js/       # @supabase/storage-js - File storage client\n│   └── functions-js/     # @supabase/functions-js - Edge Functions client\n├── CONTRIBUTING.md       # Contribution guidelines\n├── docs/                 # Comprehensive documentation guides\n│   ├── TESTING.md        # Testing guide\n│   ├── RELEASE.md        # Release workflows\n│   ├── MIGRATION.md      # Migration guide\n│   └── JSR_PUBLISHING.md # JSR publishing guide\n├── scripts/              # Automation scripts\n│   ├── release-canary.ts # Canary release automation\n│   ├── release-stable.ts # Stable release automation\n│   └── update-version-files.ts # Version management\n├── nx.json               # Nx workspace configuration\n├── tsconfig.base.json    # Base TypeScript configuration\n├── package.json          # Root package with workspace scripts\n└── commitlint.config.js  # Commit message validation\n```\n\n### Migration Benefits\n\n- **Dependency Consolidation**: 22 previously duplicated dependencies now centrally managed\n- **Atomic Changes**: Cross-library fixes in single PRs\n- **Immediate Integration Testing**: No manual release coordination needed\n- **Unified Versioning**: Fixed version mode with automated releases using `nx release`\n- **Intelligent Building**: Nx only rebuilds/tests what actually changed\n\n## Core Development Principles\n\n### 1. Zero Breaking Changes\n\nEvery change must maintain full backward compatibility. The migration itself introduces no breaking changes - all packages maintain their original npm names and APIs.\n\n### 2. Hybrid Release Model with Fixed Versioning\n\nUses automated canary releases with batched stable releases:\n\n- **Canary**: Every commit to master → prerelease (e.g., `2.80.1-canary.0`) with `canary` dist-tag\n- **Stable**: Manual promotion of validated canary to `latest` dist-tag\n- **Fixed Versioning**: All packages share identical version numbers (e.g., all at 2.80.0)\n- **Version Line**: Continuing with v2.x.x to maintain ecosystem stability\n\n**Three Release Workflows:**\n\n1. **Canary** (`.github/workflows/main-ci-release.yml`) - Automated on every master commit\n2. **Stable** (`.github/workflows/release-stable.yml`) - Manual by repository owners\n3. **Preview** (`.github/workflows/preview-release.yml`) - PR-based testing via pkg.pr.new\n\n> **📖 See [RELEASE.md](../docs/RELEASE.md) for complete release documentation**\n\n### 3. Workspace Dependencies\n\nInternal dependencies use the `*` protocol:\n\n```json\n// packages/core/supabase-js/package.json\n{\n  \"dependencies\": {\n    \"@supabase/auth-js\": \"*\",\n    \"@supabase/realtime-js\": \"*\",\n    \"@supabase/functions-js\": \"*\",\n    \"@supabase/storage-js\": \"*\",\n    \"@supabase/postgrest-js\": \"*\"\n  }\n}\n```\n\nNx automatically replaces `*` with the actual version during release.\n\n### 4. Affected-First Development\n\nAlways use `nx affected` commands to build/test only what changed, leveraging Nx's dependency graph intelligence.\n\n### 5. Conventional Commits\n\nUse conventional commit format for automated versioning:\n\n- `fix(auth-js): resolve token refresh race condition` → Patch release\n- `feat(realtime-js): add presence support` → Minor release\n- `feat(auth)!: remove deprecated method` → Major release\n- `chore(deps): update TypeScript to 5.8` → No version bump\n\n**Always use the interactive commit tool:**\n\n```bash\npnpm commit\n```\n\n> **📖 See [CONTRIBUTING.md](../CONTRIBUTING.md#commit-guidelines) for complete commit guidelines**\n\n## Essential Commands Reference\n\n### Building\n\n```bash\nnx run-many --target=build --all        # Build all packages\nnx build auth-js                         # Build specific package\nnx affected --target=build               # Build only affected\nnx build auth-js --watch                 # Development mode\n```\n\n### Testing\n\n```bash\n# Test specific packages (complete test suites with Docker setup/cleanup)\nnx test:auth auth-js                    # Complete auth-js test suite (handles Docker)\nnx test:storage storage-js              # Complete storage-js test suite (handles Docker)\nnx test:ci:postgrest postgrest-js      # Complete postgrest-js test suite (handles Docker)\nnx test functions-js                    # Standard test (uses testcontainers)\nnx test realtime-js                     # Standard test (no Docker needed)\nnx test supabase-js                     # Standard test (unit tests only)\n\n# Coverage reports\nnx test supabase-js --coverage\nnx test:coverage realtime-js\nnx test:ci functions-js                 # Includes coverage\n```\n\n**Docker Requirements:**\n\n| Package      | Docker Required | Infrastructure                  | Complete Test Command               | Individual Commands                                                                       |\n| ------------ | --------------- | ------------------------------- | ----------------------------------- | ----------------------------------------------------------------------------------------- |\n| auth-js      | ✅ Yes          | Auth Server + Postgres          | `nx test:auth auth-js`              | `nx test:suite auth-js`, `nx test:infra auth-js`, `nx test:clean-post auth-js`            |\n| storage-js   | ✅ Yes          | Storage API + PostgreSQL + Kong | `nx test:storage storage-js`        | `nx test:suite storage-js`, `nx test:infra storage-js`, `nx test:clean-post storage-js`   |\n| postgrest-js | ✅ Yes          | PostgREST + PostgreSQL          | `nx test:ci:postgrest postgrest-js` | `nx test:run postgrest-js`, `nx test:types postgrest-js`                                  |\n| functions-js | ✅ Yes          | Deno relay (testcontainers)     | `nx test functions-js`              | `nx test:ci functions-js` (with coverage)                                                 |\n| realtime-js  | ❌ No           | Mock WebSockets                 | `nx test realtime-js`               | `nx test:coverage realtime-js`, `nx test:watch realtime-js`                               |\n| supabase-js  | ❌ No           | Unit tests only                 | `nx test supabase-js`               | `nx test:all`, `nx test:unit`, `nx test:integration`, `nx test:coverage`, `nx test:watch` |\n\n**supabase-js Additional Test Commands:**\n\n```bash\nnx test:all supabase-js                  # Unit + integration + browser tests\nnx test:unit supabase-js                # Jest unit tests only\nnx test:integration supabase-js         # Node.js integration tests\nnx test:integration:browser supabase-js # Browser tests (requires Deno)\nnx test:edge-functions supabase-js      # Edge Functions tests\nnx test:deno supabase-js                # Deno runtime tests\nnx test:bun supabase-js                 # Bun runtime tests\nnx test:expo supabase-js                # React Native/Expo tests\nnx test:next supabase-js                # Next.js SSR tests\nnx test:node:playwright supabase-js     # WebSocket browser tests\nnx test:types supabase-js               # TypeScript type checking\nnx test:coverage supabase-js            # Coverage report\nnx test:watch supabase-js               # Watch mode\n```\n\n> **📖 See [TESTING.md](../docs/TESTING.md) for complete testing guide and troubleshooting**\n\n### Code Quality\n\n```bash\nnx run-many --target=lint --all          # Lint all packages\nnx lint storage-js                       # Lint specific package\nnx format                                 # Auto-format all code\nnx format:check                           # Check formatting\n```\n\n### Analysis\n\n```bash\nnx graph                                  # Interactive dependency graph\nnx show projects                          # List all projects\nnx affected --graph                       # Visualize affected projects\n```\n\n## Development Workflows\n\n### Cross-Library Bug Fix Example\n\n**Scenario**: Bug in supabase-js caused by realtime-js\n\n**Monorepo Solution**:\n\n1. Fix root cause in `packages/core/realtime-js/src/`\n2. Add unit test in `packages/core/realtime-js/test/`\n3. Add integration test in `packages/core/supabase-js/test/`\n4. Run complete test suites for both packages to verify impacts\n5. Commit: `fix(realtime-js): resolve reconnection logic affecting supabase-js`\n6. Single PR, single review, single release - all packages version together\n\n### Adding New Features\n\n1. Implement in appropriate library under `packages/core/[library]/src/`\n2. Write comprehensive unit tests in `packages/core/[library]/test/`\n3. If feature affects supabase-js, add integration tests there\n4. Update TypeScript types if needed\n5. Run complete test suite for the package before committing\n6. Use conventional commit: `feat(storage-js): add resumable uploads`\n\n### Quick Fix Workflow\n\n```bash\n# Even for single-library fixes:\ngit add .\ngit commit -m \"fix(auth-js): correct session expiry calculation\"\n# → Automatic canary: 2.80.1-canary.0 published to 'canary' dist-tag\n# Run complete test suite for the package:\nnx test:auth auth-js\n# After validation, manual promotion:\nnx release --tag=latest --yes  # Promotes to stable with same version for ALL packages\n```\n\n## TypeScript Configuration\n\n### Workspace Settings\n\n- **Target**: ES2022\n- **Module**: NodeNext\n- **Strict**: true\n- **Isolated Modules**: true (faster compilation)\n- **Composite**: true (incremental builds)\n\n### Per-Library Configs\n\nEach library has its own `tsconfig.json` extending the base configuration, allowing for library-specific adjustments while maintaining consistency.\n\n### TypeScript Project References Setup\n\nThis repository uses TypeScript project references for incremental builds and better type checking across packages.\n\n**What's Configured:**\n\n1. **tsconfig.base.json** - Base configuration inherited by all projects:\n   - `composite: true` - Enables project references\n   - `declaration: true` - Required by composite\n   - `moduleResolution: \"bundler\"` - Works with workspaces\n   - `isolatedModules: true` - Inherited but overridden in core packages\n   - `noImplicitOverride: true` - Inherited but overridden in core packages\n   - **No `customConditions`** - Removed to avoid conflicts with CommonJS packages\n\n2. **Root tsconfig.json** - References all projects in the monorepo:\n\n   ```json\n   {\n     \"extends\": \"./tsconfig.base.json\",\n     \"files\": [],\n     \"references\": [\n       { \"path\": \"./packages/core/auth-js\" },\n       { \"path\": \"./packages/core/realtime-js\" }\n       // ... all other packages\n     ]\n   }\n   ```\n\n3. **Core packages** (auth-js, realtime-js, postgrest-js, functions-js, storage-js):\n   - Keep `module: \"CommonJS\"` for backward compatibility\n   - Override `moduleResolution: \"Node\"` (required for CommonJS)\n   - Override `isolatedModules: false` (existing code doesn't use `export type`)\n   - Override `noImplicitOverride: false` (existing code doesn't use `override` keyword)\n   - Add `references` array pointing to dependencies (managed by `nx sync`)\n\n4. **Utils packages** (utils-fetch):\n   - Inherit `moduleResolution: \"bundler\"` from base\n   - Can optionally add `customConditions: [\"@supabase-js/source\"]` for source preference\n\n**Key Principles:**\n\n- ✅ **No Breaking Changes**: Build output is identical - only type-checking is affected\n- ✅ **Incremental Builds**: TypeScript only recompiles changed projects\n- ✅ **Better Performance**: Reduced memory usage during builds\n- ✅ **Automatic References**: Nx sync automatically maintains project references\n- ⚠️ **No `customConditions` in base**: Would conflict with `moduleResolution: \"Node\"`\n\n**When Adding New Packages:**\n\n1. Ensure `composite: true` and `declaration: true` are set\n2. Add `references` array pointing to dependencies\n3. If using CommonJS, override `moduleResolution: \"Node\"` and disable strict options\n4. Run `nx sync` to update root tsconfig.json automatically\n\n**Important Notes:**\n\n- TypeScript project references work WITHOUT `customConditions` - it's optional\n- `customConditions` only optimizes source file resolution during development\n- Core packages use `moduleResolution: \"Node\"` which is incompatible with `customConditions`\n- The `isolatedModules: false` override avoids requiring `export type` for type re-exports\n- All build outputs remain identical to pre-project-references setup\n\n## Testing Infrastructure\n\n### Unit Tests (Jest)\n\n- Location: `packages/core/[library]/test/`\n- Pattern: Mirror source structure\n- Principle: Test public APIs thoroughly\n- Mocking: Mock external dependencies\n\n### Integration Tests (Docker-based)\n\n**Complete Test Suites (Recommended)**:\n\n```bash\n# Auth-js: Complete test suite (handles Docker setup/cleanup automatically)\nnx test:auth auth-js\n\n# Storage-js: Complete test suite (handles Docker setup/cleanup automatically)\nnx test:storage storage-js\n\n# Postgrest-js: Complete test suite (handles Docker setup/cleanup automatically)\nnx test:ci:postgrest postgrest-js\n```\n\n**Manual Infrastructure Management** (for development):\n\n```bash\n# Auth-js\nnx test:infra auth-js        # Start Supabase CLI infrastructure\nnx test:suite auth-js        # Run tests (can run multiple times)\nnx test:clean-post auth-js   # Cleanup\n\n# Storage-js\nnx test:infra storage-js        # Start Supabase CLI infrastructure\nnx test:suite storage-js        # Run tests (can run multiple times)\nnx test:clean-post storage-js   # Cleanup\n\n# Postgrest-js\nnx test:infra postgrest-js        # Start Supabase CLI infrastructure\nnx test:run postgrest-js          # Run tests\nnx test:clean-post postgrest-js   # Cleanup\n```\n\n### Cross-Platform Tests (supabase-js)\n\nTests run against multiple environments:\n\n- Node.js (native)\n- Next.js (SSR/React)\n- Expo (React Native)\n- Bun (alternative runtime)\n- Deno (secure runtime)\n- Browser (via Puppeteer)\n\n## Library-Specific Considerations\n\n### supabase-js\n\n- Aggregates all other libraries\n- Primary integration testing location\n- Most complex cross-platform test suite (Node.js, Next.js, Expo, Bun, Deno, Browser)\n- Users typically interact through this package\n- Default branch: **master**\n\n### auth-js\n\n- Requires Docker for integration tests (GoTrue + PostgreSQL)\n- Complex session management logic\n- Security-critical - extra review care needed\n- See [auth-js README](../packages/core/auth-js/README.md) for details\n\n### realtime-js\n\n- WebSocket-based, timing-sensitive\n- Mock time in tests when possible\n- No Docker required (uses mock WebSockets)\n- See [realtime-js README](../packages/core/realtime-js/README.md) for details\n\n### storage-js\n\n- Requires Docker for integration tests (Storage API + PostgreSQL + Kong)\n- File handling varies by platform\n- See [storage-js README](../packages/core/storage-js/README.md) for details\n\n### postgrest-js\n\n- Pure HTTP client, easiest to test\n- Requires Docker for integration tests (PostgREST + PostgreSQL)\n- See [postgrest-js README](../packages/core/postgrest-js/README.md) for details\n\n### functions-js\n\n- Simplest library, minimal dependencies\n- Uses testcontainers for Deno relay\n- See [functions-js README](../packages/core/functions-js/README.md) for details\n\n## Code Style Guidelines\n\n### Formatting\n\n- Prettier handles all formatting (configured in `.prettierrc`)\n- Run `nx format` before committing\n- No formatting debates - Prettier decides\n\n### Patterns\n\n- Follow existing patterns in each library\n- Extract shared code to packages/shared/ when identified\n- Maintain consistency across monorepo\n\n### Documentation\n\n- JSDoc for all public APIs\n- README per package with examples\n- Update docs when changing APIs\n\n## Important Context\n\n### Branch Information\n\n**Current Repository:**\n\n- **Default branch**: `master` (v2 active development; all PRs land here by default; auto-publishes `@canary` on every push, stable releases are manual `workflow_dispatch` from this branch)\n- **Long-lived feature branch**: `v3` (v3-only breaking changes; `@next` prereleases are **manual `workflow_dispatch` only** — never auto-published; kept in sync with `master` by periodic `git merge master`)\n- **Repository URL**: `github.com/supabase/supabase-js`\n\n**Original Repository Branches** (for historical reference):\n\n- **master**: auth-js, postgrest-js, realtime-js, supabase-js\n- **main**: functions-js, storage-js\n\nWhen referencing original repository history or comparing changes, be aware of these branch name differences.\n\n### Package Publishing\n\n- All packages publish to npm under `@supabase` scope\n- Versions synchronized via fixed release mode (all packages always have same version)\n- Changelogs generated per package from conventional commits\n- \"No user-facing changes\" message for unchanged packages\n- Three dist-tags: `latest` (stable), `canary` (pre-release), `next` (legacy)\n\n### Docker Requirements\n\nIntegration tests for auth-js, functions-js, postgrest-js, and storage-js require Docker running locally:\n\n- **macOS/Windows**: Ensure Docker Desktop is installed and running\n- **Linux**: Ensure Docker daemon is running\n- **CI**: Docker is automatically available in GitHub Actions\n\nCheck [TESTING.md](../docs/TESTING.md) for port requirements and troubleshooting.\n\n### Commit Message Validation\n\nAll commits are validated using commitlint with strict rules:\n\n- **Type**: Required (feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert)\n- **Scope**: Required (auth, functions, postgrest, realtime, storage, supabase, repo, deps, ci, release, docs, scripts, misc)\n- **Subject**: Required, imperative mood, no period at end, max 100 characters\n- **Interactive Tool**: Use `pnpm commit` to ensure compliance\n\nSee [CONTRIBUTING.md](../CONTRIBUTING.md#commit-guidelines) for complete details.\n\n## Common Pitfalls & Solutions\n\n### Pitfall 1: Hardcoding Internal Versions\n\n❌ Wrong:\n\n```json\n\"@supabase/auth-js\": \"3.5.0\"\n```\n\n✅ Correct:\n\n```json\n\"@supabase/auth-js\": \"*\"\n```\n\n### Pitfall 2: Running npm Directly\n\n❌ Wrong:\n\n```bash\ncd packages/core/auth-js && npm test\n```\n\n✅ Correct:\n\n```bash\nnx test:auth auth-js\n```\n\n### Pitfall 3: Testing Everything\n\n❌ Wrong:\n\n```bash\nnx run-many --target=test --all  # Won't work - no standard test target for all packages\n```\n\n✅ Correct:\n\n```bash\n# Run complete test suite for the specific package\nnx test:auth auth-js\nnx test:storage storage-js\nnx test:ci:postgrest postgrest-js\nnx test functions-js\nnx test realtime-js\nnx test supabase-js\n```\n\n### Pitfall 4: Breaking Changes\n\n❌ Wrong: Changing public API signatures without proper process\n\n```typescript\n// Don't just change existing method signatures\n- signIn(email: string): Promise<void>\n+ signIn(credentials: Credentials): Promise<void>\n```\n\n✅ Correct: Add new methods, deprecate old ones gradually, use proper commit format\n\n```typescript\n// Add new method\nsignIn(credentials: Credentials): Promise<void>\n\n// Deprecate old method with backward compatibility\n/** @deprecated Use signIn(credentials) instead */\nsignInWithEmail(email: string): Promise<void> {\n  return this.signIn({ email })\n}\n```\n\nUse breaking change commit format when necessary:\n\n```bash\nfeat(auth)!: remove deprecated signInWithEmail method\n\nBREAKING CHANGE: The deprecated signInWithEmail method has been removed.\nUse signIn({ email }) instead.\n```\n\n### Pitfall 5: Running Commands Incorrectly\n\n❌ Wrong: Running npm commands directly in library directories\n\n```bash\ncd packages/core/auth-js\nnpm test\nnpm run build\n```\n\n✅ Correct: Use Nx commands from repository root\n\n```bash\nnx test:auth auth-js\nnx build auth-js --watch\n```\n\n### Pitfall 6: Not Using the Commit Tool\n\n❌ Wrong: Using git commit directly\n\n```bash\ngit commit -m \"fix auth bug\"  # Missing scope, will fail validation\n```\n\n✅ Correct: Use the interactive commit tool\n\n```bash\npnpm commit  # Guides you through proper format\n```\n\n### Pitfall 7: Not Checking Documentation\n\n❌ Wrong: Assuming you know how to run tests without checking\n\n```bash\nnx test storage-js  # Wrong - should use nx test:storage storage-js\n```\n\n✅ Correct: Check library README and TESTING.md first\n\n```bash\n# Read docs first\ncat packages/core/storage-js/README.md\ncat docs/TESTING.md\n# Then run tests with proper setup\n```\n\n## Pull Request Best Practices\n\n> **📖 See [CONTRIBUTING.md](../CONTRIBUTING.md#pull-request-process) for complete PR guidelines**\n\n### Before Creating PR\n\n1. **Ensure branch is up to date** with the PR's target branch (typically `master`; `v3` only for v3-only breaking changes):\n\n   ```bash\n   git checkout <target-branch>     # master or v3\n   git pull upstream <target-branch>\n   git checkout your-feature-branch\n   git rebase <target-branch>\n   ```\n\n2. **Run all necessary checks:**\n\n   ```bash\n   nx format                    # Format code\n   # Run complete test suite for affected packages individually\n   nx test:auth auth-js         # If auth-js changed\n   nx test:storage storage-js   # If storage-js changed\n   # ... etc for other packages\n   nx affected --target=build   # Build affected packages\n   ```\n\n3. **Use interactive commit tool:**\n\n   ```bash\n   pnpm commit\n   ```\n\n### PR Requirements\n\n- ✅ At least 1 approving review from a code owner\n- ✅ All status checks passing (CI/CD pipeline)\n- ✅ No merge conflicts with the base branch\n- ✅ Squash merge only (enforced by repository settings)\n\n### PR Description Template\n\n```markdown\n## Description\n\nBrief description of what this PR does\n\n## Type of Change\n\n- [ ] Bug fix (fix)\n- [ ] New feature (feat)\n- [ ] Breaking change (feat! or fix!)\n- [ ] Documentation update (docs)\n- [ ] Other (chore, refactor, etc.)\n\n## Testing\n\n- [ ] Unit tests added/updated\n- [ ] Integration tests added/updated (if applicable)\n- [ ] All tests passing locally\n\n## Checklist\n\n- [ ] Code formatted (`nx format`)\n- [ ] Tests passing (run complete test suites for affected packages)\n- [ ] Builds passing (`nx affected --target=build`)\n- [ ] Used conventional commits\n- [ ] Documentation updated (if needed)\n```\n\n### Requesting Preview Releases\n\nIf you need to test your changes before merging:\n\n1. Create your PR\n2. Comment: \"Can a maintainer add the preview label for testing?\"\n3. Wait for maintainer to add `trigger: preview` label\n4. Follow instructions in automated comment to install preview packages\n\n## Helpful Commands Reference\n\n### Analysis & Debugging\n\n```bash\n# Visualize dependency graph\nnx graph\n\n# Show what's affected by changes\nnx affected --graph\n\n# List all projects\nnx show projects\n\n# See project details\nnx show project auth-js --web\n\n# Clear Nx cache\nnx reset\n```\n\n### Development Workflow\n\n```bash\n# 1. Create feature branch\ngit checkout -b feat/your-feature\n\n# 2. Make changes in packages/core/[library]/\n\n# 3. Test continuously\nnx test [library] --watch\n\n# 4. Format before committing\nnx format\n\n# 5. Commit with tool\npnpm commit\n\n# 6. Before pushing\n# Run complete test suite for the package you changed\nnx test:auth auth-js         # If auth-js changed\nnx test:storage storage-js   # If storage-js changed\n# ... etc\nnx affected --target=build\nnx format:check\n\n# 7. Push and create PR\ngit push origin feat/your-feature\n```\n\n### Troubleshooting\n\n```bash\n# Clear cache and rebuild\nnx reset\nnx run-many --target=build --all\n\n# Clean install\nrm -rf node_modules\npnpm install\n\n# Check for errors\nnx run-many --target=lint --all\n\n# Run specific test file (for packages with standard test target)\nnx test realtime-js --testFile=RealtimeClient.test.ts\nnx test supabase-js --testFile=client.test.ts\n```\n\n## Additional Resources\n\n- **[README.md](../README.md)** - Repository overview and quick start\n- **[CONTRIBUTING.md](../CONTRIBUTING.md)** - Complete contribution guide\n- **[TESTING.md](../docs/TESTING.md)** - Comprehensive testing documentation\n- **[RELEASE.md](../docs/RELEASE.md)** - Release workflows and automation\n- **[MIGRATION.md](../docs/MIGRATION.md)** - Cross-cutting migration notes; per-package migrations live at `packages/core/<package>/migrations/`\n- **[Security Policy](https://github.com/supabase/supabase-js/security/policy)** - Security policy and reporting\n- **[Supabase Documentation](https://supabase.com/docs)** - Official Supabase docs\n- **[Nx Documentation](https://nx.dev)** - Nx monorepo documentation\n- **[Conventional Commits](https://www.conventionalcommits.org/)** - Commit format specification\n\n### Pitfall 5: Incomplete Cross-Library Testing\n\n❌ Wrong: Only testing in source library\n✅ Correct: Test in source library AND integration tests in supabase-js\n\n## Release Process\n\n### Hybrid Release Flow\n\n**Canary Releases (Automated)**:\n\n```bash\n# Triggered automatically on every commit to master\ngit commit -m \"fix(auth): resolve token issue\"\n# → Automatic CI: nx release --tag=canary --yes\n# → Published: 2.80.1-canary.0 to 'canary' dist-tag\n```\n\n**Stable Releases (Manual)**:\n\n```bash\n# 1. Validate canary version\n# Run complete test suites for packages individually\n\n# 2. Preview stable promotion\nnx release --dry-run\n\n# 3. Promote canary to stable\nnx release --tag=latest --yes\n\n# Alternative: Promote specific canary\nnx release --specifier=2.80.1 --tag=latest --yes\n```\n\n### What Happens During Canary Release\n\n1. CI detects conventional commits\n2. Determines version bump (patch/minor/major)\n3. Generates prerelease version (e.g., 2.80.1-canary.0)\n4. Updates all package.json files\n5. Replaces `*` with actual versions\n6. Publishes all packages to npm with `canary` dist-tag\n7. Triggers dogfooding workflows (when configured)\n\n### What Happens During Stable Release\n\n1. Promotes validated canary to `latest` dist-tag\n2. Generates curated per-package changelogs\n3. Creates GitHub release with notes\n4. All packages get identical stable version\n\n### Nx Release Configuration\n\nThe workspace is configured for hybrid releases in `nx.json`:\n\n```json\n{\n  \"release\": {\n    \"projectsRelationship\": \"fixed\",\n    \"version\": {\n      \"conventionalCommits\": true\n    },\n    \"changelog\": {\n      \"projectChangelogs\": true,\n      \"workspaceChangelog\": true\n    }\n  }\n}\n```\n\n### Release Command Reference\n\n```bash\n# Canary releases (automated in CI)\nnx release --tag=canary --yes                    # Publish to 'canary' dist-tag\nnx release --specifier=prerelease --tag=canary   # Force prerelease bump\n\n# Stable releases (manual promotion)\nnx release --tag=latest --yes                  # Promote to 'latest' dist-tag\nnx release --specifier=2.80.1 --tag=latest     # Promote specific version\n\n# Preview and debugging\nnx release --dry-run                           # Preview changes\nnx release --dry-run --verbose                 # Detailed preview\nnx release --first-release --dry-run           # First release preview\n\n# Version-specific releases\nnx release --specifier=patch --tag=latest      # Force patch bump\nnx release --specifier=minor --tag=latest      # Force minor bump\nnx release --specifier=major --tag=latest      # Force major bump\n```\n\n### Changelog Example\n\n```markdown\n## @supabase/realtime-js 2.80.1 (2025-09-16)\n\n- fix: correct reconnection logic (#123)\n\n## @supabase/auth-js 2.80.1 (2025-09-16)\n\n_No user-facing changes in this release._\n\n## @supabase/supabase-js 2.80.1 (2025-09-16)\n\n_No user-facing changes in this release._\n```\n\n## When Providing Code Suggestions\n\n1. **Consider Monorepo Impact**: Changes might affect multiple packages - always check dependencies\n2. **Use Nx Commands**: Always prefer `nx` over direct `npm` for workspace operations\n3. **Suggest Complete Test Suites**: Use complete test suites (`nx test:auth auth-js`, `nx test:storage storage-js`, etc.) for packages individually\n4. **Respect Fixed Versioning**: All packages version together - no independent versioning\n5. **Maintain Compatibility**: Never introduce breaking changes without proper process\n6. **Check Testing Requirements**: Be aware of Docker requirements for integration tests\n7. **Extract Shared Code**: Identify patterns that could be shared across packages\n8. **Follow Conventions**: Use existing patterns and structures within each library\n9. **Document Changes**: Update JSDoc and READMEs when changing public APIs\n10. **Use Conventional Commits**: Always suggest proper commit format with scope\n\n## Quick Decision Tree\n\n**Q: Where does this code belong?**\n\n- Authentication logic → auth-js\n- Database queries → postgrest-js\n- Real-time subscriptions → realtime-js\n- File operations → storage-js\n- Edge function calls → functions-js\n- Integration of above → supabase-js\n- Shared utilities → packages/shared/ (create if needed)\n\n**Q: How to test this change?**\n\n1. Unit test in source library\n2. Integration test in supabase-js if affects it\n3. Run complete test suite for the package:\n   - `nx test:auth auth-js` (handles Docker automatically)\n   - `nx test:storage storage-js` (handles Docker automatically)\n   - `nx test:ci:postgrest postgrest-js` (handles Docker automatically)\n   - `nx test functions-js` (uses testcontainers)\n   - `nx test realtime-js` (no Docker needed)\n   - `nx test supabase-js` (unit tests only)\n4. Run complete test suites for all affected packages individually\n\n**Q: How will this release?**\n\n- All packages version together in fixed mode\n- Your commit triggers automatic canary release for ALL packages\n- Weekly promotion of validated canary to stable\n- Unchanged packages show \"No user-facing changes\"\n- Single npm install updates entire SDK suite\n\nRemember: This monorepo optimizes for developer experience and maintenance efficiency while ensuring zero breaking changes for the millions of developers using Supabase SDKs.\n\n<!-- nx configuration start-->\n<!-- Leave the start & end comments to automatically receive updates. -->\n\n## General Guidelines for working with Nx\n\n- For navigating/exploring the workspace, invoke the `nx-workspace` skill first - it has patterns for querying projects, targets, and dependencies\n- When running tasks (for example build, lint, test, e2e, etc.), always prefer running the task through `nx` (i.e. `nx run`, `nx run-many`, `nx affected`) instead of using the underlying tooling directly\n- Prefix nx commands with the workspace's package manager (e.g., `pnpm nx build`, `npm exec nx test`) - avoids using globally installed CLI\n- You have access to the Nx MCP server and its tools, use them to help the user\n- For Nx plugin best practices, check `node_modules/@nx/<plugin>/PLUGIN.md`. Not all plugins have this file - proceed without it if unavailable.\n- NEVER guess CLI flags - always check nx_docs or `--help` first when unsure\n\n## Scaffolding & Generators\n\n- For scaffolding tasks (creating apps, libs, project structure, setup), ALWAYS invoke the `nx-generate` skill FIRST before exploring or calling MCP tools\n\n## When to use nx_docs\n\n- USE for: advanced config options, unfamiliar flags, migration guides, plugin configuration, edge cases\n- DON'T USE for: basic generator syntax (`nx g @nx/react:app`), standard commands, things you already know\n- The `nx-generate` skill handles generator discovery internally - don't call nx_docs just to look up generator syntax\n\n<!-- nx configuration end-->\n",".cursor/mcp.json":"{\n  \"mcpServers\": {}\n}\n","AGENTS.md":"# Agent instructions\n\nEntry point for AI/LLM agents working in or with this repository. Pointers below; nothing canonical lives in this file.\n\n## Repository overview\n\n- [`README.md`](./README.md) — what this repo is, package list, quick start\n- [`CONTRIBUTING.md`](./CONTRIBUTING.md) — contribution guidelines, commit format, PR process\n- [`.claude/CLAUDE.md`](./.claude/CLAUDE.md) — development conventions, Nx commands, testing matrix, library-specific notes (read by Claude Code; the canonical development-conventions doc)\n- [`.cursor/.cursorrules`](./.cursor/.cursorrules) — same conventions for Cursor (read by Cursor IDE)\n\n## Agent skills\n\nReusable agent skills for working in this Nx workspace (Nx-related: `nx-workspace`, `nx-generate`, `nx-import`, `nx-plugins`, `nx-run-tasks`, `link-workspace-packages`) live at:\n\n- [`.agents/skills/`](./.agents/skills/) — vendor-neutral location (Agent Skills spec)\n- [`.claude/skills/`](./.claude/skills/) — mirrored copy read by Claude Code by literal path\n\nBoth directories currently hold the same content. Treat `.agents/skills/` as the source of truth; the `.claude/skills/` copy is kept in sync until Claude Code can discover skills from `.agents/skills/` directly.\n\n## Per-package usage\n\nEach package has its own README with usage examples and API notes:\n\n- [`packages/core/supabase-js/README.md`](./packages/core/supabase-js/README.md) — `@supabase/supabase-js` (main isomorphic client)\n- [`packages/core/auth-js/README.md`](./packages/core/auth-js/README.md) — `@supabase/auth-js`\n- [`packages/core/postgrest-js/README.md`](./packages/core/postgrest-js/README.md) — `@supabase/postgrest-js`\n- [`packages/core/realtime-js/README.md`](./packages/core/realtime-js/README.md) — `@supabase/realtime-js`\n- [`packages/core/storage-js/README.md`](./packages/core/storage-js/README.md) — `@supabase/storage-js`\n- [`packages/core/functions-js/README.md`](./packages/core/functions-js/README.md) — `@supabase/functions-js`\n\n## Helping users of a published `@supabase/*` package\n\nThe published npm tarball for each package ships everything an agent needs to give a correct, version-pinned answer. After `npm install @supabase/<package>`, an agent helping with that package should look inside `node_modules/@supabase/<package>/`:\n\n- `AGENTS.md` — per-package agent entry point (read this first; it points at the resources below).\n- `README.md` — usage and quick-start.\n- `src/` — full API source with TSDoc. Every public method and type has JSDoc, most have `@example` blocks. Read source here for the canonical, version-pinned answer instead of guessing from training data.\n- `migrations/` — per-theme migration notes for changes that need caller action.\n\nSource files ship via npm because every package's `files` array in `package.json` includes `\"src\"`. Migration notes ship via `\"migrations\"`. Per-package `AGENTS.md` ships via `\"AGENTS.md\"`. All three are version-pinned by virtue of being inside the installed package.\n\nWe deliberately do NOT ship per-package skills or duplicate docs-site content. The TSDoc-in-source IS the canonical API documentation for the SDK packages.\n\nFor higher-level Supabase guidance (the documentation site, MCP tools, schema management workflows, project setup), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills):\n\n```bash\nnpx skills add supabase/agent-skills\n```\n\nOr use the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins) to install the agent skills together with the Supabase MCP server in one step. See also: [Agent Skills documentation](https://agentskills.io/home).\n\n## Migration notes\n\nMigration notes live close to the code they describe, so they ship via npm alongside the package.\n\n- **Per-package migrations**: `packages/core/<package>/migrations/<theme>.md` — one file per migration theme (e.g. `<new-feature-adoption>.md`). Each file describes what changed, who is affected, and what callers need to do.\n- **Cross-cutting migrations** (affecting the whole repo or all packages): [`docs/MIGRATION.md`](./docs/MIGRATION.md) — one H2 section per theme (e.g. Node.js version drops). Low-frequency by design; split into a directory only if the file grows past a handful of themes.\n\n## Other documentation\n\n- [`docs/TESTING.md`](./docs/TESTING.md) — testing guide with Docker requirements per package\n- [`docs/RELEASE.md`](./docs/RELEASE.md) — release workflows and versioning strategy\n- [Security Policy](https://github.com/supabase/supabase-js/security/policy) — security policies and responsible disclosure\n- [`docs/JSR_PUBLISHING.md`](./docs/JSR_PUBLISHING.md) — JSR registry publishing\n","packages/core/auth-js/AGENTS.md":"# Agent instructions for `@supabase/auth-js`\n\nSupabase Auth client SDK for JavaScript. Handles sign-in, sign-up, sessions, OAuth, MFA, and related auth flows.\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n","packages/core/auth-js/README.md":"<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase Auth JS SDK</h1>\n\n  <h3 align=\"center\">An isomorphic JavaScript SDK for the <a href=\"https://github.com/supabase/auth\">Supabase Auth</a> API.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/auth\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript/auth-signup\">Reference Docs</a>\n    ·\n    <a href=\"https://supabase.github.io/supabase-js/auth-js/v2/spec.json\">TypeDoc</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/auth-js)](https://www.npmjs.com/package/@supabase/auth-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/auth-js)](https://pkg.pr.new/~/supabase/auth-js)\n\n</div>\n\n## Requirements\n\n- **Node.js 22 or later** (Node.js 20 support dropped in v2.110.0)\n- For browser support, all modern browsers are supported\n\n> ⚠️ **Node.js 18 Deprecation Notice**\n>\n> Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped on October 31, 2025.\n\n> ⚠️ **Node.js 20 Deprecation Notice**\n>\n> Node.js 20 reached end-of-life on April 30, 2026. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/45715), support for Node.js 20 was dropped in v2.110.0.\n\n## Quick start\n\nInstall\n\n```bash\nnpm install --save @supabase/auth-js\n```\n\nUsage\n\n```js\nimport { AuthClient } from '@supabase/auth-js'\n\nconst GOTRUE_URL = 'http://localhost:9999'\n\nconst auth = new AuthClient({ url: GOTRUE_URL })\n```\n\n- `signUp()`: https://supabase.com/docs/reference/javascript/auth-signup\n- `signIn()`: https://supabase.com/docs/reference/javascript/auth-signin\n- `signOut()`: https://supabase.com/docs/reference/javascript/auth-signout\n\n### Custom `fetch` implementation\n\n`auth-js` uses the runtime's global `fetch` to make HTTP requests, but an alternative `fetch` implementation can be provided as an option. This is useful in environments where the global `fetch` is unavailable or where you want to customize request behavior:\n\n```js\nimport { AuthClient } from '@supabase/auth-js'\n\nconst AUTH_URL = 'http://localhost:9999'\n\nconst auth = new AuthClient({ url: AUTH_URL, fetch: fetch })\n```\n\n## Development\n\nThis package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:\n\n### Building\n\n```bash\n# Complete build (from monorepo root)\npnpm nx build auth-js\n\n# Build with watch mode for development\npnpm nx build auth-js --watch\n\n# Individual build targets\npnpm nx build:main auth-js    # CommonJS build (dist/main/)\npnpm nx build:module auth-js  # ES Modules build (dist/module/)\n\n# Other useful commands\npnpm nx lint auth-js          # Run ESLint\npnpm nx typecheck auth-js     # TypeScript type checking\npnpm nx docs auth-js          # Generate documentation\n```\n\n#### Build Outputs\n\n- **CommonJS (`dist/main/`)** - For Node.js environments\n- **ES Modules (`dist/module/`)** - For modern bundlers (Webpack, Vite, Rollup)\n- **TypeScript definitions (`dist/module/index.d.ts`)** - Type definitions for TypeScript projects\n\n### Testing\n\nThe auth-js package has two test suites:\n\n1. **CLI Tests** - Main test suite using Supabase CLI (331 tests)\n2. **Docker Tests** - Edge case tests requiring specific GoTrue configurations (11 tests)\n\n#### Prerequisites\n\n- **Supabase CLI** - Required for main test suite ([installation guide](https://supabase.com/docs/guides/cli))\n- **Docker** - Required for edge case tests\n\n#### Running Tests\n\n```bash\n# Run main test suite with Supabase CLI (recommended)\npnpm nx test:auth auth-js\n\n# Run Docker-only edge case tests\npnpm nx test:docker auth-js\n\n# Run both test suites\npnpm nx test:auth auth-js && pnpm nx test:docker auth-js\n```\n\n#### Main Test Suite (Supabase CLI)\n\nThe `test:auth` command automatically:\n\n1. Stops any existing Supabase instance\n2. Starts a local Supabase instance via CLI\n3. Runs the test suite (excludes `docker-tests/` folder)\n4. Cleans up after tests complete\n\n```bash\n# Individual commands for manual control\npnpm nx test:infra auth-js    # Start Supabase CLI\npnpm nx test:suite auth-js    # Run tests only\npnpm nx test:clean-post auth-js  # Stop Supabase CLI\n```\n\n#### Docker Tests (Edge Cases)\n\nThe `test:docker` target runs tests that require specific GoTrue configurations not possible with a single Supabase CLI instance:\n\n- **Signup disabled** - Tests for disabled signup functionality\n- **Asymmetric JWT (RS256)** - Tests for RS256 JWT verification\n- **Phone OTP / SMS** - Tests requiring Twilio SMS provider\n- **Anonymous sign-in disabled** - Tests for disabled anonymous auth\n\nThese tests are located in `test/docker-tests/` and use the Docker Compose setup in `infra/docker-compose.yml`.\n\n```bash\n# Individual commands for manual control\npnpm nx test:docker:infra auth-js    # Start Docker containers\npnpm nx test:docker:suite auth-js    # Run Docker tests only\npnpm nx test:docker:clean-post auth-js  # Stop Docker containers\n```\n\n#### Development Testing\n\nFor actively developing and debugging tests:\n\n```bash\n# Start Supabase CLI once\npnpm nx test:infra auth-js\n\n# Run tests multiple times (faster since instance stays up)\npnpm nx test:suite auth-js\n\n# Clean up when done\npnpm nx test:clean-post auth-js\n```\n\n#### Test Infrastructure\n\n| Suite        | Infrastructure | Configuration               |\n| ------------ | -------------- | --------------------------- |\n| CLI Tests    | Supabase CLI   | `test/supabase/config.toml` |\n| Docker Tests | Docker Compose | `infra/docker-compose.yml`  |\n\n### Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n","packages/core/auth-js/example/react/README.md":"# Supabase `auth-js` example\n\n- Created based on the [Quickstart example](https://supabase.com/docs/guides/auth/quickstarts/react) in the Supabase docs.\n- Bootstrapped with Vite CLI\n\n## Setup\n\n### With a Supabase project\n\n### 1. Create new project\n\nSign up to Supabase - [https://supabase.com/dashboard](https://supabase.com/dashboard) and create a new project. Wait for your database to start.\n\n### 2. Get the URL and Key\n\nCreate a copy of `.env.local.example`:\n\n```bash\ncp .env.local.example .env.local\n```\n\n1. Go to the Project Settings (the cog icon)\n2. Open the Data API tab, and find your API URL\n3. Open the API Keys tab and create a new Publishable key\n4. Set them both in your newly created `.env.local` file.O\n\n### 3. Enable Auth providers\n\n1. From the sidenav, go to Authentication -> Configuration -> Sign In/Providers (https://supabase.com/dashboard/project/<YOUR_PROJECT_ID>/auth/providers)\n2. Enable providers as needed (for this example: Anonymous, Email, Phone, GitHub, Google)\n\n## Run\n\n### Install root dependencies and build `auth-js`\n\n```bash\nnpm i\n```\n\n```bash\nnpx nx build auth-js\n```\n\n### Install the dependencies and run the example\n\n```bash\ncd example/react\n```\n\n```bash\nnpm i; npm run dev\n```\n","packages/core/auth-js/migrations/README.md":"# Migration notes for `@supabase/auth-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/auth-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/auth-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/auth-js`:\n\n1. Read the migration files in `node_modules/@supabase/auth-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/auth-js` only.\n","packages/core/auth-js/test/README.md":"# Testing\n\n## Prerequisites\n\n- Docker & docker compose\n\n### Basic testing\n\nRun all tests:\n\n```sh\nnpm run test\n```\n\n> Note: If tests fail due to connection issues, your tests may be running too soon and the infra is not yet ready.\n> If that's the case, adjust the `sleep 10` duration in:\n> `\"test:infra\": \"cd infra && docker-compose down && docker-compose pull && docker-compose up -d && sleep 10\",`\n> to a value that works for your system setup.\n\n### Advanced\n\n**Start all the infrastructure:**\n\n```sh\nnpm run test:infra\n```\n\nYou can now open the mock mail server on `http://localhost:9000`\n\n**Run the tests only:**\n\n```sh\nnpm run test:suite\n```\n\nAll emails will appear in the mock mail server.\n\n## Passkey (WebAuthn) Tests\n\nPasskey coverage is split across two files:\n\n- `passkey.methods.test.ts` — unit tests for all `auth.passkey.*`, `signInWithPasskey()`,\n  `registerPasskey()` and `admin.passkey.*` methods with mocked `fetch` and a simulated\n  browser environment (no infra needed)\n- `passkey.e2e.test.ts` — full registration/authentication ceremonies against the\n  Supabase CLI Auth server\n\nThe e2e tests rely on:\n\n- `[auth.passkey]` and `[auth.webauthn]` in `test/supabase/config.toml` (requires\n  Supabase CLI >= 2.105.0)\n- `test/lib/software-authenticator.ts`, a minimal software WebAuthn authenticator\n  (ES256, \"none\" attestation, discoverable credentials) that stands in for\n  `navigator.credentials` since the tests run in Node\n\n## RSA Signing Keys\n\n### Security Model\n\nThe auth-js tests require RSA signing keys to verify RS256 JWT tokens. **These keys are NEVER committed to the repository** for security reasons.\n\n### Key Generation\n\nKeys are automatically generated before tests run:\n\n- **Locally**: `nx test:auth auth-js` or `nx test:docker auth-js` automatically generates keys via the `test:generate-keys` target\n- **CI**: GitHub Actions generates fresh keys before each test run\n\n### Manual Key Generation\n\nIf you need to generate keys manually:\n\n```bash\ncd packages/core/auth-js/test\nnode generate-signing-keys.js\n```\n\nThis creates `test/supabase/signing_keys.json` (gitignored).\n\n### JWT Token Generation\n\nJWT tokens (anon, service_role, admin) are **automatically generated** at runtime from the signing keys in `test/lib/clients.ts`. No manual updates needed!\n\nFor debugging/inspection only:\n\n```bash\ncd packages/core/auth-js/test\nnode generate-jwt.js\n```\n\nThis displays the tokens but you don't need to copy them anywhere - they're generated automatically.\n\n## Important Notes\n\n⚠️ **NEVER commit `signing_keys.json`** - It's in `.gitignore` for security\n\n⚠️ **These are TEST KEYS only** - Never use in production\n\n✅ **Fresh keys per test run** - CI generates new keys every time for maximum security\n","packages/core/functions-js/AGENTS.md":"# Agent instructions for `@supabase/functions-js`\n\nJavaScript SDK for invoking Supabase Edge Functions.\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n","packages/core/functions-js/README.md":"<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase Functions JS SDK</h1>\n\n  <h3 align=\"center\">JavaScript SDK to interact with Supabase Edge Functions.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/functions\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript/functions-invoke\">Reference Docs</a>\n    ·\n    <a href=\"https://supabase.github.io/supabase-js/functions-js/v2/spec.json\">TypeDoc</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/functions-js)](https://www.npmjs.com/package/@supabase/functions-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/functions-js)](https://pkg.pr.new/~/supabase/functions-js)\n\n</div>\n\n## Requirements\n\n- **Node.js 22 or later** (Node.js 20 support dropped in v2.110.0)\n- For browser support, all modern browsers are supported\n\n> ⚠️ **Node.js 18 Deprecation Notice**\n>\n> Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped on October 31, 2025.\n\n> ⚠️ **Node.js 20 Deprecation Notice**\n>\n> Node.js 20 reached end-of-life on April 30, 2026. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/45715), support for Node.js 20 was dropped in v2.110.0.\n\n## Quick Start\n\n### Installation\n\n```bash\nnpm install @supabase/functions-js\n```\n\n### Usage\n\n```js\nimport { FunctionsClient } from '@supabase/functions-js'\n\nconst functionsUrl = 'https://<project_ref>.supabase.co/functions/v1'\nconst publishableKey = '<publishable_key>'\n\nconst functions = new FunctionsClient(functionsUrl, {\n  headers: {\n    Authorization: `Bearer ${publishableKey}`,\n  },\n})\n\n// Invoke a function\nconst { data, error } = await functions.invoke('hello-world', {\n  body: { name: 'Functions' },\n})\n```\n\n## Development\n\nThis package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:\n\n### Building\n\n```bash\n# Complete build (from monorepo root)\npnpm nx build functions-js\n\n# Build with watch mode for development\npnpm nx build functions-js --watch\n\n# Individual build targets\npnpm nx build:main functions-js    # CommonJS build (dist/main/)\npnpm nx build:module functions-js  # ES Modules build (dist/module/)\n\n# Other useful commands\npnpm nx clean functions-js         # Clean build artifacts\npnpm nx typecheck functions-js     # TypeScript type checking\npnpm nx docs functions-js          # Generate documentation\n```\n\n#### Build Outputs\n\n- **CommonJS (`dist/main/`)** - For Node.js environments\n- **ES Modules (`dist/module/`)** - For modern bundlers (Webpack, Vite, Rollup)\n- **TypeScript definitions (`dist/module/index.d.ts`)** - Type definitions for TypeScript projects\n\n### Testing\n\n**Docker Required** for relay tests. The functions-js tests use testcontainers to spin up a Deno relay server for testing Edge Function invocations.\n\n```bash\n# Run all tests (from monorepo root)\npnpm nx test functions-js\n\n# Run tests with coverage report\npnpm nx test functions-js --coverage\n\n# Run tests in watch mode during development\npnpm nx test functions-js --watch\n\n# CI test command (runs with coverage)\npnpm nx test:ci functions-js\n```\n\n#### Test Requirements\n\n- **Node.js 22+** - Required for testcontainers\n- **Docker** - Must be installed and running for relay tests\n- No Supabase instance needed - Tests use mocked services and testcontainers\n\n#### What Gets Tested\n\n- **Function invocation** - Testing the `invoke()` method with various options\n- **Relay functionality** - Using a containerized Deno relay to test real Edge Function scenarios\n- **Error handling** - Ensuring proper error responses and retries\n- **Request/response models** - Validating headers, body, and response formats\n\n### Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n","packages/core/functions-js/migrations/README.md":"# Migration notes for `@supabase/functions-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/functions-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/functions-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/functions-js`:\n\n1. Read the migration files in `node_modules/@supabase/functions-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/functions-js` only.\n","packages/core/postgrest-js/AGENTS.md":"# Agent instructions for `@supabase/postgrest-js`\n\nIsomorphic PostgREST client for database operations (select, insert, update, upsert, delete, filters, RPC).\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n","packages/core/postgrest-js/README.md":"<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase PostgREST JS SDK</h1>\n\n  <h3 align=\"center\">Isomorphic JavaScript SDK for <a href=\"https://postgrest.org\">PostgREST</a> with an ORM-like interface.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/database\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript/select\">Reference Docs</a>\n    ·\n    <a href=\"https://supabase.github.io/supabase-js/postgrest-js/v2/spec.json\">TypeDoc</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/postgrest-js)](https://www.npmjs.com/package/@supabase/postgrest-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/postgrest-js)](https://pkg.pr.new/~/supabase/postgrest-js)\n\n</div>\n\n### Quick start\n\nInstall\n\n```bash\nnpm install @supabase/postgrest-js\n```\n\nUsage\n\n```js\nimport { PostgrestClient } from '@supabase/postgrest-js'\n\nconst REST_URL = 'http://localhost:3000'\nconst postgrest = new PostgrestClient(REST_URL)\n```\n\n- [select()](https://supabase.com/docs/reference/javascript/select)\n- [insert()](https://supabase.com/docs/reference/javascript/insert)\n- [update()](https://supabase.com/docs/reference/javascript/update)\n- [delete()](https://supabase.com/docs/reference/javascript/delete)\n\n#### Custom `fetch` implementation\n\n`postgrest-js` uses the runtime's global `fetch` to make HTTP requests, but an alternative `fetch` implementation can be provided as an option. This is useful in environments where the global `fetch` is unavailable or where you want to customize request behavior:\n\n```js\nimport { PostgrestClient } from '@supabase/postgrest-js'\n\nconst REST_URL = 'http://localhost:3000'\nconst postgrest = new PostgrestClient(REST_URL, {\n  fetch: (...args) => fetch(...args),\n})\n```\n\n## Development\n\nThis package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:\n\n### Building\n\n```bash\n# Build (from monorepo root)\npnpm nx build postgrest-js\n\n# Build with watch mode for development\npnpm nx build:watch postgrest-js\n\n# TypeScript type checking\npnpm nx type-check postgrest-js\n\n# Generate documentation\npnpm nx docs postgrest-js\n```\n\n### Testing\n\n**Supabase CLI Required!** The `postgrest-js` tests use the [Supabase CLI](https://supabase.com/docs/guides/local-development/cli/getting-started) to run a local PostgreSQL database and PostgREST server.\n\n#### Quick Start\n\n```bash\n# Run all tests (from monorepo root)\npnpm nx test:ci:postgrest postgrest-js\n```\n\nThis single command automatically:\n\n1. Stops any existing Supabase CLI containers\n2. Starts PostgreSQL database and PostgREST server via Supabase CLI\n3. Resets and seeds the database\n4. Runs all Jest unit tests with coverage\n5. Cleans up containers\n\n#### Individual Test Commands\n\n```bash\n# Run Jest tests with coverage (requires infrastructure running)\npnpm nx test:run postgrest-js\n\n# Run type tests with tstyche\npnpm nx test:types postgrest-js\n\n# Run smoke tests (CommonJS and ESM imports)\npnpm nx test:smoke postgrest-js\n\n# Format code\npnpm nx format postgrest-js\n\n# Check formatting\npnpm nx format:check postgrest-js\n```\n\n#### Test Infrastructure\n\nThe tests use Supabase CLI to spin up:\n\n- **PostgreSQL** - Database with test schema and seed data (port 54322)\n- **PostgREST** - REST API server that the client connects to (port 54321)\n\n```bash\n# Manually manage test infrastructure (from monorepo root)\npnpm nx test:infra postgrest-js      # Start containers\npnpm nx test:clean-pre postgrest-js  # Stop and remove containers\n```\n\nOr directly via Supabase CLI:\n\n```bash\ncd packages/core/postgrest-js\nnpx supabase --workdir ./test start        # Start all services\nnpx supabase --workdir ./test db reset     # Reset and seed database\nnpx supabase --workdir ./test stop         # Stop all services\n```\n\n#### Regenerating TypeScript Types\n\nWhen the database schema changes, regenerate TypeScript types from the actual database:\n\n```bash\n# From the monorepo root\npnpm run codegen:postgrest\n```\n\nThis command automatically:\n\n1. Cleans up any existing Supabase containers\n2. Starts Supabase (PostgreSQL, PostgREST, and all services)\n3. Generates TypeScript types from the database schema\n4. Post-processes the generated types (updates JSON type definitions)\n5. Formats the generated file with Prettier\n6. Cleans up Supabase containers\n\nThe generated types are written to `test/types.generated.ts`.\n\n#### Test Types Explained\n\n- **Unit Tests** - Jest tests covering all client functionality (`pnpm nx test:run postgrest-js`)\n- **Type Tests** - Validates TypeScript types using tstyche (`pnpm nx test:types postgrest-js`)\n- **Smoke Tests** - Basic import/require tests for CommonJS and ESM (`pnpm nx test:smoke postgrest-js`)\n\n#### Prerequisites\n\n- **Supabase CLI** must be installed ([instructions](https://supabase.com/docs/guides/local-development/cli/getting-started)) or can be used through `npx` (`npx supabase`)\n- **Docker** must be installed and running (Supabase CLI uses Docker under the hood)\n- **Port 54321** - PostgREST API\n- **Port 54322** - PostgreSQL database\n- **Port 54323** - Supabase Studio (used for type generation)\n\n#### PostgREST v12 Backward Compatibility Tests\n\nWe maintain backward compatibility tests for PostgREST v12 (the current Supabase CLI uses v14+). These tests ensure the SDK works correctly for users still running older PostgREST versions.\n\n```bash\n# Run v12 compatibility tests (requires Docker)\npnpm nx test:ci:v12 postgrest-js\n```\n\nThis command:\n\n1. Starts PostgREST v12 + PostgreSQL in Docker (ports 3012/5433)\n2. Runs runtime tests that verify v12-specific behavior\n3. Cleans up containers\n\n**Type-only tests** for v12 compatibility also run as part of the regular type tests:\n\n```bash\npnpm nx test:types postgrest-js  # Includes v12-compat.test-d.ts\n```\n\n**Note:** These v12 tests will be removed when v3 ships (sometime in 2026).\n\n### Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n\n## License\n\nThis repo is licensed under MIT License.\n","packages/core/postgrest-js/migrations/README.md":"# Migration notes for `@supabase/postgrest-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/postgrest-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/postgrest-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/postgrest-js`:\n\n1. Read the migration files in `node_modules/@supabase/postgrest-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/postgrest-js` only.\n","packages/core/realtime-js/AGENTS.md":"# Agent instructions for `@supabase/realtime-js`\n\nListen to realtime updates from a Supabase PostgreSQL database. Handles channels, presence, broadcast, and Postgres CDC subscriptions.\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n","packages/core/realtime-js/README.md":"<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase Realtime JS SDK</h1>\n\n  <h3 align=\"center\">Send ephemeral messages with <b>Broadcast</b>, track and synchronize state with <b>Presence</b>, and listen to database changes with <b>Postgres Change Data Capture (CDC)</b>.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/realtime\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript\">Reference Docs</a>\n    ·\n    <a href=\"https://multiplayer.dev\">Multiplayer Demo</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/realtime-js)](https://www.npmjs.com/package/@supabase/realtime-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/realtime-js)](https://pkg.pr.new/~/supabase/realtime-js)\n\n</div>\n\n# Overview\n\nThis SDK enables you to use the following Supabase Realtime's features:\n\n- **Broadcast**: send ephemeral messages from client to clients with minimal latency. Use cases include sharing cursor positions between users.\n- **Presence**: track and synchronize shared state across clients with the help of CRDTs. Use cases include tracking which users are currently viewing a specific webpage.\n- **Postgres Change Data Capture (CDC)**: listen for changes in your PostgreSQL database and send them to clients.\n\n# Usage\n\n## Installing the Package\n\n```bash\nnpm install @supabase/realtime-js\n```\n\n## Creating a Channel\n\n```js\nimport { RealtimeClient } from '@supabase/realtime-js'\n\nconst client = new RealtimeClient(REALTIME_URL, {\n  params: {\n    apikey: API_KEY,\n  },\n})\n\nconst channel = client.channel('test-channel', {})\n\nchannel.subscribe((status, err) => {\n  if (status === 'SUBSCRIBED') {\n    console.log('Connected!')\n  }\n\n  if (status === 'CHANNEL_ERROR') {\n    console.log(`There was an error subscribing to channel: ${err.message}`)\n  }\n\n  if (status === 'TIMED_OUT') {\n    console.log('Realtime server did not respond in time.')\n  }\n\n  if (status === 'CLOSED') {\n    console.log('Realtime channel was unexpectedly closed.')\n  }\n})\n```\n\n### Notes:\n\n- `REALTIME_URL` is `'ws://localhost:4000/socket'` when developing locally and `'wss://<project_ref>.supabase.co/realtime/v1'` when connecting to your Supabase project.\n- `API_KEY` is a JWT whose claims must contain `exp` and `role` (existing database role).\n- Channel name can be any `string`.\n- Setting `private` to `true` means that the client will use RLS to determine if the user can connect or not to a given channel.\n\n## Broadcast\n\nYour client can send and receive messages based on the `event`.\n\n```js\n// Setup...\n\nconst channel = client.channel('broadcast-test', { broadcast: { ack: false, self: false } })\n\nchannel.on('broadcast', { event: 'some-event' }, (payload) => console.log(payload))\n\nchannel.subscribe(async (status) => {\n  if (status === 'SUBSCRIBED') {\n    // Send message to other clients listening to 'broadcast-test' channel\n    await channel.send({\n      type: 'broadcast',\n      event: 'some-event',\n      payload: { hello: 'world' },\n    })\n  }\n})\n```\n\n### Notes:\n\n- Setting `ack` to `true` means that the `channel.send` promise will resolve once server replies with acknowledgment that it received the broadcast message request.\n- Setting `self` to `true` means that the client will receive the broadcast message it sent out.\n\n### Broadcast Replay\n\nBroadcast Replay enables **private** channels to access messages that were sent earlier. Only messages published via [Broadcast From the Database](https://supabase.com/docs/guides/realtime/broadcast#trigger-broadcast-messages-from-your-database) are available for replay.\n\nYou can configure replay with the following options:\n\n- **`since`** (Required): The epoch timestamp in milliseconds, specifying the earliest point from which messages should be retrieved.\n- **`limit`** (Optional): The number of messages to return. This must be a positive integer, with a maximum value of 25.\n\nExample:\n\n```typescript\nconst twelveHours = 12 * 60 * 60 * 1000\nconst twelveHoursAgo = Date.now() - twelveHours\n\nconst config = { private: true, broadcast: { replay: { since: twelveHoursAgo, limit: 10 } } }\n\nsupabase\n  .channel('main:room', { config })\n  .on('broadcast', { event: 'my_event' }, (payload) => {\n    if (payload?.meta?.replayed) {\n      console.log('This message was sent earlier:', payload)\n    } else {\n      console.log('This is a new message', payload)\n    }\n    // ...\n  })\n  .subscribe()\n```\n\n## Presence\n\nYour client can track and sync state that's stored in the channel.\n\n```js\n// Setup...\n\nconst channel = client.channel('presence-test', {\n  config: {\n    presence: {\n      key: '',\n    },\n  },\n})\n\nchannel.on('presence', { event: 'sync' }, () => {\n  console.log('Online users: ', channel.presenceState())\n})\n\nchannel.on('presence', { event: 'join' }, ({ newPresences }) => {\n  console.log('New users have joined: ', newPresences)\n})\n\nchannel.on('presence', { event: 'leave' }, ({ leftPresences }) => {\n  console.log('Users have left: ', leftPresences)\n})\n\nchannel.subscribe(async (status) => {\n  if (status === 'SUBSCRIBED') {\n    const status = await channel.track({ user_id: 1 })\n    console.log(status)\n  }\n})\n```\n\n> `config.presence.enabled` (set automatically if you add an `.on('presence', ...)` listener)\n> controls whether _this_ client receives presence state and updates from other clients —\n> without it, `presenceState()` stays empty for you. It does not affect whether other clients\n> see you: calling `track()` always makes you visible to subscribers that do have presence\n> enabled. On RLS-protected channels, receiving presence updates additionally requires the\n> `presence.read` policy to authorize this client.\n\n## Postgres CDC\n\nReceive database changes on the client.\n\n```js\n// Setup...\n\nconst channel = client.channel('db-changes')\n\nchannel.on('postgres_changes', { event: '*', schema: 'public' }, (payload) => {\n  console.log('All changes in public schema: ', payload)\n})\n\nchannel.on(\n  'postgres_changes',\n  { event: 'INSERT', schema: 'public', table: 'messages' },\n  (payload) => {\n    console.log('All inserts in messages table: ', payload)\n  }\n)\n\nchannel.on(\n  'postgres_changes',\n  { event: 'UPDATE', schema: 'public', table: 'users', filter: 'username=eq.Realtime' },\n  (payload) => {\n    console.log('All updates on users table when username is Realtime: ', payload)\n  }\n)\n\nchannel.subscribe(async (status) => {\n  if (status === 'SUBSCRIBED') {\n    console.log('Ready to receive database changes!')\n  }\n})\n```\n\n### Filters\n\nThe `filter` option accepts **either** a raw string **or** a\n`postgresChangesFilter()` builder — both produce the exact same wire format, so\nyou can mix and match and existing string filters keep working unchanged:\n\n```js\n// Raw string — always supported, fully backward compatible\n{ event: 'UPDATE', schema: 'public', table: 'users', filter: 'id=eq.1' }\n\n// Builder — type-checked, ergonomic; the SDK serializes it for you\n{ event: 'UPDATE', schema: 'public', table: 'users', filter: postgresChangesFilter().eq('id', 1) }\n```\n\nA filter is a `column=operator.value` expression evaluated server-side. The\nfollowing operators are supported:\n\n| Operator              | String form                  | Builder                                | Meaning                           |\n| --------------------- | ---------------------------- | -------------------------------------- | --------------------------------- |\n| `eq`                  | `id=eq.1`                    | `.eq('id', 1)`                         | equal                             |\n| `neq`                 | `id=neq.1`                   | `.neq('id', 1)`                        | not equal                         |\n| `lt` `lte` `gt` `gte` | `age=gte.18`                 | `.gte('age', 18)`                      | comparison                        |\n| `in`                  | `status=in.(active,pending)` | `.in('status', ['active', 'pending'])` | in list                           |\n| `like` `ilike`        | `title=like.%foo%`           | `.like('title', '%foo%')`              | pattern match (case in/sensitive) |\n| `is`                  | `deleted_at=is.null`         | `.is('deleted_at', null)`              | `IS null/true/false/unknown`      |\n| `match` `imatch`      | `title=match.^foo`           | `.match('title', '^foo')`              | POSIX regex match (`~` / `~*`)    |\n| `isdistinct`          | `value=isdistinct.1`         | `.isDistinct('value', 1)`              | NULL-safe inequality              |\n\n**Negation** — prefix any operator with `not.` (string) or use\n`.not(column, operator, value)` (builder):\n\n```js\n// String\n{ event: '*', schema: 'public', table: 'posts', filter: 'status=not.in.(draft,archived)' }\n\n// Builder\n{\n  event: '*',\n  schema: 'public',\n  table: 'posts',\n  filter: postgresChangesFilter().not('status', 'in', ['draft', 'archived']),\n}\n```\n\n**AND composition** — multiple conditions are combined with commas and applied\nas an `AND`. With the builder you just chain calls:\n\n```js\n// String\n{ event: 'UPDATE', schema: 'public', table: 'orders', filter: 'amount=gt.100,status=in.(open,pending)' }\n\n// Builder — equivalent, chained\n{\n  event: 'UPDATE',\n  schema: 'public',\n  table: 'orders',\n  filter: postgresChangesFilter().gt('amount', 100).in('status', ['open', 'pending']),\n}\n```\n\n#### Building filters with `postgresChangesFilter()`\n\nThe builder (modeled on the `postgrest-js` filter methods) is the recommended,\ntype-checked way to compose filters — but it is entirely optional; raw strings\nremain fully supported.\n\n```js\nimport { postgresChangesFilter } from '@supabase/realtime-js'\n\nchannel.on(\n  'postgres_changes',\n  {\n    event: 'UPDATE',\n    schema: 'public',\n    table: 'orders',\n    // → 'amount=gt.100,status=not.in.(draft,archived)'\n    filter: postgresChangesFilter().gt('amount', 100).not('status', 'in', ['draft', 'archived']),\n  },\n  (payload) => console.log(payload)\n)\n```\n\nThe builder exposes `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `in`, `like`,\n`ilike`, `match`, `imatch`, `is`, `isDistinct` and `not`. Call `.build()` if you\nneed the raw string yourself (e.g. to log it or store it).\n\n**Values are sent verbatim** — the server has no quoting/escaping, so spaces and\nquotes are preserved as-is. The server separates conditions by commas outside\nparentheses, so a literal comma in a scalar value can't be expressed (commas\ninside `in.(…)` are fine); the builder throws on such values rather than\nsilently producing a broken filter.\n\n> **Note for PostgREST users:** Realtime evaluates filters server-side over a\n> single table's WAL — there is no resource embedding (`!inner`, embedded\n> filters) and no `or()` grouping. Use `%` (not `*`) for `like`/`ilike`\n> wildcards, since filters travel in the WebSocket payload rather than a URL.\n\n### Selecting columns\n\nUse `select` to receive only a subset of columns instead of the full row. This\nreduces payload size (helpful for large `bytea`/`jsonb` columns). The selected\ncolumns must be selectable by the subscribing role:\n\n```js\nchannel.on(\n  'postgres_changes',\n  { event: '*', schema: 'public', table: 'users', select: ['id', 'first_name'] },\n  (payload) => {\n    // payload.new only contains { id, first_name }\n    console.log(payload)\n  }\n)\n```\n\n## Get All Channels\n\nYou can see all the channels that your client has instantiatied.\n\n```js\n// Setup...\n\nclient.getChannels()\n```\n\n## Cleanup\n\nIt is highly recommended that you clean up your channels after you're done with them.\n\n- Remove a single channel\n\n```js\n// Setup...\n\nconst channel = client.channel('some-channel-to-remove')\n\nchannel.unsubscribe()\nclient.removeChannel(channel)\n```\n\n- Remove all channels and close the connection\n\n```js\n// Setup...\n\nclient.removeAllChannels()\nclient.disconnect()\n```\n\n## Development\n\nThis package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:\n\n### Building\n\n```bash\n# Complete build (from monorepo root)\npnpm nx build realtime-js\n\n# Build with watch mode for development\npnpm nx build realtime-js --watch\n\n# Individual build targets\npnpm nx build:main realtime-js    # CommonJS build (dist/main/)\npnpm nx build:module realtime-js  # ES Modules build (dist/module/)\n\n# Other useful commands\npnpm nx clean realtime-js         # Clean build artifacts\npnpm nx lint realtime-js          # Run ESLint\npnpm nx typecheck realtime-js     # TypeScript type checking\n```\n\n#### Build Outputs\n\n- **CommonJS (`dist/main/`)** - For Node.js environments\n- **ES Modules (`dist/module/`)** - For modern bundlers (Webpack, Vite, Rollup)\n- **TypeScript definitions (`dist/module/index.d.ts`)** - Type definitions for TypeScript projects\n\nNote: Unlike some other packages, realtime-js doesn't include a UMD build since it's primarily used in Node.js or bundled applications.\n\n#### Validating Package Exports\n\n```bash\n# Check if package exports are correctly configured\npnpm nx check-exports realtime-js\n```\n\nThis command uses [\"Are the types wrong?\"](https://github.com/arethetypeswrong/arethetypeswrong.github.io) to verify that the package exports work correctly in different environments. Run this before publishing to ensure your package can be imported correctly by all consumers.\n\n### Testing\n\n**No Docker or Supabase instance required!** The realtime-js tests use mocked WebSocket connections, so they're completely self-contained.\n\n```bash\n# Run unit tests (from monorepo root)\npnpm nx test realtime-js\n\n# Run tests with coverage report\npnpm nx test:coverage realtime-js\n\n# Run tests in watch mode during development\npnpm nx test:watch realtime-js\n```\n\n#### Test Scripts Explained\n\n- **test** - Runs all unit tests once using Vitest\n- **test:coverage** - Runs tests and generates coverage report with terminal output\n- **test:watch** - Runs tests in interactive watch mode for development\n\nThe tests mock WebSocket connections using `mock-socket`, so you can run them anytime without any external dependencies.\n\n### Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n\n## Credits\n\nThis repo draws heavily from [phoenix-js](https://github.com/phoenixframework/phoenix/tree/master/assets/js/phoenix).\n\n## License\n\nMIT.\n","packages/core/realtime-js/example/README.md":"# Realtime Chat Example\n\nA minimal anonymous chat app showcasing Supabase Realtime features:\n\n- **Broadcast** - Real-time message delivery\n- **Presence** - Online user indicators\n- **Database** - Message persistence\n\n## Features\n\n- Anonymous users with random usernames (stored in localStorage)\n- 4 chat rooms: General, Random, Tech, Off-Topic\n- Real-time messages\n- Online users per room\n- Message history on join\n\n## Setup\n\n### 1. Create a Supabase Project\n\nCreate a new project at [database.new](https://database.new)\n\n### 2. Run the Database Migration\n\nGo to the [SQL Editor](https://supabase.com/dashboard/project/_/sql) in your Supabase dashboard and run the migration you find in [supabase/migrations/001_create_messages_table.sql](./supabase/migrations/001_create_messages_table.sql).\n\n### 3. Configure Environment Variables\n\nCopy `.env.example` to `.env` and fill in your Supabase credentials:\n\n```bash\ncp .env.example .env\n```\n\nUpdate the values:\n\n```env\nNEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co\nNEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=your-publishable-key\n```\n\nFind these in your [Supabase project settings](https://supabase.com/dashboard/project/_/settings/api).\n\n### 4. Install Dependencies\n\n```bash\nnpm install\n```\n\n### 5. Run the App\n\n```bash\nnpm run dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000) to start chatting.\n\n## How It Works\n\n### Broadcast\n\nMessages are instantly delivered to all connected clients via Supabase Realtime Broadcast:\n\n```typescript\nchannel.send({\n  type: 'broadcast',\n  event: 'message',\n  payload: message,\n})\n```\n\n### Presence\n\nOnline users are tracked using Supabase Realtime Presence:\n\n```typescript\nchannel.on('presence', { event: 'sync' }, () => {\n  const users = Object.values(channel.presenceState()).flat()\n  setOnlineUsers(users)\n})\n```\n\n### Persistence\n\nMessages are also stored in the database so users see history when joining:\n\n```typescript\nconst { data } = await supabase\n  .from('messages')\n  .select('*')\n  .eq('room', room)\n  .order('created_at', { ascending: true })\n  .limit(50)\n```\n\n## Local Development\n\nYou can run Supabase locally using the Supabase CLI and Docker.\n\n### Prerequisites\n\n- [Docker](https://docs.docker.com/get-docker/) installed and running\n- [Supabase CLI](https://supabase.com/docs/guides/cli) (installed or used through `npx`)\n\n### 1. Start Supabase\n\n```bash\nnpx supabase start\n```\n\nThis will start all Supabase services locally. Once started, you'll see output with your local credentials:\n\n```\n╭──────────────────────────────────────╮\n│ 🔧 Development Tools                 │\n├─────────┬────────────────────────────┤\n│ Studio  │ http://127.0.0.1:54323     │\n│ ...     │ ...                        │\n╰─────────┴────────────────────────────╯\n\n╭──────────────────────────────────────────────╮\n│ 🌐 APIs                                      │\n├────────────────┬─────────────────────────────┤\n│ Project URL    │ http://127.0.0.1:54321      │\n│ ...            │ ...                         │\n╰────────────────┴─────────────────────────────╯\n...\n╭──────────────────────────────────────────────────╮\n│ 🔑 Authentication Keys                           │\n├─────────────┬────────────────────────────────────┤\n│ Publishable │ sb_publishable_...                 │\n│ Secret      │ sb_secret_...                      │\n╰─────────────┴────────────────────────────────────╯\n...\n```\n\n### 2. Configure Environment\n\nCopy `.env.example` to `.env.local`:\n\n```bash\ncp .env.example .env.local\n```\n\nUpdate the values:\n\n```env\nNEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321\nNEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_....\n```\n\n### 3. Run Migrations\n\nApply the database migration:\n\n```bash\nnpx supabase db reset\n```\n\nThis will apply all migrations from `supabase/migrations/`.\n\n### 5. Access Local Dashboard\n\nOpen [http://127.0.0.1:54323](http://127.0.0.1:54323) to access Supabase Studio locally. Here you can:\n\n- View and edit data in the Table Editor\n- Run SQL queries\n- Monitor Realtime connections\n- Check logs\n\n### Stopping Supabase\n\n```bash\nnpx supabase stop\n```\n","packages/core/realtime-js/migrations/README.md":"# Migration notes for `@supabase/realtime-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/realtime-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/realtime-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/realtime-js`:\n\n1. Read the migration files in `node_modules/@supabase/realtime-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/realtime-js` only.\n","packages/core/storage-js/AGENTS.md":"# Agent instructions for `@supabase/storage-js`\n\nIsomorphic storage client for Supabase. Handles bucket and object operations: upload, download, list, signed URLs, transformations.\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n","packages/core/storage-js/README.md":"<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase Storage JS SDK</h1>\n\n  <h3 align=\"center\">JavaScript SDK to interact with Supabase Storage, including file storage and vector embeddings.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/storage\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript/storage-createbucket\">Reference Docs</a>\n    ·\n    <a href=\"https://supabase.github.io/supabase-js/storage-js/v2/spec.json\">TypeDoc</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/storage-js)](https://www.npmjs.com/package/@supabase/storage-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/storage-js)](https://pkg.pr.new/~/supabase/storage-js)\n\n</div>\n\n## Requirements\n\n- **Node.js 22 or later** (Node.js 20 support dropped in v2.110.0)\n- For browser support, all modern browsers are supported\n\n> ⚠️ **Node.js 18 Deprecation Notice**\n>\n> Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped on October 31, 2025.\n\n> ⚠️ **Node.js 20 Deprecation Notice**\n>\n> Node.js 20 reached end-of-life on April 30, 2026. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/45715), support for Node.js 20 was dropped in v2.110.0.\n\n## Features\n\n- **File Storage**: Upload, download, list, move, and delete files\n- **Access Control**: Public and private buckets with fine-grained permissions\n- **Signed URLs**: Generate time-limited URLs for secure file access\n- **Image Transformations**: On-the-fly image resizing and optimization\n- **Vector Embeddings**: Store and query high-dimensional embeddings with similarity search\n- **Analytics Buckets**: Iceberg table-based buckets optimized for analytical queries and data processing\n- **Lifecycle**: Expire previous versions of objects after a number of days\n\n## Quick Start Guide\n\n### Installing the module\n\n```bash\nnpm install @supabase/storage-js\n```\n\n### Connecting to the storage backend\n\nThere are two ways to use the Storage SDK:\n\n#### Option 1: Via Supabase Client (Recommended)\n\nIf you're already using `@supabase/supabase-js`, access storage through the client:\n\n```js\nimport { createClient } from '@supabase/supabase-js'\n\n// Use publishable key for frontend applications\nconst supabase = createClient('https://<project_ref>.supabase.co', '<your-publishable-key>')\n\n// Access storage\nconst storage = supabase.storage\n\n// Access different bucket types\nconst regularBucket = storage.from('my-bucket')\nconst vectorBucket = storage.vectors.from('embeddings-bucket')\nconst analyticsBucket = storage.analytics // Analytics API\n```\n\n#### Option 2: Standalone StorageClient\n\nFor backend applications or when you need to bypass Row Level Security:\n\n```js\nimport { StorageClient } from '@supabase/storage-js'\n\nconst STORAGE_URL = 'https://<project_ref>.supabase.co/storage/v1'\nconst SERVICE_KEY = '<your-secret-key>' // Use secret key for backend operations\n\nconst storageClient = new StorageClient(STORAGE_URL, {\n  apikey: SERVICE_KEY,\n  Authorization: `Bearer ${SERVICE_KEY}`,\n})\n\n// Access different bucket types\nconst regularBucket = storageClient.from('my-bucket')\nconst vectorBucket = storageClient.vectors.from('embeddings-bucket')\nconst analyticsBucket = storageClient.analytics // Analytics API\n```\n\n> **When to use each approach:**\n>\n> - Use `supabase.storage` when working with other Supabase features (auth, database, etc.) in frontend applications\n> - Use `new StorageClient()` for backend applications, Edge Functions, or when you need to bypass RLS policies\n\n> **Note:** Refer to the [Storage Access Control guide](https://supabase.com/docs/guides/storage/access-control) for detailed information on creating RLS policies.\n\n### Understanding Bucket Types\n\nSupabase Storage supports three types of buckets, each optimized for different use cases:\n\n#### 1. Regular Storage Buckets (File Storage)\n\nStandard buckets for storing files, images, videos, and other assets.\n\n```js\n// Create regular storage bucket\nconst { data, error } = await storageClient.createBucket('my-files', {\n  public: false,\n})\n\n// Upload files\nawait storageClient.from('my-files').upload('avatar.png', file)\n```\n\n**Use cases:** User uploads, media assets, documents, backups\n\n#### 2. Vector Buckets (Embeddings Storage)\n\nSpecialized buckets for storing and querying high-dimensional vector embeddings.\n\n```js\n// Create vector bucket\nawait storageClient.vectors.createBucket('embeddings-prod')\n\n// Create index and insert vectors\nconst bucket = storageClient.vectors.from('embeddings-prod')\nawait bucket.createIndex({\n  indexName: 'documents',\n  dimension: 1536,\n  distanceMetric: 'cosine',\n})\n```\n\n**Use cases:** Semantic search, AI-powered recommendations, similarity matching\n\n**[See full Vector Embeddings documentation below](#vector-embeddings)**\n\n#### 3. Analytics Buckets\n\nSpecialized buckets using Apache Iceberg table format, optimized for analytical queries and large-scale data processing.\n\n```js\n// Create analytics bucket\nawait storageClient.analytics.createBucket('analytics-data')\n\n// List analytics buckets\nconst { data, error } = await storageClient.analytics.listBuckets()\n\n// Delete analytics bucket\nawait storageClient.analytics.deleteBucket('analytics-data')\n```\n\n**Use cases:** Time-series data, analytical queries, data lakes, large-scale data processing, business intelligence\n\n**[See full Analytics Buckets documentation below](#analytics-buckets)**\n\n---\n\n### Handling resources\n\n#### Handling Storage Buckets\n\n- Create a new Storage bucket:\n\n  ```js\n  const { data, error } = await storageClient.createBucket(\n    'test_bucket', // Bucket name (must be unique)\n    { public: false } // Bucket options\n  )\n  ```\n\n- Retrieve the details of an existing Storage bucket:\n\n  ```js\n  const { data, error } = await storageClient.getBucket('test_bucket')\n  ```\n\n- Update a new Storage bucket:\n\n  ```js\n  const { data, error } = await storageClient.updateBucket(\n    'test_bucket', // Bucket name\n    { public: false } // Bucket options\n  )\n  ```\n\n- Remove all objects inside a single bucket:\n\n  ```js\n  const { data, error } = await storageClient.emptyBucket('test_bucket')\n  ```\n\n- Delete an existing bucket (a bucket can't be deleted with existing objects inside it):\n\n  ```js\n  const { data, error } = await storageClient.deleteBucket('test_bucket')\n  ```\n\n- Retrieve the details of all Storage buckets within an existing project:\n\n  ```js\n  // List all buckets\n  const { data, error } = await storageClient.listBuckets()\n\n  // List buckets with options (pagination, sorting, search)\n  const { data, error } = await storageClient.listBuckets({\n    limit: 10,\n    offset: 0,\n    sortColumn: 'created_at',\n    sortOrder: 'desc',\n    search: 'prod',\n  })\n  ```\n\n- Manage a bucket's lifecycle policy. Rules expire **previous versions** of objects after a number of days, so versioning needs to be enabled or the policy has nothing to act on. This is Standard buckets only, and the project must have lifecycle enabled.\n\n  ```js\n  // Replaces every existing rule\n  const { data, error } = await storageClient.updateBucketLifecycle('test_bucket', {\n    rules: [\n      {\n        id: 'expire-old-versions',\n        status: 'Enabled',\n        filter: {},\n        noncurrentVersionExpiration: { noncurrentDays: 30 },\n      },\n    ],\n  })\n\n  // Fails with NoSuchLifecycleConfiguration when the bucket has no policy\n  const { data: config, error: configError } = await storageClient.getBucketLifecycle('test_bucket')\n\n  await storageClient.deleteBucketLifecycle('test_bucket')\n  ```\n\n#### Handling Files\n\n- Upload a file to an existing bucket:\n\n  ```js\n  const fileBody = ... // load your file here\n\n  const { data, error } = await storageClient.from('bucket').upload('path/to/file', fileBody)\n  ```\n\n  > Note:  \n  > The path in `data.Key` is prefixed by the bucket ID and is not the value which should be passed to the `download` method in order to fetch the file.  \n  > To fetch the file via the `download` method, use `data.path` and `data.bucketId` as follows:\n  >\n  > ```javascript\n  > const { data, error } = await storageClient.from('bucket').upload('/folder/file.txt', fileBody)\n  > // check for errors\n  > const { data2, error2 } = await storageClient.from(data.bucketId).download(data.path)\n  > ```\n\n  > Note: The `upload` method also accepts a map of optional parameters. For a complete list see the [Supabase API reference](https://supabase.com/docs/reference/javascript/storage-from-upload).\n\n- Download a file from an exisiting bucket:\n\n  ```js\n  const { data, error } = await storageClient.from('bucket').download('path/to/file')\n  ```\n\n- List all the files within a bucket:\n\n  ```js\n  const { data, error } = await storageClient.from('bucket').list('folder')\n  ```\n\n  > Note: The `list` method also accepts a map of optional parameters. For a complete list see the [Supabase API reference](https://supabase.com/docs/reference/javascript/storage-from-list).\n\n- Replace an existing file at the specified path with a new one:\n\n  ```js\n  const fileBody = ... // load your file here\n\n  const { data, error } = await storageClient\n    .from('bucket')\n    .update('path/to/file', fileBody)\n  ```\n\n  > Note: The `upload` method also accepts a map of optional parameters. For a complete list see the [Supabase API reference](https://supabase.com/docs/reference/javascript/storage-from-upload).\n\n- Move an existing file:\n\n  ```js\n  const { data, error } = await storageClient\n    .from('bucket')\n    .move('old/path/to/file', 'new/path/to/file')\n  ```\n\n- Delete files within the same bucket:\n\n  ```js\n  const { data, error } = await storageClient.from('bucket').remove(['path/to/file'])\n  ```\n\n- Create signed URL to download file without requiring permissions:\n\n  ```js\n  const expireIn = 60\n\n  const { data, error } = await storageClient\n    .from('bucket')\n    .createSignedUrl('path/to/file', expireIn)\n  ```\n\n- Retrieve URLs for assets in public buckets:\n\n  ```js\n  const { data, error } = await storageClient.from('public-bucket').getPublicUrl('path/to/file')\n  ```\n\n## Analytics Buckets\n\nSupabase Storage provides specialized analytics buckets using Apache Iceberg table format, optimized for analytical workloads and large-scale data processing. These buckets are designed for data lake architectures, time-series data, and business intelligence applications.\n\n### What are Analytics Buckets?\n\nAnalytics buckets use the Apache Iceberg open table format, providing:\n\n- **ACID transactions** for data consistency\n- **Schema evolution** without data rewrites\n- **Time travel** to query historical data\n- **Efficient metadata management** for large datasets\n- **Optimized for analytical queries** rather than individual file operations\n\n### When to Use Analytics Buckets\n\n**Use analytics buckets for:**\n\n- Time-series data (logs, metrics, events)\n- Data lake architectures\n- Business intelligence and reporting\n- Large-scale batch processing\n- Analytical workloads requiring ACID guarantees\n\n**Use regular storage buckets for:**\n\n- User file uploads (images, documents, videos)\n- Individual file management\n- Content delivery\n- Simple object storage needs\n\n### Quick Start\n\nYou can access analytics functionality through the `analytics` property on your storage client:\n\n#### Via Supabase Client\n\n```typescript\nimport { createClient } from '@supabase/supabase-js'\n\nconst supabase = createClient('https://your-project.supabase.co', 'your-publishable-key')\n\n// Access analytics operations\nconst analytics = supabase.storage.analytics\n\n// Create an analytics bucket\nconst { data, error } = await analytics.createBucket('analytics-data')\nif (error) {\n  console.error('Failed to create analytics bucket:', error.message)\n} else {\n  console.log('Created bucket:', data.name)\n}\n```\n\n#### Via StorageClient\n\n```typescript\nimport { StorageClient } from '@supabase/storage-js'\n\nconst storageClient = new StorageClient('https://your-project.supabase.co/storage/v1', {\n  apikey: 'YOUR_API_KEY',\n  Authorization: 'Bearer YOUR_TOKEN',\n})\n\n// Access analytics operations\nconst analytics = storageClient.analytics\n\n// Create an analytics bucket\nawait analytics.createBucket('analytics-data')\n```\n\n### API Reference\n\n#### Create Analytics Bucket\n\nCreates a new analytics bucket using Iceberg table format:\n\n```typescript\nconst { data, error } = await analytics.createBucket('my-analytics-bucket')\n\nif (error) {\n  console.error('Error:', error.message)\n} else {\n  console.log('Created bucket:', data)\n}\n```\n\n**Returns:**\n\n```typescript\n{\n  data: {\n    id: string\n    type: 'ANALYTICS'\n    format: string\n    created_at: string\n    updated_at: string\n  } | null\n  error: StorageError | null\n}\n```\n\n#### List Analytics Buckets\n\nRetrieves all analytics buckets in your project with optional filtering and pagination:\n\n```typescript\nconst { data, error } = await analytics.listBuckets({\n  limit: 10,\n  offset: 0,\n  sortColumn: 'created_at',\n  sortOrder: 'desc',\n  search: 'prod',\n})\n\nif (data) {\n  console.log(`Found ${data.length} analytics buckets`)\n  data.forEach((bucket) => {\n    console.log(`- ${bucket.id} (created: ${bucket.created_at})`)\n  })\n}\n```\n\n**Parameters:**\n\n- `limit?: number` - Maximum number of buckets to return\n- `offset?: number` - Number of buckets to skip (for pagination)\n- `sortColumn?: 'id' | 'name' | 'created_at' | 'updated_at'` - Column to sort by\n- `sortOrder?: 'asc' | 'desc'` - Sort direction\n- `search?: string` - Search term to filter bucket names\n\n**Returns:**\n\n```typescript\n{\n  data: AnalyticBucket[] | null\n  error: StorageError | null\n}\n```\n\n**Example with Pagination:**\n\n```typescript\n// Fetch first page\nconst firstPage = await analytics.listBuckets({\n  limit: 100,\n  offset: 0,\n  sortColumn: 'created_at',\n  sortOrder: 'desc',\n})\n\n// Fetch second page\nconst secondPage = await analytics.listBuckets({\n  limit: 100,\n  offset: 100,\n  sortColumn: 'created_at',\n  sortOrder: 'desc',\n})\n```\n\n#### Delete Analytics Bucket\n\nDeletes an analytics bucket. The bucket must be empty before deletion.\n\n```typescript\nconst { data, error } = await analytics.deleteBucket('old-analytics-bucket')\n\nif (error) {\n  console.error('Failed to delete:', error.message)\n} else {\n  console.log('Bucket deleted:', data.message)\n}\n```\n\n**Returns:**\n\n```typescript\n{\n  data: { message: string } | null\n  error: StorageError | null\n}\n```\n\n> **Note:** A bucket cannot be deleted if it contains data. You must empty the bucket first.\n\n#### Get Iceberg Catalog for Advanced Operations\n\nFor advanced operations like creating tables, namespaces, and querying Iceberg metadata, use the `from()` method to get a configured [iceberg-js](https://github.com/supabase/iceberg-js) client:\n\n```typescript\n// Get an Iceberg REST Catalog client for your analytics bucket\nconst catalog = analytics.from('analytics-data')\n\n// Create a namespace\nawait catalog.createNamespace({ namespace: ['default'] }, { properties: { owner: 'data-team' } })\n\n// Create a table with schema\nawait catalog.createTable(\n  { namespace: ['default'] },\n  {\n    name: 'events',\n    schema: {\n      type: 'struct',\n      fields: [\n        { id: 1, name: 'id', type: 'long', required: true },\n        { id: 2, name: 'timestamp', type: 'timestamp', required: true },\n        { id: 3, name: 'user_id', type: 'string', required: false },\n      ],\n      'schema-id': 0,\n      'identifier-field-ids': [1],\n    },\n    'partition-spec': {\n      'spec-id': 0,\n      fields: [],\n    },\n    'write-order': {\n      'order-id': 0,\n      fields: [],\n    },\n    properties: {\n      'write.format.default': 'parquet',\n    },\n  }\n)\n\n// List tables in namespace\nconst tables = await catalog.listTables({ namespace: ['default'] })\nconsole.log(tables) // [{ namespace: ['default'], name: 'events' }]\n\n// Load table metadata\nconst table = await catalog.loadTable({ namespace: ['default'], name: 'events' })\n\n// Update table properties\nawait catalog.updateTable(\n  { namespace: ['default'], name: 'events' },\n  { properties: { 'read.split.target-size': '134217728' } }\n)\n\n// Drop table\nawait catalog.dropTable({ namespace: ['default'], name: 'events' })\n\n// Drop namespace\nawait catalog.dropNamespace({ namespace: ['default'] })\n```\n\n**Returns:** `IcebergRestCatalog` instance from [iceberg-js](https://github.com/supabase/iceberg-js)\n\n> **Note:** The `from()` method returns an Iceberg REST Catalog client that provides full access to the Apache Iceberg REST API. For complete documentation of available operations, see the [iceberg-js documentation](https://supabase.github.io/iceberg-js/).\n\n### Error Handling\n\nAnalytics buckets use the same error handling pattern as the rest of the Storage SDK:\n\n```typescript\nconst { data, error } = await analytics.createBucket('my-bucket')\n\nif (error) {\n  console.error('Error:', error.message)\n  console.error('Status:', error.status)\n  console.error('Status Code:', error.statusCode)\n  // Handle error appropriately\n}\n```\n\n#### Throwing Errors\n\nYou can configure the client to throw errors instead of returning them:\n\n```typescript\nconst analytics = storageClient.analytics\nanalytics.throwOnError()\n\ntry {\n  const { data } = await analytics.createBucket('my-bucket')\n  // data is guaranteed to be present\n  console.log('Success:', data)\n} catch (error) {\n  if (error instanceof StorageApiError) {\n    console.error('API Error:', error.statusCode, error.message)\n  }\n}\n```\n\n### TypeScript Types\n\nThe library exports TypeScript types for analytics buckets:\n\n```typescript\nimport type { AnalyticBucket, BucketType, StorageError } from '@supabase/storage-js'\n\n// AnalyticBucket type\ninterface AnalyticBucket {\n  id: string\n  type: 'ANALYTICS'\n  format: string\n  created_at: string\n  updated_at: string\n}\n```\n\n### Common Patterns\n\n#### Checking if a Bucket Exists\n\n```typescript\nasync function bucketExists(bucketName: string): Promise<boolean> {\n  const { data, error } = await analytics.listBuckets({\n    search: bucketName,\n  })\n\n  if (error) {\n    console.error('Error checking bucket:', error.message)\n    return false\n  }\n\n  return data?.some((bucket) => bucket.id === bucketName) ?? false\n}\n```\n\n#### Creating Bucket with Error Handling\n\n```typescript\nasync function ensureAnalyticsBucket(bucketName: string) {\n  // Try to create the bucket\n  const { data, error } = await analytics.createBucket(bucketName)\n\n  if (error) {\n    // Check if bucket already exists (conflict error)\n    if (error.statusCode === '409') {\n      console.log(`Bucket '${bucketName}' already exists`)\n      return { success: true, created: false }\n    }\n\n    // Other error occurred\n    console.error('Failed to create bucket:', error.message)\n    return { success: false, error }\n  }\n\n  console.log(`Created new bucket: '${bucketName}'`)\n  return { success: true, created: true, data }\n}\n```\n\n#### Listing All Buckets with Pagination\n\n```typescript\nasync function getAllAnalyticsBuckets() {\n  const allBuckets: AnalyticBucket[] = []\n  let offset = 0\n  const limit = 100\n\n  while (true) {\n    const { data, error } = await analytics.listBuckets({\n      limit,\n      offset,\n      sortColumn: 'created_at',\n      sortOrder: 'desc',\n    })\n\n    if (error) {\n      console.error('Error fetching buckets:', error.message)\n      break\n    }\n\n    if (!data || data.length === 0) {\n      break\n    }\n\n    allBuckets.push(...data)\n\n    // If we got fewer results than the limit, we've reached the end\n    if (data.length < limit) {\n      break\n    }\n\n    offset += limit\n  }\n\n  return allBuckets\n}\n```\n\n## Vector Embeddings\n\nSupabase Storage provides built-in support for storing and querying high-dimensional vector embeddings, powered by S3 Vectors. This enables semantic search, similarity matching, and AI-powered applications without needing a separate vector database.\n\n> **Note:** Vector embeddings functionality is available in `@supabase/storage-js` v2.76 and later.\n\n### Features\n\n- **Vector Buckets**: Organize vector indexes into logical containers\n- **Vector Indexes**: Define schemas with configurable dimensions and distance metrics\n- **Batch Operations**: Insert/update/delete up to 500 vectors per request\n- **Similarity Search**: Query for nearest neighbors using cosine, euclidean, or dot product distance\n- **Metadata Filtering**: Store and filter vectors by arbitrary JSON metadata\n- **Pagination**: Efficiently scan large vector datasets\n- **Parallel Scanning**: Distribute scans across multiple workers for high throughput\n- **Cross-platform**: Works in Node.js, browsers, and edge runtimes\n\n### Quick Start\n\nYou can access vector functionality in three ways, depending on your use case:\n\n#### Option 1: Via Supabase Client (Most Common)\n\nIf you're using the full Supabase client:\n\n```typescript\nimport { createClient } from '@supabase/supabase-js'\n\nconst supabase = createClient('https://your-project.supabase.co', 'your-publishable-key')\n\n// Access vector operations through storage\nconst vectors = supabase.storage.vectors\n\n// Create a vector bucket\nawait vectors.createBucket('embeddings-prod')\n\n// Create an index\nconst bucket = vectors.from('embeddings-prod')\nawait bucket.createIndex({\n  indexName: 'documents-openai',\n  dataType: 'float32',\n  dimension: 1536,\n  distanceMetric: 'cosine',\n})\n\n// Insert vectors\nconst index = bucket.index('documents-openai')\nawait index.putVectors({\n  vectors: [\n    {\n      key: 'doc-1',\n      data: { float32: [0.1, 0.2, 0.3 /* ...1536 dimensions */] },\n      metadata: { title: 'Introduction', category: 'docs' },\n    },\n  ],\n})\n\n// Query similar vectors\nconst { data, error } = await index.queryVectors({\n  queryVector: { float32: [0.15, 0.25, 0.35 /* ...1536 dimensions */] },\n  topK: 5,\n  returnDistance: true,\n  returnMetadata: true,\n})\n\nif (data) {\n  data.vectors.forEach((match) => {\n    console.log(`${match.key}: distance=${match.distance}`)\n    console.log('Metadata:', match.metadata)\n  })\n}\n```\n\n#### Option 2: Via StorageClient\n\nIf you're using the standalone `StorageClient` for storage operations, access vectors through the `vectors` property:\n\n```typescript\nimport { StorageClient } from '@supabase/storage-js'\n\nconst storageClient = new StorageClient('https://your-project.supabase.co/storage/v1', {\n  apikey: 'YOUR_API_KEY',\n  Authorization: 'Bearer YOUR_TOKEN',\n})\n\n// Access vector operations\nconst vectors = storageClient.vectors\n\n// Use the same API as shown in Option 1\nawait vectors.createBucket('embeddings-prod')\nconst bucket = vectors.from('embeddings-prod')\n// ... rest of operations\n```\n\n#### Option 3: Standalone Vector Client\n\nFor vector-only applications that don't need regular file storage operations:\n\n```typescript\nimport { StorageVectorsClient } from '@supabase/storage-js'\n\n// Initialize standalone vector client\nconst vectorClient = new StorageVectorsClient('https://your-project.supabase.co/storage/v1', {\n  headers: { Authorization: 'Bearer YOUR_TOKEN' },\n})\n\n// Use the same API as shown in Option 1\nawait vectorClient.createBucket('embeddings-prod')\nconst bucket = vectorClient.from('embeddings-prod')\n// ... rest of operations\n```\n\n> **When to use each approach:**\n>\n> - **Option 1**: When using other Supabase features (auth, database, realtime)\n> - **Option 2**: When working with both file storage and vectors\n> - **Option 3**: For dedicated vector-only applications without file storage\n\n### API Reference\n\n#### Client Initialization\n\n```typescript\nconst vectorClient = new StorageVectorsClient(url, options?)\n```\n\n**Options:**\n\n- `headers?: Record<string, string>` - Custom HTTP headers (e.g., Authorization)\n- `fetch?: Fetch` - Custom fetch implementation\n\n#### Vector Buckets\n\nVector buckets are top-level containers for organizing vector indexes.\n\n##### Create Bucket\n\n```typescript\nconst { data, error } = await vectorClient.createBucket('my-bucket')\n```\n\n##### Get Bucket\n\n```typescript\nconst { data, error } = await vectorClient.getBucket('my-bucket')\nconsole.log('Created at:', new Date(data.vectorBucket.creationTime! * 1000))\n```\n\n##### List Buckets\n\n```typescript\nconst { data, error } = await vectorClient.listBuckets({\n  prefix: 'prod-',\n  maxResults: 100,\n})\n\n// Pagination\nif (data?.nextToken) {\n  const next = await vectorClient.listBuckets({ nextToken: data.nextToken })\n}\n```\n\n##### Delete Bucket\n\n```typescript\n// Bucket must be empty (all indexes deleted first)\nconst { error } = await vectorClient.deleteBucket('my-bucket')\n```\n\n#### Vector Indexes\n\nVector indexes define the schema for embeddings including dimension and distance metric.\n\n##### Create Index\n\n```typescript\nconst bucket = vectorClient.from('my-bucket')\n\nawait bucket.createIndex({\n  indexName: 'my-index',\n  dataType: 'float32',\n  dimension: 1536,\n  distanceMetric: 'cosine', // 'cosine' | 'euclidean' | 'dotproduct'\n  metadataConfiguration: {\n    nonFilterableMetadataKeys: ['raw_text', 'internal_id'],\n  },\n})\n```\n\n**Distance Metrics:**\n\n- `cosine` - Cosine similarity (normalized dot product)\n- `euclidean` - Euclidean distance (L2 norm)\n- `dotproduct` - Dot product similarity\n\n##### Get Index\n\n```typescript\nconst { data, error } = await bucket.getIndex('my-index')\nconsole.log('Dimension:', data?.index.dimension)\nconsole.log('Distance metric:', data?.index.distanceMetric)\n```\n\n##### List Indexes\n\n```typescript\nconst { data, error } = await bucket.listIndexes({\n  prefix: 'documents-',\n  maxResults: 100,\n})\n```\n\n##### Delete Index\n\n```typescript\n// Deletes index and all its vectors\nawait bucket.deleteIndex('my-index')\n```\n\n#### Vector Operations\n\n##### Insert/Update Vectors (Upsert)\n\n```typescript\nconst index = vectorClient.from('my-bucket').index('my-index')\n\nawait index.putVectors({\n  vectors: [\n    {\n      key: 'unique-id-1',\n      data: {\n        float32: [\n          /* 1536 numbers */\n        ],\n      },\n      metadata: {\n        title: 'Document Title',\n        category: 'technical',\n        page: 1,\n      },\n    },\n    // ... up to 500 vectors per request\n  ],\n})\n```\n\n**Limitations:**\n\n- 1-500 vectors per request\n- Vectors must match index dimension\n- Keys must be unique within index\n\n##### Get Vectors by Key\n\n```typescript\nconst { data, error } = await index.getVectors({\n  keys: ['doc-1', 'doc-2', 'doc-3'],\n  returnData: true, // Include embeddings\n  returnMetadata: true, // Include metadata\n})\n\ndata?.vectors.forEach((v) => {\n  console.log(v.key, v.metadata)\n})\n```\n\n##### Query Similar Vectors (ANN Search)\n\n```typescript\nconst { data, error } = await index.queryVectors({\n  queryVector: {\n    float32: [\n      /* 1536 numbers */\n    ],\n  },\n  topK: 10,\n  filter: {\n    category: 'technical',\n    published: true,\n  },\n  returnDistance: true,\n  returnMetadata: true,\n})\n\n// Results ordered by similarity\ndata?.vectors.forEach((match) => {\n  console.log(`${match.key}: distance=${match.distance}`)\n})\n```\n\nS3 vector buckets support deep queries with `topK` up to 10,000, returning at most 100 vectors per response. Pass the response's `nextToken` with the same query to retrieve the next page:\n\n```typescript\nconst query = {\n  queryVector: { float32: embedding },\n  topK: 1000,\n  returnDistance: true,\n}\n\nlet nextToken: string | undefined\n\ndo {\n  const { data, error } = await index.queryVectors({ ...query, nextToken })\n  if (error) throw error\n\n  for (const vector of data.vectors) {\n    console.log(`${vector.key}: distance=${vector.distance}`)\n  }\n\n  nextToken = data.nextToken\n} while (nextToken)\n```\n\nThe pgvector backend supports `topK` up to 100 and does not support `nextToken` pagination.\n\n**Filter Syntax:**\nThe `filter` parameter accepts arbitrary JSON for metadata filtering. Non-filterable keys (configured at index creation) cannot be used in filters but can still be returned.\n\n##### List/Scan Vectors\n\n```typescript\n// Simple pagination\nlet nextToken: string | undefined\ndo {\n  const { data } = await index.listVectors({\n    maxResults: 500,\n    nextToken,\n    returnMetadata: true,\n  })\n\n  console.log('Batch:', data?.vectors.length)\n  nextToken = data?.nextToken\n} while (nextToken)\n\n// Parallel scanning (4 workers)\nconst workers = [0, 1, 2, 3].map(async (segmentIndex) => {\n  const { data } = await index.listVectors({\n    segmentCount: 4,\n    segmentIndex,\n    returnMetadata: true,\n  })\n  return data?.vectors || []\n})\n\nconst results = await Promise.all(workers)\nconst allVectors = results.flat()\n```\n\n**Limitations:**\n\n- `maxResults`: 1-1000 (default: 500)\n- `segmentCount`: 1-16\n- Response may be limited by 1MB size\n\n##### Delete Vectors\n\n```typescript\nawait index.deleteVectors({\n  keys: ['doc-1', 'doc-2', 'doc-3'],\n  // ... up to 500 keys per request\n})\n```\n\n### Error Handling\n\nThe library uses a consistent error handling pattern:\n\n```typescript\nconst { data, error } = await vectorClient.createBucket('my-bucket')\n\nif (error) {\n  console.error('Error:', error.message)\n  console.error('Status:', error.status)\n  console.error('Code:', error.statusCode)\n}\n```\n\n#### Error Codes\n\n| Code                         | HTTP | Description             |\n| ---------------------------- | ---- | ----------------------- |\n| `InternalError`              | 500  | Internal server error   |\n| `S3VectorConflictException`  | 409  | Resource already exists |\n| `S3VectorNotFoundException`  | 404  | Resource not found      |\n| `S3VectorBucketNotEmpty`     | 400  | Bucket contains indexes |\n| `S3VectorMaxBucketsExceeded` | 400  | Bucket quota exceeded   |\n| `S3VectorMaxIndexesExceeded` | 400  | Index quota exceeded    |\n\n#### Throwing Errors\n\nYou can configure the client to throw errors instead:\n\n```typescript\nconst vectorClient = new StorageVectorsClient(url, options)\nvectorClient.throwOnError()\n\ntry {\n  const { data } = await vectorClient.createBucket('my-bucket')\n  // data is guaranteed to be present\n} catch (error) {\n  if (error instanceof StorageVectorsApiError) {\n    console.error('API Error:', error.statusCode)\n  }\n}\n```\n\n### Advanced Usage\n\n#### Scoped Clients\n\nCreate scoped clients for cleaner code:\n\n```typescript\n// Bucket-scoped operations\nconst bucket = vectorClient.from('embeddings-prod')\nawait bucket.createIndex({\n  /* ... */\n})\nawait bucket.listIndexes()\n\n// Index-scoped operations\nconst index = bucket.index('documents-openai')\nawait index.putVectors({\n  /* ... */\n})\nawait index.queryVectors({\n  /* ... */\n})\n```\n\n#### Custom Fetch\n\nProvide a custom fetch implementation:\n\n```typescript\nimport { StorageVectorsClient } from '@supabase/storage-js'\n\nconst vectorClient = new StorageVectorsClient(url, {\n  fetch: customFetch,\n  headers: {\n    /* ... */\n  },\n})\n```\n\n#### Batch Processing\n\nProcess large datasets in batches:\n\n```typescript\nasync function insertLargeDataset(vectors: VectorObject[]) {\n  const batchSize = 500\n\n  for (let i = 0; i < vectors.length; i += batchSize) {\n    const batch = vectors.slice(i, i + batchSize)\n    await index.putVectors({ vectors: batch })\n    console.log(`Inserted ${i + batch.length}/${vectors.length}`)\n  }\n}\n```\n\n#### Float32 Validation\n\nEnsure vectors are properly normalized to float32:\n\n```typescript\nimport { normalizeToFloat32 } from '@supabase/storage-js'\n\nconst vector = normalizeToFloat32([0.1, 0.2, 0.3 /* ... */])\n```\n\n### Type Definitions\n\nThe library exports comprehensive TypeScript types:\n\n```typescript\nimport type {\n  VectorBucket,\n  VectorIndex,\n  VectorData,\n  VectorObject,\n  VectorMatch,\n  VectorMetadata,\n  DistanceMetric,\n  ApiResponse,\n  StorageVectorsError,\n} from '@supabase/storage-js'\n```\n\n## Development\n\nThis package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:\n\n### Building\n\n#### Build Scripts Overview\n\n```bash\n# Build the package\npnpm nx build storage-js\n\n# Watch mode for development\npnpm nx build storage-js --watch\n\n# Generate documentation\npnpm nx docs storage-js\n```\n\n### Testing\n\n**Important:** The storage-js tests require a local Supabase stack running via the Supabase CLI. Docker must be running since the Supabase CLI uses it internally.\n\n#### Prerequisites\n\n1. **Docker** must be installed and running (used by Supabase CLI internally)\n2. **Supabase CLI** — installed automatically via `pnpm exec supabase`\n\n#### Test Scripts Overview\n\n| Script            | Description                       | What it does                                                      |\n| ----------------- | --------------------------------- | ----------------------------------------------------------------- |\n| `test:storage`    | **Complete test workflow**        | Runs the full test cycle: clean → start infra → run tests → clean |\n| `test:suite`      | **Jest tests only**               | Runs Jest tests with coverage (requires infra to be running)      |\n| `test:infra`      | **Start test infrastructure**     | Starts Supabase CLI stack (PostgreSQL, Storage API, Kong, etc.)   |\n| `test:clean-post` | **Stop and clean infrastructure** | Stops the Supabase CLI stack                                      |\n\n#### Running Tests\n\n##### Option 1: Complete Test Run (Recommended)\n\nThis handles everything automatically - starting infrastructure, running tests, and cleaning up:\n\n```bash\n# From monorepo root\npnpm nx test:storage storage-js\n```\n\nThis command will:\n\n1. Stop any existing test containers\n2. Build and start fresh test infrastructure\n3. Wait for services to be ready\n4. Run all Jest tests with coverage\n5. Clean up all containers after tests complete\n\n##### Option 2: Manual Infrastructure Management\n\nUseful for development when you want to run tests multiple times without restarting Docker:\n\n```bash\n# Step 1: Start the test infrastructure\n# From root\npnpm nx test:infra storage-js\n# This starts: PostgreSQL, Storage API, Kong Gateway, and imgproxy\n\n# Step 2: Run tests (can run multiple times)\npnpm nx test:suite storage-js\n\n# Step 3: When done, clean up the infrastructure\npnpm nx test:clean-post storage-js\n```\n\n##### Option 3: Development Mode\n\nFor actively developing and debugging tests:\n\n```bash\n# Start infrastructure once (from root)\npnpm nx test:infra storage-js\n\n# Run tests in watch mode\npnpm nx test:suite storage-js --watch\n\n# Clean up when done\npnpm nx test:clean-post storage-js\n```\n\n#### Test Infrastructure Details\n\nThe test infrastructure is managed via the Supabase CLI (`pnpm exec supabase start --workdir test`), which starts a local Supabase stack defined by the config in `test/`. This includes PostgreSQL, the Storage API, Kong Gateway, and supporting services.\n\n#### Common Issues and Solutions\n\n| Issue                             | Solution                                                                                          |\n| --------------------------------- | ------------------------------------------------------------------------------------------------- |\n| Port conflicts                    | Another service is using a required port. Run `pnpm nx test:clean-post storage-js` then try again |\n| \"request failed, reason:\" errors  | Infrastructure isn't running. Run `pnpm nx test:infra storage-js` first                           |\n| Tests fail with connection errors | Ensure Docker is running (Supabase CLI requires Docker)                                           |\n| Stack already running             | Run `pnpm nx test:clean-post storage-js` to stop it before restarting                             |\n\n#### Understanding Test Failures\n\n- **StorageUnknownError with \"request failed\"**: Infrastructure not running\n- **Snapshot failures**: Expected test data has changed — review and update snapshots if needed\n\n### Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n","packages/core/storage-js/migrations/README.md":"# Migration notes for `@supabase/storage-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/storage-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/storage-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/storage-js`:\n\n1. Read the migration files in `node_modules/@supabase/storage-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/storage-js` only.\n","packages/core/supabase-js/AGENTS.md":"# Agent instructions for `@supabase/supabase-js`\n\nMain isomorphic Supabase client for JavaScript. Aggregates `@supabase/auth-js`, `@supabase/postgrest-js`, `@supabase/realtime-js`, `@supabase/storage-js`, and `@supabase/functions-js` into one client.\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n","packages/core/supabase-js/README.md":"<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase JS SDK</h1>\n\n  <h3 align=\"center\">Isomorphic JavaScript SDK for Supabase - combining Auth, Database, Storage, Functions, and Realtime.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/getting-started\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript/start\">Reference Docs</a>\n    ·\n    <a href=\"https://supabase.github.io/supabase-js/supabase-js/v2/spec.json\">TypeDoc</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/supabase-js)](https://www.npmjs.com/package/@supabase/supabase-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/supabase-js)](https://pkg.pr.new/~/supabase/supabase-js)\n\n</div>\n\n## Usage\n\nFirst of all, you need to install the library:\n\n```sh\nnpm install @supabase/supabase-js\n```\n\nThen you're able to import the library and establish the connection with the database:\n\n```js\nimport { createClient } from '@supabase/supabase-js'\n\n// Create a single supabase client for interacting with your database\nconst supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')\n```\n\n### UMD\n\nYou can use plain `<script>`s to import supabase-js from CDNs, like:\n\n```html\n<script src=\"https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2\"></script>\n```\n\nor even:\n\n```html\n<script src=\"https://unpkg.com/@supabase/supabase-js@2\"></script>\n```\n\nThen you can use it from a global `supabase` variable:\n\n```html\n<script>\n  const { createClient } = supabase\n  const _supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')\n\n  console.log('Supabase Instance: ', _supabase)\n  // ...\n</script>\n```\n\n### ESM\n\nYou can use `<script type=\"module\">` to import supabase-js from CDNs, like:\n\n```html\n<script type=\"module\">\n  import { createClient } from 'https://cdn.jsdelivr.net/npm/@supabase/supabase-js/+esm'\n  const supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')\n\n  console.log('Supabase Instance: ', supabase)\n  // ...\n</script>\n```\n\n### Deno\n\nYou can use supabase-js in the Deno runtime via [JSR](https://jsr.io/@supabase/supabase-js):\n\n```js\nimport { createClient } from 'jsr:@supabase/supabase-js@2'\n```\n\n### Custom `fetch` implementation\n\n`supabase-js` uses the runtime's global `fetch` to make HTTP requests, but an alternative `fetch` implementation can be provided as an option. This is useful in environments where the global `fetch` is unavailable or where you want to customize request behavior:\n\n```js\nimport { createClient } from '@supabase/supabase-js'\n\n// Provide a custom `fetch` implementation as an option\nconst supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key', {\n  global: {\n    fetch: (...args) => fetch(...args),\n  },\n})\n```\n\n### Distributed Tracing with OpenTelemetry\n\nThe Supabase JS SDK can attach W3C/OpenTelemetry trace context headers (`traceparent`, `tracestate`, `baggage`) to outgoing requests, enabling end-to-end request tracing from your client application through Supabase services.\n\nTrace propagation is **opt-in** and disabled by default. When enabled, headers are only attached to requests targeting Supabase domains (`*.supabase.co`, `*.supabase.in`, `localhost`).\n\n#### Enable trace propagation\n\nOpting in takes two steps: install `@opentelemetry/api`, and load the tracing runtime by importing the `@supabase/supabase-js/tracing` subpath once at your application entry point. The main bundle contains no OpenTelemetry code — the subpath import is what wires it up.\n\n```js\nimport '@supabase/supabase-js/tracing'\nimport { createClient } from '@supabase/supabase-js'\nimport { trace } from '@opentelemetry/api'\n\nconst supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key', {\n  tracePropagation: true,\n})\n\nconst tracer = trace.getTracer('my-app')\nawait tracer.startActiveSpan('fetch-users', async (span) => {\n  // This request now includes the active trace context.\n  const { data, error } = await supabase.from('users').select('*')\n  span.end()\n})\n```\n\nThe subpath imports `@opentelemetry/api` directly, so module resolution fails loudly if it is not installed. If `tracePropagation` is enabled without the subpath import, the SDK logs a one-time warning and sends requests without trace headers; if no active context exists at request time, it silently no-ops.\n\nTrace propagation is not available via the CDN/UMD build (`https://cdn.jsdelivr.net/.../supabase.js`) — there is no way to load the tracing runtime there.\n\n#### Advanced configuration\n\n```typescript\ninterface TracePropagationOptions {\n  // Enable trace propagation (default: false).\n  enabled?: boolean\n\n  // Respect upstream sampling decisions (default: true).\n  // When true, non-sampled requests carry only `traceparent` (flag preserved,\n  // so nothing is recorded downstream) — Supabase logs still get a trace_id,\n  // while `tracestate` and `baggage` are withheld.\n  respectSamplingDecision?: boolean\n}\n```\n\n```js\n// Always propagate the full trace context, even for non-sampled traces.\nconst supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key', {\n  tracePropagation: { enabled: true, respectSamplingDecision: false },\n})\n```\n\n## Support Policy\n\nThis section outlines the scope of support for various runtime environments in Supabase JavaScript client.\n\n### Node.js\n\nWe only support Node.js versions that are in **Active LTS** or **Maintenance** status as defined by the [official Node.js release schedule](https://nodejs.org/en/about/previous-releases#release-schedule). This means we support versions that are currently receiving long-term support and critical bug fixes.\n\nWhen a Node.js version reaches end-of-life and is no longer in Active LTS or Maintenance status, Supabase will drop it in a **minor release**, and **this won't be considered a breaking change**.\n\n> ⚠️ **Node.js 18 Deprecation Notice**\n>\n> Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped in version `2.79.0`.\n>\n> If you must use Node.js 18, please use version `2.78.0`, which is the last version that supported Node.js 18.\n\n> ⚠️ **Node.js 20 Deprecation Notice**\n>\n> Node.js 20 reached end-of-life on April 30, 2026. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/45715), support for Node.js 20 was dropped in version `2.110.0`.\n>\n> If you must use Node.js 20, please use version `2.109.0`, which is the last version that supported Node.js 20.\n\n### Deno\n\nWe support Deno versions that are currently receiving active development and security updates. We follow the [official Deno release schedule](https://docs.deno.com/runtime/fundamentals/stability_and_releases/) and only support versions from the `stable` and `lts` release channels.\n\nWhen a Deno version reaches end-of-life and is no longer receiving security updates, Supabase will drop it in a **minor release**, and **this won't be considered a breaking change**.\n\n### Browsers\n\nAll modern browsers are supported. We support browsers that provide native `fetch` API. For Realtime features, browsers must also support native `WebSocket` API.\n\n### Bun\n\nWe support Bun runtime environments. Bun provides native fetch support and is compatible with Node.js APIs. Since Bun does not follow a structured release schedule like Node.js or Deno, we support current stable versions of Bun and may drop support for older versions in minor releases without considering it a breaking change.\n\n### React Native\n\nWe support React Native environments with fetch polyfills provided by the framework. Since React Native does not follow a structured release schedule, we support current stable versions and may drop support for older versions in minor releases without considering it a breaking change.\n\n### Cloudflare Workers\n\nWe support Cloudflare Workers runtime environments. Cloudflare Workers provides native fetch support. Since Cloudflare Workers does not follow a structured release schedule, we support current stable versions and may drop support for older versions in minor releases without considering it a breaking change.\n\n### Important Notes\n\n- **Experimental features**: Features marked as experimental may be removed or changed without notice\n\n## Known Build Warnings\n\n### `UNUSED_EXTERNAL_IMPORT` in Vite / Rollup / Nuxt\n\nWhen bundling your app, you may see warnings like:\n\n```\n\"PostgrestError\" is imported from external module \"@supabase/postgrest-js\" but never used in \"...supabase-js/dist/index.mjs\".\n\"FunctionRegion\", \"FunctionsError\", \"FunctionsFetchError\", \"FunctionsHttpError\" and \"FunctionsRelayError\" are imported from external module \"@supabase/functions-js\" but never used in \"...\".\n```\n\n**This is a false positive — your bundle is fine.** Here is why it happens:\n\n`@supabase/supabase-js` re-exports `PostgrestError`, `FunctionsError`, and related symbols so you can import them directly from `@supabase/supabase-js`. However, our build tool merges all imports from the same package into a single import statement in the built output:\n\n```js\n// dist/index.mjs (simplified)\nimport { PostgrestClient, PostgrestError } from '@supabase/postgrest-js'\n//       ^ used internally    ^ re-exported for you\n```\n\nYour bundler checks which names from that import are used _in the code body_, and flags `PostgrestError` as unused because it only appears in an `export` statement — not called or assigned. The export itself is the usage, but downstream bundlers don't track this correctly. This is a known Rollup/Vite limitation with re-exported external imports.\n\n**Nothing is broken.** Tree-shaking and bundle size are unaffected.\n\nTo suppress the warning:\n\n**Vite / Rollup (`vite.config.js` or `rollup.config.js`):**\n\n```js\nexport default {\n  build: {\n    rollupOptions: {\n      onwarn(warning, warn) {\n        if (warning.code === 'UNUSED_EXTERNAL_IMPORT' && warning.exporter?.includes('@supabase/'))\n          return\n        warn(warning)\n      },\n    },\n  },\n}\n```\n\n**Nuxt (`nuxt.config.ts`):**\n\n```ts\nexport default defineNuxtConfig({\n  vite: {\n    build: {\n      rollupOptions: {\n        onwarn(warning, warn) {\n          if (warning.code === 'UNUSED_EXTERNAL_IMPORT' && warning.exporter?.includes('@supabase/'))\n            return\n          warn(warning)\n        },\n      },\n    },\n  },\n})\n```\n\n## Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n\n### Building\n\n```bash\n# From the monorepo root\npnpm nx build supabase-js\n\n# Or with watch mode for development\npnpm nx build supabase-js --watch\n```\n\n### Testing\n\nThere's a complete guide on how to set up your environment for running locally the `supabase-js` integration tests. Please refer to [TESTING.md](./TESTING.md).\n\n## Badges\n\n[![Coverage Status](https://coveralls.io/repos/github/supabase/supabase-js/badge.svg?branch=master)](https://coveralls.io/github/supabase/supabase-js?branch=master)\n","packages/core/supabase-js/migrations/README.md":"# Migration notes for `@supabase/supabase-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/supabase-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/supabase-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/supabase-js`:\n\n1. Read the migration files in `node_modules/@supabase/supabase-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/supabase-js` only.\n","packages/core/supabase-js/test/integration/expo/README.md":"# supabase-js Expo integration test\n\nAn Expo SDK 53 app used as an integration target for `@supabase/supabase-js`. The test suite under `__tests__/` is exercised by:\n\n```bash\nnx test:expo supabase-js\n```\n\nfrom the repository root. CI runs it as part of the `integration-tests` workflow against pkg.pr.new preview builds of `@supabase/supabase-js`.\n\n## Local development\n\n```bash\ncd packages/core/supabase-js/test/integration/expo\nnpm install --legacy-peer-deps --ignore-scripts\nnpm test\n```\n\n`--legacy-peer-deps` is required because preview packages are published with version `0.0.0-automated`, which does not satisfy peer-dependency ranges like `^2.76.1`.\n\n## Why jest is pinned to 29 here\n\nThe rest of the monorepo runs jest 30 (declared at the workspace root). This subdir pins `jest@29.7.0` directly.\n\n`jest-expo` — at every published version including the current latest `jest-expo@56` — depends on jest 29.x internals: `@jest/globals@^29.2.1`, `@jest/create-cache-key-function@^29.2.1`, `babel-jest@^29.2.1`, `jest-environment-jsdom@^29.2.1`, `jest-snapshot@^29.2.1`. The Expo team has not migrated jest-expo to jest 30 yet.\n\nWithout an explicit pin here, `npm install --legacy-peer-deps` lets npm treat the root-hoisted `jest@30` as satisfying `jest-expo`'s optional `jest >=29` peer, so jest is not installed locally. At test time, Node's module resolution then walks up to the root `jest-runtime@30` while `jest-environment-jsdom@29` (a hard dep of jest-expo, installed locally) creates the moduleMocker via `jest-mock@29`. jest 30's runtime calls `_moduleMocker.clearMocksOnScope`, a method that only exists in jest-mock 30 — so CI fails with:\n\n```\nTypeError: this._moduleMocker.clearMocksOnScope is not a function\n```\n\nPinning `jest@29.7.0` in this subdir's `package.json` forces npm to install a complete jest 29 toolchain locally (since the root's jest 30 no longer satisfies the explicit `29.7.0` request). Node's lookup from this dir finds the local v29 internals before walking up. Root and every other package keep jest 30; only this expo test runs on jest 29.\n\n**Remove the pin** when jest-expo ships a jest-30-compatible release — at which point this subdir can fall back to whatever the workspace root provides.\n","packages/core/supabase-js/test/integration/next/README.md":"<a href=\"https://demo-nextjs-with-supabase.vercel.app/\">\n  <img alt=\"Next.js and Supabase Starter Kit - the fastest way to build apps with Next.js and Supabase\" src=\"https://demo-nextjs-with-supabase.vercel.app/opengraph-image.png\">\n  <h1 align=\"center\">Next.js and Supabase Starter Kit</h1>\n</a>\n\n<p align=\"center\">\n The fastest way to build apps with Next.js and Supabase\n</p>\n\n<p align=\"center\">\n  <a href=\"#features\"><strong>Features</strong></a> ·\n  <a href=\"#demo\"><strong>Demo</strong></a> ·\n  <a href=\"#deploy-to-vercel\"><strong>Deploy to Vercel</strong></a> ·\n  <a href=\"#clone-and-run-locally\"><strong>Clone and run locally</strong></a> ·\n  <a href=\"#feedback-and-issues\"><strong>Feedback and issues</strong></a>\n  <a href=\"#more-supabase-examples\"><strong>More Examples</strong></a>\n</p>\n<br/>\n\n## Features\n\n- Works across the entire [Next.js](https://nextjs.org) stack\n  - App Router\n  - Pages Router\n  - Middleware\n  - Client\n  - Server\n  - It just works!\n- supabase-ssr. A package to configure Supabase Auth to use cookies\n- Password-based authentication block installed via the [Supabase UI Library](https://supabase.com/ui/docs/nextjs/password-based-auth)\n- Styling with [Tailwind CSS](https://tailwindcss.com)\n- Components with [shadcn/ui](https://ui.shadcn.com/)\n- Optional deployment with [Supabase Vercel Integration and Vercel deploy](#deploy-your-own)\n  - Environment variables automatically assigned to Vercel project\n\n## Demo\n\nYou can view a fully working demo at [demo-nextjs-with-supabase.vercel.app](https://demo-nextjs-with-supabase.vercel.app/).\n\n## Deploy to Vercel\n\nVercel deployment will guide you through creating a Supabase account and project.\n\nAfter installation of the Supabase integration, all relevant environment variables will be assigned to the project so the deployment is fully functioning.\n\n[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fnext.js%2Ftree%2Fcanary%2Fexamples%2Fwith-supabase&project-name=nextjs-with-supabase&repository-name=nextjs-with-supabase&demo-title=nextjs-with-supabase&demo-description=This+starter+configures+Supabase+Auth+to+use+cookies%2C+making+the+user%27s+session+available+throughout+the+entire+Next.js+app+-+Client+Components%2C+Server+Components%2C+Route+Handlers%2C+Server+Actions+and+Middleware.&demo-url=https%3A%2F%2Fdemo-nextjs-with-supabase.vercel.app%2F&external-id=https%3A%2F%2Fgithub.com%2Fvercel%2Fnext.js%2Ftree%2Fcanary%2Fexamples%2Fwith-supabase&demo-image=https%3A%2F%2Fdemo-nextjs-with-supabase.vercel.app%2Fopengraph-image.png)\n\nThe above will also clone the Starter kit to your GitHub, you can clone that locally and develop locally.\n\nIf you wish to just develop locally and not deploy to Vercel, [follow the steps below](#clone-and-run-locally).\n\n## Clone and run locally\n\n1. You'll first need a Supabase project which can be made [via the Supabase dashboard](https://database.new)\n\n2. Create a Next.js app using the Supabase Starter template npx command\n\n   ```bash\n   npx create-next-app --example with-supabase with-supabase-app\n   ```\n\n   ```bash\n   yarn create next-app --example with-supabase with-supabase-app\n   ```\n\n   ```bash\n   pnpm create next-app --example with-supabase with-supabase-app\n   ```\n\n3. Use `cd` to change into the app's directory\n\n   ```bash\n   cd with-supabase-app\n   ```\n\n4. Rename `.env.example` to `.env.local` and update the following:\n\n   ```\n   NEXT_PUBLIC_SUPABASE_URL=[INSERT SUPABASE PROJECT URL]\n   NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=[INSERT SUPABASE PROJECT API PUBLISHABLE KEY]\n   ```\n\n   Both `NEXT_PUBLIC_SUPABASE_URL` and `NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY` can be found in [your Supabase project's API settings](https://supabase.com/dashboard/project/_?showConnect=true)\n\n5. You can now run the Next.js local development server:\n\n   ```bash\n   npm run dev\n   ```\n\n   The starter kit should now be running on [localhost:3000](http://localhost:3000/).\n\n6. This template comes with the default shadcn/ui style initialized. If you instead want other ui.shadcn styles, delete `components.json` and [re-install shadcn/ui](https://ui.shadcn.com/docs/installation/next)\n\n> Check out [the docs for Local Development](https://supabase.com/docs/guides/getting-started/local-development) to also run Supabase locally.\n\n## Feedback and issues\n\nPlease file feedback and issues over on the [Supabase GitHub org](https://github.com/supabase/supabase/issues/new/choose).\n\n## More Supabase examples\n\n- [Next.js Subscription Payments Starter](https://github.com/vercel/nextjs-subscription-payments)\n- [Cookie-based Auth and the Next.js 13 App Router (free course)](https://youtube.com/playlist?list=PL5S4mPUpp4OtMhpnp93EFSo42iQ40XjbF)\n- [Supabase Auth and the Next.js App Router](https://github.com/supabase/supabase/tree/master/examples/auth/nextjs)\n","packages/shared/tracing/README.md":"# @supabase/tracing\n\nW3C/OpenTelemetry trace context propagation utilities for the Supabase JS SDK.\n\nThis package provides utilities for extracting, parsing, validating, and propagating trace context headers according to the [W3C Trace Context](https://www.w3.org/TR/trace-context/) specification.\n\n## Features\n\n- Build a trace context extractor from a caller-supplied OpenTelemetry API object\n- Parse and validate W3C `traceparent` headers\n- Validate target URLs for trace propagation\n- Default Supabase domain allowlist\n- TypeScript type definitions\n- Zero dependencies — this package never imports `@opentelemetry/api`; callers pass the API object in\n\n## Installation\n\nThis package is typically used internally by `@supabase/supabase-js` and does not need to be installed directly.\n\n## Usage\n\n### Create a Trace Context Extractor\n\n```typescript\nimport { createTraceContextExtractor } from '@supabase/tracing'\nimport { propagation, context } from '@opentelemetry/api'\n\n// The caller owns the OpenTelemetry dependency and passes it in.\nconst extract = createTraceContextExtractor({ propagation, context })\n\nconst traceContext = extract()\n// { traceparent, tracestate, baggage } or null when there is no active trace\n```\n\n### Parse Traceparent Header\n\n```typescript\nimport { parseTraceParent } from '@supabase/tracing'\n\nconst parsed = parseTraceParent('00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01')\n\nconsole.log(parsed)\n// {\n//   version: '00',\n//   traceId: '0af7651916cd43dd8448eb211c80319c',\n//   parentId: 'b7ad6b7169203331',\n//   traceFlags: '01',\n//   isSampled: true\n// }\n```\n\n### Validate Target URLs\n\n```typescript\nimport { shouldPropagateToTarget } from '@supabase/tracing'\n\nconst targets = [\n  'myproject.supabase.co',\n  /.*\\.supabase\\.co$/,\n  (url) => url.hostname === 'localhost',\n]\n\nconst shouldPropagate = shouldPropagateToTarget(\n  'https://myproject.supabase.co/rest/v1/table',\n  targets\n)\n// true\n```\n\n### Get Default Targets\n\n```typescript\nimport { getDefaultPropagationTargets } from '@supabase/tracing'\n\nconst targets = getDefaultPropagationTargets('https://myproject.supabase.co')\n// Returns array of default Supabase domains\n```\n\n## Type Definitions\n\n```typescript\ninterface TraceContext {\n  traceparent?: string\n  tracestate?: string\n  baggage?: string\n}\n\ninterface ParsedTraceParent {\n  version: string\n  traceId: string\n  parentId: string\n  traceFlags: string\n  isSampled: boolean\n}\n\ntype TracePropagationTarget = string | RegExp | ((url: URL) => boolean)\n```\n\n## License\n\nMIT\n"},"files":{".agents/skills/link-workspace-packages/SKILL.md":"---\nname: link-workspace-packages\ndescription: 'Link workspace packages in monorepos (npm, yarn, pnpm, bun). USE WHEN: (1) you just created or generated new packages and need to wire up their dependencies, (2) user imports from a sibling package and needs to add it as a dependency, (3) you get resolution errors for workspace packages (@org/*) like \"cannot find module\", \"failed to resolve import\", \"TS2307\", or \"cannot resolve\". DO NOT patch around with tsconfig paths or manual package.json edits - use the package manager''s workspace commands to fix actual linking.'\n---\n\n# Link Workspace Packages\n\nAdd dependencies between packages in a monorepo. All package managers support workspaces but with different syntax.\n\n## Detect Package Manager\n\nCheck whether there's a `packageManager` field in the root-level `package.json`.\n\nAlternatively check lockfile in repo root:\n\n- `pnpm-lock.yaml` → pnpm\n- `yarn.lock` → yarn\n- `bun.lock` / `bun.lockb` → bun\n- `package-lock.json` → npm\n\n## Workflow\n\n1. Identify consumer package (the one importing)\n2. Identify provider package(s) (being imported)\n3. Add dependency using package manager's workspace syntax\n4. Verify symlinks created in consumer's `node_modules/`\n\n---\n\n## pnpm\n\nUses `workspace:` protocol - symlinks only created when explicitly declared.\n\n```bash\n# From consumer directory\npnpm add @org/ui --workspace\n\n# Or with --filter from anywhere\npnpm add @org/ui --filter @org/app --workspace\n```\n\nResult in `package.json`:\n\n```json\n{ \"dependencies\": { \"@org/ui\": \"workspace:*\" } }\n```\n\n---\n\n## yarn (v2+/berry)\n\nAlso uses `workspace:` protocol.\n\n```bash\nyarn workspace @org/app add @org/ui\n```\n\nResult in `package.json`:\n\n```json\n{ \"dependencies\": { \"@org/ui\": \"workspace:^\" } }\n```\n\n---\n\n## npm\n\nNo `workspace:` protocol. npm auto-symlinks workspace packages.\n\n```bash\nnpm install @org/ui --workspace @org/app\n```\n\nResult in `package.json`:\n\n```json\n{ \"dependencies\": { \"@org/ui\": \"*\" } }\n```\n\nnpm resolves to local workspace automatically during install.\n\n---\n\n## bun\n\nSupports `workspace:` protocol (pnpm-compatible).\n\n```bash\ncd packages/app && bun add @org/ui\n```\n\nResult in `package.json`:\n\n```json\n{ \"dependencies\": { \"@org/ui\": \"workspace:*\" } }\n```\n\n---\n\n## Examples\n\n**Example 1: pnpm - link ui lib to app**\n\n```bash\npnpm add @org/ui --filter @org/app --workspace\n```\n\n**Example 2: npm - link multiple packages**\n\n```bash\nnpm install @org/data-access @org/ui --workspace @org/dashboard\n```\n\n**Example 3: Debug \"Cannot find module\"**\n\n1. Check if dependency is declared in consumer's `package.json`\n2. If not, add it using appropriate command above\n3. Run install (`pnpm install`, `npm install`, etc.)\n\n## Notes\n\n- Symlinks appear in `<consumer>/node_modules/@org/<package>`\n- **Hoisting differs by manager:**\n  - npm/bun: hoist shared deps to root `node_modules`\n  - pnpm: no hoisting (strict isolation, prevents phantom deps)\n  - yarn berry: uses Plug'n'Play by default (no `node_modules`)\n- Root `package.json` should have `\"private\": true` to prevent accidental publish\n",".agents/skills/nx-generate/SKILL.md":"---\nname: nx-generate\ndescription: Generate code using nx generators. INVOKE IMMEDIATELY when user mentions scaffolding, setup, structure, creating apps/libs, or setting up project structure. Trigger words - scaffold, setup, create a ... app, create a ... lib, project structure, generate, add a new project. ALWAYS use this BEFORE calling nx_docs or exploring - this skill handles discovery internally.\nsubagent: general-purpose\ncontext: fork\n---\n\n# Run Nx Generator\n\nNx generators are powerful tools that scaffold projects, make automated code migrations or automate repetitive tasks in a monorepo. They ensure consistency across the codebase and reduce boilerplate work.\n\nThis skill applies when the user wants to:\n\n- Create new projects like libraries or applications\n- Scaffold features or boilerplate code\n- Run workspace-specific or custom generators\n- Do anything else that an nx generator exists for\n\n## Key Principles\n\n1. **Always use `--no-interactive`** - Prevents prompts that would hang execution\n2. **Read the generator source code** - The schema alone is not enough; understand what the generator actually does\n3. **Match existing repo patterns** - Study similar artifacts in the repo and follow their conventions\n4. **Verify with lint/test/build/typecheck etc.** - Generated code must pass verification. The listed targets are just an example, use what's appropriate for this workspace.\n\n## Steps\n\n### 1. Discover Available Generators\n\nUse the Nx CLI to discover available generators:\n\n- List all generators for a plugin: `npx nx list @nx/react`\n- View available plugins: `npx nx list`\n\nThis includes plugin generators (e.g., `@nx/react:library`) and local workspace generators.\n\n### 2. Match Generator to User Request\n\nIdentify which generator(s) could fulfill the user's needs. Consider what artifact type they want, which framework is relevant, and any specific generator names mentioned.\n\n**IMPORTANT**: When both a local workspace generator and an external plugin generator could satisfy the request, **always prefer the local workspace generator**. Local generators are customized for the specific repo's patterns.\n\nIf no suitable generator exists, you can stop using this skill. However, the burden of proof is high—carefully consider all available generators before deciding none apply.\n\n### 3. Get Generator Options\n\nUse the `--help` flag to understand available options:\n\n```bash\nnpx nx g @nx/react:library --help\n```\n\nPay attention to required options, defaults that might need overriding, and options relevant to the user's request.\n\n### Library Buildability\n\n**Default to non-buildable libraries** unless there's a specific reason for buildable.\n\n| Type                        | When to use                                                       | Generator flags                     |\n| --------------------------- | ----------------------------------------------------------------- | ----------------------------------- |\n| **Non-buildable** (default) | Internal monorepo libs consumed by apps                           | No `--bundler` flag                 |\n| **Buildable**               | Publishing to npm, cross-repo sharing, stable libs for cache hits | `--bundler=vite` or `--bundler=swc` |\n\nNon-buildable libs:\n\n- Export `.ts`/`.tsx` source directly\n- Consumer's bundler compiles them\n- Faster dev experience, less config\n\nBuildable libs:\n\n- Have their own build target\n- Useful for stable libs that rarely change (cache hits)\n- Required for npm publishing\n\n**If unclear, ask the user:** \"Should this library be buildable (own build step, better caching) or non-buildable (source consumed directly, simpler setup)?\"\n\n### 4. Read Generator Source Code\n\n**This step is critical.** The schema alone does not tell you everything. Reading the source code helps you:\n\n- Know exactly what files will be created/modified and where\n- Understand side effects (updating configs, installing deps, etc.)\n- Identify behaviors and options not obvious from the schema\n- Understand how options interact with each other\n\nTo find generator source code:\n\n- For plugin generators: Use `node -e \"console.log(require.resolve('@nx/<plugin>/generators.json'));\"` to find the generators.json, then locate the source from there\n- If that fails, read directly from `node_modules/<plugin>/generators.json`\n- For local generators: Typically in `tools/generators/` or a local plugin directory. Search the repo for the generator name.\n\nAfter reading the source, reconsider: Is this the right generator? If not, go back to step 2.\n\n> **⚠️ `--directory` flag behavior can be misleading.**\n> It should specify the full path of the generated library or component, not the parent path that it will be generated in.\n>\n> ```bash\n> # ✅ Correct - directory is the full path for the library\n> nx g @nx/react:library --directory=libs/my-lib\n> # generates libs/my-lib/package.json and more\n>\n> # ❌ Wrong - this will create files at libs and libs/src/...\n> nx g @nx/react:library --name=my-lib --directory=libs\n> # generates libs/package.json and more\n> ```\n\n### 5. Examine Existing Patterns\n\nBefore generating, examine the target area of the codebase:\n\n- Look at similar existing artifacts (other libraries, applications, etc.)\n- Identify naming conventions, file structures, and configuration patterns\n- Note which test runners, build tools, and linters are used\n- Configure the generator to match these patterns\n\n### 6. Dry-Run to Verify File Placement\n\n**Always run with `--dry-run` first** to verify files will be created in the correct location:\n\n```bash\nnpx nx g @nx/react:library --name=my-lib --dry-run --no-interactive\n```\n\nReview the output carefully. If files would be created in the wrong location, adjust your options based on what you learned from the generator source code.\n\nNote: Some generators don't support dry-run (e.g., if they install npm packages). If dry-run fails for this reason, proceed to running the generator for real.\n\n### 7. Run the Generator\n\nExecute the generator:\n\n```bash\nnx generate <generator-name> <options> --no-interactive\n```\n\n> **Tip:** New packages often need workspace dependencies wired up (e.g., importing shared types, being consumed by apps). The `link-workspace-packages` skill can help add these correctly.\n\n### 8. Modify Generated Code (If Needed)\n\nGenerators provide a starting point. Modify the output as needed to:\n\n- Add or modify functionality as requested\n- Adjust imports, exports, or configurations\n- Integrate with existing code patterns\n\n**Important:** If you replace or delete generated test files (e.g., `*.spec.ts`), either write meaningful replacement tests or remove the `test` target from the project configuration. Empty test suites will cause `nx test` to fail.\n\n### 9. Format and Verify\n\nFormat all generated/modified files:\n\n```bash\nnx format --fix\n```\n\nThis example is for built-in nx formatting with prettier. There might be other formatting tools for this workspace, use these when appropriate.\n\nThen verify the generated code works. Keep in mind that the changes you make with a generator or subsequent modifications might impact various projects so it's usually not enough to only run targets for the artifact you just created.\n\n```bash\n# these targets are just an example!\nnx run-many -t build,lint,test,typecheck\n```\n\nThese targets are common examples used across many workspaces. You should do research into other targets available for this workspace and its projects. CI configuration is usually a good guide for what the critical targets are that have to pass.\n\nIf verification fails with manageable issues (a few lint errors, minor type issues), fix them. If issues are extensive, attempt obvious fixes first, then escalate to the user with details about what was generated, what's failing, and what you've attempted.\n",".agents/skills/nx-import/SKILL.md":"---\nname: nx-import\ndescription: Import, merge, or combine repositories into an Nx workspace using nx import. USE WHEN the user asks to adopt Nx across repos, move projects into a monorepo, or bring code/history from another repository.\n---\n\n## Quick Start\n\n- `nx import` brings code from a source repository or folder into the current workspace, preserving commit history.\n- After nx `22.6.0`, `nx import` responds with .ndjson outputs and follow-up questions. For earlier versions, always run with `--no-interactive` and specify all flags directly.\n- Run `nx import --help` for available options.\n- Make sure the destination directory is empty before importing.\n  EXAMPLE: target has `libs/utils` and `libs/models`; source has `libs/ui` and `libs/data-access` — you cannot import `libs/` into `libs/` directly. Import each source library individually.\n\nPrimary docs:\n\n- https://nx.dev/docs/guides/adopting-nx/import-project\n- https://nx.dev/docs/guides/adopting-nx/preserving-git-histories\n\nRead the nx docs if you have the tools for it.\n\n## Import Strategy\n\n**Subdirectory-at-a-time** (`nx import <source> apps --source=apps`):\n\n- **Recommended for monorepo sources** — files land at top level, no redundant config\n- Caveats: multiple import commands (separate merge commits each); dest must not have conflicting directories; root configs (deps, plugins, targetDefaults) not imported\n- **Directory conflicts**: Import into alternate-named dir (e.g. `imported-apps/`), then rename\n\n**Whole repo** (`nx import <source> imported --source=.`):\n\n- **Only for non-monorepo sources** (single-project repos)\n- For monorepos, creates messy nested config (`imported/nx.json`, `imported/tsconfig.base.json`, etc.)\n- If you must: keep imported `tsconfig.base.json` (projects extend it), prefix workspace globs and executor paths\n\n### Directory Conventions\n\n- **Always prefer the destination's existing conventions.** Source uses `libs/`but dest uses `packages/`? Import into `packages/` (`nx import <source> packages/foo --source=libs/foo`).\n- If dest has no convention (empty workspace), ask the user.\n\n### Application vs Library Detection\n\nBefore importing, identify whether the source is an **application** or a **library**:\n\n- **Applications**: Deployable end products. Common indicators:\n  - _Frontend_: `next.config.*`, `vite.config.*` with a build entry point, framework-specific app scaffolding (CRA, Angular CLI app, etc.)\n  - _Backend (Node.js)_: Express/Fastify/NestJS server entrypoint, no `\"exports\"` field in `package.json`\n  - _JVM_: Maven `pom.xml` with `<packaging>jar</packaging>` or `<packaging>war</packaging>` and a `main` class; Gradle `application` plugin or `mainClass` setting\n  - _.NET_: `.csproj`/`.fsproj` with `<OutputType>Exe</OutputType>` or `<OutputType>WinExe</OutputType>`\n  - _General_: Dockerfile, a runnable entrypoint, no public API surface intended for import by other projects\n- **Libraries**: Reusable packages consumed by other projects. Common indicators: `\"main\"`/`\"exports\"` in `package.json`, Maven/Gradle packaging as a library jar, .NET `<OutputType>Library</OutputType>`, named exports intended for import by other packages.\n\n**Destination directory rules**:\n\n- Applications → `apps/<name>`. Check workspace globs (e.g. `pnpm-workspace.yaml`, `workspaces` in root `package.json`) for an existing `apps/*` entry.\n  - If `apps/*` is **not** present, add it before importing: update the workspace glob config and commit (or stage) the change.\n  - Example: `nx import <source> apps/my-app --source=packages/my-app`\n- Libraries → follow the dest's existing convention (`packages/`, `libs/`, etc.).\n\n## Common Issues\n\n### pnpm Workspace Globs (Critical)\n\n`nx import` adds the imported directory itself (e.g. `apps`) to `pnpm-workspace.yaml`, **NOT** glob patterns for packages within it. Cross-package imports will fail with `Cannot find module`.\n\n**Fix**: Replace with proper globs from the source config (e.g. `apps/*`, `libs/shared/*`), then `pnpm install`.\n\n### Root Dependencies and Config Not Imported (Critical)\n\n`nx import` does **NOT** merge from the source's root:\n\n- `dependencies`/`devDependencies` from `package.json`\n- `targetDefaults` from `nx.json` (e.g. `\"@nx/esbuild:esbuild\": { \"dependsOn\": [\"^build\"] }` — critical for build ordering)\n- `namedInputs` from `nx.json` (e.g. `production` exclusion patterns for test files)\n- Plugin configurations from `nx.json`\n\n**Fix**: Diff source and dest `package.json` + `nx.json`. Add missing deps, merge relevant `targetDefaults` and `namedInputs`.\n\n### TypeScript Project References\n\nAfter import, run `nx sync --yes`. If it reports nothing but typecheck still fails, `nx reset` first, then `nx sync --yes` again.\n\n### Explicit Executor Path Fixups\n\nInferred targets (via Nx plugins) resolve config relative to project root — no changes needed. Explicit executor targets (e.g. `@nx/esbuild:esbuild`) have workspace-root-relative paths (`main`, `outputPath`, `tsConfig`, `assets`, `sourceRoot`) that must be prefixed with the import destination directory.\n\n### Plugin Detection\n\n- **Whole-repo import**: `nx import` detects and offers to install plugins. Accept them.\n- **Subdirectory import**: Plugins NOT auto-detected. Manually add with `npx nx add @nx/PLUGIN`. Check `include`/`exclude` patterns — defaults won't match alternate directories (e.g. `apps-beta/`).\n- Run `npx nx reset` after any plugin config changes.\n\n### Redundant Root Files (Whole-Repo Only)\n\nWhole-repo import brings ALL source root files into the dest subdirectory. Clean up:\n\n- `pnpm-lock.yaml` — stale; dest has its own lockfile\n- `pnpm-workspace.yaml` — source workspace config; conflicts with dest\n- `node_modules/` — stale symlinks pointing to source filesystem\n- `.gitignore` — redundant with dest root `.gitignore`\n- `nx.json` — source Nx config; dest has its own\n- `README.md` — optional; keep or remove\n\n**Don't blindly delete** `tsconfig.base.json` — imported projects may extend it via relative paths.\n\n### Root ESLint Config Missing (Subdirectory Import)\n\nSubdirectory import doesn't bring the source's root `eslint.config.mjs`, but project configs reference `../../eslint.config.mjs`.\n\n**Fix order**:\n\n1. Install ESLint deps first: `pnpm add -wD eslint@^9 @nx/eslint-plugin typescript-eslint` (plus framework-specific plugins)\n2. Create root `eslint.config.mjs` (copy from source or create with `@nx/eslint-plugin` base rules)\n3. Then `npx nx add @nx/eslint` to register the plugin in `nx.json`\n\nInstall `typescript-eslint` explicitly — pnpm's strict hoisting won't auto-resolve this transitive dep of `@nx/eslint-plugin`.\n\n### ESLint Version Pinning (Critical)\n\n**Pin ESLint to v9** (`eslint@^9.0.0`). ESLint 10 breaks `@nx/eslint` and many plugins with cryptic errors like `Cannot read properties of undefined (reading 'version')`.\n\n`@nx/eslint` may peer-depend on ESLint 8, causing the wrong version to resolve. If lint fails with `Cannot read properties of undefined (reading 'allow')`, add `pnpm.overrides`:\n\n```json\n{ \"pnpm\": { \"overrides\": { \"eslint\": \"^9.0.0\" } } }\n```\n\n### Dependency Version Conflicts\n\nAfter import, compare key deps (`typescript`, `eslint`, framework-specific). If dest uses newer versions, upgrade imported packages to match (usually safe). If source is newer, may need to upgrade dest first. Use `pnpm.overrides` to enforce single-version policy if desired.\n\n### Module Boundaries\n\nImported projects may lack `tags`. Add tags or update `@nx/enforce-module-boundaries` rules.\n\n### Project Name Collisions (Multi-Import)\n\nSame `name` in `package.json` across source and dest causes `MultipleProjectsWithSameNameError`. **Fix**: Rename conflicting names (e.g. `@org/api` → `@org/teama-api`), update all dep references and import statements, `pnpm install`. The root `package.json` of each imported repo also becomes a project — rename those too.\n\n### Workspace Dep Import Ordering\n\n`pnpm install` fails during `nx import` if a `\"workspace:*\"` dependency hasn't been imported yet. File operations still succeed. **Fix**: Import all projects first, then `pnpm install --no-frozen-lockfile`.\n\n### `.gitkeep` Blocking Subdirectory Import\n\nThe TS preset creates `packages/.gitkeep`. Remove it and commit before importing.\n\n### Frontend tsconfig Base Settings (Critical)\n\nThe TS preset defaults (`module: \"nodenext\"`, `moduleResolution: \"nodenext\"`, `lib: [\"es2022\"]`) are incompatible with frontend frameworks (React, Next.js, Vue, Vite). After importing frontend projects, verify the dest root `tsconfig.base.json`:\n\n- **`moduleResolution`**: Must be `\"bundler\"` (not `\"nodenext\"`)\n- **`module`**: Must be `\"esnext\"` (not `\"nodenext\"`)\n- **`lib`**: Must include `\"dom\"` and `\"dom.iterable\"` (frontend projects need these)\n- **`jsx`**: `\"react-jsx\"` for React-only workspaces, per-project for mixed frameworks\n\nFor **subdirectory imports**, the dest root tsconfig is authoritative — update it. For **whole-repo imports**, imported projects may extend their own nested `tsconfig.base.json`, making this less critical.\n\nIf the dest also has backend projects needing `nodenext`, use per-project overrides instead of changing the root.\n\n**Gotcha**: TypeScript does NOT merge `lib` arrays — a project-level override **replaces** the base array entirely. Always include all needed entries (e.g. `es2022`, `dom`, `dom.iterable`) in any project-level `lib`.\n\n### `@nx/react` Typings for Libraries\n\nReact libraries generated with `@nx/react:library` reference `@nx/react/typings/cssmodule.d.ts` and `@nx/react/typings/image.d.ts` in their tsconfig `types`. These fail with `Cannot find type definition file` unless `@nx/react` is installed in the dest workspace.\n\n**Fix**: `pnpm add -wD @nx/react`\n\n### Jest Preset Missing (Subdirectory Import)\n\nNx presets create `jest.preset.js` at the workspace root, and project jest configs reference it (e.g. `../../jest.preset.js`). Subdirectory import does NOT bring this file.\n\n**Fix**:\n\n1. Run `npx nx add @nx/jest` — registers `@nx/jest/plugin` in `nx.json` and updates `namedInputs`\n2. Create `jest.preset.js` at workspace root (see `references/JEST.md` for content) — `nx add` only creates this when a generator runs, not on bare `nx add`\n3. Install test runner deps: `pnpm add -wD jest jest-environment-jsdom ts-jest @types/jest`\n4. Install framework-specific test deps as needed (see `references/JEST.md`)\n\nFor deeper Jest issues (tsconfig.spec.json, Babel transforms, CI atomization, Jest vs Vitest coexistence), see `references/JEST.md`.\n\n### Target Name Prefixing (Whole-Repo Import)\n\nWhen importing a project with existing npm scripts (`build`, `dev`, `start`, `lint`), Nx plugins auto-prefix inferred target names to avoid conflicts: e.g. `next:build`, `vite:build`, `eslint:lint`.\n\n**Fix**: Remove the Nx-rewritten npm scripts from the imported `package.json`, then either:\n\n- Accept the prefixed names (e.g. `nx run app:next:build`)\n- Rename plugin target names in `nx.json` to use unprefixed names\n\n## Non-Nx Source Issues\n\nWhen the source is a plain pnpm/npm workspace without `nx.json`.\n\n### npm Script Rewriting (Critical)\n\nNx rewrites `package.json` scripts during init, creating broken commands (e.g. `vitest run` → `nx test run`). **Fix**: Remove all rewritten scripts — Nx plugins infer targets from config files.\n\n### `noEmit` → `composite` + `emitDeclarationOnly` (Critical)\n\nPlain TS projects use `\"noEmit\": true`, incompatible with Nx project references.\n\n**Symptoms**: \"typecheck target is disabled because one or more project references set 'noEmit: true'\" or TS6310.\n\n**Fix** in **all** imported tsconfigs:\n\n1. Remove `\"noEmit\": true`. If inherited via extends chain, set `\"noEmit\": false` explicitly.\n2. Add `\"composite\": true`, `\"emitDeclarationOnly\": true`, `\"declarationMap\": true`\n3. Add `\"outDir\": \"dist\"` and `\"tsBuildInfoFile\": \"dist/tsconfig.tsbuildinfo\"`\n4. Add `\"extends\": \"../../tsconfig.base.json\"` if missing. Remove settings now inherited from base.\n\n### Stale node_modules and Lockfiles\n\n`nx import` may bring `node_modules/` (pnpm symlinks pointing to the source filesystem) and `pnpm-lock.yaml` from the source. Both are stale.\n\n**Fix**: `rm -rf imported/node_modules imported/pnpm-lock.yaml imported/pnpm-workspace.yaml imported/.gitignore`, then `pnpm install`.\n\n### ESLint Config Handling\n\n- **Legacy `.eslintrc.json` (ESLint 8)**: Delete all `.eslintrc.*`, remove v8 deps, create flat `eslint.config.mjs`.\n- **Flat config (`eslint.config.js`)**: Self-contained configs can often be left as-is.\n- **No ESLint**: Create both root and project-level configs from scratch.\n\n### TypeScript `paths` Aliases\n\nNx uses `package.json` `\"exports\"` + pnpm workspace linking instead of tsconfig `\"paths\"`. If packages have proper `\"exports\"`, paths are redundant. Otherwise, update paths for the new directory structure.\n\n## Technology-specific Guidance\n\nIdentify technologies in the source repo, then read and apply the matching reference file(s).\n\nAvailable references:\n\n- `references/ESLINT.md` — ESLint projects: duplicate `lint`/`eslint:lint` targets, legacy `.eslintrc.*` linting generated files, flat config `.cjs` self-linting, `typescript-eslint` v7/v9 peer dep conflict, mixed ESLint v8+v9 in one workspace.\n- `references/GRADLE.md`\n- `references/JEST.md` — Jest testing: `@nx/jest/plugin` setup, jest.preset.js, testing deps by framework, tsconfig.spec.json, Jest vs Vitest coexistence, Babel transforms, CI atomization.\n- `references/NEXT.md` — Next.js projects: `@nx/next/plugin` targets, `withNx`, Next.js TS config (`noEmit`, `jsx: \"preserve\"`), auto-installing deps via wrong PM, non-Nx `create-next-app` imports, mixed Next.js+Vite coexistence.\n- `references/TURBOREPO.md`\n- `references/VITE.md` — Vite projects (React, Vue, or both): `@nx/vite/plugin` typecheck target, `resolve.alias`/`__dirname` fixes, framework deps, Vue-specific setup, mixed React+Vue coexistence.\n",".agents/skills/nx-import/references/ESLINT.md":"## ESLint\n\nESLint-specific guidance for `nx import`. For generic import issues (root deps, pnpm globs, project references), see `SKILL.md`.\n\n---\n\n### How `@nx/eslint/plugin` Works\n\n`@nx/eslint/plugin` scans for ESLint config files and creates a lint target for each project. It detects **both** flat config files (`eslint.config.{js,mjs,cjs,ts,mts,cts}`) and legacy config files (`.eslintrc.{json,js,cjs,mjs,yml,yaml}`).\n\n**Plugin options (set during `nx add @nx/eslint`):**\n\n```json\n{\n  \"plugin\": \"@nx/eslint/plugin\",\n  \"options\": {\n    \"targetName\": \"eslint:lint\"\n  }\n}\n```\n\n**Auto-installation**: `nx import` auto-detects ESLint config files and offers to install `@nx/eslint`. Accept the offer — it registers the plugin and updates `namedInputs.production` to exclude ESLint config files.\n\n---\n\n### Duplicate `lint` and `eslint:lint` Targets\n\nAfter import, projects will have **two** lint-related targets if the source `package.json` has a `\"lint\"` npm script:\n\n- `eslint:lint` — inferred by `@nx/eslint/plugin`; has proper caching and input/output tracking\n- `lint` — created by Nx from the npm script via `nx:run-script`; no caching intelligence, just wraps `npm run lint`\n\n**Fix**: Remove the `\"lint\"` script from each project's `package.json`. Keep `\"lint:fix\"` if present — there is no plugin-inferred equivalent for auto-fixing.\n\n---\n\n### Legacy `.eslintrc.*` Configs Linting Generated Files\n\nWhen `@nx/eslint/plugin` runs `eslint .` on a project with a legacy `.eslintrc.*` config that uses `parserOptions.project`, it tries to lint **all** files in the project directory including:\n\n- Generated `dist/**/*.d.ts` files (not in tsconfig `include`)\n- The `.eslintrc.js` config file itself (not in tsconfig `include`)\n\nThis causes `Parsing error: ESLint was configured to run on X using parserOptions.project, however that TSConfig does not include this file`.\n\n**Fix**: Add `ignorePatterns` to the `.eslintrc.*` config:\n\n```json\n// .eslintrc.json\n{\n  \"ignorePatterns\": [\"dist/**\"]\n}\n```\n\n```js\n// .eslintrc.js — also ignore the config file itself since module.exports isn't in tsconfig\nmodule.exports = {\n  ignorePatterns: ['dist/**', '.eslintrc.js'],\n  // ...\n}\n```\n\n---\n\n### Flat Config `.cjs` Files Self-Linting\n\nWhen a project uses `eslint.config.cjs` (CJS flat config), `eslint .` lints the config file itself. The `require()` call on line 1 triggers `@typescript-eslint/no-require-imports`.\n\n**Fix**: Add the config filename to the top-level `ignores` array:\n\n```js\nmodule.exports = tseslint.config(\n  {\n    ignores: ['dist/**', 'node_modules/**', 'eslint.config.cjs'],\n  }\n  // ...\n)\n```\n\nThe same applies to `eslint.config.js` in a CJS project (no `\"type\": \"module\"`) if it uses `require()`.\n\n---\n\n### `typescript-eslint` Version Conflict With ESLint 9\n\n`typescript-eslint@7.x` declares `peerDependencies: { \"eslint\": \"^8.56.0\" }`, but it is commonly used alongside `\"eslint\": \"^9.0.0\"`. npm treats this as a hard peer dep conflict and refuses to install.\n\n**Root cause**: `@nx/eslint` init adds `eslint@~8.57.0` at the workspace root (for its own peer deps). Workspace packages that request `eslint@^9.0.0` + `typescript-eslint@^7.0.0` trigger the conflict when npm resolves their deps.\n\n**Fix**: Upgrade `typescript-eslint` from `^7.0.0` to `^8.0.0` directly in the affected workspace package's `package.json`. The `tseslint.config()` API and `tseslint.configs.recommended` are identical between v7 and v8 — no config changes needed.\n\n```json\n// packages/my-package/package.json\n{\n  \"devDependencies\": {\n    \"typescript-eslint\": \"^8.0.0\"\n  }\n}\n```\n\n**Note**: npm's root-level `\"overrides\"` field does not force versions for workspace packages' direct dependencies — update each package.json individually.\n\n---\n\n### Mixed ESLint v8 and v9 in One Workspace\n\nLegacy v8 and flat-config v9 packages can coexist in the same workspace. Each package resolves its own `eslint` version. The root `eslint@~8.57.0` (added by `@nx/eslint` init) is used by legacy v8 packages; v9 packages get their own hoisted `eslint@9`.\n\n`@nx/eslint/plugin` infers `eslint:lint` targets for **both** config formats. Legacy packages run ESLint v8 with `.eslintrc.*`; flat-config packages run ESLint v9 with `eslint.config.*`. No special nx.json configuration is needed to support both simultaneously.\n",".agents/skills/nx-import/references/JEST.md":"## Jest\n\nJest-specific guidance for `nx import`. For the basic \"Jest Preset Missing\" fix (create `jest.preset.js`, install deps), see `SKILL.md`. This file covers deeper Jest integration issues.\n\n---\n\n### How `@nx/jest` Works\n\n`@nx/jest/plugin` scans for `jest.config.{ts,js,cjs,mjs,cts,mts}` and creates a `test` target for each project.\n\n**Plugin options:**\n\n```json\n{\n  \"plugin\": \"@nx/jest/plugin\",\n  \"options\": {\n    \"targetName\": \"test\"\n  }\n}\n```\n\n`npx nx add @nx/jest` does two things:\n\n1. **Registers `@nx/jest/plugin` in `nx.json`** — without this, no `test` targets are inferred\n2. Updates `namedInputs.production` to exclude test files\n\n**Gotcha**: `nx add @nx/jest` does NOT create `jest.preset.js` — that file is only generated when you run a generator (e.g. `@nx/jest:configuration`). For imports, you must create it manually (see \"Jest Preset\" section below).\n\n**Other gotcha**: If you create `jest.preset.js` manually but skip `npx nx add @nx/jest`, the plugin won't be registered and `nx run PROJECT:test` will fail with \"Cannot find target 'test'\". You need both.\n\n---\n\n### Jest Preset\n\nThe preset provides shared Jest configuration (test patterns, ts-jest transform, resolver, jsdom environment).\n\n**Root `jest.preset.js`:**\n\n```js\nconst nxPreset = require('@nx/jest/preset').default\nmodule.exports = { ...nxPreset }\n```\n\n**Project `jest.config.ts`:**\n\n```ts\nexport default {\n  displayName: 'my-lib',\n  preset: '../../jest.preset.js',\n  // project-specific overrides\n}\n```\n\nThe `preset` path is relative from the project root to the workspace root. Subdirectory imports preserve the original relative path (e.g. `../../jest.preset.js`), which resolves correctly if the import destination matches the source directory depth.\n\n---\n\n### Testing Dependencies\n\n#### Core (always needed)\n\n```\npnpm add -wD jest ts-jest @types/jest @nx/jest\n```\n\n#### Environment-specific\n\n- **DOM testing** (React, Vue, browser libs): `jest-environment-jsdom`\n- **Node testing** (APIs, CLIs): no extra deps (Jest defaults to `node` env, but Nx preset defaults to `jsdom`)\n\n#### React testing\n\n```\npnpm add -wD @testing-library/react @testing-library/jest-dom\n```\n\n#### React with Babel (non-ts-jest transform)\n\nSome React projects use Babel instead of ts-jest for JSX transformation:\n\n```\npnpm add -wD babel-jest @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript\n```\n\n**When**: Project `jest.config` has `transform` using `babel-jest` instead of `ts-jest`. Common in older Nx workspaces and CRA migrations.\n\n#### Vue testing\n\n```\npnpm add -wD @vue/test-utils\n```\n\nVue projects typically use Vitest (not Jest) — see VITE.md.\n\n---\n\n### `tsconfig.spec.json`\n\nJest projects need a `tsconfig.spec.json` that includes test files:\n\n```json\n{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../../dist/out-tsc\",\n    \"module\": \"commonjs\",\n    \"types\": [\"jest\", \"node\"]\n  },\n  \"include\": [\"jest.config.ts\", \"src/**/*.test.ts\", \"src/**/*.spec.ts\", \"src/**/*.d.ts\"]\n}\n```\n\n**Common issues after import:**\n\n- Missing `\"types\": [\"jest\", \"node\"]` — causes `describe`/`it`/`expect` to be unrecognized\n- Missing `\"module\": \"commonjs\"` — Jest doesn't support ESM by default (ts-jest transpiles to CJS)\n- `include` array missing test patterns — TypeScript won't check test files\n\n---\n\n### Jest vs Vitest Coexistence\n\nWorkspaces can have both:\n\n- **Jest**: Next.js apps, older React libs, Node libraries\n- **Vitest**: Vite-based React/Vue apps and libs\n\nBoth `@nx/jest/plugin` and `@nx/vite/plugin` (which infers Vitest targets) coexist without conflicts — they detect different config files (`jest.config.*` vs `vite.config.*`).\n\n**Target naming**: Both default to `test`. If a project somehow has both config files, rename one:\n\n```json\n{\n  \"plugin\": \"@nx/jest/plugin\",\n  \"options\": { \"targetName\": \"jest-test\" }\n}\n```\n\n---\n\n### `@testing-library/jest-dom` — Jest vs Vitest\n\nProjects migrating from Jest to Vitest (or workspaces with both) need different imports:\n\n**Jest** (in `test-setup.ts`):\n\n```ts\nimport '@testing-library/jest-dom'\n```\n\n**Vitest** (in `test-setup.ts`):\n\n```ts\nimport '@testing-library/jest-dom/vitest'\n```\n\nIf the source used Jest but the dest workspace uses Vitest for that project type, update the import path. Also add `@testing-library/jest-dom` to tsconfig `types` array.\n\n---\n\n### Non-Nx Source: Test Script Rewriting\n\nNx rewrites `package.json` scripts during init. Test scripts get broken:\n\n- `\"test\": \"jest\"` → `\"test\": \"nx test\"` (circular if no executor configured)\n- `\"test\": \"vitest run\"` → `\"test\": \"nx test run\"` (broken — `run` becomes an argument)\n\n**Fix**: Remove all rewritten test scripts. `@nx/jest/plugin` and `@nx/vite/plugin` infer test targets from config files.\n\n---\n\n### CI Atomization\n\n`@nx/jest/plugin` supports splitting tests per-file for CI parallelism:\n\n```json\n{\n  \"plugin\": \"@nx/jest/plugin\",\n  \"options\": {\n    \"targetName\": \"test\",\n    \"ciTargetName\": \"test-ci\"\n  }\n}\n```\n\nThis creates `test-ci--src/lib/foo.spec.ts` targets for each test file, enabling Nx Cloud distribution. Not relevant during import, but useful for post-import CI setup.\n\n---\n\n### Common Post-Import Issues\n\n1. **\"Cannot find target 'test'\"**: `@nx/jest/plugin` not registered in `nx.json`. Run `npx nx add @nx/jest` or manually add the plugin entry.\n\n2. **\"Cannot find module 'jest-preset'\"**: `jest.preset.js` missing at workspace root. Create it (see SKILL.md).\n\n3. **\"Cannot find type definition file for 'jest'\"**: Missing `@types/jest` or `tsconfig.spec.json` doesn't have `\"types\": [\"jest\", \"node\"]`.\n\n4. **Tests fail with \"Cannot use import statement outside a module\"**: `ts-jest` not installed or not configured as transform. Check `jest.config.ts` transform section.\n\n5. **Snapshot path mismatches**: After import, `__snapshots__` directories may have paths baked in. Run tests once with `--updateSnapshot` to regenerate.\n\n---\n\n## Fix Order\n\n### Subdirectory Import (Nx Source)\n\n1. `npx nx add @nx/jest` — registers plugin in `nx.json` (does NOT create `jest.preset.js`)\n2. Create `jest.preset.js` manually (see \"Jest Preset\" section above)\n3. Install deps: `pnpm add -wD jest jest-environment-jsdom ts-jest @types/jest`\n4. Install framework test deps: `@testing-library/react @testing-library/jest-dom` (React), `@vue/test-utils` (Vue)\n5. Verify `tsconfig.spec.json` has `\"types\": [\"jest\", \"node\"]`\n6. `nx run-many -t test`\n\n### Whole-Repo Import (Non-Nx Source)\n\n1. Remove rewritten test scripts from `package.json`\n2. `npx nx add @nx/jest` — registers plugin (does NOT create preset)\n3. Create `jest.preset.js` manually\n4. Install deps (same as above)\n5. Verify/fix `jest.config.*` — ensure `preset` path points to root `jest.preset.js`\n6. Verify/fix `tsconfig.spec.json` — add `types`, `module`, `include` if missing\n7. `nx run-many -t test`\n",".agents/skills/nx-import/references/VITE.md":"## Vite\n\nVite-specific guidance for `nx import`. For generic import issues (pnpm globs, root deps, project references, name collisions, ESLint, frontend tsconfig base settings, `@nx/react` typings, Jest preset, non-Nx source handling), see `SKILL.md`.\n\n---\n\n### `@nx/vite/plugin` Typecheck Target\n\n`@nx/vite/plugin` defaults `typecheckTargetName` to `\"vite:typecheck\"`. If the workspace expects `\"typecheck\"`, set it explicitly in `nx.json`. If `@nx/js/typescript` is also registered, rename one target to avoid conflicts (e.g. `\"tsc-typecheck\"` for the JS plugin).\n\nKeep both plugins only if the workspace has non-Vite pure TS libraries — `@nx/js/typescript` handles those while `@nx/vite/plugin` handles Vite projects.\n\n### @nx/vite Plugin Install Failure\n\nPlugin init loads `vite.config.ts` before deps are available. **Fix**: `pnpm add -wD vite @vitejs/plugin-react` (or `@vitejs/plugin-vue`) first, then `pnpm exec nx add @nx/vite`.\n\n### Vite `resolve.alias` and `__dirname` (Non-Nx Sources)\n\n**`__dirname` undefined** (CJS-only): Replace with `fileURLToPath(new URL('./src', import.meta.url))` from `'node:url'`.\n\n**`@/` path alias**: Vite's `resolve.alias` works at runtime but TS needs matching `\"paths\"`. Set `\"baseUrl\": \".\"` in project tsconfig.\n\n**PostCSS/Tailwind**: Verify `content` globs resolve correctly after import.\n\n### Missing TypeScript `types` (Non-Nx Sources)\n\nNon-Nx tsconfigs may not declare all needed types. Ensure Vite projects include `\"types\": [\"node\", \"vite/client\"]` in their tsconfig.\n\n### `noEmit` Fix: Vite-Specific Notes\n\nSee SKILL.md for the generic noEmit→composite fix. Vite-specific additions:\n\n- Non-Nx Vite projects often have **both** `tsconfig.app.json` and `tsconfig.node.json` with `noEmit` — fix both\n- Solution-style tsconfigs (`\"files\": [], \"references\": [...]`) may lack `extends`. Add `extends` pointing to the dest root `tsconfig.base.json` so base settings (`moduleResolution`, `lib`) apply.\n- This is safe — Vite/Vitest ignore TypeScript emit settings.\n\n### Dependency Version Conflicts\n\n**Shared Vite deps (both frameworks):** `vite`, `vitest`, `jsdom`, `@types/node`, `typescript` (dev)\n\n**Vite 6→7**: Typecheck fails (`Plugin<any>` type mismatch); build/serve still works. Fix: align versions.\n**Vitest 3→4**: Usually works; type conflicts may surface in shared test utils.\n\n---\n\n## React Router 7 (Vite-Based)\n\nReact Router 7 (`@react-router/dev`) uses Vite under the hood with a `vite.config.ts` and a `react-router.config.ts`. The `@nx/vite/plugin` detects `vite.config.ts` and creates inferred targets.\n\n### Targets\n\n`@nx/vite/plugin` creates `build`, `dev`, `serve` targets. The `build` target invokes the script defined in `package.json` (usually `react-router build`), not `vite build` directly.\n\n**No separate typecheck target from `@nx/vite/plugin`** — React Router 7 typegen is run as part of `typecheck` (e.g. `react-router typegen && tsc`). The `typecheck` target is inferred from the tsconfig. Keep the `typecheck` script in `package.json` if present; it is not rewritten.\n\n### tsconfig Notes\n\nReact Router 7 uses a single `tsconfig.json` (no `tsconfig.app.json`/`tsconfig.node.json` split). It includes:\n\n- `\"rootDirs\": [\".\", \"./.react-router/types\"]` — for generated type files; keep as-is\n- `\"paths\": { \"~/*\": [\"./app/*\"] }` — self-referential alias; keep as-is\n- `\"noEmit\": true` — replace with composite settings per SKILL.md\n\n### Build Output\n\nReact Router 7 outputs to `build/` (not `dist/`). Add `build` to the dest root `.gitignore`.\n\n### Generated Types Directory\n\nReact Router 7 generates `.react-router/` at the project root for route type generation. Add `.react-router` to the dest root `.gitignore`.\n\n---\n\n## TanStack Start (Vite-Based)\n\nTanStack Start uses Vinxi under the hood, which wraps Vite. Projects have a standard `vite.config.ts` that `@nx/vite/plugin` detects normally.\n\n### Targets\n\n`@nx/vite/plugin` creates `build`, `dev`, `preview`, `serve-static`, `typecheck` targets. The `build` target runs `vite build` which invokes the TanStack Start Vinxi pipeline (produces both client and SSR bundles).\n\n### tsconfig Notes\n\nTanStack Start uses a single `tsconfig.json` with `\"allowImportingTsExtensions\": true` and `\"noEmit\": true`. Apply the standard noEmit → composite fix. `allowImportingTsExtensions` is compatible with `emitDeclarationOnly: true` — no change needed.\n\n### `paths` Aliases\n\nTanStack Start commonly uses `\"#/*\": [\"./src/*\"]` and `\"@/*\": [\"./src/*\"]`. These are self-referential — keep as-is for a single-project app.\n\n### Uncommitted Source Repo\n\n`create-tan-stack` initializes a git repo but does NOT make an initial commit. Before importing, commit first:\n\n```bash\ngit -C /path/to/source add . && git -C /path/to/source commit -m \"Initial commit\"\n```\n\n### Generated and Build Directories\n\nTanStack Start / Vinxi / Nitro generate several directories that must be added to the dest root `.gitignore`:\n\n- `.vinxi` — Vinxi build cache\n- `.tanstack` — TanStack generated files\n- `.nitro` — Nitro build artifacts\n- `.output` — server-side build output (SSR/edge)\n\nThese are not covered by `dist` or `build`.\n\n---\n\n## React-Specific\n\n### React Dependencies\n\n**Production:** `react`, `react-dom`\n**Dev:** `@types/react`, `@types/react-dom`, `@vitejs/plugin-react`, `@testing-library/react`, `@testing-library/jest-dom`, `jsdom`\n**ESLint (Nx sources):** `eslint-plugin-import`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`, `eslint-plugin-react-hooks`\n**ESLint (`create-vite`):** `eslint-plugin-react-refresh`, `eslint-plugin-react-hooks` — self-contained flat configs can be left as-is\n**Nx plugins:** `@nx/react` (generators), `@nx/vite`, `@nx/vitest`, `@nx/eslint`\n\n### React TypeScript Configuration\n\nAdd `\"jsx\": \"react-jsx\"` — in `tsconfig.base.json` for single-framework workspaces, per-project for mixed (see Mixed section).\n\n### React ESLint Config\n\n```js\nimport nx from '@nx/eslint-plugin'\nimport baseConfig from '../../eslint.config.mjs'\nexport default [\n  ...baseConfig,\n  ...nx.configs['flat/react'],\n  { files: ['**/*.ts', '**/*.tsx'], rules: {} },\n]\n```\n\n### React Version Conflicts\n\nReact 18 (source) + React 19 (dest): pnpm may hoist mismatched `react-dom`, causing `TypeError: Cannot read properties of undefined (reading 'S')`. **Fix**: Align versions with `pnpm.overrides`.\n\n### `@testing-library/jest-dom` with Vitest\n\nIf source used Jest: change import to `@testing-library/jest-dom/vitest` in test-setup.ts, add to tsconfig `types`.\n\n---\n\n## Vue-Specific\n\n### Vue Dependencies\n\n**Production:** `vue` (plus `vue-router`, `pinia` if used)\n**Dev:** `@vitejs/plugin-vue`, `vue-tsc`, `@vue/test-utils`, `jsdom`\n**ESLint:** `eslint-plugin-vue`, `vue-eslint-parser`, `@vue/eslint-config-typescript`, `@vue/eslint-config-prettier`\n**Nx plugins:** `@nx/vue` (generators), `@nx/vite`, `@nx/vitest`, `@nx/eslint` (install AFTER deps — see below)\n\n### Vue TypeScript Configuration\n\nAdd to `tsconfig.base.json` (single-framework) or per-project (mixed):\n\n```json\n{ \"jsx\": \"preserve\", \"jsxImportSource\": \"vue\", \"resolveJsonModule\": true }\n```\n\n### `vue-shims.d.ts`\n\nVue SFC files need a type declaration. Usually exists in each project's `src/` and imports cleanly. If missing:\n\n```ts\ndeclare module '*.vue' {\n  import { defineComponent } from 'vue'\n  const component: ReturnType<typeof defineComponent>\n  export default component\n}\n```\n\n### `vue-tsc` Auto-Detection\n\nBoth `@nx/js/typescript` and `@nx/vite/plugin` auto-detect `vue-tsc` when installed — no manual config needed. Remove source scripts like `\"typecheck\": \"vue-tsc --noEmit\"`.\n\n### ESLint Plugin Installation Order (Critical)\n\n`@nx/eslint` init **crashes** if Vue ESLint deps aren't installed first (it loads all config files).\n\n**Correct order:**\n\n1. `pnpm add -wD eslint@^9 eslint-plugin-vue vue-eslint-parser @vue/eslint-config-typescript @typescript-eslint/parser @nx/eslint-plugin typescript-eslint`\n2. Create root `eslint.config.mjs`\n3. Then `npx nx add @nx/eslint`\n\n### Vue ESLint Config Pattern\n\n```js\nimport vue from 'eslint-plugin-vue'\nimport vueParser from 'vue-eslint-parser'\nimport tsParser from '@typescript-eslint/parser'\nimport baseConfig from '../../eslint.config.mjs'\nexport default [\n  ...baseConfig,\n  ...vue.configs['flat/recommended'],\n  {\n    files: ['**/*.vue'],\n    languageOptions: { parser: vueParser, parserOptions: { parser: tsParser } },\n  },\n  {\n    files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.vue'],\n    rules: { 'vue/multi-word-component-names': 'off' },\n  },\n]\n```\n\n**Important**: `vue-eslint-parser` override must come **AFTER** base config — `flat/typescript` sets the TS parser globally without a `files` filter, breaking `.vue` parsing.\n\n`vue-eslint-parser` must be an explicit pnpm dependency (strict resolution prevents transitive import).\n\n**Known issue**: Some generated Vue ESLint configs omit `vue-eslint-parser`. Use the pattern above instead.\n\n---\n\n## Mixed React + Vue\n\nWhen both frameworks coexist, several settings become per-project.\n\n### tsconfig `jsx` — Per-Project Only\n\n- React: `\"jsx\": \"react-jsx\"` in project tsconfig\n- Vue: `\"jsx\": \"preserve\"`, `\"jsxImportSource\": \"vue\"` in project tsconfig\n- Root: **NO** `jsx` setting\n\n### Typecheck — Auto-Detects Framework\n\n`@nx/vite/plugin` uses `vue-tsc` for Vue projects and `tsc` for React automatically.\n\n```json\n{\n  \"plugins\": [\n    { \"plugin\": \"@nx/eslint/plugin\", \"options\": { \"targetName\": \"lint\" } },\n    {\n      \"plugin\": \"@nx/vite/plugin\",\n      \"options\": {\n        \"buildTargetName\": \"build\",\n        \"typecheckTargetName\": \"typecheck\",\n        \"testTargetName\": \"test\"\n      }\n    }\n  ]\n}\n```\n\nRemove `@nx/js/typescript` if all projects use Vite. Keep it (renamed to `\"tsc-typecheck\"`) only for non-Vite pure TS libs.\n\n### ESLint — Three-Tier Config\n\n1. **Root**: Base rules only, no framework-specific rules\n2. **React projects**: Extend root + `nx.configs['flat/react']`\n3. **Vue projects**: Extend root + `vue.configs['flat/recommended']` + `vue-eslint-parser`\n\n**Required packages**: Shared (`eslint@^9`, `@nx/eslint-plugin`, `typescript-eslint`, `@typescript-eslint/parser`), React (`eslint-plugin-import`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`, `eslint-plugin-react-hooks`), Vue (`eslint-plugin-vue`, `vue-eslint-parser`)\n\n`@nx/react`/`@nx/vue` are for generators only — no target conflicts.\n\n---\n\n## Redundant npm Scripts After Import\n\n`nx import` copies `package.json` verbatim, so npm scripts come along. For Vite-based projects `@nx/vite/plugin` already infers the same targets from `vite.config.ts` — the npm scripts just shadow the plugin with weaker `nx:run-script` wrappers (no first-class caching inputs/outputs). Remove them after import.\n\n### Standalone Vite App (`create-vite`)\n\nRemove the following scripts — every one is redundant:\n\n| Script                        | Plugin replacement                                                           |\n| ----------------------------- | ---------------------------------------------------------------------------- |\n| `dev: vite`                   | `@nx/vite/plugin` → `dev`                                                    |\n| `build: tsc -b && vite build` | `@nx/vite/plugin` → `build`; `typecheck` via `@nx/js/typescript` handles tsc |\n| `preview: vite preview`       | `@nx/vite/plugin` → `preview`                                                |\n| `lint: eslint .`              | `@nx/eslint/plugin` → `eslint:lint`                                          |\n\n### TanStack Start\n\nRemove `build`, `dev`, `preview`, and `test` scripts, but move any hardcoded `--port` flag to `vite.config.ts` first:\n\n```ts\n// vite.config.ts\nexport default defineConfig({\n  server: { port: 3000 },  // replaces `vite dev --port 3000`\n  ...\n})\n```\n\n### React Router 7 — Keep ALL scripts\n\nDo **not** remove React Router 7 scripts. They use the framework CLI (`react-router build`, `react-router dev`, `react-router-serve`) which is not interchangeable with plain `vite`:\n\n- `typecheck` runs `react-router typegen && tsc` — typegen must precede `tsc` or it fails on missing route types\n- `start` serves the SSR bundle — no plugin equivalent\n\n---\n\n## Fix Orders\n\n### Nx Source\n\n1. Generic fixes from SKILL.md (pnpm globs, root deps, executor paths, frontend tsconfig base settings, `@nx/react` typings)\n2. Configure `@nx/vite/plugin` typecheck target\n3. **React**: `jsx: \"react-jsx\"` (root or per-project)\n4. **Vue**: `jsx: \"preserve\"` + `jsxImportSource: \"vue\"`; verify `vue-shims.d.ts`; install ESLint deps before `@nx/eslint`\n5. **Mixed**: `jsx` per-project; remove/rename `@nx/js/typescript`\n6. `nx sync --yes && nx reset && nx run-many -t typecheck,build,test,lint`\n\n### Non-Nx Source (additional steps)\n\n0. Import into `apps/<name>` (see SKILL.md: \"Application vs Library Detection\")\n1. Generic fixes from SKILL.md (stale files cleanup, pnpm globs, rewritten scripts, target name prefixing, noEmit→composite, ESLint handling)\n2. Fix `noEmit` in **all** tsconfigs (app, node, etc. — non-Nx projects often have multiple)\n3. Add `extends` to solution-style tsconfigs so root settings apply\n4. Fix `resolve.alias` / `__dirname` / `baseUrl`\n5. Ensure `types` include `vite/client` and `node`\n6. Install `@nx/vite` manually if it failed during import\n7. Remove redundant npm scripts so `@nx/vite/plugin` infers them natively (see \"Redundant npm Scripts\" section)\n8. **Vue**: Add `outDir` + `**/*.vue.d.ts` to ESLint ignores\n9. Full verification\n\n### Multiple-Source Imports\n\nSee SKILL.md for generic multi-import (name collisions, dep refs). Vite-specific: fix tsconfig `references` paths for alternate directories (`../../libs/` → `../../libs-beta/`).\n\n### Non-Nx Source: React Router 7\n\n1. Ensure source has at least one commit (see SKILL.md: \"Source Repo Has No Commits\")\n2. `nx import` whole-repo into `apps/<name>` (see SKILL.md: \"Application vs Library Detection\") → auto-installs `@nx/vite`, `@nx/react`\n3. Stale file cleanup: `node_modules/`, `package-lock.json`, `.gitignore`\n4. Fix `tsconfig.json`: `noEmit` → `composite + emitDeclarationOnly + outDir + tsBuildInfoFile`\n5. Add `build` and `.react-router` to dest root `.gitignore`\n6. **Keep all npm scripts** — React Router 7 uses framework CLI (`react-router build/dev`), not plain vite (see \"Redundant npm Scripts\" above)\n7. `npm install && nx reset && nx sync --yes`\n\n### Non-Nx Source: TanStack Start\n\n1. Ensure source has at least one commit — `create-tan-stack` does NOT auto-commit (see SKILL.md)\n2. `nx import` whole-repo into `apps/<name>` (see SKILL.md: \"Application vs Library Detection\") → auto-installs `@nx/vite`, `@nx/vitest`\n3. Stale file cleanup: `node_modules/`, `package-lock.json`, `.gitignore`\n4. Fix `tsconfig.json`: `noEmit` → `composite + emitDeclarationOnly + outDir + tsBuildInfoFile`\n5. Keep `allowImportingTsExtensions` — compatible with `emitDeclarationOnly: true`\n6. Add `.vinxi`, `.tanstack`, `.nitro`, `.output` to dest root `.gitignore`\n7. Move hardcoded `--port` from `dev` script into `vite.config.ts` (`server: { port: N }`)\n8. Remove redundant npm scripts — `@nx/vite/plugin` infers `build`, `dev`, `preview`, `test` (see \"Redundant npm Scripts\" above)\n9. `npm install && nx reset && nx sync --yes`\n\n### Quick Reference: React vs Vue\n\n| Aspect        | React                    | Vue                                       |\n| ------------- | ------------------------ | ----------------------------------------- |\n| Vite plugin   | `@vitejs/plugin-react`   | `@vitejs/plugin-vue`                      |\n| Type checker  | `tsc`                    | `vue-tsc` (auto-detected)                 |\n| SFC support   | N/A                      | `vue-shims.d.ts` needed                   |\n| tsconfig jsx  | `\"react-jsx\"`            | `\"preserve\"` + `\"jsxImportSource\": \"vue\"` |\n| ESLint parser | Standard TS              | `vue-eslint-parser` + TS sub-parser       |\n| ESLint setup  | Straightforward          | Must install deps before `@nx/eslint`     |\n| Test utils    | `@testing-library/react` | `@vue/test-utils`                         |\n\n### Quick Reference: Vite-Based React Frameworks\n\n| Aspect             | Vite (standalone) | React Router 7          | TanStack Start           |\n| ------------------ | ----------------- | ----------------------- | ------------------------ |\n| Build config       | `vite.config.ts`  | `vite.config.ts`        | `vite.config.ts`         |\n| Build output       | `dist/`           | `build/`                | `dist/`                  |\n| SSR bundle         | No                | Yes (`build/server/`)   | Yes (`dist/server/`)     |\n| tsconfig layout    | app + node split  | Single tsconfig         | Single tsconfig          |\n| Auto-committed     | Depends on tool   | Usually yes             | **No — commit first**    |\n| `nx import` plugin | `@nx/vite`        | `@nx/vite`, `@nx/react` | `@nx/vite`, `@nx/vitest` |\n\n---\n\n## Iteration Log\n\n### Scenario 6: Multiple non-Nx React apps (CRA, Next.js, React Router 7, TanStack Start, Vite) → TS preset (PASS)\n\n- Sources: 5 standalone non-Nx repos with different build tools\n- Dest: CNW ts preset (Nx 22.5.1), npm workspaces, `packages/*`\n- Import: whole-repo for each, sequential into `packages/<name>`\n- Pre-import fixes:\n  1. Removed `packages/.gitkeep` and committed\n  2. `git init && git add . && git commit` in Vite app (no git at all)\n  3. `git add . && git commit` in TanStack app (git init'd but no commits)\n- Import: `npm exec nx -- import <source> packages/<name> --source=. --ref=main --no-interactive`\n  - Next.js import auto-installed `@nx/eslint`, `@nx/next`\n  - React Router 7 import auto-installed `@nx/vite`, `@nx/react`, `@nx/docker` (Dockerfile present)\n  - TanStack import auto-installed `@nx/vitest`\n- Post-import fixes:\n  1. Removed stale `node_modules/`, `package-lock.json`, `.gitignore` from each package\n  2. Removed Nx-rewritten scripts from `board-games-nextjs/package.json` (had `\"build\": \"nx next:build\"`, etc.)\n  3. Updated root `tsconfig.base.json`: `nodenext` → `bundler`, added `dom`/`dom.iterable` to lib, added `jsx: react-jsx`\n  4. Added `build` to dest root `.gitignore` (CRA and React Router 7 output there)\n  5. Fixed `noEmit` → `composite + emitDeclarationOnly` in: `board-games-vite/tsconfig.app.json`, `board-games-vite/tsconfig.node.json`, `board-games-react-router/tsconfig.json`, `board-games-tanstack/tsconfig.json`\n  6. Fixed `tsBuildInfoFile` paths from `./node_modules/.tmp/...` to `./dist/...`\n  7. Installed root `@types/react`, `@types/react-dom`, `@types/node`\n- All targets green: `build` for all 5 projects; `typecheck` for Vite/React Router/TanStack; `next:build` for Next.js\n",".agents/skills/nx-plugins/SKILL.md":"---\nname: nx-plugins\ndescription: Find and add Nx plugins. USE WHEN user wants to discover available plugins, install a new plugin, or add support for a specific framework or technology to the workspace.\n---\n\n## Finding and Installing new plugins\n\n- List plugins: `pnpm nx list`\n- Install plugins `pnpm nx add <plugin>`. Example: `pnpm nx add @nx/react`.\n",".agents/skills/nx-run-tasks/SKILL.md":"---\nname: nx-run-tasks\ndescription: Helps with running tasks in an Nx workspace. USE WHEN the user wants to execute build, test, lint, serve, or run any other tasks defined in the workspace.\n---\n\nYou can run tasks with Nx in the following way.\n\nKeep in mind that you might have to prefix things with npx/pnpx/yarn if the user doesn't have nx installed globally. Look at the package.json or lockfile to determine which package manager is in use.\n\nFor more details on any command, run it with `--help` (e.g. `nx run-many --help`, `nx affected --help`).\n\n## Understand which tasks can be run\n\nYou can check those via `nx show project <projectname> --json`, for example `nx show project myapp --json`. It contains a `targets` section which has information about targets that can be run. You can also just look at the `package.json` scripts or `project.json` targets, but you might miss out on inferred tasks by Nx plugins.\n\n## Run a single task\n\n```\nnx run <project>:<task>\n```\n\nwhere `project` is the project name defined in `package.json` or `project.json` (if present).\n\n## Run multiple tasks\n\n```\nnx run-many -t build test lint typecheck\n```\n\nYou can pass a `-p` flag to filter to specific projects, otherwise it runs on all projects. You can also use `--exclude` to exclude projects, and `--parallel` to control the number of parallel processes (default is 3).\n\nExamples:\n\n- `nx run-many -t test -p proj1 proj2` — test specific projects\n- `nx run-many -t test --projects=*-app --exclude=excluded-app` — test projects matching a pattern\n- `nx run-many -t test --projects=tag:api-*` — test projects by tag\n\n## Run tasks for affected projects\n\nUse `nx affected` to only run tasks on projects that have been changed and projects that depend on changed projects. This is especially useful in CI and for large workspaces.\n\n```\nnx affected -t build test lint\n```\n\nBy default it compares against the base branch. You can customize this:\n\n- `nx affected -t test --base=main --head=HEAD` — compare against a specific base and head\n- `nx affected -t test --files=libs/mylib/src/index.ts` — specify changed files directly\n\n## Useful flags\n\nThese flags work with `run`, `run-many`, and `affected`:\n\n- `--skipNxCache` — rerun tasks even when results are cached\n- `--verbose` — print additional information such as stack traces\n- `--nxBail` — stop execution after the first failed task\n- `--configuration=<name>` — use a specific configuration (e.g. `production`)\n",".agents/skills/nx-workspace/SKILL.md":"---\nname: nx-workspace\ndescription: \"Explore and understand Nx workspaces. USE WHEN answering questions about the workspace, projects, or tasks. ALSO USE WHEN an nx command fails or you need to check available targets/configuration before running a task. EXAMPLES: 'What projects are in this workspace?', 'How is project X configured?', 'What depends on library Y?', 'What targets can I run?', 'Cannot find configuration for task', 'debug nx task failure'.\"\n---\n\n# Nx Workspace Exploration\n\nThis skill provides read-only exploration of Nx workspaces. Use it to understand workspace structure, project configuration, available targets, and dependencies.\n\nKeep in mind that you might have to prefix commands with `npx`/`pnpx`/`yarn` if nx isn't installed globally. Check the lockfile to determine the package manager in use.\n\n## Listing Projects\n\nUse `nx show projects` to list projects in the workspace.\n\nThe project filtering syntax (`-p`/`--projects`) works across many Nx commands including `nx run-many`, `nx release`, `nx show projects`, and more. Filters support explicit names, glob patterns, tag references (e.g. `tag:name`), directories, and negation (e.g. `!project-name`).\n\n```bash\n# List all projects\nnx show projects\n\n# Filter by pattern (glob)\nnx show projects --projects \"apps/*\"\nnx show projects --projects \"shared-*\"\n\n# Filter by tag\nnx show projects --projects \"tag:publishable\"\nnx show projects -p 'tag:publishable,!tag:internal'\n\n# Filter by target (projects that have a specific target)\nnx show projects --withTarget build\n\n# Combine filters\nnx show projects --type lib --withTarget test\nnx show projects --affected --exclude=\"*-e2e\"\nnx show projects -p \"tag:scope:client,packages/*\"\n\n# Negate patterns\nnx show projects -p '!tag:private'\nnx show projects -p '!*-e2e'\n\n# Output as JSON\nnx show projects --json\n```\n\n## Project Configuration\n\nUse `nx show project <name> --json` to get the full resolved configuration for a project.\n\n**Important**: Do NOT read `project.json` directly - it only contains partial configuration. The `nx show project --json` command returns the full resolved config including inferred targets from plugins.\n\nYou can read the full project schema at `node_modules/nx/schemas/project-schema.json` to understand nx project configuration options.\n\n```bash\n# Get full project configuration\nnx show project my-app --json\n\n# Extract specific parts from the JSON\nnx show project my-app --json | jq '.targets'\nnx show project my-app --json | jq '.targets.build'\nnx show project my-app --json | jq '.targets | keys'\n\n# Check project metadata\nnx show project my-app --json | jq '{name, root, sourceRoot, projectType, tags}'\n```\n\n## Target Information\n\nTargets define what tasks can be run on a project.\n\n```bash\n# List all targets for a project\nnx show project my-app --json | jq '.targets | keys'\n\n# Get full target configuration\nnx show project my-app --json | jq '.targets.build'\n\n# Check target executor/command\nnx show project my-app --json | jq '.targets.build.executor'\nnx show project my-app --json | jq '.targets.build.command'\n\n# View target options\nnx show project my-app --json | jq '.targets.build.options'\n\n# Check target inputs/outputs (for caching)\nnx show project my-app --json | jq '.targets.build.inputs'\nnx show project my-app --json | jq '.targets.build.outputs'\n\n# Find projects with a specific target\nnx show projects --withTarget serve\nnx show projects --withTarget e2e\n```\n\n## Workspace Configuration\n\nRead `nx.json` directly for workspace-level configuration.\nYou can read the full project schema at `node_modules/nx/schemas/nx-schema.json` to understand nx project configuration options.\n\n```bash\n# Read the full nx.json\ncat nx.json\n\n# Or use jq for specific sections\ncat nx.json | jq '.targetDefaults'\ncat nx.json | jq '.namedInputs'\ncat nx.json | jq '.plugins'\ncat nx.json | jq '.generators'\n```\n\nKey nx.json sections:\n\n- `targetDefaults` - Default configuration applied to all targets of a given name\n- `namedInputs` - Reusable input definitions for caching\n- `plugins` - Nx plugins and their configuration\n- ...and much more, read the schema or nx.json for details\n\n## Affected Projects\n\nIf the user is asking about affected projects, read the [affected projects reference](references/AFFECTED.md) for detailed commands and examples.\n\n## Common Exploration Patterns\n\n### \"What's in this workspace?\"\n\n```bash\nnx show projects\nnx show projects --type app\nnx show projects --type lib\n```\n\n### \"How do I build/test/lint project X?\"\n\n```bash\nnx show project X --json | jq '.targets | keys'\nnx show project X --json | jq '.targets.build'\n```\n\n### \"What depends on library Y?\"\n\n```bash\n# Use the project graph to find dependents\nnx graph --print | jq '.graph.dependencies | to_entries[] | select(.value[].target == \"Y\") | .key'\n```\n\n## Programmatic Answers\n\nWhen processing nx CLI results, use command-line tools to compute the answer programmatically rather than counting or parsing output manually. Always use `--json` flags to get structured output that can be processed with `jq`, `grep`, or other tools you have installed locally.\n\n### Listing Projects\n\n```bash\nnx show projects --json\n```\n\nExample output:\n\n```json\n[\"my-app\", \"my-app-e2e\", \"shared-ui\", \"shared-utils\", \"api\"]\n```\n\nCommon operations:\n\n```bash\n# Count projects\nnx show projects --json | jq 'length'\n\n# Filter by pattern\nnx show projects --json | jq '.[] | select(startswith(\"shared-\"))'\n\n# Get affected projects as array\nnx show projects --affected --json | jq '.'\n```\n\n### Project Details\n\n```bash\nnx show project my-app --json\n```\n\nExample output:\n\n```json\n{\n  \"root\": \"apps/my-app\",\n  \"name\": \"my-app\",\n  \"sourceRoot\": \"apps/my-app/src\",\n  \"projectType\": \"application\",\n  \"tags\": [\"type:app\", \"scope:client\"],\n  \"targets\": {\n    \"build\": {\n      \"executor\": \"@nx/vite:build\",\n      \"options\": { \"outputPath\": \"dist/apps/my-app\" }\n    },\n    \"serve\": {\n      \"executor\": \"@nx/vite:dev-server\",\n      \"options\": { \"buildTarget\": \"my-app:build\" }\n    },\n    \"test\": {\n      \"executor\": \"@nx/vite:test\",\n      \"options\": {}\n    }\n  },\n  \"implicitDependencies\": []\n}\n```\n\nCommon operations:\n\n```bash\n# Get target names\nnx show project my-app --json | jq '.targets | keys'\n\n# Get specific target config\nnx show project my-app --json | jq '.targets.build'\n\n# Get tags\nnx show project my-app --json | jq '.tags'\n\n# Get project root\nnx show project my-app --json | jq -r '.root'\n```\n\n### Project Graph\n\n```bash\nnx graph --print\n```\n\nExample output:\n\n```json\n{\n  \"graph\": {\n    \"nodes\": {\n      \"my-app\": {\n        \"name\": \"my-app\",\n        \"type\": \"app\",\n        \"data\": { \"root\": \"apps/my-app\", \"tags\": [\"type:app\"] }\n      },\n      \"shared-ui\": {\n        \"name\": \"shared-ui\",\n        \"type\": \"lib\",\n        \"data\": { \"root\": \"libs/shared-ui\", \"tags\": [\"type:ui\"] }\n      }\n    },\n    \"dependencies\": {\n      \"my-app\": [{ \"source\": \"my-app\", \"target\": \"shared-ui\", \"type\": \"static\" }],\n      \"shared-ui\": []\n    }\n  }\n}\n```\n\nCommon operations:\n\n```bash\n# Get all project names from graph\nnx graph --print | jq '.graph.nodes | keys'\n\n# Find dependencies of a project\nnx graph --print | jq '.graph.dependencies[\"my-app\"]'\n\n# Find projects that depend on a library\nnx graph --print | jq '.graph.dependencies | to_entries[] | select(.value[].target == \"shared-ui\") | .key'\n```\n\n## Troubleshooting\n\n### \"Cannot find configuration for task X:target\"\n\n```bash\n# Check what targets exist on the project\nnx show project X --json | jq '.targets | keys'\n\n# Check if any projects have that target\nnx show projects --withTarget target\n```\n\n### \"The workspace is out of sync\"\n\n```bash\nnx sync\nnx reset  # if sync doesn't fix stale cache\n```\n",".agents/skills/nx-workspace/references/AFFECTED.md":"## Affected Projects\n\nFind projects affected by changes in the current branch.\n\n```bash\n# Affected since base branch (auto-detected)\nnx show projects --affected\n\n# Affected with explicit base\nnx show projects --affected --base=main\nnx show projects --affected --base=origin/main\n\n# Affected between two commits\nnx show projects --affected --base=abc123 --head=def456\n\n# Affected apps only\nnx show projects --affected --type app\n\n# Affected excluding e2e projects\nnx show projects --affected --exclude=\"*-e2e\"\n\n# Affected by uncommitted changes\nnx show projects --affected --uncommitted\n\n# Affected by untracked files\nnx show projects --affected --untracked\n```\n",".claude/CLAUDE.md":"# Claude AI Instructions for Supabase JS Libraries Monorepo\n\nYou are assisting with development in a unified Nx monorepo that consolidates all Supabase JavaScript SDKs, built with Nx for optimal developer experience and maintainability. This strategic migration from 6 separate repositories addresses critical maintenance overhead, dependency duplication, and release coordination challenges while maintaining **zero breaking changes** for consumers.\n\n> **📚 Essential Documentation**: Always refer to these guides for detailed information:\n>\n> - **[CONTRIBUTING.md](../CONTRIBUTING.md)** - Development guidelines, commit format, PR process\n> - **[TESTING.md](../docs/TESTING.md)** - Complete testing guide with Docker requirements\n> - **[RELEASE.md](../docs/RELEASE.md)** - Release workflows and versioning strategy\n> - **[MIGRATION.md](../docs/MIGRATION.md)** - Cross-cutting migration notes (one H2 per theme). Per-package migrations live at `packages/core/<package>/migrations/`.\n> - **[Security Policy](https://github.com/supabase/supabase-js/security/policy)** - Security policies and responsible disclosure\n\n## Repository Architecture\n\n### Monorepo Structure\n\n```text\nsupabase-js/\n├── packages/core/\n│   ├── supabase-js/      # @supabase/supabase-js - Main isomorphic client for Supabase\n│   ├── auth-js/          # @supabase/auth-js - Authentication client\n│   ├── postgrest-js/     # @supabase/postgrest-js - PostgREST client for database operations\n│   ├── realtime-js/      # @supabase/realtime-js - Real-time subscriptions client\n│   ├── storage-js/       # @supabase/storage-js - File storage client\n│   └── functions-js/     # @supabase/functions-js - Edge Functions client\n├── CONTRIBUTING.md       # Contribution guidelines\n├── docs/                 # Comprehensive documentation guides\n│   ├── TESTING.md        # Testing guide\n│   ├── RELEASE.md        # Release workflows\n│   ├── MIGRATION.md      # Migration guide\n│   └── JSR_PUBLISHING.md # JSR publishing guide\n├── scripts/              # Automation scripts\n│   ├── release-canary.ts # Canary release automation\n│   ├── release-stable.ts # Stable release automation\n│   └── update-version-files.ts # Version management\n├── nx.json               # Nx workspace configuration\n├── tsconfig.base.json    # Base TypeScript configuration\n├── package.json          # Root package with workspace scripts\n└── commitlint.config.js  # Commit message validation\n```\n\n### Migration Benefits\n\n- **Dependency Consolidation**: 22 previously duplicated dependencies now centrally managed\n- **Atomic Changes**: Cross-library fixes in single PRs\n- **Immediate Integration Testing**: No manual release coordination needed\n- **Unified Versioning**: Fixed version mode with automated releases using `nx release`\n- **Intelligent Building**: Nx only rebuilds/tests what actually changed\n\n## Core Development Principles\n\n### 1. Zero Breaking Changes\n\nEvery change must maintain full backward compatibility. The migration itself introduces no breaking changes - all packages maintain their original npm names and APIs.\n\n### 2. Hybrid Release Model with Fixed Versioning\n\nUses automated canary releases with batched stable releases:\n\n- **Canary**: Every commit to master → prerelease (e.g., `2.80.1-canary.0`) with `canary` dist-tag\n- **Stable**: Manual promotion of validated canary to `latest` dist-tag\n- **Fixed Versioning**: All packages share identical version numbers (e.g., all at 2.80.0)\n- **Version Line**: Continuing with v2.x.x to maintain ecosystem stability\n\n**Three Release Workflows:**\n\n1. **Canary** (`.github/workflows/main-ci-release.yml`) - Automated on every master commit\n2. **Stable** (`.github/workflows/release-stable.yml`) - Manual by repository owners\n3. **Preview** (`.github/workflows/preview-release.yml`) - PR-based testing via pkg.pr.new\n\n> **📖 See [RELEASE.md](../docs/RELEASE.md) for complete release documentation**\n\n### 3. Workspace Dependencies\n\nInternal dependencies use the `*` protocol:\n\n```json\n// packages/core/supabase-js/package.json\n{\n  \"dependencies\": {\n    \"@supabase/auth-js\": \"*\",\n    \"@supabase/realtime-js\": \"*\",\n    \"@supabase/functions-js\": \"*\",\n    \"@supabase/storage-js\": \"*\",\n    \"@supabase/postgrest-js\": \"*\"\n  }\n}\n```\n\nNx automatically replaces `*` with the actual version during release.\n\n### 4. Affected-First Development\n\nAlways use `nx affected` commands to build/test only what changed, leveraging Nx's dependency graph intelligence.\n\n### 5. Conventional Commits\n\nUse conventional commit format for automated versioning:\n\n- `fix(auth-js): resolve token refresh race condition` → Patch release\n- `feat(realtime-js): add presence support` → Minor release\n- `feat(auth)!: remove deprecated method` → Major release\n- `chore(deps): update TypeScript to 5.8` → No version bump\n\n**Always use the interactive commit tool:**\n\n```bash\npnpm commit\n```\n\n> **📖 See [CONTRIBUTING.md](../CONTRIBUTING.md#commit-guidelines) for complete commit guidelines**\n\n## Essential Commands Reference\n\n### Building\n\n```bash\nnx run-many --target=build --all        # Build all packages\nnx build auth-js                         # Build specific package\nnx affected --target=build               # Build only affected\nnx build auth-js --watch                 # Development mode\n```\n\n### Testing\n\n```bash\n# Test specific packages (complete test suites with Docker setup/cleanup)\nnx test:auth auth-js                    # Complete auth-js test suite (handles Docker)\nnx test:storage storage-js              # Complete storage-js test suite (handles Docker)\nnx test:ci:postgrest postgrest-js      # Complete postgrest-js test suite (handles Docker)\nnx test functions-js                    # Standard test (uses testcontainers)\nnx test realtime-js                     # Standard test (no Docker needed)\nnx test supabase-js                     # Standard test (unit tests only)\n\n# Coverage reports\nnx test supabase-js --coverage\nnx test:coverage realtime-js\nnx test:ci functions-js                 # Includes coverage\n```\n\n**Docker Requirements:**\n\n| Package      | Docker Required | Infrastructure                  | Complete Test Command               | Individual Commands                                                                       |\n| ------------ | --------------- | ------------------------------- | ----------------------------------- | ----------------------------------------------------------------------------------------- |\n| auth-js      | ✅ Yes          | Auth Server + Postgres          | `nx test:auth auth-js`              | `nx test:suite auth-js`, `nx test:infra auth-js`, `nx test:clean-post auth-js`            |\n| storage-js   | ✅ Yes          | Storage API + PostgreSQL + Kong | `nx test:storage storage-js`        | `nx test:suite storage-js`, `nx test:infra storage-js`, `nx test:clean-post storage-js`   |\n| postgrest-js | ✅ Yes          | PostgREST + PostgreSQL          | `nx test:ci:postgrest postgrest-js` | `nx test:run postgrest-js`, `nx test:types postgrest-js`                                  |\n| functions-js | ✅ Yes          | Deno relay (testcontainers)     | `nx test functions-js`              | `nx test:ci functions-js` (with coverage)                                                 |\n| realtime-js  | ❌ No           | Mock WebSockets                 | `nx test realtime-js`               | `nx test:coverage realtime-js`, `nx test:watch realtime-js`                               |\n| supabase-js  | ❌ No           | Unit tests only                 | `nx test supabase-js`               | `nx test:all`, `nx test:unit`, `nx test:integration`, `nx test:coverage`, `nx test:watch` |\n\n**supabase-js Additional Test Commands:**\n\n```bash\nnx test:all supabase-js                  # Unit + integration + browser tests\nnx test:unit supabase-js                # Jest unit tests only\nnx test:integration supabase-js         # Node.js integration tests\nnx test:integration:browser supabase-js # Browser tests (requires Deno)\nnx test:edge-functions supabase-js      # Edge Functions tests\nnx test:deno supabase-js                # Deno runtime tests\nnx test:bun supabase-js                 # Bun runtime tests\nnx test:expo supabase-js                # React Native/Expo tests\nnx test:next supabase-js                # Next.js SSR tests\nnx test:node:playwright supabase-js     # WebSocket browser tests\nnx test:types supabase-js               # TypeScript type checking\nnx test:coverage supabase-js            # Coverage report\nnx test:watch supabase-js               # Watch mode\n```\n\n> **📖 See [TESTING.md](../docs/TESTING.md) for complete testing guide and troubleshooting**\n\n### Code Quality\n\n```bash\nnx run-many --target=lint --all          # Lint all packages\nnx lint storage-js                       # Lint specific package\nnx format                                 # Auto-format all code\nnx format:check                           # Check formatting\n```\n\n### Analysis\n\n```bash\nnx graph                                  # Interactive dependency graph\nnx show projects                          # List all projects\nnx affected --graph                       # Visualize affected projects\n```\n\n## Development Workflows\n\n### Cross-Library Bug Fix Example\n\n**Scenario**: Bug in supabase-js caused by realtime-js\n\n**Monorepo Solution**:\n\n1. Fix root cause in `packages/core/realtime-js/src/`\n2. Add unit test in `packages/core/realtime-js/test/`\n3. Add integration test in `packages/core/supabase-js/test/`\n4. Run complete test suites for both packages to verify impacts\n5. Commit: `fix(realtime-js): resolve reconnection logic affecting supabase-js`\n6. Single PR, single review, single release - all packages version together\n\n### Adding New Features\n\n1. Implement in appropriate library under `packages/core/[library]/src/`\n2. Write comprehensive unit tests in `packages/core/[library]/test/`\n3. If feature affects supabase-js, add integration tests there\n4. Update TypeScript types if needed\n5. Run complete test suite for the package before committing\n6. Use conventional commit: `feat(storage-js): add resumable uploads`\n\n### Quick Fix Workflow\n\n```bash\n# Even for single-library fixes:\ngit add .\ngit commit -m \"fix(auth-js): correct session expiry calculation\"\n# → Automatic canary: 2.80.1-canary.0 published to 'canary' dist-tag\n# Run complete test suite for the package:\nnx test:auth auth-js\n# After validation, manual promotion:\nnx release --tag=latest --yes  # Promotes to stable with same version for ALL packages\n```\n\n## TypeScript Configuration\n\n### Workspace Settings\n\n- **Target**: ES2022\n- **Module**: NodeNext\n- **Strict**: true\n- **Isolated Modules**: true (faster compilation)\n- **Composite**: true (incremental builds)\n\n### Per-Library Configs\n\nEach library has its own `tsconfig.json` extending the base configuration, allowing for library-specific adjustments while maintaining consistency.\n\n### TypeScript Project References Setup\n\nThis repository uses TypeScript project references for incremental builds and better type checking across packages.\n\n**What's Configured:**\n\n1. **tsconfig.base.json** - Base configuration inherited by all projects:\n   - `composite: true` - Enables project references\n   - `declaration: true` - Required by composite\n   - `moduleResolution: \"bundler\"` - Works with workspaces\n   - `isolatedModules: true` - Inherited but overridden in core packages\n   - `noImplicitOverride: true` - Inherited but overridden in core packages\n   - **No `customConditions`** - Removed to avoid conflicts with CommonJS packages\n\n2. **Root tsconfig.json** - References all projects in the monorepo:\n\n   ```json\n   {\n     \"extends\": \"./tsconfig.base.json\",\n     \"files\": [],\n     \"references\": [\n       { \"path\": \"./packages/core/auth-js\" },\n       { \"path\": \"./packages/core/realtime-js\" }\n       // ... all other packages\n     ]\n   }\n   ```\n\n3. **Core packages** (auth-js, realtime-js, postgrest-js, functions-js, storage-js):\n   - Keep `module: \"CommonJS\"` for backward compatibility\n   - Override `moduleResolution: \"Node\"` (required for CommonJS)\n   - Override `isolatedModules: false` (existing code doesn't use `export type`)\n   - Override `noImplicitOverride: false` (existing code doesn't use `override` keyword)\n   - Add `references` array pointing to dependencies (managed by `nx sync`)\n\n4. **Utils packages** (utils-fetch):\n   - Inherit `moduleResolution: \"bundler\"` from base\n   - Can optionally add `customConditions: [\"@supabase-js/source\"]` for source preference\n\n**Key Principles:**\n\n- ✅ **No Breaking Changes**: Build output is identical - only type-checking is affected\n- ✅ **Incremental Builds**: TypeScript only recompiles changed projects\n- ✅ **Better Performance**: Reduced memory usage during builds\n- ✅ **Automatic References**: Nx sync automatically maintains project references\n- ⚠️ **No `customConditions` in base**: Would conflict with `moduleResolution: \"Node\"`\n\n**When Adding New Packages:**\n\n1. Ensure `composite: true` and `declaration: true` are set\n2. Add `references` array pointing to dependencies\n3. If using CommonJS, override `moduleResolution: \"Node\"` and disable strict options\n4. Run `nx sync` to update root tsconfig.json automatically\n\n**Important Notes:**\n\n- TypeScript project references work WITHOUT `customConditions` - it's optional\n- `customConditions` only optimizes source file resolution during development\n- Core packages use `moduleResolution: \"Node\"` which is incompatible with `customConditions`\n- The `isolatedModules: false` override avoids requiring `export type` for type re-exports\n- All build outputs remain identical to pre-project-references setup\n\n## Testing Infrastructure\n\n### Unit Tests (Jest)\n\n- Location: `packages/core/[library]/test/`\n- Pattern: Mirror source structure\n- Principle: Test public APIs thoroughly\n- Mocking: Mock external dependencies\n\n### Integration Tests (Docker-based)\n\n**Complete Test Suites (Recommended)**:\n\n```bash\n# Auth-js: Complete test suite (handles Docker setup/cleanup automatically)\nnx test:auth auth-js\n\n# Storage-js: Complete test suite (handles Docker setup/cleanup automatically)\nnx test:storage storage-js\n\n# Postgrest-js: Complete test suite (handles Docker setup/cleanup automatically)\nnx test:ci:postgrest postgrest-js\n```\n\n**Manual Infrastructure Management** (for development):\n\n```bash\n# Auth-js\nnx test:infra auth-js        # Start Supabase CLI infrastructure\nnx test:suite auth-js        # Run tests (can run multiple times)\nnx test:clean-post auth-js   # Cleanup\n\n# Storage-js\nnx test:infra storage-js        # Start Supabase CLI infrastructure\nnx test:suite storage-js        # Run tests (can run multiple times)\nnx test:clean-post storage-js   # Cleanup\n\n# Postgrest-js\nnx test:infra postgrest-js        # Start Supabase CLI infrastructure\nnx test:run postgrest-js          # Run tests\nnx test:clean-post postgrest-js   # Cleanup\n```\n\n### Cross-Platform Tests (supabase-js)\n\nTests run against multiple environments:\n\n- Node.js (native)\n- Next.js (SSR/React)\n- Expo (React Native)\n- Bun (alternative runtime)\n- Deno (secure runtime)\n- Browser (via Puppeteer)\n\n## Library-Specific Considerations\n\n### supabase-js\n\n- Aggregates all other libraries\n- Primary integration testing location\n- Most complex cross-platform test suite (Node.js, Next.js, Expo, Bun, Deno, Browser)\n- Users typically interact through this package\n- Default branch: **master**\n\n### auth-js\n\n- Requires Docker for integration tests (GoTrue + PostgreSQL)\n- Complex session management logic\n- Security-critical - extra review care needed\n- See [auth-js README](../packages/core/auth-js/README.md) for details\n\n### realtime-js\n\n- WebSocket-based, timing-sensitive\n- Mock time in tests when possible\n- No Docker required (uses mock WebSockets)\n- See [realtime-js README](../packages/core/realtime-js/README.md) for details\n\n### storage-js\n\n- Requires Docker for integration tests (Storage API + PostgreSQL + Kong)\n- File handling varies by platform\n- See [storage-js README](../packages/core/storage-js/README.md) for details\n\n### postgrest-js\n\n- Pure HTTP client, easiest to test\n- Requires Docker for integration tests (PostgREST + PostgreSQL)\n- See [postgrest-js README](../packages/core/postgrest-js/README.md) for details\n\n### functions-js\n\n- Simplest library, minimal dependencies\n- Uses testcontainers for Deno relay\n- See [functions-js README](../packages/core/functions-js/README.md) for details\n\n## Code Style Guidelines\n\n### Formatting\n\n- Prettier handles all formatting (configured in `.prettierrc`)\n- Run `nx format` before committing\n- No formatting debates - Prettier decides\n\n### Patterns\n\n- Follow existing patterns in each library\n- Extract shared code to packages/shared/ when identified\n- Maintain consistency across monorepo\n\n### Documentation\n\n- JSDoc for all public APIs\n- README per package with examples\n- Update docs when changing APIs\n\n## Important Context\n\n### Branch Information\n\n**Current Repository:**\n\n- **Default branch**: `master` (v2 active development; all PRs land here by default; auto-publishes `@canary` on every push, stable releases are manual `workflow_dispatch` from this branch)\n- **Long-lived feature branch**: `v3` (v3-only breaking changes; `@next` prereleases are **manual `workflow_dispatch` only** — never auto-published; kept in sync with `master` by periodic `git merge master`)\n- **Repository URL**: `github.com/supabase/supabase-js`\n\n**Original Repository Branches** (for historical reference):\n\n- **master**: auth-js, postgrest-js, realtime-js, supabase-js\n- **main**: functions-js, storage-js\n\nWhen referencing original repository history or comparing changes, be aware of these branch name differences.\n\n### Package Publishing\n\n- All packages publish to npm under `@supabase` scope\n- Versions synchronized via fixed release mode (all packages always have same version)\n- Changelogs generated per package from conventional commits\n- \"No user-facing changes\" message for unchanged packages\n- Three dist-tags: `latest` (stable), `canary` (pre-release), `next` (legacy)\n\n### Docker Requirements\n\nIntegration tests for auth-js, functions-js, postgrest-js, and storage-js require Docker running locally:\n\n- **macOS/Windows**: Ensure Docker Desktop is installed and running\n- **Linux**: Ensure Docker daemon is running\n- **CI**: Docker is automatically available in GitHub Actions\n\nCheck [TESTING.md](../docs/TESTING.md) for port requirements and troubleshooting.\n\n### Commit Message Validation\n\nAll commits are validated using commitlint with strict rules:\n\n- **Type**: Required (feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert)\n- **Scope**: Required (auth, functions, postgrest, realtime, storage, supabase, repo, deps, ci, release, docs, scripts, misc)\n- **Subject**: Required, imperative mood, no period at end, max 100 characters\n- **Interactive Tool**: Use `pnpm commit` to ensure compliance\n\nSee [CONTRIBUTING.md](../CONTRIBUTING.md#commit-guidelines) for complete details.\n\n## Common Pitfalls & Solutions\n\n### Pitfall 1: Hardcoding Internal Versions\n\n❌ Wrong:\n\n```json\n\"@supabase/auth-js\": \"3.5.0\"\n```\n\n✅ Correct:\n\n```json\n\"@supabase/auth-js\": \"*\"\n```\n\n### Pitfall 2: Running npm Directly\n\n❌ Wrong:\n\n```bash\ncd packages/core/auth-js && npm test\n```\n\n✅ Correct:\n\n```bash\nnx test:auth auth-js\n```\n\n### Pitfall 3: Testing Everything\n\n❌ Wrong:\n\n```bash\nnx run-many --target=test --all  # Won't work - no standard test target for all packages\n```\n\n✅ Correct:\n\n```bash\n# Run complete test suite for the specific package\nnx test:auth auth-js\nnx test:storage storage-js\nnx test:ci:postgrest postgrest-js\nnx test functions-js\nnx test realtime-js\nnx test supabase-js\n```\n\n### Pitfall 4: Breaking Changes\n\n❌ Wrong: Changing public API signatures without proper process\n\n```typescript\n// Don't just change existing method signatures\n- signIn(email: string): Promise<void>\n+ signIn(credentials: Credentials): Promise<void>\n```\n\n✅ Correct: Add new methods, deprecate old ones gradually, use proper commit format\n\n```typescript\n// Add new method\nsignIn(credentials: Credentials): Promise<void>\n\n// Deprecate old method with backward compatibility\n/** @deprecated Use signIn(credentials) instead */\nsignInWithEmail(email: string): Promise<void> {\n  return this.signIn({ email })\n}\n```\n\nUse breaking change commit format when necessary:\n\n```bash\nfeat(auth)!: remove deprecated signInWithEmail method\n\nBREAKING CHANGE: The deprecated signInWithEmail method has been removed.\nUse signIn({ email }) instead.\n```\n\n### Pitfall 5: Running Commands Incorrectly\n\n❌ Wrong: Running npm commands directly in library directories\n\n```bash\ncd packages/core/auth-js\nnpm test\nnpm run build\n```\n\n✅ Correct: Use Nx commands from repository root\n\n```bash\nnx test:auth auth-js\nnx build auth-js --watch\n```\n\n### Pitfall 6: Not Using the Commit Tool\n\n❌ Wrong: Using git commit directly\n\n```bash\ngit commit -m \"fix auth bug\"  # Missing scope, will fail validation\n```\n\n✅ Correct: Use the interactive commit tool\n\n```bash\npnpm commit  # Guides you through proper format\n```\n\n### Pitfall 7: Not Checking Documentation\n\n❌ Wrong: Assuming you know how to run tests without checking\n\n```bash\nnx test storage-js  # Wrong - should use nx test:storage storage-js\n```\n\n✅ Correct: Check library README and TESTING.md first\n\n```bash\n# Read docs first\ncat packages/core/storage-js/README.md\ncat docs/TESTING.md\n# Then run tests with proper setup\n```\n\n## Pull Request Best Practices\n\n> **📖 See [CONTRIBUTING.md](../CONTRIBUTING.md#pull-request-process) for complete PR guidelines**\n\n### Before Creating PR\n\n1. **Ensure branch is up to date** with the PR's target branch (typically `master`; `v3` only for v3-only breaking changes):\n\n   ```bash\n   git checkout <target-branch>     # master or v3\n   git pull upstream <target-branch>\n   git checkout your-feature-branch\n   git rebase <target-branch>\n   ```\n\n2. **Run all necessary checks:**\n\n   ```bash\n   nx format                    # Format code\n   # Run complete test suite for affected packages individually\n   nx test:auth auth-js         # If auth-js changed\n   nx test:storage storage-js   # If storage-js changed\n   # ... etc for other packages\n   nx affected --target=build   # Build affected packages\n   ```\n\n3. **Use interactive commit tool:**\n\n   ```bash\n   pnpm commit\n   ```\n\n### PR Requirements\n\n- ✅ At least 1 approving review from a code owner\n- ✅ All status checks passing (CI/CD pipeline)\n- ✅ No merge conflicts with the base branch\n- ✅ Squash merge only (enforced by repository settings)\n\n### PR Description Template\n\n```markdown\n## Description\n\nBrief description of what this PR does\n\n## Type of Change\n\n- [ ] Bug fix (fix)\n- [ ] New feature (feat)\n- [ ] Breaking change (feat! or fix!)\n- [ ] Documentation update (docs)\n- [ ] Other (chore, refactor, etc.)\n\n## Testing\n\n- [ ] Unit tests added/updated\n- [ ] Integration tests added/updated (if applicable)\n- [ ] All tests passing locally\n\n## Checklist\n\n- [ ] Code formatted (`nx format`)\n- [ ] Tests passing (run complete test suites for affected packages)\n- [ ] Builds passing (`nx affected --target=build`)\n- [ ] Used conventional commits\n- [ ] Documentation updated (if needed)\n```\n\n### Requesting Preview Releases\n\nIf you need to test your changes before merging:\n\n1. Create your PR\n2. Comment: \"Can a maintainer add the preview label for testing?\"\n3. Wait for maintainer to add `trigger: preview` label\n4. Follow instructions in automated comment to install preview packages\n\n## Helpful Commands Reference\n\n### Analysis & Debugging\n\n```bash\n# Visualize dependency graph\nnx graph\n\n# Show what's affected by changes\nnx affected --graph\n\n# List all projects\nnx show projects\n\n# See project details\nnx show project auth-js --web\n\n# Clear Nx cache\nnx reset\n```\n\n### Development Workflow\n\n```bash\n# 1. Create feature branch\ngit checkout -b feat/your-feature\n\n# 2. Make changes in packages/core/[library]/\n\n# 3. Test continuously\nnx test [library] --watch\n\n# 4. Format before committing\nnx format\n\n# 5. Commit with tool\npnpm commit\n\n# 6. Before pushing\n# Run complete test suite for the package you changed\nnx test:auth auth-js         # If auth-js changed\nnx test:storage storage-js   # If storage-js changed\n# ... etc\nnx affected --target=build\nnx format:check\n\n# 7. Push and create PR\ngit push origin feat/your-feature\n```\n\n### Troubleshooting\n\n```bash\n# Clear cache and rebuild\nnx reset\nnx run-many --target=build --all\n\n# Clean install\nrm -rf node_modules\npnpm install\n\n# Check for errors\nnx run-many --target=lint --all\n\n# Run specific test file (for packages with standard test target)\nnx test realtime-js --testFile=RealtimeClient.test.ts\nnx test supabase-js --testFile=client.test.ts\n```\n\n## Additional Resources\n\n- **[README.md](../README.md)** - Repository overview and quick start\n- **[CONTRIBUTING.md](../CONTRIBUTING.md)** - Complete contribution guide\n- **[TESTING.md](../docs/TESTING.md)** - Comprehensive testing documentation\n- **[RELEASE.md](../docs/RELEASE.md)** - Release workflows and automation\n- **[MIGRATION.md](../docs/MIGRATION.md)** - Cross-cutting migration notes; per-package migrations live at `packages/core/<package>/migrations/`\n- **[Security Policy](https://github.com/supabase/supabase-js/security/policy)** - Security policy and reporting\n- **[Supabase Documentation](https://supabase.com/docs)** - Official Supabase docs\n- **[Nx Documentation](https://nx.dev)** - Nx monorepo documentation\n- **[Conventional Commits](https://www.conventionalcommits.org/)** - Commit format specification\n\n### Pitfall 5: Incomplete Cross-Library Testing\n\n❌ Wrong: Only testing in source library\n✅ Correct: Test in source library AND integration tests in supabase-js\n\n## Release Process\n\n### Hybrid Release Flow\n\n**Canary Releases (Automated)**:\n\n```bash\n# Triggered automatically on every commit to master\ngit commit -m \"fix(auth): resolve token issue\"\n# → Automatic CI: nx release --tag=canary --yes\n# → Published: 2.80.1-canary.0 to 'canary' dist-tag\n```\n\n**Stable Releases (Manual)**:\n\n```bash\n# 1. Validate canary version\n# Run complete test suites for packages individually\n\n# 2. Preview stable promotion\nnx release --dry-run\n\n# 3. Promote canary to stable\nnx release --tag=latest --yes\n\n# Alternative: Promote specific canary\nnx release --specifier=2.80.1 --tag=latest --yes\n```\n\n### What Happens During Canary Release\n\n1. CI detects conventional commits\n2. Determines version bump (patch/minor/major)\n3. Generates prerelease version (e.g., 2.80.1-canary.0)\n4. Updates all package.json files\n5. Replaces `*` with actual versions\n6. Publishes all packages to npm with `canary` dist-tag\n7. Triggers dogfooding workflows (when configured)\n\n### What Happens During Stable Release\n\n1. Promotes validated canary to `latest` dist-tag\n2. Generates curated per-package changelogs\n3. Creates GitHub release with notes\n4. All packages get identical stable version\n\n### Nx Release Configuration\n\nThe workspace is configured for hybrid releases in `nx.json`:\n\n```json\n{\n  \"release\": {\n    \"projectsRelationship\": \"fixed\",\n    \"version\": {\n      \"conventionalCommits\": true\n    },\n    \"changelog\": {\n      \"projectChangelogs\": true,\n      \"workspaceChangelog\": true\n    }\n  }\n}\n```\n\n### Release Command Reference\n\n```bash\n# Canary releases (automated in CI)\nnx release --tag=canary --yes                    # Publish to 'canary' dist-tag\nnx release --specifier=prerelease --tag=canary   # Force prerelease bump\n\n# Stable releases (manual promotion)\nnx release --tag=latest --yes                  # Promote to 'latest' dist-tag\nnx release --specifier=2.80.1 --tag=latest     # Promote specific version\n\n# Preview and debugging\nnx release --dry-run                           # Preview changes\nnx release --dry-run --verbose                 # Detailed preview\nnx release --first-release --dry-run           # First release preview\n\n# Version-specific releases\nnx release --specifier=patch --tag=latest      # Force patch bump\nnx release --specifier=minor --tag=latest      # Force minor bump\nnx release --specifier=major --tag=latest      # Force major bump\n```\n\n### Changelog Example\n\n```markdown\n## @supabase/realtime-js 2.80.1 (2025-09-16)\n\n- fix: correct reconnection logic (#123)\n\n## @supabase/auth-js 2.80.1 (2025-09-16)\n\n_No user-facing changes in this release._\n\n## @supabase/supabase-js 2.80.1 (2025-09-16)\n\n_No user-facing changes in this release._\n```\n\n## When Providing Code Suggestions\n\n1. **Consider Monorepo Impact**: Changes might affect multiple packages - always check dependencies\n2. **Use Nx Commands**: Always prefer `nx` over direct `npm` for workspace operations\n3. **Suggest Complete Test Suites**: Use complete test suites (`nx test:auth auth-js`, `nx test:storage storage-js`, etc.) for packages individually\n4. **Respect Fixed Versioning**: All packages version together - no independent versioning\n5. **Maintain Compatibility**: Never introduce breaking changes without proper process\n6. **Check Testing Requirements**: Be aware of Docker requirements for integration tests\n7. **Extract Shared Code**: Identify patterns that could be shared across packages\n8. **Follow Conventions**: Use existing patterns and structures within each library\n9. **Document Changes**: Update JSDoc and READMEs when changing public APIs\n10. **Use Conventional Commits**: Always suggest proper commit format with scope\n\n## Quick Decision Tree\n\n**Q: Where does this code belong?**\n\n- Authentication logic → auth-js\n- Database queries → postgrest-js\n- Real-time subscriptions → realtime-js\n- File operations → storage-js\n- Edge function calls → functions-js\n- Integration of above → supabase-js\n- Shared utilities → packages/shared/ (create if needed)\n\n**Q: How to test this change?**\n\n1. Unit test in source library\n2. Integration test in supabase-js if affects it\n3. Run complete test suite for the package:\n   - `nx test:auth auth-js` (handles Docker automatically)\n   - `nx test:storage storage-js` (handles Docker automatically)\n   - `nx test:ci:postgrest postgrest-js` (handles Docker automatically)\n   - `nx test functions-js` (uses testcontainers)\n   - `nx test realtime-js` (no Docker needed)\n   - `nx test supabase-js` (unit tests only)\n4. Run complete test suites for all affected packages individually\n\n**Q: How will this release?**\n\n- All packages version together in fixed mode\n- Your commit triggers automatic canary release for ALL packages\n- Weekly promotion of validated canary to stable\n- Unchanged packages show \"No user-facing changes\"\n- Single npm install updates entire SDK suite\n\nRemember: This monorepo optimizes for developer experience and maintenance efficiency while ensuring zero breaking changes for the millions of developers using Supabase SDKs.\n\n<!-- nx configuration start-->\n<!-- Leave the start & end comments to automatically receive updates. -->\n\n## General Guidelines for working with Nx\n\n- For navigating/exploring the workspace, invoke the `nx-workspace` skill first - it has patterns for querying projects, targets, and dependencies\n- When running tasks (for example build, lint, test, e2e, etc.), always prefer running the task through `nx` (i.e. `nx run`, `nx run-many`, `nx affected`) instead of using the underlying tooling directly\n- Prefix nx commands with the workspace's package manager (e.g., `pnpm nx build`, `npm exec nx test`) - avoids using globally installed CLI\n- You have access to the Nx MCP server and its tools, use them to help the user\n- For Nx plugin best practices, check `node_modules/@nx/<plugin>/PLUGIN.md`. Not all plugins have this file - proceed without it if unavailable.\n- NEVER guess CLI flags - always check nx_docs or `--help` first when unsure\n\n## Scaffolding & Generators\n\n- For scaffolding tasks (creating apps, libs, project structure, setup), ALWAYS invoke the `nx-generate` skill FIRST before exploring or calling MCP tools\n\n## When to use nx_docs\n\n- USE for: advanced config options, unfamiliar flags, migration guides, plugin configuration, edge cases\n- DON'T USE for: basic generator syntax (`nx g @nx/react:app`), standard commands, things you already know\n- The `nx-generate` skill handles generator discovery internally - don't call nx_docs just to look up generator syntax\n\n<!-- nx configuration end-->\n",".cursor/mcp.json":"{\n  \"mcpServers\": {}\n}\n","AGENTS.md":"# Agent instructions\n\nEntry point for AI/LLM agents working in or with this repository. Pointers below; nothing canonical lives in this file.\n\n## Repository overview\n\n- [`README.md`](./README.md) — what this repo is, package list, quick start\n- [`CONTRIBUTING.md`](./CONTRIBUTING.md) — contribution guidelines, commit format, PR process\n- [`.claude/CLAUDE.md`](./.claude/CLAUDE.md) — development conventions, Nx commands, testing matrix, library-specific notes (read by Claude Code; the canonical development-conventions doc)\n- [`.cursor/.cursorrules`](./.cursor/.cursorrules) — same conventions for Cursor (read by Cursor IDE)\n\n## Agent skills\n\nReusable agent skills for working in this Nx workspace (Nx-related: `nx-workspace`, `nx-generate`, `nx-import`, `nx-plugins`, `nx-run-tasks`, `link-workspace-packages`) live at:\n\n- [`.agents/skills/`](./.agents/skills/) — vendor-neutral location (Agent Skills spec)\n- [`.claude/skills/`](./.claude/skills/) — mirrored copy read by Claude Code by literal path\n\nBoth directories currently hold the same content. Treat `.agents/skills/` as the source of truth; the `.claude/skills/` copy is kept in sync until Claude Code can discover skills from `.agents/skills/` directly.\n\n## Per-package usage\n\nEach package has its own README with usage examples and API notes:\n\n- [`packages/core/supabase-js/README.md`](./packages/core/supabase-js/README.md) — `@supabase/supabase-js` (main isomorphic client)\n- [`packages/core/auth-js/README.md`](./packages/core/auth-js/README.md) — `@supabase/auth-js`\n- [`packages/core/postgrest-js/README.md`](./packages/core/postgrest-js/README.md) — `@supabase/postgrest-js`\n- [`packages/core/realtime-js/README.md`](./packages/core/realtime-js/README.md) — `@supabase/realtime-js`\n- [`packages/core/storage-js/README.md`](./packages/core/storage-js/README.md) — `@supabase/storage-js`\n- [`packages/core/functions-js/README.md`](./packages/core/functions-js/README.md) — `@supabase/functions-js`\n\n## Helping users of a published `@supabase/*` package\n\nThe published npm tarball for each package ships everything an agent needs to give a correct, version-pinned answer. After `npm install @supabase/<package>`, an agent helping with that package should look inside `node_modules/@supabase/<package>/`:\n\n- `AGENTS.md` — per-package agent entry point (read this first; it points at the resources below).\n- `README.md` — usage and quick-start.\n- `src/` — full API source with TSDoc. Every public method and type has JSDoc, most have `@example` blocks. Read source here for the canonical, version-pinned answer instead of guessing from training data.\n- `migrations/` — per-theme migration notes for changes that need caller action.\n\nSource files ship via npm because every package's `files` array in `package.json` includes `\"src\"`. Migration notes ship via `\"migrations\"`. Per-package `AGENTS.md` ships via `\"AGENTS.md\"`. All three are version-pinned by virtue of being inside the installed package.\n\nWe deliberately do NOT ship per-package skills or duplicate docs-site content. The TSDoc-in-source IS the canonical API documentation for the SDK packages.\n\nFor higher-level Supabase guidance (the documentation site, MCP tools, schema management workflows, project setup), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills):\n\n```bash\nnpx skills add supabase/agent-skills\n```\n\nOr use the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins) to install the agent skills together with the Supabase MCP server in one step. See also: [Agent Skills documentation](https://agentskills.io/home).\n\n## Migration notes\n\nMigration notes live close to the code they describe, so they ship via npm alongside the package.\n\n- **Per-package migrations**: `packages/core/<package>/migrations/<theme>.md` — one file per migration theme (e.g. `<new-feature-adoption>.md`). Each file describes what changed, who is affected, and what callers need to do.\n- **Cross-cutting migrations** (affecting the whole repo or all packages): [`docs/MIGRATION.md`](./docs/MIGRATION.md) — one H2 section per theme (e.g. Node.js version drops). Low-frequency by design; split into a directory only if the file grows past a handful of themes.\n\n## Other documentation\n\n- [`docs/TESTING.md`](./docs/TESTING.md) — testing guide with Docker requirements per package\n- [`docs/RELEASE.md`](./docs/RELEASE.md) — release workflows and versioning strategy\n- [Security Policy](https://github.com/supabase/supabase-js/security/policy) — security policies and responsible disclosure\n- [`docs/JSR_PUBLISHING.md`](./docs/JSR_PUBLISHING.md) — JSR registry publishing\n","packages/core/auth-js/AGENTS.md":"# Agent instructions for `@supabase/auth-js`\n\nSupabase Auth client SDK for JavaScript. Handles sign-in, sign-up, sessions, OAuth, MFA, and related auth flows.\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n","packages/core/auth-js/README.md":"<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase Auth JS SDK</h1>\n\n  <h3 align=\"center\">An isomorphic JavaScript SDK for the <a href=\"https://github.com/supabase/auth\">Supabase Auth</a> API.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/auth\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript/auth-signup\">Reference Docs</a>\n    ·\n    <a href=\"https://supabase.github.io/supabase-js/auth-js/v2/spec.json\">TypeDoc</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/auth-js)](https://www.npmjs.com/package/@supabase/auth-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/auth-js)](https://pkg.pr.new/~/supabase/auth-js)\n\n</div>\n\n## Requirements\n\n- **Node.js 22 or later** (Node.js 20 support dropped in v2.110.0)\n- For browser support, all modern browsers are supported\n\n> ⚠️ **Node.js 18 Deprecation Notice**\n>\n> Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped on October 31, 2025.\n\n> ⚠️ **Node.js 20 Deprecation Notice**\n>\n> Node.js 20 reached end-of-life on April 30, 2026. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/45715), support for Node.js 20 was dropped in v2.110.0.\n\n## Quick start\n\nInstall\n\n```bash\nnpm install --save @supabase/auth-js\n```\n\nUsage\n\n```js\nimport { AuthClient } from '@supabase/auth-js'\n\nconst GOTRUE_URL = 'http://localhost:9999'\n\nconst auth = new AuthClient({ url: GOTRUE_URL })\n```\n\n- `signUp()`: https://supabase.com/docs/reference/javascript/auth-signup\n- `signIn()`: https://supabase.com/docs/reference/javascript/auth-signin\n- `signOut()`: https://supabase.com/docs/reference/javascript/auth-signout\n\n### Custom `fetch` implementation\n\n`auth-js` uses the runtime's global `fetch` to make HTTP requests, but an alternative `fetch` implementation can be provided as an option. This is useful in environments where the global `fetch` is unavailable or where you want to customize request behavior:\n\n```js\nimport { AuthClient } from '@supabase/auth-js'\n\nconst AUTH_URL = 'http://localhost:9999'\n\nconst auth = new AuthClient({ url: AUTH_URL, fetch: fetch })\n```\n\n## Development\n\nThis package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:\n\n### Building\n\n```bash\n# Complete build (from monorepo root)\npnpm nx build auth-js\n\n# Build with watch mode for development\npnpm nx build auth-js --watch\n\n# Individual build targets\npnpm nx build:main auth-js    # CommonJS build (dist/main/)\npnpm nx build:module auth-js  # ES Modules build (dist/module/)\n\n# Other useful commands\npnpm nx lint auth-js          # Run ESLint\npnpm nx typecheck auth-js     # TypeScript type checking\npnpm nx docs auth-js          # Generate documentation\n```\n\n#### Build Outputs\n\n- **CommonJS (`dist/main/`)** - For Node.js environments\n- **ES Modules (`dist/module/`)** - For modern bundlers (Webpack, Vite, Rollup)\n- **TypeScript definitions (`dist/module/index.d.ts`)** - Type definitions for TypeScript projects\n\n### Testing\n\nThe auth-js package has two test suites:\n\n1. **CLI Tests** - Main test suite using Supabase CLI (331 tests)\n2. **Docker Tests** - Edge case tests requiring specific GoTrue configurations (11 tests)\n\n#### Prerequisites\n\n- **Supabase CLI** - Required for main test suite ([installation guide](https://supabase.com/docs/guides/cli))\n- **Docker** - Required for edge case tests\n\n#### Running Tests\n\n```bash\n# Run main test suite with Supabase CLI (recommended)\npnpm nx test:auth auth-js\n\n# Run Docker-only edge case tests\npnpm nx test:docker auth-js\n\n# Run both test suites\npnpm nx test:auth auth-js && pnpm nx test:docker auth-js\n```\n\n#### Main Test Suite (Supabase CLI)\n\nThe `test:auth` command automatically:\n\n1. Stops any existing Supabase instance\n2. Starts a local Supabase instance via CLI\n3. Runs the test suite (excludes `docker-tests/` folder)\n4. Cleans up after tests complete\n\n```bash\n# Individual commands for manual control\npnpm nx test:infra auth-js    # Start Supabase CLI\npnpm nx test:suite auth-js    # Run tests only\npnpm nx test:clean-post auth-js  # Stop Supabase CLI\n```\n\n#### Docker Tests (Edge Cases)\n\nThe `test:docker` target runs tests that require specific GoTrue configurations not possible with a single Supabase CLI instance:\n\n- **Signup disabled** - Tests for disabled signup functionality\n- **Asymmetric JWT (RS256)** - Tests for RS256 JWT verification\n- **Phone OTP / SMS** - Tests requiring Twilio SMS provider\n- **Anonymous sign-in disabled** - Tests for disabled anonymous auth\n\nThese tests are located in `test/docker-tests/` and use the Docker Compose setup in `infra/docker-compose.yml`.\n\n```bash\n# Individual commands for manual control\npnpm nx test:docker:infra auth-js    # Start Docker containers\npnpm nx test:docker:suite auth-js    # Run Docker tests only\npnpm nx test:docker:clean-post auth-js  # Stop Docker containers\n```\n\n#### Development Testing\n\nFor actively developing and debugging tests:\n\n```bash\n# Start Supabase CLI once\npnpm nx test:infra auth-js\n\n# Run tests multiple times (faster since instance stays up)\npnpm nx test:suite auth-js\n\n# Clean up when done\npnpm nx test:clean-post auth-js\n```\n\n#### Test Infrastructure\n\n| Suite        | Infrastructure | Configuration               |\n| ------------ | -------------- | --------------------------- |\n| CLI Tests    | Supabase CLI   | `test/supabase/config.toml` |\n| Docker Tests | Docker Compose | `infra/docker-compose.yml`  |\n\n### Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n","packages/core/auth-js/example/react/README.md":"# Supabase `auth-js` example\n\n- Created based on the [Quickstart example](https://supabase.com/docs/guides/auth/quickstarts/react) in the Supabase docs.\n- Bootstrapped with Vite CLI\n\n## Setup\n\n### With a Supabase project\n\n### 1. Create new project\n\nSign up to Supabase - [https://supabase.com/dashboard](https://supabase.com/dashboard) and create a new project. Wait for your database to start.\n\n### 2. Get the URL and Key\n\nCreate a copy of `.env.local.example`:\n\n```bash\ncp .env.local.example .env.local\n```\n\n1. Go to the Project Settings (the cog icon)\n2. Open the Data API tab, and find your API URL\n3. Open the API Keys tab and create a new Publishable key\n4. Set them both in your newly created `.env.local` file.O\n\n### 3. Enable Auth providers\n\n1. From the sidenav, go to Authentication -> Configuration -> Sign In/Providers (https://supabase.com/dashboard/project/<YOUR_PROJECT_ID>/auth/providers)\n2. Enable providers as needed (for this example: Anonymous, Email, Phone, GitHub, Google)\n\n## Run\n\n### Install root dependencies and build `auth-js`\n\n```bash\nnpm i\n```\n\n```bash\nnpx nx build auth-js\n```\n\n### Install the dependencies and run the example\n\n```bash\ncd example/react\n```\n\n```bash\nnpm i; npm run dev\n```\n","packages/core/auth-js/migrations/README.md":"# Migration notes for `@supabase/auth-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/auth-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/auth-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/auth-js`:\n\n1. Read the migration files in `node_modules/@supabase/auth-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/auth-js` only.\n","packages/core/auth-js/test/README.md":"# Testing\n\n## Prerequisites\n\n- Docker & docker compose\n\n### Basic testing\n\nRun all tests:\n\n```sh\nnpm run test\n```\n\n> Note: If tests fail due to connection issues, your tests may be running too soon and the infra is not yet ready.\n> If that's the case, adjust the `sleep 10` duration in:\n> `\"test:infra\": \"cd infra && docker-compose down && docker-compose pull && docker-compose up -d && sleep 10\",`\n> to a value that works for your system setup.\n\n### Advanced\n\n**Start all the infrastructure:**\n\n```sh\nnpm run test:infra\n```\n\nYou can now open the mock mail server on `http://localhost:9000`\n\n**Run the tests only:**\n\n```sh\nnpm run test:suite\n```\n\nAll emails will appear in the mock mail server.\n\n## Passkey (WebAuthn) Tests\n\nPasskey coverage is split across two files:\n\n- `passkey.methods.test.ts` — unit tests for all `auth.passkey.*`, `signInWithPasskey()`,\n  `registerPasskey()` and `admin.passkey.*` methods with mocked `fetch` and a simulated\n  browser environment (no infra needed)\n- `passkey.e2e.test.ts` — full registration/authentication ceremonies against the\n  Supabase CLI Auth server\n\nThe e2e tests rely on:\n\n- `[auth.passkey]` and `[auth.webauthn]` in `test/supabase/config.toml` (requires\n  Supabase CLI >= 2.105.0)\n- `test/lib/software-authenticator.ts`, a minimal software WebAuthn authenticator\n  (ES256, \"none\" attestation, discoverable credentials) that stands in for\n  `navigator.credentials` since the tests run in Node\n\n## RSA Signing Keys\n\n### Security Model\n\nThe auth-js tests require RSA signing keys to verify RS256 JWT tokens. **These keys are NEVER committed to the repository** for security reasons.\n\n### Key Generation\n\nKeys are automatically generated before tests run:\n\n- **Locally**: `nx test:auth auth-js` or `nx test:docker auth-js` automatically generates keys via the `test:generate-keys` target\n- **CI**: GitHub Actions generates fresh keys before each test run\n\n### Manual Key Generation\n\nIf you need to generate keys manually:\n\n```bash\ncd packages/core/auth-js/test\nnode generate-signing-keys.js\n```\n\nThis creates `test/supabase/signing_keys.json` (gitignored).\n\n### JWT Token Generation\n\nJWT tokens (anon, service_role, admin) are **automatically generated** at runtime from the signing keys in `test/lib/clients.ts`. No manual updates needed!\n\nFor debugging/inspection only:\n\n```bash\ncd packages/core/auth-js/test\nnode generate-jwt.js\n```\n\nThis displays the tokens but you don't need to copy them anywhere - they're generated automatically.\n\n## Important Notes\n\n⚠️ **NEVER commit `signing_keys.json`** - It's in `.gitignore` for security\n\n⚠️ **These are TEST KEYS only** - Never use in production\n\n✅ **Fresh keys per test run** - CI generates new keys every time for maximum security\n","packages/core/functions-js/AGENTS.md":"# Agent instructions for `@supabase/functions-js`\n\nJavaScript SDK for invoking Supabase Edge Functions.\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n","packages/core/functions-js/README.md":"<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase Functions JS SDK</h1>\n\n  <h3 align=\"center\">JavaScript SDK to interact with Supabase Edge Functions.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/functions\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript/functions-invoke\">Reference Docs</a>\n    ·\n    <a href=\"https://supabase.github.io/supabase-js/functions-js/v2/spec.json\">TypeDoc</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/functions-js)](https://www.npmjs.com/package/@supabase/functions-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/functions-js)](https://pkg.pr.new/~/supabase/functions-js)\n\n</div>\n\n## Requirements\n\n- **Node.js 22 or later** (Node.js 20 support dropped in v2.110.0)\n- For browser support, all modern browsers are supported\n\n> ⚠️ **Node.js 18 Deprecation Notice**\n>\n> Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped on October 31, 2025.\n\n> ⚠️ **Node.js 20 Deprecation Notice**\n>\n> Node.js 20 reached end-of-life on April 30, 2026. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/45715), support for Node.js 20 was dropped in v2.110.0.\n\n## Quick Start\n\n### Installation\n\n```bash\nnpm install @supabase/functions-js\n```\n\n### Usage\n\n```js\nimport { FunctionsClient } from '@supabase/functions-js'\n\nconst functionsUrl = 'https://<project_ref>.supabase.co/functions/v1'\nconst publishableKey = '<publishable_key>'\n\nconst functions = new FunctionsClient(functionsUrl, {\n  headers: {\n    Authorization: `Bearer ${publishableKey}`,\n  },\n})\n\n// Invoke a function\nconst { data, error } = await functions.invoke('hello-world', {\n  body: { name: 'Functions' },\n})\n```\n\n## Development\n\nThis package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:\n\n### Building\n\n```bash\n# Complete build (from monorepo root)\npnpm nx build functions-js\n\n# Build with watch mode for development\npnpm nx build functions-js --watch\n\n# Individual build targets\npnpm nx build:main functions-js    # CommonJS build (dist/main/)\npnpm nx build:module functions-js  # ES Modules build (dist/module/)\n\n# Other useful commands\npnpm nx clean functions-js         # Clean build artifacts\npnpm nx typecheck functions-js     # TypeScript type checking\npnpm nx docs functions-js          # Generate documentation\n```\n\n#### Build Outputs\n\n- **CommonJS (`dist/main/`)** - For Node.js environments\n- **ES Modules (`dist/module/`)** - For modern bundlers (Webpack, Vite, Rollup)\n- **TypeScript definitions (`dist/module/index.d.ts`)** - Type definitions for TypeScript projects\n\n### Testing\n\n**Docker Required** for relay tests. The functions-js tests use testcontainers to spin up a Deno relay server for testing Edge Function invocations.\n\n```bash\n# Run all tests (from monorepo root)\npnpm nx test functions-js\n\n# Run tests with coverage report\npnpm nx test functions-js --coverage\n\n# Run tests in watch mode during development\npnpm nx test functions-js --watch\n\n# CI test command (runs with coverage)\npnpm nx test:ci functions-js\n```\n\n#### Test Requirements\n\n- **Node.js 22+** - Required for testcontainers\n- **Docker** - Must be installed and running for relay tests\n- No Supabase instance needed - Tests use mocked services and testcontainers\n\n#### What Gets Tested\n\n- **Function invocation** - Testing the `invoke()` method with various options\n- **Relay functionality** - Using a containerized Deno relay to test real Edge Function scenarios\n- **Error handling** - Ensuring proper error responses and retries\n- **Request/response models** - Validating headers, body, and response formats\n\n### Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n","packages/core/functions-js/migrations/README.md":"# Migration notes for `@supabase/functions-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/functions-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/functions-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/functions-js`:\n\n1. Read the migration files in `node_modules/@supabase/functions-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/functions-js` only.\n","packages/core/postgrest-js/AGENTS.md":"# Agent instructions for `@supabase/postgrest-js`\n\nIsomorphic PostgREST client for database operations (select, insert, update, upsert, delete, filters, RPC).\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n","packages/core/postgrest-js/README.md":"<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase PostgREST JS SDK</h1>\n\n  <h3 align=\"center\">Isomorphic JavaScript SDK for <a href=\"https://postgrest.org\">PostgREST</a> with an ORM-like interface.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/database\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript/select\">Reference Docs</a>\n    ·\n    <a href=\"https://supabase.github.io/supabase-js/postgrest-js/v2/spec.json\">TypeDoc</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/postgrest-js)](https://www.npmjs.com/package/@supabase/postgrest-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/postgrest-js)](https://pkg.pr.new/~/supabase/postgrest-js)\n\n</div>\n\n### Quick start\n\nInstall\n\n```bash\nnpm install @supabase/postgrest-js\n```\n\nUsage\n\n```js\nimport { PostgrestClient } from '@supabase/postgrest-js'\n\nconst REST_URL = 'http://localhost:3000'\nconst postgrest = new PostgrestClient(REST_URL)\n```\n\n- [select()](https://supabase.com/docs/reference/javascript/select)\n- [insert()](https://supabase.com/docs/reference/javascript/insert)\n- [update()](https://supabase.com/docs/reference/javascript/update)\n- [delete()](https://supabase.com/docs/reference/javascript/delete)\n\n#### Custom `fetch` implementation\n\n`postgrest-js` uses the runtime's global `fetch` to make HTTP requests, but an alternative `fetch` implementation can be provided as an option. This is useful in environments where the global `fetch` is unavailable or where you want to customize request behavior:\n\n```js\nimport { PostgrestClient } from '@supabase/postgrest-js'\n\nconst REST_URL = 'http://localhost:3000'\nconst postgrest = new PostgrestClient(REST_URL, {\n  fetch: (...args) => fetch(...args),\n})\n```\n\n## Development\n\nThis package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:\n\n### Building\n\n```bash\n# Build (from monorepo root)\npnpm nx build postgrest-js\n\n# Build with watch mode for development\npnpm nx build:watch postgrest-js\n\n# TypeScript type checking\npnpm nx type-check postgrest-js\n\n# Generate documentation\npnpm nx docs postgrest-js\n```\n\n### Testing\n\n**Supabase CLI Required!** The `postgrest-js` tests use the [Supabase CLI](https://supabase.com/docs/guides/local-development/cli/getting-started) to run a local PostgreSQL database and PostgREST server.\n\n#### Quick Start\n\n```bash\n# Run all tests (from monorepo root)\npnpm nx test:ci:postgrest postgrest-js\n```\n\nThis single command automatically:\n\n1. Stops any existing Supabase CLI containers\n2. Starts PostgreSQL database and PostgREST server via Supabase CLI\n3. Resets and seeds the database\n4. Runs all Jest unit tests with coverage\n5. Cleans up containers\n\n#### Individual Test Commands\n\n```bash\n# Run Jest tests with coverage (requires infrastructure running)\npnpm nx test:run postgrest-js\n\n# Run type tests with tstyche\npnpm nx test:types postgrest-js\n\n# Run smoke tests (CommonJS and ESM imports)\npnpm nx test:smoke postgrest-js\n\n# Format code\npnpm nx format postgrest-js\n\n# Check formatting\npnpm nx format:check postgrest-js\n```\n\n#### Test Infrastructure\n\nThe tests use Supabase CLI to spin up:\n\n- **PostgreSQL** - Database with test schema and seed data (port 54322)\n- **PostgREST** - REST API server that the client connects to (port 54321)\n\n```bash\n# Manually manage test infrastructure (from monorepo root)\npnpm nx test:infra postgrest-js      # Start containers\npnpm nx test:clean-pre postgrest-js  # Stop and remove containers\n```\n\nOr directly via Supabase CLI:\n\n```bash\ncd packages/core/postgrest-js\nnpx supabase --workdir ./test start        # Start all services\nnpx supabase --workdir ./test db reset     # Reset and seed database\nnpx supabase --workdir ./test stop         # Stop all services\n```\n\n#### Regenerating TypeScript Types\n\nWhen the database schema changes, regenerate TypeScript types from the actual database:\n\n```bash\n# From the monorepo root\npnpm run codegen:postgrest\n```\n\nThis command automatically:\n\n1. Cleans up any existing Supabase containers\n2. Starts Supabase (PostgreSQL, PostgREST, and all services)\n3. Generates TypeScript types from the database schema\n4. Post-processes the generated types (updates JSON type definitions)\n5. Formats the generated file with Prettier\n6. Cleans up Supabase containers\n\nThe generated types are written to `test/types.generated.ts`.\n\n#### Test Types Explained\n\n- **Unit Tests** - Jest tests covering all client functionality (`pnpm nx test:run postgrest-js`)\n- **Type Tests** - Validates TypeScript types using tstyche (`pnpm nx test:types postgrest-js`)\n- **Smoke Tests** - Basic import/require tests for CommonJS and ESM (`pnpm nx test:smoke postgrest-js`)\n\n#### Prerequisites\n\n- **Supabase CLI** must be installed ([instructions](https://supabase.com/docs/guides/local-development/cli/getting-started)) or can be used through `npx` (`npx supabase`)\n- **Docker** must be installed and running (Supabase CLI uses Docker under the hood)\n- **Port 54321** - PostgREST API\n- **Port 54322** - PostgreSQL database\n- **Port 54323** - Supabase Studio (used for type generation)\n\n#### PostgREST v12 Backward Compatibility Tests\n\nWe maintain backward compatibility tests for PostgREST v12 (the current Supabase CLI uses v14+). These tests ensure the SDK works correctly for users still running older PostgREST versions.\n\n```bash\n# Run v12 compatibility tests (requires Docker)\npnpm nx test:ci:v12 postgrest-js\n```\n\nThis command:\n\n1. Starts PostgREST v12 + PostgreSQL in Docker (ports 3012/5433)\n2. Runs runtime tests that verify v12-specific behavior\n3. Cleans up containers\n\n**Type-only tests** for v12 compatibility also run as part of the regular type tests:\n\n```bash\npnpm nx test:types postgrest-js  # Includes v12-compat.test-d.ts\n```\n\n**Note:** These v12 tests will be removed when v3 ships (sometime in 2026).\n\n### Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n\n## License\n\nThis repo is licensed under MIT License.\n","packages/core/postgrest-js/migrations/README.md":"# Migration notes for `@supabase/postgrest-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/postgrest-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/postgrest-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/postgrest-js`:\n\n1. Read the migration files in `node_modules/@supabase/postgrest-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/postgrest-js` only.\n","packages/core/realtime-js/AGENTS.md":"# Agent instructions for `@supabase/realtime-js`\n\nListen to realtime updates from a Supabase PostgreSQL database. Handles channels, presence, broadcast, and Postgres CDC subscriptions.\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n","packages/core/realtime-js/README.md":"<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase Realtime JS SDK</h1>\n\n  <h3 align=\"center\">Send ephemeral messages with <b>Broadcast</b>, track and synchronize state with <b>Presence</b>, and listen to database changes with <b>Postgres Change Data Capture (CDC)</b>.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/realtime\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript\">Reference Docs</a>\n    ·\n    <a href=\"https://multiplayer.dev\">Multiplayer Demo</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/realtime-js)](https://www.npmjs.com/package/@supabase/realtime-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/realtime-js)](https://pkg.pr.new/~/supabase/realtime-js)\n\n</div>\n\n# Overview\n\nThis SDK enables you to use the following Supabase Realtime's features:\n\n- **Broadcast**: send ephemeral messages from client to clients with minimal latency. Use cases include sharing cursor positions between users.\n- **Presence**: track and synchronize shared state across clients with the help of CRDTs. Use cases include tracking which users are currently viewing a specific webpage.\n- **Postgres Change Data Capture (CDC)**: listen for changes in your PostgreSQL database and send them to clients.\n\n# Usage\n\n## Installing the Package\n\n```bash\nnpm install @supabase/realtime-js\n```\n\n## Creating a Channel\n\n```js\nimport { RealtimeClient } from '@supabase/realtime-js'\n\nconst client = new RealtimeClient(REALTIME_URL, {\n  params: {\n    apikey: API_KEY,\n  },\n})\n\nconst channel = client.channel('test-channel', {})\n\nchannel.subscribe((status, err) => {\n  if (status === 'SUBSCRIBED') {\n    console.log('Connected!')\n  }\n\n  if (status === 'CHANNEL_ERROR') {\n    console.log(`There was an error subscribing to channel: ${err.message}`)\n  }\n\n  if (status === 'TIMED_OUT') {\n    console.log('Realtime server did not respond in time.')\n  }\n\n  if (status === 'CLOSED') {\n    console.log('Realtime channel was unexpectedly closed.')\n  }\n})\n```\n\n### Notes:\n\n- `REALTIME_URL` is `'ws://localhost:4000/socket'` when developing locally and `'wss://<project_ref>.supabase.co/realtime/v1'` when connecting to your Supabase project.\n- `API_KEY` is a JWT whose claims must contain `exp` and `role` (existing database role).\n- Channel name can be any `string`.\n- Setting `private` to `true` means that the client will use RLS to determine if the user can connect or not to a given channel.\n\n## Broadcast\n\nYour client can send and receive messages based on the `event`.\n\n```js\n// Setup...\n\nconst channel = client.channel('broadcast-test', { broadcast: { ack: false, self: false } })\n\nchannel.on('broadcast', { event: 'some-event' }, (payload) => console.log(payload))\n\nchannel.subscribe(async (status) => {\n  if (status === 'SUBSCRIBED') {\n    // Send message to other clients listening to 'broadcast-test' channel\n    await channel.send({\n      type: 'broadcast',\n      event: 'some-event',\n      payload: { hello: 'world' },\n    })\n  }\n})\n```\n\n### Notes:\n\n- Setting `ack` to `true` means that the `channel.send` promise will resolve once server replies with acknowledgment that it received the broadcast message request.\n- Setting `self` to `true` means that the client will receive the broadcast message it sent out.\n\n### Broadcast Replay\n\nBroadcast Replay enables **private** channels to access messages that were sent earlier. Only messages published via [Broadcast From the Database](https://supabase.com/docs/guides/realtime/broadcast#trigger-broadcast-messages-from-your-database) are available for replay.\n\nYou can configure replay with the following options:\n\n- **`since`** (Required): The epoch timestamp in milliseconds, specifying the earliest point from which messages should be retrieved.\n- **`limit`** (Optional): The number of messages to return. This must be a positive integer, with a maximum value of 25.\n\nExample:\n\n```typescript\nconst twelveHours = 12 * 60 * 60 * 1000\nconst twelveHoursAgo = Date.now() - twelveHours\n\nconst config = { private: true, broadcast: { replay: { since: twelveHoursAgo, limit: 10 } } }\n\nsupabase\n  .channel('main:room', { config })\n  .on('broadcast', { event: 'my_event' }, (payload) => {\n    if (payload?.meta?.replayed) {\n      console.log('This message was sent earlier:', payload)\n    } else {\n      console.log('This is a new message', payload)\n    }\n    // ...\n  })\n  .subscribe()\n```\n\n## Presence\n\nYour client can track and sync state that's stored in the channel.\n\n```js\n// Setup...\n\nconst channel = client.channel('presence-test', {\n  config: {\n    presence: {\n      key: '',\n    },\n  },\n})\n\nchannel.on('presence', { event: 'sync' }, () => {\n  console.log('Online users: ', channel.presenceState())\n})\n\nchannel.on('presence', { event: 'join' }, ({ newPresences }) => {\n  console.log('New users have joined: ', newPresences)\n})\n\nchannel.on('presence', { event: 'leave' }, ({ leftPresences }) => {\n  console.log('Users have left: ', leftPresences)\n})\n\nchannel.subscribe(async (status) => {\n  if (status === 'SUBSCRIBED') {\n    const status = await channel.track({ user_id: 1 })\n    console.log(status)\n  }\n})\n```\n\n> `config.presence.enabled` (set automatically if you add an `.on('presence', ...)` listener)\n> controls whether _this_ client receives presence state and updates from other clients —\n> without it, `presenceState()` stays empty for you. It does not affect whether other clients\n> see you: calling `track()` always makes you visible to subscribers that do have presence\n> enabled. On RLS-protected channels, receiving presence updates additionally requires the\n> `presence.read` policy to authorize this client.\n\n## Postgres CDC\n\nReceive database changes on the client.\n\n```js\n// Setup...\n\nconst channel = client.channel('db-changes')\n\nchannel.on('postgres_changes', { event: '*', schema: 'public' }, (payload) => {\n  console.log('All changes in public schema: ', payload)\n})\n\nchannel.on(\n  'postgres_changes',\n  { event: 'INSERT', schema: 'public', table: 'messages' },\n  (payload) => {\n    console.log('All inserts in messages table: ', payload)\n  }\n)\n\nchannel.on(\n  'postgres_changes',\n  { event: 'UPDATE', schema: 'public', table: 'users', filter: 'username=eq.Realtime' },\n  (payload) => {\n    console.log('All updates on users table when username is Realtime: ', payload)\n  }\n)\n\nchannel.subscribe(async (status) => {\n  if (status === 'SUBSCRIBED') {\n    console.log('Ready to receive database changes!')\n  }\n})\n```\n\n### Filters\n\nThe `filter` option accepts **either** a raw string **or** a\n`postgresChangesFilter()` builder — both produce the exact same wire format, so\nyou can mix and match and existing string filters keep working unchanged:\n\n```js\n// Raw string — always supported, fully backward compatible\n{ event: 'UPDATE', schema: 'public', table: 'users', filter: 'id=eq.1' }\n\n// Builder — type-checked, ergonomic; the SDK serializes it for you\n{ event: 'UPDATE', schema: 'public', table: 'users', filter: postgresChangesFilter().eq('id', 1) }\n```\n\nA filter is a `column=operator.value` expression evaluated server-side. The\nfollowing operators are supported:\n\n| Operator              | String form                  | Builder                                | Meaning                           |\n| --------------------- | ---------------------------- | -------------------------------------- | --------------------------------- |\n| `eq`                  | `id=eq.1`                    | `.eq('id', 1)`                         | equal                             |\n| `neq`                 | `id=neq.1`                   | `.neq('id', 1)`                        | not equal                         |\n| `lt` `lte` `gt` `gte` | `age=gte.18`                 | `.gte('age', 18)`                      | comparison                        |\n| `in`                  | `status=in.(active,pending)` | `.in('status', ['active', 'pending'])` | in list                           |\n| `like` `ilike`        | `title=like.%foo%`           | `.like('title', '%foo%')`              | pattern match (case in/sensitive) |\n| `is`                  | `deleted_at=is.null`         | `.is('deleted_at', null)`              | `IS null/true/false/unknown`      |\n| `match` `imatch`      | `title=match.^foo`           | `.match('title', '^foo')`              | POSIX regex match (`~` / `~*`)    |\n| `isdistinct`          | `value=isdistinct.1`         | `.isDistinct('value', 1)`              | NULL-safe inequality              |\n\n**Negation** — prefix any operator with `not.` (string) or use\n`.not(column, operator, value)` (builder):\n\n```js\n// String\n{ event: '*', schema: 'public', table: 'posts', filter: 'status=not.in.(draft,archived)' }\n\n// Builder\n{\n  event: '*',\n  schema: 'public',\n  table: 'posts',\n  filter: postgresChangesFilter().not('status', 'in', ['draft', 'archived']),\n}\n```\n\n**AND composition** — multiple conditions are combined with commas and applied\nas an `AND`. With the builder you just chain calls:\n\n```js\n// String\n{ event: 'UPDATE', schema: 'public', table: 'orders', filter: 'amount=gt.100,status=in.(open,pending)' }\n\n// Builder — equivalent, chained\n{\n  event: 'UPDATE',\n  schema: 'public',\n  table: 'orders',\n  filter: postgresChangesFilter().gt('amount', 100).in('status', ['open', 'pending']),\n}\n```\n\n#### Building filters with `postgresChangesFilter()`\n\nThe builder (modeled on the `postgrest-js` filter methods) is the recommended,\ntype-checked way to compose filters — but it is entirely optional; raw strings\nremain fully supported.\n\n```js\nimport { postgresChangesFilter } from '@supabase/realtime-js'\n\nchannel.on(\n  'postgres_changes',\n  {\n    event: 'UPDATE',\n    schema: 'public',\n    table: 'orders',\n    // → 'amount=gt.100,status=not.in.(draft,archived)'\n    filter: postgresChangesFilter().gt('amount', 100).not('status', 'in', ['draft', 'archived']),\n  },\n  (payload) => console.log(payload)\n)\n```\n\nThe builder exposes `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `in`, `like`,\n`ilike`, `match`, `imatch`, `is`, `isDistinct` and `not`. Call `.build()` if you\nneed the raw string yourself (e.g. to log it or store it).\n\n**Values are sent verbatim** — the server has no quoting/escaping, so spaces and\nquotes are preserved as-is. The server separates conditions by commas outside\nparentheses, so a literal comma in a scalar value can't be expressed (commas\ninside `in.(…)` are fine); the builder throws on such values rather than\nsilently producing a broken filter.\n\n> **Note for PostgREST users:** Realtime evaluates filters server-side over a\n> single table's WAL — there is no resource embedding (`!inner`, embedded\n> filters) and no `or()` grouping. Use `%` (not `*`) for `like`/`ilike`\n> wildcards, since filters travel in the WebSocket payload rather than a URL.\n\n### Selecting columns\n\nUse `select` to receive only a subset of columns instead of the full row. This\nreduces payload size (helpful for large `bytea`/`jsonb` columns). The selected\ncolumns must be selectable by the subscribing role:\n\n```js\nchannel.on(\n  'postgres_changes',\n  { event: '*', schema: 'public', table: 'users', select: ['id', 'first_name'] },\n  (payload) => {\n    // payload.new only contains { id, first_name }\n    console.log(payload)\n  }\n)\n```\n\n## Get All Channels\n\nYou can see all the channels that your client has instantiatied.\n\n```js\n// Setup...\n\nclient.getChannels()\n```\n\n## Cleanup\n\nIt is highly recommended that you clean up your channels after you're done with them.\n\n- Remove a single channel\n\n```js\n// Setup...\n\nconst channel = client.channel('some-channel-to-remove')\n\nchannel.unsubscribe()\nclient.removeChannel(channel)\n```\n\n- Remove all channels and close the connection\n\n```js\n// Setup...\n\nclient.removeAllChannels()\nclient.disconnect()\n```\n\n## Development\n\nThis package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:\n\n### Building\n\n```bash\n# Complete build (from monorepo root)\npnpm nx build realtime-js\n\n# Build with watch mode for development\npnpm nx build realtime-js --watch\n\n# Individual build targets\npnpm nx build:main realtime-js    # CommonJS build (dist/main/)\npnpm nx build:module realtime-js  # ES Modules build (dist/module/)\n\n# Other useful commands\npnpm nx clean realtime-js         # Clean build artifacts\npnpm nx lint realtime-js          # Run ESLint\npnpm nx typecheck realtime-js     # TypeScript type checking\n```\n\n#### Build Outputs\n\n- **CommonJS (`dist/main/`)** - For Node.js environments\n- **ES Modules (`dist/module/`)** - For modern bundlers (Webpack, Vite, Rollup)\n- **TypeScript definitions (`dist/module/index.d.ts`)** - Type definitions for TypeScript projects\n\nNote: Unlike some other packages, realtime-js doesn't include a UMD build since it's primarily used in Node.js or bundled applications.\n\n#### Validating Package Exports\n\n```bash\n# Check if package exports are correctly configured\npnpm nx check-exports realtime-js\n```\n\nThis command uses [\"Are the types wrong?\"](https://github.com/arethetypeswrong/arethetypeswrong.github.io) to verify that the package exports work correctly in different environments. Run this before publishing to ensure your package can be imported correctly by all consumers.\n\n### Testing\n\n**No Docker or Supabase instance required!** The realtime-js tests use mocked WebSocket connections, so they're completely self-contained.\n\n```bash\n# Run unit tests (from monorepo root)\npnpm nx test realtime-js\n\n# Run tests with coverage report\npnpm nx test:coverage realtime-js\n\n# Run tests in watch mode during development\npnpm nx test:watch realtime-js\n```\n\n#### Test Scripts Explained\n\n- **test** - Runs all unit tests once using Vitest\n- **test:coverage** - Runs tests and generates coverage report with terminal output\n- **test:watch** - Runs tests in interactive watch mode for development\n\nThe tests mock WebSocket connections using `mock-socket`, so you can run them anytime without any external dependencies.\n\n### Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n\n## Credits\n\nThis repo draws heavily from [phoenix-js](https://github.com/phoenixframework/phoenix/tree/master/assets/js/phoenix).\n\n## License\n\nMIT.\n","packages/core/realtime-js/example/README.md":"# Realtime Chat Example\n\nA minimal anonymous chat app showcasing Supabase Realtime features:\n\n- **Broadcast** - Real-time message delivery\n- **Presence** - Online user indicators\n- **Database** - Message persistence\n\n## Features\n\n- Anonymous users with random usernames (stored in localStorage)\n- 4 chat rooms: General, Random, Tech, Off-Topic\n- Real-time messages\n- Online users per room\n- Message history on join\n\n## Setup\n\n### 1. Create a Supabase Project\n\nCreate a new project at [database.new](https://database.new)\n\n### 2. Run the Database Migration\n\nGo to the [SQL Editor](https://supabase.com/dashboard/project/_/sql) in your Supabase dashboard and run the migration you find in [supabase/migrations/001_create_messages_table.sql](./supabase/migrations/001_create_messages_table.sql).\n\n### 3. Configure Environment Variables\n\nCopy `.env.example` to `.env` and fill in your Supabase credentials:\n\n```bash\ncp .env.example .env\n```\n\nUpdate the values:\n\n```env\nNEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co\nNEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=your-publishable-key\n```\n\nFind these in your [Supabase project settings](https://supabase.com/dashboard/project/_/settings/api).\n\n### 4. Install Dependencies\n\n```bash\nnpm install\n```\n\n### 5. Run the App\n\n```bash\nnpm run dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000) to start chatting.\n\n## How It Works\n\n### Broadcast\n\nMessages are instantly delivered to all connected clients via Supabase Realtime Broadcast:\n\n```typescript\nchannel.send({\n  type: 'broadcast',\n  event: 'message',\n  payload: message,\n})\n```\n\n### Presence\n\nOnline users are tracked using Supabase Realtime Presence:\n\n```typescript\nchannel.on('presence', { event: 'sync' }, () => {\n  const users = Object.values(channel.presenceState()).flat()\n  setOnlineUsers(users)\n})\n```\n\n### Persistence\n\nMessages are also stored in the database so users see history when joining:\n\n```typescript\nconst { data } = await supabase\n  .from('messages')\n  .select('*')\n  .eq('room', room)\n  .order('created_at', { ascending: true })\n  .limit(50)\n```\n\n## Local Development\n\nYou can run Supabase locally using the Supabase CLI and Docker.\n\n### Prerequisites\n\n- [Docker](https://docs.docker.com/get-docker/) installed and running\n- [Supabase CLI](https://supabase.com/docs/guides/cli) (installed or used through `npx`)\n\n### 1. Start Supabase\n\n```bash\nnpx supabase start\n```\n\nThis will start all Supabase services locally. Once started, you'll see output with your local credentials:\n\n```\n╭──────────────────────────────────────╮\n│ 🔧 Development Tools                 │\n├─────────┬────────────────────────────┤\n│ Studio  │ http://127.0.0.1:54323     │\n│ ...     │ ...                        │\n╰─────────┴────────────────────────────╯\n\n╭──────────────────────────────────────────────╮\n│ 🌐 APIs                                      │\n├────────────────┬─────────────────────────────┤\n│ Project URL    │ http://127.0.0.1:54321      │\n│ ...            │ ...                         │\n╰────────────────┴─────────────────────────────╯\n...\n╭──────────────────────────────────────────────────╮\n│ 🔑 Authentication Keys                           │\n├─────────────┬────────────────────────────────────┤\n│ Publishable │ sb_publishable_...                 │\n│ Secret      │ sb_secret_...                      │\n╰─────────────┴────────────────────────────────────╯\n...\n```\n\n### 2. Configure Environment\n\nCopy `.env.example` to `.env.local`:\n\n```bash\ncp .env.example .env.local\n```\n\nUpdate the values:\n\n```env\nNEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321\nNEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_....\n```\n\n### 3. Run Migrations\n\nApply the database migration:\n\n```bash\nnpx supabase db reset\n```\n\nThis will apply all migrations from `supabase/migrations/`.\n\n### 5. Access Local Dashboard\n\nOpen [http://127.0.0.1:54323](http://127.0.0.1:54323) to access Supabase Studio locally. Here you can:\n\n- View and edit data in the Table Editor\n- Run SQL queries\n- Monitor Realtime connections\n- Check logs\n\n### Stopping Supabase\n\n```bash\nnpx supabase stop\n```\n","packages/core/realtime-js/migrations/README.md":"# Migration notes for `@supabase/realtime-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/realtime-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/realtime-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/realtime-js`:\n\n1. Read the migration files in `node_modules/@supabase/realtime-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/realtime-js` only.\n","packages/core/storage-js/AGENTS.md":"# Agent instructions for `@supabase/storage-js`\n\nIsomorphic storage client for Supabase. Handles bucket and object operations: upload, download, list, signed URLs, transformations.\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n","packages/core/storage-js/README.md":"<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase Storage JS SDK</h1>\n\n  <h3 align=\"center\">JavaScript SDK to interact with Supabase Storage, including file storage and vector embeddings.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/storage\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript/storage-createbucket\">Reference Docs</a>\n    ·\n    <a href=\"https://supabase.github.io/supabase-js/storage-js/v2/spec.json\">TypeDoc</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/storage-js)](https://www.npmjs.com/package/@supabase/storage-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/storage-js)](https://pkg.pr.new/~/supabase/storage-js)\n\n</div>\n\n## Requirements\n\n- **Node.js 22 or later** (Node.js 20 support dropped in v2.110.0)\n- For browser support, all modern browsers are supported\n\n> ⚠️ **Node.js 18 Deprecation Notice**\n>\n> Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped on October 31, 2025.\n\n> ⚠️ **Node.js 20 Deprecation Notice**\n>\n> Node.js 20 reached end-of-life on April 30, 2026. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/45715), support for Node.js 20 was dropped in v2.110.0.\n\n## Features\n\n- **File Storage**: Upload, download, list, move, and delete files\n- **Access Control**: Public and private buckets with fine-grained permissions\n- **Signed URLs**: Generate time-limited URLs for secure file access\n- **Image Transformations**: On-the-fly image resizing and optimization\n- **Vector Embeddings**: Store and query high-dimensional embeddings with similarity search\n- **Analytics Buckets**: Iceberg table-based buckets optimized for analytical queries and data processing\n- **Lifecycle**: Expire previous versions of objects after a number of days\n\n## Quick Start Guide\n\n### Installing the module\n\n```bash\nnpm install @supabase/storage-js\n```\n\n### Connecting to the storage backend\n\nThere are two ways to use the Storage SDK:\n\n#### Option 1: Via Supabase Client (Recommended)\n\nIf you're already using `@supabase/supabase-js`, access storage through the client:\n\n```js\nimport { createClient } from '@supabase/supabase-js'\n\n// Use publishable key for frontend applications\nconst supabase = createClient('https://<project_ref>.supabase.co', '<your-publishable-key>')\n\n// Access storage\nconst storage = supabase.storage\n\n// Access different bucket types\nconst regularBucket = storage.from('my-bucket')\nconst vectorBucket = storage.vectors.from('embeddings-bucket')\nconst analyticsBucket = storage.analytics // Analytics API\n```\n\n#### Option 2: Standalone StorageClient\n\nFor backend applications or when you need to bypass Row Level Security:\n\n```js\nimport { StorageClient } from '@supabase/storage-js'\n\nconst STORAGE_URL = 'https://<project_ref>.supabase.co/storage/v1'\nconst SERVICE_KEY = '<your-secret-key>' // Use secret key for backend operations\n\nconst storageClient = new StorageClient(STORAGE_URL, {\n  apikey: SERVICE_KEY,\n  Authorization: `Bearer ${SERVICE_KEY}`,\n})\n\n// Access different bucket types\nconst regularBucket = storageClient.from('my-bucket')\nconst vectorBucket = storageClient.vectors.from('embeddings-bucket')\nconst analyticsBucket = storageClient.analytics // Analytics API\n```\n\n> **When to use each approach:**\n>\n> - Use `supabase.storage` when working with other Supabase features (auth, database, etc.) in frontend applications\n> - Use `new StorageClient()` for backend applications, Edge Functions, or when you need to bypass RLS policies\n\n> **Note:** Refer to the [Storage Access Control guide](https://supabase.com/docs/guides/storage/access-control) for detailed information on creating RLS policies.\n\n### Understanding Bucket Types\n\nSupabase Storage supports three types of buckets, each optimized for different use cases:\n\n#### 1. Regular Storage Buckets (File Storage)\n\nStandard buckets for storing files, images, videos, and other assets.\n\n```js\n// Create regular storage bucket\nconst { data, error } = await storageClient.createBucket('my-files', {\n  public: false,\n})\n\n// Upload files\nawait storageClient.from('my-files').upload('avatar.png', file)\n```\n\n**Use cases:** User uploads, media assets, documents, backups\n\n#### 2. Vector Buckets (Embeddings Storage)\n\nSpecialized buckets for storing and querying high-dimensional vector embeddings.\n\n```js\n// Create vector bucket\nawait storageClient.vectors.createBucket('embeddings-prod')\n\n// Create index and insert vectors\nconst bucket = storageClient.vectors.from('embeddings-prod')\nawait bucket.createIndex({\n  indexName: 'documents',\n  dimension: 1536,\n  distanceMetric: 'cosine',\n})\n```\n\n**Use cases:** Semantic search, AI-powered recommendations, similarity matching\n\n**[See full Vector Embeddings documentation below](#vector-embeddings)**\n\n#### 3. Analytics Buckets\n\nSpecialized buckets using Apache Iceberg table format, optimized for analytical queries and large-scale data processing.\n\n```js\n// Create analytics bucket\nawait storageClient.analytics.createBucket('analytics-data')\n\n// List analytics buckets\nconst { data, error } = await storageClient.analytics.listBuckets()\n\n// Delete analytics bucket\nawait storageClient.analytics.deleteBucket('analytics-data')\n```\n\n**Use cases:** Time-series data, analytical queries, data lakes, large-scale data processing, business intelligence\n\n**[See full Analytics Buckets documentation below](#analytics-buckets)**\n\n---\n\n### Handling resources\n\n#### Handling Storage Buckets\n\n- Create a new Storage bucket:\n\n  ```js\n  const { data, error } = await storageClient.createBucket(\n    'test_bucket', // Bucket name (must be unique)\n    { public: false } // Bucket options\n  )\n  ```\n\n- Retrieve the details of an existing Storage bucket:\n\n  ```js\n  const { data, error } = await storageClient.getBucket('test_bucket')\n  ```\n\n- Update a new Storage bucket:\n\n  ```js\n  const { data, error } = await storageClient.updateBucket(\n    'test_bucket', // Bucket name\n    { public: false } // Bucket options\n  )\n  ```\n\n- Remove all objects inside a single bucket:\n\n  ```js\n  const { data, error } = await storageClient.emptyBucket('test_bucket')\n  ```\n\n- Delete an existing bucket (a bucket can't be deleted with existing objects inside it):\n\n  ```js\n  const { data, error } = await storageClient.deleteBucket('test_bucket')\n  ```\n\n- Retrieve the details of all Storage buckets within an existing project:\n\n  ```js\n  // List all buckets\n  const { data, error } = await storageClient.listBuckets()\n\n  // List buckets with options (pagination, sorting, search)\n  const { data, error } = await storageClient.listBuckets({\n    limit: 10,\n    offset: 0,\n    sortColumn: 'created_at',\n    sortOrder: 'desc',\n    search: 'prod',\n  })\n  ```\n\n- Manage a bucket's lifecycle policy. Rules expire **previous versions** of objects after a number of days, so versioning needs to be enabled or the policy has nothing to act on. This is Standard buckets only, and the project must have lifecycle enabled.\n\n  ```js\n  // Replaces every existing rule\n  const { data, error } = await storageClient.updateBucketLifecycle('test_bucket', {\n    rules: [\n      {\n        id: 'expire-old-versions',\n        status: 'Enabled',\n        filter: {},\n        noncurrentVersionExpiration: { noncurrentDays: 30 },\n      },\n    ],\n  })\n\n  // Fails with NoSuchLifecycleConfiguration when the bucket has no policy\n  const { data: config, error: configError } = await storageClient.getBucketLifecycle('test_bucket')\n\n  await storageClient.deleteBucketLifecycle('test_bucket')\n  ```\n\n#### Handling Files\n\n- Upload a file to an existing bucket:\n\n  ```js\n  const fileBody = ... // load your file here\n\n  const { data, error } = await storageClient.from('bucket').upload('path/to/file', fileBody)\n  ```\n\n  > Note:  \n  > The path in `data.Key` is prefixed by the bucket ID and is not the value which should be passed to the `download` method in order to fetch the file.  \n  > To fetch the file via the `download` method, use `data.path` and `data.bucketId` as follows:\n  >\n  > ```javascript\n  > const { data, error } = await storageClient.from('bucket').upload('/folder/file.txt', fileBody)\n  > // check for errors\n  > const { data2, error2 } = await storageClient.from(data.bucketId).download(data.path)\n  > ```\n\n  > Note: The `upload` method also accepts a map of optional parameters. For a complete list see the [Supabase API reference](https://supabase.com/docs/reference/javascript/storage-from-upload).\n\n- Download a file from an exisiting bucket:\n\n  ```js\n  const { data, error } = await storageClient.from('bucket').download('path/to/file')\n  ```\n\n- List all the files within a bucket:\n\n  ```js\n  const { data, error } = await storageClient.from('bucket').list('folder')\n  ```\n\n  > Note: The `list` method also accepts a map of optional parameters. For a complete list see the [Supabase API reference](https://supabase.com/docs/reference/javascript/storage-from-list).\n\n- Replace an existing file at the specified path with a new one:\n\n  ```js\n  const fileBody = ... // load your file here\n\n  const { data, error } = await storageClient\n    .from('bucket')\n    .update('path/to/file', fileBody)\n  ```\n\n  > Note: The `upload` method also accepts a map of optional parameters. For a complete list see the [Supabase API reference](https://supabase.com/docs/reference/javascript/storage-from-upload).\n\n- Move an existing file:\n\n  ```js\n  const { data, error } = await storageClient\n    .from('bucket')\n    .move('old/path/to/file', 'new/path/to/file')\n  ```\n\n- Delete files within the same bucket:\n\n  ```js\n  const { data, error } = await storageClient.from('bucket').remove(['path/to/file'])\n  ```\n\n- Create signed URL to download file without requiring permissions:\n\n  ```js\n  const expireIn = 60\n\n  const { data, error } = await storageClient\n    .from('bucket')\n    .createSignedUrl('path/to/file', expireIn)\n  ```\n\n- Retrieve URLs for assets in public buckets:\n\n  ```js\n  const { data, error } = await storageClient.from('public-bucket').getPublicUrl('path/to/file')\n  ```\n\n## Analytics Buckets\n\nSupabase Storage provides specialized analytics buckets using Apache Iceberg table format, optimized for analytical workloads and large-scale data processing. These buckets are designed for data lake architectures, time-series data, and business intelligence applications.\n\n### What are Analytics Buckets?\n\nAnalytics buckets use the Apache Iceberg open table format, providing:\n\n- **ACID transactions** for data consistency\n- **Schema evolution** without data rewrites\n- **Time travel** to query historical data\n- **Efficient metadata management** for large datasets\n- **Optimized for analytical queries** rather than individual file operations\n\n### When to Use Analytics Buckets\n\n**Use analytics buckets for:**\n\n- Time-series data (logs, metrics, events)\n- Data lake architectures\n- Business intelligence and reporting\n- Large-scale batch processing\n- Analytical workloads requiring ACID guarantees\n\n**Use regular storage buckets for:**\n\n- User file uploads (images, documents, videos)\n- Individual file management\n- Content delivery\n- Simple object storage needs\n\n### Quick Start\n\nYou can access analytics functionality through the `analytics` property on your storage client:\n\n#### Via Supabase Client\n\n```typescript\nimport { createClient } from '@supabase/supabase-js'\n\nconst supabase = createClient('https://your-project.supabase.co', 'your-publishable-key')\n\n// Access analytics operations\nconst analytics = supabase.storage.analytics\n\n// Create an analytics bucket\nconst { data, error } = await analytics.createBucket('analytics-data')\nif (error) {\n  console.error('Failed to create analytics bucket:', error.message)\n} else {\n  console.log('Created bucket:', data.name)\n}\n```\n\n#### Via StorageClient\n\n```typescript\nimport { StorageClient } from '@supabase/storage-js'\n\nconst storageClient = new StorageClient('https://your-project.supabase.co/storage/v1', {\n  apikey: 'YOUR_API_KEY',\n  Authorization: 'Bearer YOUR_TOKEN',\n})\n\n// Access analytics operations\nconst analytics = storageClient.analytics\n\n// Create an analytics bucket\nawait analytics.createBucket('analytics-data')\n```\n\n### API Reference\n\n#### Create Analytics Bucket\n\nCreates a new analytics bucket using Iceberg table format:\n\n```typescript\nconst { data, error } = await analytics.createBucket('my-analytics-bucket')\n\nif (error) {\n  console.error('Error:', error.message)\n} else {\n  console.log('Created bucket:', data)\n}\n```\n\n**Returns:**\n\n```typescript\n{\n  data: {\n    id: string\n    type: 'ANALYTICS'\n    format: string\n    created_at: string\n    updated_at: string\n  } | null\n  error: StorageError | null\n}\n```\n\n#### List Analytics Buckets\n\nRetrieves all analytics buckets in your project with optional filtering and pagination:\n\n```typescript\nconst { data, error } = await analytics.listBuckets({\n  limit: 10,\n  offset: 0,\n  sortColumn: 'created_at',\n  sortOrder: 'desc',\n  search: 'prod',\n})\n\nif (data) {\n  console.log(`Found ${data.length} analytics buckets`)\n  data.forEach((bucket) => {\n    console.log(`- ${bucket.id} (created: ${bucket.created_at})`)\n  })\n}\n```\n\n**Parameters:**\n\n- `limit?: number` - Maximum number of buckets to return\n- `offset?: number` - Number of buckets to skip (for pagination)\n- `sortColumn?: 'id' | 'name' | 'created_at' | 'updated_at'` - Column to sort by\n- `sortOrder?: 'asc' | 'desc'` - Sort direction\n- `search?: string` - Search term to filter bucket names\n\n**Returns:**\n\n```typescript\n{\n  data: AnalyticBucket[] | null\n  error: StorageError | null\n}\n```\n\n**Example with Pagination:**\n\n```typescript\n// Fetch first page\nconst firstPage = await analytics.listBuckets({\n  limit: 100,\n  offset: 0,\n  sortColumn: 'created_at',\n  sortOrder: 'desc',\n})\n\n// Fetch second page\nconst secondPage = await analytics.listBuckets({\n  limit: 100,\n  offset: 100,\n  sortColumn: 'created_at',\n  sortOrder: 'desc',\n})\n```\n\n#### Delete Analytics Bucket\n\nDeletes an analytics bucket. The bucket must be empty before deletion.\n\n```typescript\nconst { data, error } = await analytics.deleteBucket('old-analytics-bucket')\n\nif (error) {\n  console.error('Failed to delete:', error.message)\n} else {\n  console.log('Bucket deleted:', data.message)\n}\n```\n\n**Returns:**\n\n```typescript\n{\n  data: { message: string } | null\n  error: StorageError | null\n}\n```\n\n> **Note:** A bucket cannot be deleted if it contains data. You must empty the bucket first.\n\n#### Get Iceberg Catalog for Advanced Operations\n\nFor advanced operations like creating tables, namespaces, and querying Iceberg metadata, use the `from()` method to get a configured [iceberg-js](https://github.com/supabase/iceberg-js) client:\n\n```typescript\n// Get an Iceberg REST Catalog client for your analytics bucket\nconst catalog = analytics.from('analytics-data')\n\n// Create a namespace\nawait catalog.createNamespace({ namespace: ['default'] }, { properties: { owner: 'data-team' } })\n\n// Create a table with schema\nawait catalog.createTable(\n  { namespace: ['default'] },\n  {\n    name: 'events',\n    schema: {\n      type: 'struct',\n      fields: [\n        { id: 1, name: 'id', type: 'long', required: true },\n        { id: 2, name: 'timestamp', type: 'timestamp', required: true },\n        { id: 3, name: 'user_id', type: 'string', required: false },\n      ],\n      'schema-id': 0,\n      'identifier-field-ids': [1],\n    },\n    'partition-spec': {\n      'spec-id': 0,\n      fields: [],\n    },\n    'write-order': {\n      'order-id': 0,\n      fields: [],\n    },\n    properties: {\n      'write.format.default': 'parquet',\n    },\n  }\n)\n\n// List tables in namespace\nconst tables = await catalog.listTables({ namespace: ['default'] })\nconsole.log(tables) // [{ namespace: ['default'], name: 'events' }]\n\n// Load table metadata\nconst table = await catalog.loadTable({ namespace: ['default'], name: 'events' })\n\n// Update table properties\nawait catalog.updateTable(\n  { namespace: ['default'], name: 'events' },\n  { properties: { 'read.split.target-size': '134217728' } }\n)\n\n// Drop table\nawait catalog.dropTable({ namespace: ['default'], name: 'events' })\n\n// Drop namespace\nawait catalog.dropNamespace({ namespace: ['default'] })\n```\n\n**Returns:** `IcebergRestCatalog` instance from [iceberg-js](https://github.com/supabase/iceberg-js)\n\n> **Note:** The `from()` method returns an Iceberg REST Catalog client that provides full access to the Apache Iceberg REST API. For complete documentation of available operations, see the [iceberg-js documentation](https://supabase.github.io/iceberg-js/).\n\n### Error Handling\n\nAnalytics buckets use the same error handling pattern as the rest of the Storage SDK:\n\n```typescript\nconst { data, error } = await analytics.createBucket('my-bucket')\n\nif (error) {\n  console.error('Error:', error.message)\n  console.error('Status:', error.status)\n  console.error('Status Code:', error.statusCode)\n  // Handle error appropriately\n}\n```\n\n#### Throwing Errors\n\nYou can configure the client to throw errors instead of returning them:\n\n```typescript\nconst analytics = storageClient.analytics\nanalytics.throwOnError()\n\ntry {\n  const { data } = await analytics.createBucket('my-bucket')\n  // data is guaranteed to be present\n  console.log('Success:', data)\n} catch (error) {\n  if (error instanceof StorageApiError) {\n    console.error('API Error:', error.statusCode, error.message)\n  }\n}\n```\n\n### TypeScript Types\n\nThe library exports TypeScript types for analytics buckets:\n\n```typescript\nimport type { AnalyticBucket, BucketType, StorageError } from '@supabase/storage-js'\n\n// AnalyticBucket type\ninterface AnalyticBucket {\n  id: string\n  type: 'ANALYTICS'\n  format: string\n  created_at: string\n  updated_at: string\n}\n```\n\n### Common Patterns\n\n#### Checking if a Bucket Exists\n\n```typescript\nasync function bucketExists(bucketName: string): Promise<boolean> {\n  const { data, error } = await analytics.listBuckets({\n    search: bucketName,\n  })\n\n  if (error) {\n    console.error('Error checking bucket:', error.message)\n    return false\n  }\n\n  return data?.some((bucket) => bucket.id === bucketName) ?? false\n}\n```\n\n#### Creating Bucket with Error Handling\n\n```typescript\nasync function ensureAnalyticsBucket(bucketName: string) {\n  // Try to create the bucket\n  const { data, error } = await analytics.createBucket(bucketName)\n\n  if (error) {\n    // Check if bucket already exists (conflict error)\n    if (error.statusCode === '409') {\n      console.log(`Bucket '${bucketName}' already exists`)\n      return { success: true, created: false }\n    }\n\n    // Other error occurred\n    console.error('Failed to create bucket:', error.message)\n    return { success: false, error }\n  }\n\n  console.log(`Created new bucket: '${bucketName}'`)\n  return { success: true, created: true, data }\n}\n```\n\n#### Listing All Buckets with Pagination\n\n```typescript\nasync function getAllAnalyticsBuckets() {\n  const allBuckets: AnalyticBucket[] = []\n  let offset = 0\n  const limit = 100\n\n  while (true) {\n    const { data, error } = await analytics.listBuckets({\n      limit,\n      offset,\n      sortColumn: 'created_at',\n      sortOrder: 'desc',\n    })\n\n    if (error) {\n      console.error('Error fetching buckets:', error.message)\n      break\n    }\n\n    if (!data || data.length === 0) {\n      break\n    }\n\n    allBuckets.push(...data)\n\n    // If we got fewer results than the limit, we've reached the end\n    if (data.length < limit) {\n      break\n    }\n\n    offset += limit\n  }\n\n  return allBuckets\n}\n```\n\n## Vector Embeddings\n\nSupabase Storage provides built-in support for storing and querying high-dimensional vector embeddings, powered by S3 Vectors. This enables semantic search, similarity matching, and AI-powered applications without needing a separate vector database.\n\n> **Note:** Vector embeddings functionality is available in `@supabase/storage-js` v2.76 and later.\n\n### Features\n\n- **Vector Buckets**: Organize vector indexes into logical containers\n- **Vector Indexes**: Define schemas with configurable dimensions and distance metrics\n- **Batch Operations**: Insert/update/delete up to 500 vectors per request\n- **Similarity Search**: Query for nearest neighbors using cosine, euclidean, or dot product distance\n- **Metadata Filtering**: Store and filter vectors by arbitrary JSON metadata\n- **Pagination**: Efficiently scan large vector datasets\n- **Parallel Scanning**: Distribute scans across multiple workers for high throughput\n- **Cross-platform**: Works in Node.js, browsers, and edge runtimes\n\n### Quick Start\n\nYou can access vector functionality in three ways, depending on your use case:\n\n#### Option 1: Via Supabase Client (Most Common)\n\nIf you're using the full Supabase client:\n\n```typescript\nimport { createClient } from '@supabase/supabase-js'\n\nconst supabase = createClient('https://your-project.supabase.co', 'your-publishable-key')\n\n// Access vector operations through storage\nconst vectors = supabase.storage.vectors\n\n// Create a vector bucket\nawait vectors.createBucket('embeddings-prod')\n\n// Create an index\nconst bucket = vectors.from('embeddings-prod')\nawait bucket.createIndex({\n  indexName: 'documents-openai',\n  dataType: 'float32',\n  dimension: 1536,\n  distanceMetric: 'cosine',\n})\n\n// Insert vectors\nconst index = bucket.index('documents-openai')\nawait index.putVectors({\n  vectors: [\n    {\n      key: 'doc-1',\n      data: { float32: [0.1, 0.2, 0.3 /* ...1536 dimensions */] },\n      metadata: { title: 'Introduction', category: 'docs' },\n    },\n  ],\n})\n\n// Query similar vectors\nconst { data, error } = await index.queryVectors({\n  queryVector: { float32: [0.15, 0.25, 0.35 /* ...1536 dimensions */] },\n  topK: 5,\n  returnDistance: true,\n  returnMetadata: true,\n})\n\nif (data) {\n  data.vectors.forEach((match) => {\n    console.log(`${match.key}: distance=${match.distance}`)\n    console.log('Metadata:', match.metadata)\n  })\n}\n```\n\n#### Option 2: Via StorageClient\n\nIf you're using the standalone `StorageClient` for storage operations, access vectors through the `vectors` property:\n\n```typescript\nimport { StorageClient } from '@supabase/storage-js'\n\nconst storageClient = new StorageClient('https://your-project.supabase.co/storage/v1', {\n  apikey: 'YOUR_API_KEY',\n  Authorization: 'Bearer YOUR_TOKEN',\n})\n\n// Access vector operations\nconst vectors = storageClient.vectors\n\n// Use the same API as shown in Option 1\nawait vectors.createBucket('embeddings-prod')\nconst bucket = vectors.from('embeddings-prod')\n// ... rest of operations\n```\n\n#### Option 3: Standalone Vector Client\n\nFor vector-only applications that don't need regular file storage operations:\n\n```typescript\nimport { StorageVectorsClient } from '@supabase/storage-js'\n\n// Initialize standalone vector client\nconst vectorClient = new StorageVectorsClient('https://your-project.supabase.co/storage/v1', {\n  headers: { Authorization: 'Bearer YOUR_TOKEN' },\n})\n\n// Use the same API as shown in Option 1\nawait vectorClient.createBucket('embeddings-prod')\nconst bucket = vectorClient.from('embeddings-prod')\n// ... rest of operations\n```\n\n> **When to use each approach:**\n>\n> - **Option 1**: When using other Supabase features (auth, database, realtime)\n> - **Option 2**: When working with both file storage and vectors\n> - **Option 3**: For dedicated vector-only applications without file storage\n\n### API Reference\n\n#### Client Initialization\n\n```typescript\nconst vectorClient = new StorageVectorsClient(url, options?)\n```\n\n**Options:**\n\n- `headers?: Record<string, string>` - Custom HTTP headers (e.g., Authorization)\n- `fetch?: Fetch` - Custom fetch implementation\n\n#### Vector Buckets\n\nVector buckets are top-level containers for organizing vector indexes.\n\n##### Create Bucket\n\n```typescript\nconst { data, error } = await vectorClient.createBucket('my-bucket')\n```\n\n##### Get Bucket\n\n```typescript\nconst { data, error } = await vectorClient.getBucket('my-bucket')\nconsole.log('Created at:', new Date(data.vectorBucket.creationTime! * 1000))\n```\n\n##### List Buckets\n\n```typescript\nconst { data, error } = await vectorClient.listBuckets({\n  prefix: 'prod-',\n  maxResults: 100,\n})\n\n// Pagination\nif (data?.nextToken) {\n  const next = await vectorClient.listBuckets({ nextToken: data.nextToken })\n}\n```\n\n##### Delete Bucket\n\n```typescript\n// Bucket must be empty (all indexes deleted first)\nconst { error } = await vectorClient.deleteBucket('my-bucket')\n```\n\n#### Vector Indexes\n\nVector indexes define the schema for embeddings including dimension and distance metric.\n\n##### Create Index\n\n```typescript\nconst bucket = vectorClient.from('my-bucket')\n\nawait bucket.createIndex({\n  indexName: 'my-index',\n  dataType: 'float32',\n  dimension: 1536,\n  distanceMetric: 'cosine', // 'cosine' | 'euclidean' | 'dotproduct'\n  metadataConfiguration: {\n    nonFilterableMetadataKeys: ['raw_text', 'internal_id'],\n  },\n})\n```\n\n**Distance Metrics:**\n\n- `cosine` - Cosine similarity (normalized dot product)\n- `euclidean` - Euclidean distance (L2 norm)\n- `dotproduct` - Dot product similarity\n\n##### Get Index\n\n```typescript\nconst { data, error } = await bucket.getIndex('my-index')\nconsole.log('Dimension:', data?.index.dimension)\nconsole.log('Distance metric:', data?.index.distanceMetric)\n```\n\n##### List Indexes\n\n```typescript\nconst { data, error } = await bucket.listIndexes({\n  prefix: 'documents-',\n  maxResults: 100,\n})\n```\n\n##### Delete Index\n\n```typescript\n// Deletes index and all its vectors\nawait bucket.deleteIndex('my-index')\n```\n\n#### Vector Operations\n\n##### Insert/Update Vectors (Upsert)\n\n```typescript\nconst index = vectorClient.from('my-bucket').index('my-index')\n\nawait index.putVectors({\n  vectors: [\n    {\n      key: 'unique-id-1',\n      data: {\n        float32: [\n          /* 1536 numbers */\n        ],\n      },\n      metadata: {\n        title: 'Document Title',\n        category: 'technical',\n        page: 1,\n      },\n    },\n    // ... up to 500 vectors per request\n  ],\n})\n```\n\n**Limitations:**\n\n- 1-500 vectors per request\n- Vectors must match index dimension\n- Keys must be unique within index\n\n##### Get Vectors by Key\n\n```typescript\nconst { data, error } = await index.getVectors({\n  keys: ['doc-1', 'doc-2', 'doc-3'],\n  returnData: true, // Include embeddings\n  returnMetadata: true, // Include metadata\n})\n\ndata?.vectors.forEach((v) => {\n  console.log(v.key, v.metadata)\n})\n```\n\n##### Query Similar Vectors (ANN Search)\n\n```typescript\nconst { data, error } = await index.queryVectors({\n  queryVector: {\n    float32: [\n      /* 1536 numbers */\n    ],\n  },\n  topK: 10,\n  filter: {\n    category: 'technical',\n    published: true,\n  },\n  returnDistance: true,\n  returnMetadata: true,\n})\n\n// Results ordered by similarity\ndata?.vectors.forEach((match) => {\n  console.log(`${match.key}: distance=${match.distance}`)\n})\n```\n\nS3 vector buckets support deep queries with `topK` up to 10,000, returning at most 100 vectors per response. Pass the response's `nextToken` with the same query to retrieve the next page:\n\n```typescript\nconst query = {\n  queryVector: { float32: embedding },\n  topK: 1000,\n  returnDistance: true,\n}\n\nlet nextToken: string | undefined\n\ndo {\n  const { data, error } = await index.queryVectors({ ...query, nextToken })\n  if (error) throw error\n\n  for (const vector of data.vectors) {\n    console.log(`${vector.key}: distance=${vector.distance}`)\n  }\n\n  nextToken = data.nextToken\n} while (nextToken)\n```\n\nThe pgvector backend supports `topK` up to 100 and does not support `nextToken` pagination.\n\n**Filter Syntax:**\nThe `filter` parameter accepts arbitrary JSON for metadata filtering. Non-filterable keys (configured at index creation) cannot be used in filters but can still be returned.\n\n##### List/Scan Vectors\n\n```typescript\n// Simple pagination\nlet nextToken: string | undefined\ndo {\n  const { data } = await index.listVectors({\n    maxResults: 500,\n    nextToken,\n    returnMetadata: true,\n  })\n\n  console.log('Batch:', data?.vectors.length)\n  nextToken = data?.nextToken\n} while (nextToken)\n\n// Parallel scanning (4 workers)\nconst workers = [0, 1, 2, 3].map(async (segmentIndex) => {\n  const { data } = await index.listVectors({\n    segmentCount: 4,\n    segmentIndex,\n    returnMetadata: true,\n  })\n  return data?.vectors || []\n})\n\nconst results = await Promise.all(workers)\nconst allVectors = results.flat()\n```\n\n**Limitations:**\n\n- `maxResults`: 1-1000 (default: 500)\n- `segmentCount`: 1-16\n- Response may be limited by 1MB size\n\n##### Delete Vectors\n\n```typescript\nawait index.deleteVectors({\n  keys: ['doc-1', 'doc-2', 'doc-3'],\n  // ... up to 500 keys per request\n})\n```\n\n### Error Handling\n\nThe library uses a consistent error handling pattern:\n\n```typescript\nconst { data, error } = await vectorClient.createBucket('my-bucket')\n\nif (error) {\n  console.error('Error:', error.message)\n  console.error('Status:', error.status)\n  console.error('Code:', error.statusCode)\n}\n```\n\n#### Error Codes\n\n| Code                         | HTTP | Description             |\n| ---------------------------- | ---- | ----------------------- |\n| `InternalError`              | 500  | Internal server error   |\n| `S3VectorConflictException`  | 409  | Resource already exists |\n| `S3VectorNotFoundException`  | 404  | Resource not found      |\n| `S3VectorBucketNotEmpty`     | 400  | Bucket contains indexes |\n| `S3VectorMaxBucketsExceeded` | 400  | Bucket quota exceeded   |\n| `S3VectorMaxIndexesExceeded` | 400  | Index quota exceeded    |\n\n#### Throwing Errors\n\nYou can configure the client to throw errors instead:\n\n```typescript\nconst vectorClient = new StorageVectorsClient(url, options)\nvectorClient.throwOnError()\n\ntry {\n  const { data } = await vectorClient.createBucket('my-bucket')\n  // data is guaranteed to be present\n} catch (error) {\n  if (error instanceof StorageVectorsApiError) {\n    console.error('API Error:', error.statusCode)\n  }\n}\n```\n\n### Advanced Usage\n\n#### Scoped Clients\n\nCreate scoped clients for cleaner code:\n\n```typescript\n// Bucket-scoped operations\nconst bucket = vectorClient.from('embeddings-prod')\nawait bucket.createIndex({\n  /* ... */\n})\nawait bucket.listIndexes()\n\n// Index-scoped operations\nconst index = bucket.index('documents-openai')\nawait index.putVectors({\n  /* ... */\n})\nawait index.queryVectors({\n  /* ... */\n})\n```\n\n#### Custom Fetch\n\nProvide a custom fetch implementation:\n\n```typescript\nimport { StorageVectorsClient } from '@supabase/storage-js'\n\nconst vectorClient = new StorageVectorsClient(url, {\n  fetch: customFetch,\n  headers: {\n    /* ... */\n  },\n})\n```\n\n#### Batch Processing\n\nProcess large datasets in batches:\n\n```typescript\nasync function insertLargeDataset(vectors: VectorObject[]) {\n  const batchSize = 500\n\n  for (let i = 0; i < vectors.length; i += batchSize) {\n    const batch = vectors.slice(i, i + batchSize)\n    await index.putVectors({ vectors: batch })\n    console.log(`Inserted ${i + batch.length}/${vectors.length}`)\n  }\n}\n```\n\n#### Float32 Validation\n\nEnsure vectors are properly normalized to float32:\n\n```typescript\nimport { normalizeToFloat32 } from '@supabase/storage-js'\n\nconst vector = normalizeToFloat32([0.1, 0.2, 0.3 /* ... */])\n```\n\n### Type Definitions\n\nThe library exports comprehensive TypeScript types:\n\n```typescript\nimport type {\n  VectorBucket,\n  VectorIndex,\n  VectorData,\n  VectorObject,\n  VectorMatch,\n  VectorMetadata,\n  DistanceMetric,\n  ApiResponse,\n  StorageVectorsError,\n} from '@supabase/storage-js'\n```\n\n## Development\n\nThis package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:\n\n### Building\n\n#### Build Scripts Overview\n\n```bash\n# Build the package\npnpm nx build storage-js\n\n# Watch mode for development\npnpm nx build storage-js --watch\n\n# Generate documentation\npnpm nx docs storage-js\n```\n\n### Testing\n\n**Important:** The storage-js tests require a local Supabase stack running via the Supabase CLI. Docker must be running since the Supabase CLI uses it internally.\n\n#### Prerequisites\n\n1. **Docker** must be installed and running (used by Supabase CLI internally)\n2. **Supabase CLI** — installed automatically via `pnpm exec supabase`\n\n#### Test Scripts Overview\n\n| Script            | Description                       | What it does                                                      |\n| ----------------- | --------------------------------- | ----------------------------------------------------------------- |\n| `test:storage`    | **Complete test workflow**        | Runs the full test cycle: clean → start infra → run tests → clean |\n| `test:suite`      | **Jest tests only**               | Runs Jest tests with coverage (requires infra to be running)      |\n| `test:infra`      | **Start test infrastructure**     | Starts Supabase CLI stack (PostgreSQL, Storage API, Kong, etc.)   |\n| `test:clean-post` | **Stop and clean infrastructure** | Stops the Supabase CLI stack                                      |\n\n#### Running Tests\n\n##### Option 1: Complete Test Run (Recommended)\n\nThis handles everything automatically - starting infrastructure, running tests, and cleaning up:\n\n```bash\n# From monorepo root\npnpm nx test:storage storage-js\n```\n\nThis command will:\n\n1. Stop any existing test containers\n2. Build and start fresh test infrastructure\n3. Wait for services to be ready\n4. Run all Jest tests with coverage\n5. Clean up all containers after tests complete\n\n##### Option 2: Manual Infrastructure Management\n\nUseful for development when you want to run tests multiple times without restarting Docker:\n\n```bash\n# Step 1: Start the test infrastructure\n# From root\npnpm nx test:infra storage-js\n# This starts: PostgreSQL, Storage API, Kong Gateway, and imgproxy\n\n# Step 2: Run tests (can run multiple times)\npnpm nx test:suite storage-js\n\n# Step 3: When done, clean up the infrastructure\npnpm nx test:clean-post storage-js\n```\n\n##### Option 3: Development Mode\n\nFor actively developing and debugging tests:\n\n```bash\n# Start infrastructure once (from root)\npnpm nx test:infra storage-js\n\n# Run tests in watch mode\npnpm nx test:suite storage-js --watch\n\n# Clean up when done\npnpm nx test:clean-post storage-js\n```\n\n#### Test Infrastructure Details\n\nThe test infrastructure is managed via the Supabase CLI (`pnpm exec supabase start --workdir test`), which starts a local Supabase stack defined by the config in `test/`. This includes PostgreSQL, the Storage API, Kong Gateway, and supporting services.\n\n#### Common Issues and Solutions\n\n| Issue                             | Solution                                                                                          |\n| --------------------------------- | ------------------------------------------------------------------------------------------------- |\n| Port conflicts                    | Another service is using a required port. Run `pnpm nx test:clean-post storage-js` then try again |\n| \"request failed, reason:\" errors  | Infrastructure isn't running. Run `pnpm nx test:infra storage-js` first                           |\n| Tests fail with connection errors | Ensure Docker is running (Supabase CLI requires Docker)                                           |\n| Stack already running             | Run `pnpm nx test:clean-post storage-js` to stop it before restarting                             |\n\n#### Understanding Test Failures\n\n- **StorageUnknownError with \"request failed\"**: Infrastructure not running\n- **Snapshot failures**: Expected test data has changed — review and update snapshots if needed\n\n### Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n","packages/core/storage-js/migrations/README.md":"# Migration notes for `@supabase/storage-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/storage-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/storage-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/storage-js`:\n\n1. Read the migration files in `node_modules/@supabase/storage-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/storage-js` only.\n","packages/core/supabase-js/AGENTS.md":"# Agent instructions for `@supabase/supabase-js`\n\nMain isomorphic Supabase client for JavaScript. Aggregates `@supabase/auth-js`, `@supabase/postgrest-js`, `@supabase/realtime-js`, `@supabase/storage-js`, and `@supabase/functions-js` into one client.\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n","packages/core/supabase-js/README.md":"<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase JS SDK</h1>\n\n  <h3 align=\"center\">Isomorphic JavaScript SDK for Supabase - combining Auth, Database, Storage, Functions, and Realtime.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/getting-started\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript/start\">Reference Docs</a>\n    ·\n    <a href=\"https://supabase.github.io/supabase-js/supabase-js/v2/spec.json\">TypeDoc</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/supabase-js)](https://www.npmjs.com/package/@supabase/supabase-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/supabase-js)](https://pkg.pr.new/~/supabase/supabase-js)\n\n</div>\n\n## Usage\n\nFirst of all, you need to install the library:\n\n```sh\nnpm install @supabase/supabase-js\n```\n\nThen you're able to import the library and establish the connection with the database:\n\n```js\nimport { createClient } from '@supabase/supabase-js'\n\n// Create a single supabase client for interacting with your database\nconst supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')\n```\n\n### UMD\n\nYou can use plain `<script>`s to import supabase-js from CDNs, like:\n\n```html\n<script src=\"https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2\"></script>\n```\n\nor even:\n\n```html\n<script src=\"https://unpkg.com/@supabase/supabase-js@2\"></script>\n```\n\nThen you can use it from a global `supabase` variable:\n\n```html\n<script>\n  const { createClient } = supabase\n  const _supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')\n\n  console.log('Supabase Instance: ', _supabase)\n  // ...\n</script>\n```\n\n### ESM\n\nYou can use `<script type=\"module\">` to import supabase-js from CDNs, like:\n\n```html\n<script type=\"module\">\n  import { createClient } from 'https://cdn.jsdelivr.net/npm/@supabase/supabase-js/+esm'\n  const supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')\n\n  console.log('Supabase Instance: ', supabase)\n  // ...\n</script>\n```\n\n### Deno\n\nYou can use supabase-js in the Deno runtime via [JSR](https://jsr.io/@supabase/supabase-js):\n\n```js\nimport { createClient } from 'jsr:@supabase/supabase-js@2'\n```\n\n### Custom `fetch` implementation\n\n`supabase-js` uses the runtime's global `fetch` to make HTTP requests, but an alternative `fetch` implementation can be provided as an option. This is useful in environments where the global `fetch` is unavailable or where you want to customize request behavior:\n\n```js\nimport { createClient } from '@supabase/supabase-js'\n\n// Provide a custom `fetch` implementation as an option\nconst supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key', {\n  global: {\n    fetch: (...args) => fetch(...args),\n  },\n})\n```\n\n### Distributed Tracing with OpenTelemetry\n\nThe Supabase JS SDK can attach W3C/OpenTelemetry trace context headers (`traceparent`, `tracestate`, `baggage`) to outgoing requests, enabling end-to-end request tracing from your client application through Supabase services.\n\nTrace propagation is **opt-in** and disabled by default. When enabled, headers are only attached to requests targeting Supabase domains (`*.supabase.co`, `*.supabase.in`, `localhost`).\n\n#### Enable trace propagation\n\nOpting in takes two steps: install `@opentelemetry/api`, and load the tracing runtime by importing the `@supabase/supabase-js/tracing` subpath once at your application entry point. The main bundle contains no OpenTelemetry code — the subpath import is what wires it up.\n\n```js\nimport '@supabase/supabase-js/tracing'\nimport { createClient } from '@supabase/supabase-js'\nimport { trace } from '@opentelemetry/api'\n\nconst supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key', {\n  tracePropagation: true,\n})\n\nconst tracer = trace.getTracer('my-app')\nawait tracer.startActiveSpan('fetch-users', async (span) => {\n  // This request now includes the active trace context.\n  const { data, error } = await supabase.from('users').select('*')\n  span.end()\n})\n```\n\nThe subpath imports `@opentelemetry/api` directly, so module resolution fails loudly if it is not installed. If `tracePropagation` is enabled without the subpath import, the SDK logs a one-time warning and sends requests without trace headers; if no active context exists at request time, it silently no-ops.\n\nTrace propagation is not available via the CDN/UMD build (`https://cdn.jsdelivr.net/.../supabase.js`) — there is no way to load the tracing runtime there.\n\n#### Advanced configuration\n\n```typescript\ninterface TracePropagationOptions {\n  // Enable trace propagation (default: false).\n  enabled?: boolean\n\n  // Respect upstream sampling decisions (default: true).\n  // When true, non-sampled requests carry only `traceparent` (flag preserved,\n  // so nothing is recorded downstream) — Supabase logs still get a trace_id,\n  // while `tracestate` and `baggage` are withheld.\n  respectSamplingDecision?: boolean\n}\n```\n\n```js\n// Always propagate the full trace context, even for non-sampled traces.\nconst supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key', {\n  tracePropagation: { enabled: true, respectSamplingDecision: false },\n})\n```\n\n## Support Policy\n\nThis section outlines the scope of support for various runtime environments in Supabase JavaScript client.\n\n### Node.js\n\nWe only support Node.js versions that are in **Active LTS** or **Maintenance** status as defined by the [official Node.js release schedule](https://nodejs.org/en/about/previous-releases#release-schedule). This means we support versions that are currently receiving long-term support and critical bug fixes.\n\nWhen a Node.js version reaches end-of-life and is no longer in Active LTS or Maintenance status, Supabase will drop it in a **minor release**, and **this won't be considered a breaking change**.\n\n> ⚠️ **Node.js 18 Deprecation Notice**\n>\n> Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped in version `2.79.0`.\n>\n> If you must use Node.js 18, please use version `2.78.0`, which is the last version that supported Node.js 18.\n\n> ⚠️ **Node.js 20 Deprecation Notice**\n>\n> Node.js 20 reached end-of-life on April 30, 2026. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/45715), support for Node.js 20 was dropped in version `2.110.0`.\n>\n> If you must use Node.js 20, please use version `2.109.0`, which is the last version that supported Node.js 20.\n\n### Deno\n\nWe support Deno versions that are currently receiving active development and security updates. We follow the [official Deno release schedule](https://docs.deno.com/runtime/fundamentals/stability_and_releases/) and only support versions from the `stable` and `lts` release channels.\n\nWhen a Deno version reaches end-of-life and is no longer receiving security updates, Supabase will drop it in a **minor release**, and **this won't be considered a breaking change**.\n\n### Browsers\n\nAll modern browsers are supported. We support browsers that provide native `fetch` API. For Realtime features, browsers must also support native `WebSocket` API.\n\n### Bun\n\nWe support Bun runtime environments. Bun provides native fetch support and is compatible with Node.js APIs. Since Bun does not follow a structured release schedule like Node.js or Deno, we support current stable versions of Bun and may drop support for older versions in minor releases without considering it a breaking change.\n\n### React Native\n\nWe support React Native environments with fetch polyfills provided by the framework. Since React Native does not follow a structured release schedule, we support current stable versions and may drop support for older versions in minor releases without considering it a breaking change.\n\n### Cloudflare Workers\n\nWe support Cloudflare Workers runtime environments. Cloudflare Workers provides native fetch support. Since Cloudflare Workers does not follow a structured release schedule, we support current stable versions and may drop support for older versions in minor releases without considering it a breaking change.\n\n### Important Notes\n\n- **Experimental features**: Features marked as experimental may be removed or changed without notice\n\n## Known Build Warnings\n\n### `UNUSED_EXTERNAL_IMPORT` in Vite / Rollup / Nuxt\n\nWhen bundling your app, you may see warnings like:\n\n```\n\"PostgrestError\" is imported from external module \"@supabase/postgrest-js\" but never used in \"...supabase-js/dist/index.mjs\".\n\"FunctionRegion\", \"FunctionsError\", \"FunctionsFetchError\", \"FunctionsHttpError\" and \"FunctionsRelayError\" are imported from external module \"@supabase/functions-js\" but never used in \"...\".\n```\n\n**This is a false positive — your bundle is fine.** Here is why it happens:\n\n`@supabase/supabase-js` re-exports `PostgrestError`, `FunctionsError`, and related symbols so you can import them directly from `@supabase/supabase-js`. However, our build tool merges all imports from the same package into a single import statement in the built output:\n\n```js\n// dist/index.mjs (simplified)\nimport { PostgrestClient, PostgrestError } from '@supabase/postgrest-js'\n//       ^ used internally    ^ re-exported for you\n```\n\nYour bundler checks which names from that import are used _in the code body_, and flags `PostgrestError` as unused because it only appears in an `export` statement — not called or assigned. The export itself is the usage, but downstream bundlers don't track this correctly. This is a known Rollup/Vite limitation with re-exported external imports.\n\n**Nothing is broken.** Tree-shaking and bundle size are unaffected.\n\nTo suppress the warning:\n\n**Vite / Rollup (`vite.config.js` or `rollup.config.js`):**\n\n```js\nexport default {\n  build: {\n    rollupOptions: {\n      onwarn(warning, warn) {\n        if (warning.code === 'UNUSED_EXTERNAL_IMPORT' && warning.exporter?.includes('@supabase/'))\n          return\n        warn(warning)\n      },\n    },\n  },\n}\n```\n\n**Nuxt (`nuxt.config.ts`):**\n\n```ts\nexport default defineNuxtConfig({\n  vite: {\n    build: {\n      rollupOptions: {\n        onwarn(warning, warn) {\n          if (warning.code === 'UNUSED_EXTERNAL_IMPORT' && warning.exporter?.includes('@supabase/'))\n            return\n          warn(warning)\n        },\n      },\n    },\n  },\n})\n```\n\n## Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n\n### Building\n\n```bash\n# From the monorepo root\npnpm nx build supabase-js\n\n# Or with watch mode for development\npnpm nx build supabase-js --watch\n```\n\n### Testing\n\nThere's a complete guide on how to set up your environment for running locally the `supabase-js` integration tests. Please refer to [TESTING.md](./TESTING.md).\n\n## Badges\n\n[![Coverage Status](https://coveralls.io/repos/github/supabase/supabase-js/badge.svg?branch=master)](https://coveralls.io/github/supabase/supabase-js?branch=master)\n","packages/core/supabase-js/migrations/README.md":"# Migration notes for `@supabase/supabase-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/supabase-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/supabase-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/supabase-js`:\n\n1. Read the migration files in `node_modules/@supabase/supabase-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/supabase-js` only.\n","packages/core/supabase-js/test/integration/expo/README.md":"# supabase-js Expo integration test\n\nAn Expo SDK 53 app used as an integration target for `@supabase/supabase-js`. The test suite under `__tests__/` is exercised by:\n\n```bash\nnx test:expo supabase-js\n```\n\nfrom the repository root. CI runs it as part of the `integration-tests` workflow against pkg.pr.new preview builds of `@supabase/supabase-js`.\n\n## Local development\n\n```bash\ncd packages/core/supabase-js/test/integration/expo\nnpm install --legacy-peer-deps --ignore-scripts\nnpm test\n```\n\n`--legacy-peer-deps` is required because preview packages are published with version `0.0.0-automated`, which does not satisfy peer-dependency ranges like `^2.76.1`.\n\n## Why jest is pinned to 29 here\n\nThe rest of the monorepo runs jest 30 (declared at the workspace root). This subdir pins `jest@29.7.0` directly.\n\n`jest-expo` — at every published version including the current latest `jest-expo@56` — depends on jest 29.x internals: `@jest/globals@^29.2.1`, `@jest/create-cache-key-function@^29.2.1`, `babel-jest@^29.2.1`, `jest-environment-jsdom@^29.2.1`, `jest-snapshot@^29.2.1`. The Expo team has not migrated jest-expo to jest 30 yet.\n\nWithout an explicit pin here, `npm install --legacy-peer-deps` lets npm treat the root-hoisted `jest@30` as satisfying `jest-expo`'s optional `jest >=29` peer, so jest is not installed locally. At test time, Node's module resolution then walks up to the root `jest-runtime@30` while `jest-environment-jsdom@29` (a hard dep of jest-expo, installed locally) creates the moduleMocker via `jest-mock@29`. jest 30's runtime calls `_moduleMocker.clearMocksOnScope`, a method that only exists in jest-mock 30 — so CI fails with:\n\n```\nTypeError: this._moduleMocker.clearMocksOnScope is not a function\n```\n\nPinning `jest@29.7.0` in this subdir's `package.json` forces npm to install a complete jest 29 toolchain locally (since the root's jest 30 no longer satisfies the explicit `29.7.0` request). Node's lookup from this dir finds the local v29 internals before walking up. Root and every other package keep jest 30; only this expo test runs on jest 29.\n\n**Remove the pin** when jest-expo ships a jest-30-compatible release — at which point this subdir can fall back to whatever the workspace root provides.\n","packages/core/supabase-js/test/integration/next/README.md":"<a href=\"https://demo-nextjs-with-supabase.vercel.app/\">\n  <img alt=\"Next.js and Supabase Starter Kit - the fastest way to build apps with Next.js and Supabase\" src=\"https://demo-nextjs-with-supabase.vercel.app/opengraph-image.png\">\n  <h1 align=\"center\">Next.js and Supabase Starter Kit</h1>\n</a>\n\n<p align=\"center\">\n The fastest way to build apps with Next.js and Supabase\n</p>\n\n<p align=\"center\">\n  <a href=\"#features\"><strong>Features</strong></a> ·\n  <a href=\"#demo\"><strong>Demo</strong></a> ·\n  <a href=\"#deploy-to-vercel\"><strong>Deploy to Vercel</strong></a> ·\n  <a href=\"#clone-and-run-locally\"><strong>Clone and run locally</strong></a> ·\n  <a href=\"#feedback-and-issues\"><strong>Feedback and issues</strong></a>\n  <a href=\"#more-supabase-examples\"><strong>More Examples</strong></a>\n</p>\n<br/>\n\n## Features\n\n- Works across the entire [Next.js](https://nextjs.org) stack\n  - App Router\n  - Pages Router\n  - Middleware\n  - Client\n  - Server\n  - It just works!\n- supabase-ssr. A package to configure Supabase Auth to use cookies\n- Password-based authentication block installed via the [Supabase UI Library](https://supabase.com/ui/docs/nextjs/password-based-auth)\n- Styling with [Tailwind CSS](https://tailwindcss.com)\n- Components with [shadcn/ui](https://ui.shadcn.com/)\n- Optional deployment with [Supabase Vercel Integration and Vercel deploy](#deploy-your-own)\n  - Environment variables automatically assigned to Vercel project\n\n## Demo\n\nYou can view a fully working demo at [demo-nextjs-with-supabase.vercel.app](https://demo-nextjs-with-supabase.vercel.app/).\n\n## Deploy to Vercel\n\nVercel deployment will guide you through creating a Supabase account and project.\n\nAfter installation of the Supabase integration, all relevant environment variables will be assigned to the project so the deployment is fully functioning.\n\n[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fnext.js%2Ftree%2Fcanary%2Fexamples%2Fwith-supabase&project-name=nextjs-with-supabase&repository-name=nextjs-with-supabase&demo-title=nextjs-with-supabase&demo-description=This+starter+configures+Supabase+Auth+to+use+cookies%2C+making+the+user%27s+session+available+throughout+the+entire+Next.js+app+-+Client+Components%2C+Server+Components%2C+Route+Handlers%2C+Server+Actions+and+Middleware.&demo-url=https%3A%2F%2Fdemo-nextjs-with-supabase.vercel.app%2F&external-id=https%3A%2F%2Fgithub.com%2Fvercel%2Fnext.js%2Ftree%2Fcanary%2Fexamples%2Fwith-supabase&demo-image=https%3A%2F%2Fdemo-nextjs-with-supabase.vercel.app%2Fopengraph-image.png)\n\nThe above will also clone the Starter kit to your GitHub, you can clone that locally and develop locally.\n\nIf you wish to just develop locally and not deploy to Vercel, [follow the steps below](#clone-and-run-locally).\n\n## Clone and run locally\n\n1. You'll first need a Supabase project which can be made [via the Supabase dashboard](https://database.new)\n\n2. Create a Next.js app using the Supabase Starter template npx command\n\n   ```bash\n   npx create-next-app --example with-supabase with-supabase-app\n   ```\n\n   ```bash\n   yarn create next-app --example with-supabase with-supabase-app\n   ```\n\n   ```bash\n   pnpm create next-app --example with-supabase with-supabase-app\n   ```\n\n3. Use `cd` to change into the app's directory\n\n   ```bash\n   cd with-supabase-app\n   ```\n\n4. Rename `.env.example` to `.env.local` and update the following:\n\n   ```\n   NEXT_PUBLIC_SUPABASE_URL=[INSERT SUPABASE PROJECT URL]\n   NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=[INSERT SUPABASE PROJECT API PUBLISHABLE KEY]\n   ```\n\n   Both `NEXT_PUBLIC_SUPABASE_URL` and `NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY` can be found in [your Supabase project's API settings](https://supabase.com/dashboard/project/_?showConnect=true)\n\n5. You can now run the Next.js local development server:\n\n   ```bash\n   npm run dev\n   ```\n\n   The starter kit should now be running on [localhost:3000](http://localhost:3000/).\n\n6. This template comes with the default shadcn/ui style initialized. If you instead want other ui.shadcn styles, delete `components.json` and [re-install shadcn/ui](https://ui.shadcn.com/docs/installation/next)\n\n> Check out [the docs for Local Development](https://supabase.com/docs/guides/getting-started/local-development) to also run Supabase locally.\n\n## Feedback and issues\n\nPlease file feedback and issues over on the [Supabase GitHub org](https://github.com/supabase/supabase/issues/new/choose).\n\n## More Supabase examples\n\n- [Next.js Subscription Payments Starter](https://github.com/vercel/nextjs-subscription-payments)\n- [Cookie-based Auth and the Next.js 13 App Router (free course)](https://youtube.com/playlist?list=PL5S4mPUpp4OtMhpnp93EFSo42iQ40XjbF)\n- [Supabase Auth and the Next.js App Router](https://github.com/supabase/supabase/tree/master/examples/auth/nextjs)\n","packages/shared/tracing/README.md":"# @supabase/tracing\n\nW3C/OpenTelemetry trace context propagation utilities for the Supabase JS SDK.\n\nThis package provides utilities for extracting, parsing, validating, and propagating trace context headers according to the [W3C Trace Context](https://www.w3.org/TR/trace-context/) specification.\n\n## Features\n\n- Build a trace context extractor from a caller-supplied OpenTelemetry API object\n- Parse and validate W3C `traceparent` headers\n- Validate target URLs for trace propagation\n- Default Supabase domain allowlist\n- TypeScript type definitions\n- Zero dependencies — this package never imports `@opentelemetry/api`; callers pass the API object in\n\n## Installation\n\nThis package is typically used internally by `@supabase/supabase-js` and does not need to be installed directly.\n\n## Usage\n\n### Create a Trace Context Extractor\n\n```typescript\nimport { createTraceContextExtractor } from '@supabase/tracing'\nimport { propagation, context } from '@opentelemetry/api'\n\n// The caller owns the OpenTelemetry dependency and passes it in.\nconst extract = createTraceContextExtractor({ propagation, context })\n\nconst traceContext = extract()\n// { traceparent, tracestate, baggage } or null when there is no active trace\n```\n\n### Parse Traceparent Header\n\n```typescript\nimport { parseTraceParent } from '@supabase/tracing'\n\nconst parsed = parseTraceParent('00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01')\n\nconsole.log(parsed)\n// {\n//   version: '00',\n//   traceId: '0af7651916cd43dd8448eb211c80319c',\n//   parentId: 'b7ad6b7169203331',\n//   traceFlags: '01',\n//   isSampled: true\n// }\n```\n\n### Validate Target URLs\n\n```typescript\nimport { shouldPropagateToTarget } from '@supabase/tracing'\n\nconst targets = [\n  'myproject.supabase.co',\n  /.*\\.supabase\\.co$/,\n  (url) => url.hostname === 'localhost',\n]\n\nconst shouldPropagate = shouldPropagateToTarget(\n  'https://myproject.supabase.co/rest/v1/table',\n  targets\n)\n// true\n```\n\n### Get Default Targets\n\n```typescript\nimport { getDefaultPropagationTargets } from '@supabase/tracing'\n\nconst targets = getDefaultPropagationTargets('https://myproject.supabase.co')\n// Returns array of default Supabase domains\n```\n\n## Type Definitions\n\n```typescript\ninterface TraceContext {\n  traceparent?: string\n  tracestate?: string\n  baggage?: string\n}\n\ninterface ParsedTraceParent {\n  version: string\n  traceId: string\n  parentId: string\n  traceFlags: string\n  isSampled: boolean\n}\n\ntype TracePropagationTarget = string | RegExp | ((url: URL) => boolean)\n```\n\n## License\n\nMIT\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Agent instructions\n\nEntry point for AI/LLM agents working in or with this repository. Pointers below; nothing canonical lives in this file.\n\n## Repository overview\n\n- [`README.md`](./README.md) — what this repo is, package list, quick start\n- [`CONTRIBUTING.md`](./CONTRIBUTING.md) — contribution guidelines, commit format, PR process\n- [`.claude/CLAUDE.md`](./.claude/CLAUDE.md) — development conventions, Nx commands, testing matrix, library-specific notes (read by Claude Code; the canonical development-conventions doc)\n- [`.cursor/.cursorrules`](./.cursor/.cursorrules) — same conventions for Cursor (read by Cursor IDE)\n\n## Agent skills\n\nReusable agent skills for working in this Nx workspace (Nx-related: `nx-workspace`, `nx-generate`, `nx-import`, `nx-plugins`, `nx-run-tasks`, `link-workspace-packages`) live at:\n\n- [`.agents/skills/`](./.agents/skills/) — vendor-neutral location (Agent Skills spec)\n- [`.claude/skills/`](./.claude/skills/) — mirrored copy read by Claude Code by literal path\n\nBoth directories currently hold the same content. Treat `.agents/skills/` as the source of truth; the `.claude/skills/` copy is kept in sync until Claude Code can discover skills from `.agents/skills/` directly.\n\n## Per-package usage\n\nEach package has its own README with usage examples and API notes:\n\n- [`packages/core/supabase-js/README.md`](./packages/core/supabase-js/README.md) — `@supabase/supabase-js` (main isomorphic client)\n- [`packages/core/auth-js/README.md`](./packages/core/auth-js/README.md) — `@supabase/auth-js`\n- [`packages/core/postgrest-js/README.md`](./packages/core/postgrest-js/README.md) — `@supabase/postgrest-js`\n- [`packages/core/realtime-js/README.md`](./packages/core/realtime-js/README.md) — `@supabase/realtime-js`\n- [`packages/core/storage-js/README.md`](./packages/core/storage-js/README.md) — `@supabase/storage-js`\n- [`packages/core/functions-js/README.md`](./packages/core/functions-js/README.md) — `@supabase/functions-js`\n\n## Helping users of a published `@supabase/*` package\n\nThe published npm tarball for each package ships everything an agent needs to give a correct, version-pinned answer. After `npm install @supabase/<package>`, an agent helping with that package should look inside `node_modules/@supabase/<package>/`:\n\n- `AGENTS.md` — per-package agent entry point (read this first; it points at the resources below).\n- `README.md` — usage and quick-start.\n- `src/` — full API source with TSDoc. Every public method and type has JSDoc, most have `@example` blocks. Read source here for the canonical, version-pinned answer instead of guessing from training data.\n- `migrations/` — per-theme migration notes for changes that need caller action.\n\nSource files ship via npm because every package's `files` array in `package.json` includes `\"src\"`. Migration notes ship via `\"migrations\"`. Per-package `AGENTS.md` ships via `\"AGENTS.md\"`. All three are version-pinned by virtue of being inside the installed package.\n\nWe deliberately do NOT ship per-package skills or duplicate docs-site content. The TSDoc-in-source IS the canonical API documentation for the SDK packages.\n\nFor higher-level Supabase guidance (the documentation site, MCP tools, schema management workflows, project setup), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills):\n\n```bash\nnpx skills add supabase/agent-skills\n```\n\nOr use the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins) to install the agent skills together with the Supabase MCP server in one step. See also: [Agent Skills documentation](https://agentskills.io/home).\n\n## Migration notes\n\nMigration notes live close to the code they describe, so they ship via npm alongside the package.\n\n- **Per-package migrations**: `packages/core/<package>/migrations/<theme>.md` — one file per migration theme (e.g. `<new-feature-adoption>.md`). Each file describes what changed, who is affected, and what callers need to do.\n- **Cross-cutting migrations** (affecting the whole repo or all packages): [`docs/MIGRATION.md`](./docs/MIGRATION.md) — one H2 section per theme (e.g. Node.js version drops). Low-frequency by design; split into a directory only if the file grows past a handful of themes.\n\n## Other documentation\n\n- [`docs/TESTING.md`](./docs/TESTING.md) — testing guide with Docker requirements per package\n- [`docs/RELEASE.md`](./docs/RELEASE.md) — release workflows and versioning strategy\n- [Security Policy](https://github.com/supabase/supabase-js/security/policy) — security policies and responsible disclosure\n- [`docs/JSR_PUBLISHING.md`](./docs/JSR_PUBLISHING.md) — JSR registry publishing\n","isInternal":false,"tokens":1154,"sizeBytes":4705},{"name":"CLAUDE.md","path":".claude/CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/.claude/CLAUDE.md","title":".claude - Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# Claude AI Instructions for Supabase JS Libraries Monorepo\n\nYou are assisting with development in a unified Nx monorepo that consolidates all Supabase JavaScript SDKs, built with Nx for optimal developer experience and maintainability. This strategic migration from 6 separate repositories addresses critical maintenance overhead, dependency duplication, and release coordination challenges while maintaining **zero breaking changes** for consumers.\n\n> **📚 Essential Documentation**: Always refer to these guides for detailed information:\n>\n> - **[CONTRIBUTING.md](../CONTRIBUTING.md)** - Development guidelines, commit format, PR process\n> - **[TESTING.md](../docs/TESTING.md)** - Complete testing guide with Docker requirements\n> - **[RELEASE.md](../docs/RELEASE.md)** - Release workflows and versioning strategy\n> - **[MIGRATION.md](../docs/MIGRATION.md)** - Cross-cutting migration notes (one H2 per theme). Per-package migrations live at `packages/core/<package>/migrations/`.\n> - **[Security Policy](https://github.com/supabase/supabase-js/security/policy)** - Security policies and responsible disclosure\n\n## Repository Architecture\n\n### Monorepo Structure\n\n```text\nsupabase-js/\n├── packages/core/\n│   ├── supabase-js/      # @supabase/supabase-js - Main isomorphic client for Supabase\n│   ├── auth-js/          # @supabase/auth-js - Authentication client\n│   ├── postgrest-js/     # @supabase/postgrest-js - PostgREST client for database operations\n│   ├── realtime-js/      # @supabase/realtime-js - Real-time subscriptions client\n│   ├── storage-js/       # @supabase/storage-js - File storage client\n│   └── functions-js/     # @supabase/functions-js - Edge Functions client\n├── CONTRIBUTING.md       # Contribution guidelines\n├── docs/                 # Comprehensive documentation guides\n│   ├── TESTING.md        # Testing guide\n│   ├── RELEASE.md        # Release workflows\n│   ├── MIGRATION.md      # Migration guide\n│   └── JSR_PUBLISHING.md # JSR publishing guide\n├── scripts/              # Automation scripts\n│   ├── release-canary.ts # Canary release automation\n│   ├── release-stable.ts # Stable release automation\n│   └── update-version-files.ts # Version management\n├── nx.json               # Nx workspace configuration\n├── tsconfig.base.json    # Base TypeScript configuration\n├── package.json          # Root package with workspace scripts\n└── commitlint.config.js  # Commit message validation\n```\n\n### Migration Benefits\n\n- **Dependency Consolidation**: 22 previously duplicated dependencies now centrally managed\n- **Atomic Changes**: Cross-library fixes in single PRs\n- **Immediate Integration Testing**: No manual release coordination needed\n- **Unified Versioning**: Fixed version mode with automated releases using `nx release`\n- **Intelligent Building**: Nx only rebuilds/tests what actually changed\n\n## Core Development Principles\n\n### 1. Zero Breaking Changes\n\nEvery change must maintain full backward compatibility. The migration itself introduces no breaking changes - all packages maintain their original npm names and APIs.\n\n### 2. Hybrid Release Model with Fixed Versioning\n\nUses automated canary releases with batched stable releases:\n\n- **Canary**: Every commit to master → prerelease (e.g., `2.80.1-canary.0`) with `canary` dist-tag\n- **Stable**: Manual promotion of validated canary to `latest` dist-tag\n- **Fixed Versioning**: All packages share identical version numbers (e.g., all at 2.80.0)\n- **Version Line**: Continuing with v2.x.x to maintain ecosystem stability\n\n**Three Release Workflows:**\n\n1. **Canary** (`.github/workflows/main-ci-release.yml`) - Automated on every master commit\n2. **Stable** (`.github/workflows/release-stable.yml`) - Manual by repository owners\n3. **Preview** (`.github/workflows/preview-release.yml`) - PR-based testing via pkg.pr.new\n\n> **📖 See [RELEASE.md](../docs/RELEASE.md) for complete release documentation**\n\n### 3. Workspace Dependencies\n\nInternal dependencies use the `*` protocol:\n\n```json\n// packages/core/supabase-js/package.json\n{\n  \"dependencies\": {\n    \"@supabase/auth-js\": \"*\",\n    \"@supabase/realtime-js\": \"*\",\n    \"@supabase/functions-js\": \"*\",\n    \"@supabase/storage-js\": \"*\",\n    \"@supabase/postgrest-js\": \"*\"\n  }\n}\n```\n\nNx automatically replaces `*` with the actual version during release.\n\n### 4. Affected-First Development\n\nAlways use `nx affected` commands to build/test only what changed, leveraging Nx's dependency graph intelligence.\n\n### 5. Conventional Commits\n\nUse conventional commit format for automated versioning:\n\n- `fix(auth-js): resolve token refresh race condition` → Patch release\n- `feat(realtime-js): add presence support` → Minor release\n- `feat(auth)!: remove deprecated method` → Major release\n- `chore(deps): update TypeScript to 5.8` → No version bump\n\n**Always use the interactive commit tool:**\n\n```bash\npnpm commit\n```\n\n> **📖 See [CONTRIBUTING.md](../CONTRIBUTING.md#commit-guidelines) for complete commit guidelines**\n\n## Essential Commands Reference\n\n### Building\n\n```bash\nnx run-many --target=build --all        # Build all packages\nnx build auth-js                         # Build specific package\nnx affected --target=build               # Build only affected\nnx build auth-js --watch                 # Development mode\n```\n\n### Testing\n\n```bash\n# Test specific packages (complete test suites with Docker setup/cleanup)\nnx test:auth auth-js                    # Complete auth-js test suite (handles Docker)\nnx test:storage storage-js              # Complete storage-js test suite (handles Docker)\nnx test:ci:postgrest postgrest-js      # Complete postgrest-js test suite (handles Docker)\nnx test functions-js                    # Standard test (uses testcontainers)\nnx test realtime-js                     # Standard test (no Docker needed)\nnx test supabase-js                     # Standard test (unit tests only)\n\n# Coverage reports\nnx test supabase-js --coverage\nnx test:coverage realtime-js\nnx test:ci functions-js                 # Includes coverage\n```\n\n**Docker Requirements:**\n\n| Package      | Docker Required | Infrastructure                  | Complete Test Command               | Individual Commands                                                                       |\n| ------------ | --------------- | ------------------------------- | ----------------------------------- | ----------------------------------------------------------------------------------------- |\n| auth-js      | ✅ Yes          | Auth Server + Postgres          | `nx test:auth auth-js`              | `nx test:suite auth-js`, `nx test:infra auth-js`, `nx test:clean-post auth-js`            |\n| storage-js   | ✅ Yes          | Storage API + PostgreSQL + Kong | `nx test:storage storage-js`        | `nx test:suite storage-js`, `nx test:infra storage-js`, `nx test:clean-post storage-js`   |\n| postgrest-js | ✅ Yes          | PostgREST + PostgreSQL          | `nx test:ci:postgrest postgrest-js` | `nx test:run postgrest-js`, `nx test:types postgrest-js`                                  |\n| functions-js | ✅ Yes          | Deno relay (testcontainers)     | `nx test functions-js`              | `nx test:ci functions-js` (with coverage)                                                 |\n| realtime-js  | ❌ No           | Mock WebSockets                 | `nx test realtime-js`               | `nx test:coverage realtime-js`, `nx test:watch realtime-js`                               |\n| supabase-js  | ❌ No           | Unit tests only                 | `nx test supabase-js`               | `nx test:all`, `nx test:unit`, `nx test:integration`, `nx test:coverage`, `nx test:watch` |\n\n**supabase-js Additional Test Commands:**\n\n```bash\nnx test:all supabase-js                  # Unit + integration + browser tests\nnx test:unit supabase-js                # Jest unit tests only\nnx test:integration supabase-js         # Node.js integration tests\nnx test:integration:browser supabase-js # Browser tests (requires Deno)\nnx test:edge-functions supabase-js      # Edge Functions tests\nnx test:deno supabase-js                # Deno runtime tests\nnx test:bun supabase-js                 # Bun runtime tests\nnx test:expo supabase-js                # React Native/Expo tests\nnx test:next supabase-js                # Next.js SSR tests\nnx test:node:playwright supabase-js     # WebSocket browser tests\nnx test:types supabase-js               # TypeScript type checking\nnx test:coverage supabase-js            # Coverage report\nnx test:watch supabase-js               # Watch mode\n```\n\n> **📖 See [TESTING.md](../docs/TESTING.md) for complete testing guide and troubleshooting**\n\n### Code Quality\n\n```bash\nnx run-many --target=lint --all          # Lint all packages\nnx lint storage-js                       # Lint specific package\nnx format                                 # Auto-format all code\nnx format:check                           # Check formatting\n```\n\n### Analysis\n\n```bash\nnx graph                                  # Interactive dependency graph\nnx show projects                          # List all projects\nnx affected --graph                       # Visualize affected projects\n```\n\n## Development Workflows\n\n### Cross-Library Bug Fix Example\n\n**Scenario**: Bug in supabase-js caused by realtime-js\n\n**Monorepo Solution**:\n\n1. Fix root cause in `packages/core/realtime-js/src/`\n2. Add unit test in `packages/core/realtime-js/test/`\n3. Add integration test in `packages/core/supabase-js/test/`\n4. Run complete test suites for both packages to verify impacts\n5. Commit: `fix(realtime-js): resolve reconnection logic affecting supabase-js`\n6. Single PR, single review, single release - all packages version together\n\n### Adding New Features\n\n1. Implement in appropriate library under `packages/core/[library]/src/`\n2. Write comprehensive unit tests in `packages/core/[library]/test/`\n3. If feature affects supabase-js, add integration tests there\n4. Update TypeScript types if needed\n5. Run complete test suite for the package before committing\n6. Use conventional commit: `feat(storage-js): add resumable uploads`\n\n### Quick Fix Workflow\n\n```bash\n# Even for single-library fixes:\ngit add .\ngit commit -m \"fix(auth-js): correct session expiry calculation\"\n# → Automatic canary: 2.80.1-canary.0 published to 'canary' dist-tag\n# Run complete test suite for the package:\nnx test:auth auth-js\n# After validation, manual promotion:\nnx release --tag=latest --yes  # Promotes to stable with same version for ALL packages\n```\n\n## TypeScript Configuration\n\n### Workspace Settings\n\n- **Target**: ES2022\n- **Module**: NodeNext\n- **Strict**: true\n- **Isolated Modules**: true (faster compilation)\n- **Composite**: true (incremental builds)\n\n### Per-Library Configs\n\nEach library has its own `tsconfig.json` extending the base configuration, allowing for library-specific adjustments while maintaining consistency.\n\n### TypeScript Project References Setup\n\nThis repository uses TypeScript project references for incremental builds and better type checking across packages.\n\n**What's Configured:**\n\n1. **tsconfig.base.json** - Base configuration inherited by all projects:\n   - `composite: true` - Enables project references\n   - `declaration: true` - Required by composite\n   - `moduleResolution: \"bundler\"` - Works with workspaces\n   - `isolatedModules: true` - Inherited but overridden in core packages\n   - `noImplicitOverride: true` - Inherited but overridden in core packages\n   - **No `customConditions`** - Removed to avoid conflicts with CommonJS packages\n\n2. **Root tsconfig.json** - References all projects in the monorepo:\n\n   ```json\n   {\n     \"extends\": \"./tsconfig.base.json\",\n     \"files\": [],\n     \"references\": [\n       { \"path\": \"./packages/core/auth-js\" },\n       { \"path\": \"./packages/core/realtime-js\" }\n       // ... all other packages\n     ]\n   }\n   ```\n\n3. **Core packages** (auth-js, realtime-js, postgrest-js, functions-js, storage-js):\n   - Keep `module: \"CommonJS\"` for backward compatibility\n   - Override `moduleResolution: \"Node\"` (required for CommonJS)\n   - Override `isolatedModules: false` (existing code doesn't use `export type`)\n   - Override `noImplicitOverride: false` (existing code doesn't use `override` keyword)\n   - Add `references` array pointing to dependencies (managed by `nx sync`)\n\n4. **Utils packages** (utils-fetch):\n   - Inherit `moduleResolution: \"bundler\"` from base\n   - Can optionally add `customConditions: [\"@supabase-js/source\"]` for source preference\n\n**Key Principles:**\n\n- ✅ **No Breaking Changes**: Build output is identical - only type-checking is affected\n- ✅ **Incremental Builds**: TypeScript only recompiles changed projects\n- ✅ **Better Performance**: Reduced memory usage during builds\n- ✅ **Automatic References**: Nx sync automatically maintains project references\n- ⚠️ **No `customConditions` in base**: Would conflict with `moduleResolution: \"Node\"`\n\n**When Adding New Packages:**\n\n1. Ensure `composite: true` and `declaration: true` are set\n2. Add `references` array pointing to dependencies\n3. If using CommonJS, override `moduleResolution: \"Node\"` and disable strict options\n4. Run `nx sync` to update root tsconfig.json automatically\n\n**Important Notes:**\n\n- TypeScript project references work WITHOUT `customConditions` - it's optional\n- `customConditions` only optimizes source file resolution during development\n- Core packages use `moduleResolution: \"Node\"` which is incompatible with `customConditions`\n- The `isolatedModules: false` override avoids requiring `export type` for type re-exports\n- All build outputs remain identical to pre-project-references setup\n\n## Testing Infrastructure\n\n### Unit Tests (Jest)\n\n- Location: `packages/core/[library]/test/`\n- Pattern: Mirror source structure\n- Principle: Test public APIs thoroughly\n- Mocking: Mock external dependencies\n\n### Integration Tests (Docker-based)\n\n**Complete Test Suites (Recommended)**:\n\n```bash\n# Auth-js: Complete test suite (handles Docker setup/cleanup automatically)\nnx test:auth auth-js\n\n# Storage-js: Complete test suite (handles Docker setup/cleanup automatically)\nnx test:storage storage-js\n\n# Postgrest-js: Complete test suite (handles Docker setup/cleanup automatically)\nnx test:ci:postgrest postgrest-js\n```\n\n**Manual Infrastructure Management** (for development):\n\n```bash\n# Auth-js\nnx test:infra auth-js        # Start Supabase CLI infrastructure\nnx test:suite auth-js        # Run tests (can run multiple times)\nnx test:clean-post auth-js   # Cleanup\n\n# Storage-js\nnx test:infra storage-js        # Start Supabase CLI infrastructure\nnx test:suite storage-js        # Run tests (can run multiple times)\nnx test:clean-post storage-js   # Cleanup\n\n# Postgrest-js\nnx test:infra postgrest-js        # Start Supabase CLI infrastructure\nnx test:run postgrest-js          # Run tests\nnx test:clean-post postgrest-js   # Cleanup\n```\n\n### Cross-Platform Tests (supabase-js)\n\nTests run against multiple environments:\n\n- Node.js (native)\n- Next.js (SSR/React)\n- Expo (React Native)\n- Bun (alternative runtime)\n- Deno (secure runtime)\n- Browser (via Puppeteer)\n\n## Library-Specific Considerations\n\n### supabase-js\n\n- Aggregates all other libraries\n- Primary integration testing location\n- Most complex cross-platform test suite (Node.js, Next.js, Expo, Bun, Deno, Browser)\n- Users typically interact through this package\n- Default branch: **master**\n\n### auth-js\n\n- Requires Docker for integration tests (GoTrue + PostgreSQL)\n- Complex session management logic\n- Security-critical - extra review care needed\n- See [auth-js README](../packages/core/auth-js/README.md) for details\n\n### realtime-js\n\n- WebSocket-based, timing-sensitive\n- Mock time in tests when possible\n- No Docker required (uses mock WebSockets)\n- See [realtime-js README](../packages/core/realtime-js/README.md) for details\n\n### storage-js\n\n- Requires Docker for integration tests (Storage API + PostgreSQL + Kong)\n- File handling varies by platform\n- See [storage-js README](../packages/core/storage-js/README.md) for details\n\n### postgrest-js\n\n- Pure HTTP client, easiest to test\n- Requires Docker for integration tests (PostgREST + PostgreSQL)\n- See [postgrest-js README](../packages/core/postgrest-js/README.md) for details\n\n### functions-js\n\n- Simplest library, minimal dependencies\n- Uses testcontainers for Deno relay\n- See [functions-js README](../packages/core/functions-js/README.md) for details\n\n## Code Style Guidelines\n\n### Formatting\n\n- Prettier handles all formatting (configured in `.prettierrc`)\n- Run `nx format` before committing\n- No formatting debates - Prettier decides\n\n### Patterns\n\n- Follow existing patterns in each library\n- Extract shared code to packages/shared/ when identified\n- Maintain consistency across monorepo\n\n### Documentation\n\n- JSDoc for all public APIs\n- README per package with examples\n- Update docs when changing APIs\n\n## Important Context\n\n### Branch Information\n\n**Current Repository:**\n\n- **Default branch**: `master` (v2 active development; all PRs land here by default; auto-publishes `@canary` on every push, stable releases are manual `workflow_dispatch` from this branch)\n- **Long-lived feature branch**: `v3` (v3-only breaking changes; `@next` prereleases are **manual `workflow_dispatch` only** — never auto-published; kept in sync with `master` by periodic `git merge master`)\n- **Repository URL**: `github.com/supabase/supabase-js`\n\n**Original Repository Branches** (for historical reference):\n\n- **master**: auth-js, postgrest-js, realtime-js, supabase-js\n- **main**: functions-js, storage-js\n\nWhen referencing original repository history or comparing changes, be aware of these branch name differences.\n\n### Package Publishing\n\n- All packages publish to npm under `@supabase` scope\n- Versions synchronized via fixed release mode (all packages always have same version)\n- Changelogs generated per package from conventional commits\n- \"No user-facing changes\" message for unchanged packages\n- Three dist-tags: `latest` (stable), `canary` (pre-release), `next` (legacy)\n\n### Docker Requirements\n\nIntegration tests for auth-js, functions-js, postgrest-js, and storage-js require Docker running locally:\n\n- **macOS/Windows**: Ensure Docker Desktop is installed and running\n- **Linux**: Ensure Docker daemon is running\n- **CI**: Docker is automatically available in GitHub Actions\n\nCheck [TESTING.md](../docs/TESTING.md) for port requirements and troubleshooting.\n\n### Commit Message Validation\n\nAll commits are validated using commitlint with strict rules:\n\n- **Type**: Required (feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert)\n- **Scope**: Required (auth, functions, postgrest, realtime, storage, supabase, repo, deps, ci, release, docs, scripts, misc)\n- **Subject**: Required, imperative mood, no period at end, max 100 characters\n- **Interactive Tool**: Use `pnpm commit` to ensure compliance\n\nSee [CONTRIBUTING.md](../CONTRIBUTING.md#commit-guidelines) for complete details.\n\n## Common Pitfalls & Solutions\n\n### Pitfall 1: Hardcoding Internal Versions\n\n❌ Wrong:\n\n```json\n\"@supabase/auth-js\": \"3.5.0\"\n```\n\n✅ Correct:\n\n```json\n\"@supabase/auth-js\": \"*\"\n```\n\n### Pitfall 2: Running npm Directly\n\n❌ Wrong:\n\n```bash\ncd packages/core/auth-js && npm test\n```\n\n✅ Correct:\n\n```bash\nnx test:auth auth-js\n```\n\n### Pitfall 3: Testing Everything\n\n❌ Wrong:\n\n```bash\nnx run-many --target=test --all  # Won't work - no standard test target for all packages\n```\n\n✅ Correct:\n\n```bash\n# Run complete test suite for the specific package\nnx test:auth auth-js\nnx test:storage storage-js\nnx test:ci:postgrest postgrest-js\nnx test functions-js\nnx test realtime-js\nnx test supabase-js\n```\n\n### Pitfall 4: Breaking Changes\n\n❌ Wrong: Changing public API signatures without proper process\n\n```typescript\n// Don't just change existing method signatures\n- signIn(email: string): Promise<void>\n+ signIn(credentials: Credentials): Promise<void>\n```\n\n✅ Correct: Add new methods, deprecate old ones gradually, use proper commit format\n\n```typescript\n// Add new method\nsignIn(credentials: Credentials): Promise<void>\n\n// Deprecate old method with backward compatibility\n/** @deprecated Use signIn(credentials) instead */\nsignInWithEmail(email: string): Promise<void> {\n  return this.signIn({ email })\n}\n```\n\nUse breaking change commit format when necessary:\n\n```bash\nfeat(auth)!: remove deprecated signInWithEmail method\n\nBREAKING CHANGE: The deprecated signInWithEmail method has been removed.\nUse signIn({ email }) instead.\n```\n\n### Pitfall 5: Running Commands Incorrectly\n\n❌ Wrong: Running npm commands directly in library directories\n\n```bash\ncd packages/core/auth-js\nnpm test\nnpm run build\n```\n\n✅ Correct: Use Nx commands from repository root\n\n```bash\nnx test:auth auth-js\nnx build auth-js --watch\n```\n\n### Pitfall 6: Not Using the Commit Tool\n\n❌ Wrong: Using git commit directly\n\n```bash\ngit commit -m \"fix auth bug\"  # Missing scope, will fail validation\n```\n\n✅ Correct: Use the interactive commit tool\n\n```bash\npnpm commit  # Guides you through proper format\n```\n\n### Pitfall 7: Not Checking Documentation\n\n❌ Wrong: Assuming you know how to run tests without checking\n\n```bash\nnx test storage-js  # Wrong - should use nx test:storage storage-js\n```\n\n✅ Correct: Check library README and TESTING.md first\n\n```bash\n# Read docs first\ncat packages/core/storage-js/README.md\ncat docs/TESTING.md\n# Then run tests with proper setup\n```\n\n## Pull Request Best Practices\n\n> **📖 See [CONTRIBUTING.md](../CONTRIBUTING.md#pull-request-process) for complete PR guidelines**\n\n### Before Creating PR\n\n1. **Ensure branch is up to date** with the PR's target branch (typically `master`; `v3` only for v3-only breaking changes):\n\n   ```bash\n   git checkout <target-branch>     # master or v3\n   git pull upstream <target-branch>\n   git checkout your-feature-branch\n   git rebase <target-branch>\n   ```\n\n2. **Run all necessary checks:**\n\n   ```bash\n   nx format                    # Format code\n   # Run complete test suite for affected packages individually\n   nx test:auth auth-js         # If auth-js changed\n   nx test:storage storage-js   # If storage-js changed\n   # ... etc for other packages\n   nx affected --target=build   # Build affected packages\n   ```\n\n3. **Use interactive commit tool:**\n\n   ```bash\n   pnpm commit\n   ```\n\n### PR Requirements\n\n- ✅ At least 1 approving review from a code owner\n- ✅ All status checks passing (CI/CD pipeline)\n- ✅ No merge conflicts with the base branch\n- ✅ Squash merge only (enforced by repository settings)\n\n### PR Description Template\n\n```markdown\n## Description\n\nBrief description of what this PR does\n\n## Type of Change\n\n- [ ] Bug fix (fix)\n- [ ] New feature (feat)\n- [ ] Breaking change (feat! or fix!)\n- [ ] Documentation update (docs)\n- [ ] Other (chore, refactor, etc.)\n\n## Testing\n\n- [ ] Unit tests added/updated\n- [ ] Integration tests added/updated (if applicable)\n- [ ] All tests passing locally\n\n## Checklist\n\n- [ ] Code formatted (`nx format`)\n- [ ] Tests passing (run complete test suites for affected packages)\n- [ ] Builds passing (`nx affected --target=build`)\n- [ ] Used conventional commits\n- [ ] Documentation updated (if needed)\n```\n\n### Requesting Preview Releases\n\nIf you need to test your changes before merging:\n\n1. Create your PR\n2. Comment: \"Can a maintainer add the preview label for testing?\"\n3. Wait for maintainer to add `trigger: preview` label\n4. Follow instructions in automated comment to install preview packages\n\n## Helpful Commands Reference\n\n### Analysis & Debugging\n\n```bash\n# Visualize dependency graph\nnx graph\n\n# Show what's affected by changes\nnx affected --graph\n\n# List all projects\nnx show projects\n\n# See project details\nnx show project auth-js --web\n\n# Clear Nx cache\nnx reset\n```\n\n### Development Workflow\n\n```bash\n# 1. Create feature branch\ngit checkout -b feat/your-feature\n\n# 2. Make changes in packages/core/[library]/\n\n# 3. Test continuously\nnx test [library] --watch\n\n# 4. Format before committing\nnx format\n\n# 5. Commit with tool\npnpm commit\n\n# 6. Before pushing\n# Run complete test suite for the package you changed\nnx test:auth auth-js         # If auth-js changed\nnx test:storage storage-js   # If storage-js changed\n# ... etc\nnx affected --target=build\nnx format:check\n\n# 7. Push and create PR\ngit push origin feat/your-feature\n```\n\n### Troubleshooting\n\n```bash\n# Clear cache and rebuild\nnx reset\nnx run-many --target=build --all\n\n# Clean install\nrm -rf node_modules\npnpm install\n\n# Check for errors\nnx run-many --target=lint --all\n\n# Run specific test file (for packages with standard test target)\nnx test realtime-js --testFile=RealtimeClient.test.ts\nnx test supabase-js --testFile=client.test.ts\n```\n\n## Additional Resources\n\n- **[README.md](../README.md)** - Repository overview and quick start\n- **[CONTRIBUTING.md](../CONTRIBUTING.md)** - Complete contribution guide\n- **[TESTING.md](../docs/TESTING.md)** - Comprehensive testing documentation\n- **[RELEASE.md](../docs/RELEASE.md)** - Release workflows and automation\n- **[MIGRATION.md](../docs/MIGRATION.md)** - Cross-cutting migration notes; per-package migrations live at `packages/core/<package>/migrations/`\n- **[Security Policy](https://github.com/supabase/supabase-js/security/policy)** - Security policy and reporting\n- **[Supabase Documentation](https://supabase.com/docs)** - Official Supabase docs\n- **[Nx Documentation](https://nx.dev)** - Nx monorepo documentation\n- **[Conventional Commits](https://www.conventionalcommits.org/)** - Commit format specification\n\n### Pitfall 5: Incomplete Cross-Library Testing\n\n❌ Wrong: Only testing in source library\n✅ Correct: Test in source library AND integration tests in supabase-js\n\n## Release Process\n\n### Hybrid Release Flow\n\n**Canary Releases (Automated)**:\n\n```bash\n# Triggered automatically on every commit to master\ngit commit -m \"fix(auth): resolve token issue\"\n# → Automatic CI: nx release --tag=canary --yes\n# → Published: 2.80.1-canary.0 to 'canary' dist-tag\n```\n\n**Stable Releases (Manual)**:\n\n```bash\n# 1. Validate canary version\n# Run complete test suites for packages individually\n\n# 2. Preview stable promotion\nnx release --dry-run\n\n# 3. Promote canary to stable\nnx release --tag=latest --yes\n\n# Alternative: Promote specific canary\nnx release --specifier=2.80.1 --tag=latest --yes\n```\n\n### What Happens During Canary Release\n\n1. CI detects conventional commits\n2. Determines version bump (patch/minor/major)\n3. Generates prerelease version (e.g., 2.80.1-canary.0)\n4. Updates all package.json files\n5. Replaces `*` with actual versions\n6. Publishes all packages to npm with `canary` dist-tag\n7. Triggers dogfooding workflows (when configured)\n\n### What Happens During Stable Release\n\n1. Promotes validated canary to `latest` dist-tag\n2. Generates curated per-package changelogs\n3. Creates GitHub release with notes\n4. All packages get identical stable version\n\n### Nx Release Configuration\n\nThe workspace is configured for hybrid releases in `nx.json`:\n\n```json\n{\n  \"release\": {\n    \"projectsRelationship\": \"fixed\",\n    \"version\": {\n      \"conventionalCommits\": true\n    },\n    \"changelog\": {\n      \"projectChangelogs\": true,\n      \"workspaceChangelog\": true\n    }\n  }\n}\n```\n\n### Release Command Reference\n\n```bash\n# Canary releases (automated in CI)\nnx release --tag=canary --yes                    # Publish to 'canary' dist-tag\nnx release --specifier=prerelease --tag=canary   # Force prerelease bump\n\n# Stable releases (manual promotion)\nnx release --tag=latest --yes                  # Promote to 'latest' dist-tag\nnx release --specifier=2.80.1 --tag=latest     # Promote specific version\n\n# Preview and debugging\nnx release --dry-run                           # Preview changes\nnx release --dry-run --verbose                 # Detailed preview\nnx release --first-release --dry-run           # First release preview\n\n# Version-specific releases\nnx release --specifier=patch --tag=latest      # Force patch bump\nnx release --specifier=minor --tag=latest      # Force minor bump\nnx release --specifier=major --tag=latest      # Force major bump\n```\n\n### Changelog Example\n\n```markdown\n## @supabase/realtime-js 2.80.1 (2025-09-16)\n\n- fix: correct reconnection logic (#123)\n\n## @supabase/auth-js 2.80.1 (2025-09-16)\n\n_No user-facing changes in this release._\n\n## @supabase/supabase-js 2.80.1 (2025-09-16)\n\n_No user-facing changes in this release._\n```\n\n## When Providing Code Suggestions\n\n1. **Consider Monorepo Impact**: Changes might affect multiple packages - always check dependencies\n2. **Use Nx Commands**: Always prefer `nx` over direct `npm` for workspace operations\n3. **Suggest Complete Test Suites**: Use complete test suites (`nx test:auth auth-js`, `nx test:storage storage-js`, etc.) for packages individually\n4. **Respect Fixed Versioning**: All packages version together - no independent versioning\n5. **Maintain Compatibility**: Never introduce breaking changes without proper process\n6. **Check Testing Requirements**: Be aware of Docker requirements for integration tests\n7. **Extract Shared Code**: Identify patterns that could be shared across packages\n8. **Follow Conventions**: Use existing patterns and structures within each library\n9. **Document Changes**: Update JSDoc and READMEs when changing public APIs\n10. **Use Conventional Commits**: Always suggest proper commit format with scope\n\n## Quick Decision Tree\n\n**Q: Where does this code belong?**\n\n- Authentication logic → auth-js\n- Database queries → postgrest-js\n- Real-time subscriptions → realtime-js\n- File operations → storage-js\n- Edge function calls → functions-js\n- Integration of above → supabase-js\n- Shared utilities → packages/shared/ (create if needed)\n\n**Q: How to test this change?**\n\n1. Unit test in source library\n2. Integration test in supabase-js if affects it\n3. Run complete test suite for the package:\n   - `nx test:auth auth-js` (handles Docker automatically)\n   - `nx test:storage storage-js` (handles Docker automatically)\n   - `nx test:ci:postgrest postgrest-js` (handles Docker automatically)\n   - `nx test functions-js` (uses testcontainers)\n   - `nx test realtime-js` (no Docker needed)\n   - `nx test supabase-js` (unit tests only)\n4. Run complete test suites for all affected packages individually\n\n**Q: How will this release?**\n\n- All packages version together in fixed mode\n- Your commit triggers automatic canary release for ALL packages\n- Weekly promotion of validated canary to stable\n- Unchanged packages show \"No user-facing changes\"\n- Single npm install updates entire SDK suite\n\nRemember: This monorepo optimizes for developer experience and maintenance efficiency while ensuring zero breaking changes for the millions of developers using Supabase SDKs.\n\n<!-- nx configuration start-->\n<!-- Leave the start & end comments to automatically receive updates. -->\n\n## General Guidelines for working with Nx\n\n- For navigating/exploring the workspace, invoke the `nx-workspace` skill first - it has patterns for querying projects, targets, and dependencies\n- When running tasks (for example build, lint, test, e2e, etc.), always prefer running the task through `nx` (i.e. `nx run`, `nx run-many`, `nx affected`) instead of using the underlying tooling directly\n- Prefix nx commands with the workspace's package manager (e.g., `pnpm nx build`, `npm exec nx test`) - avoids using globally installed CLI\n- You have access to the Nx MCP server and its tools, use them to help the user\n- For Nx plugin best practices, check `node_modules/@nx/<plugin>/PLUGIN.md`. Not all plugins have this file - proceed without it if unavailable.\n- NEVER guess CLI flags - always check nx_docs or `--help` first when unsure\n\n## Scaffolding & Generators\n\n- For scaffolding tasks (creating apps, libs, project structure, setup), ALWAYS invoke the `nx-generate` skill FIRST before exploring or calling MCP tools\n\n## When to use nx_docs\n\n- USE for: advanced config options, unfamiliar flags, migration guides, plugin configuration, edge cases\n- DON'T USE for: basic generator syntax (`nx g @nx/react:app`), standard commands, things you already know\n- The `nx-generate` skill handles generator discovery internally - don't call nx_docs just to look up generator syntax\n\n<!-- nx configuration end-->\n","isInternal":false,"tokens":7581,"sizeBytes":32344},{"name":"SKILL.md","path":".agents/skills/link-workspace-packages/SKILL.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/.agents/skills/link-workspace-packages/SKILL.md","title":"link-workspace-packages","category":"anthropic-skill","format":"markdown","content":"---\nname: link-workspace-packages\ndescription: 'Link workspace packages in monorepos (npm, yarn, pnpm, bun). USE WHEN: (1) you just created or generated new packages and need to wire up their dependencies, (2) user imports from a sibling package and needs to add it as a dependency, (3) you get resolution errors for workspace packages (@org/*) like \"cannot find module\", \"failed to resolve import\", \"TS2307\", or \"cannot resolve\". DO NOT patch around with tsconfig paths or manual package.json edits - use the package manager''s workspace commands to fix actual linking.'\n---\n\n# Link Workspace Packages\n\nAdd dependencies between packages in a monorepo. All package managers support workspaces but with different syntax.\n\n## Detect Package Manager\n\nCheck whether there's a `packageManager` field in the root-level `package.json`.\n\nAlternatively check lockfile in repo root:\n\n- `pnpm-lock.yaml` → pnpm\n- `yarn.lock` → yarn\n- `bun.lock` / `bun.lockb` → bun\n- `package-lock.json` → npm\n\n## Workflow\n\n1. Identify consumer package (the one importing)\n2. Identify provider package(s) (being imported)\n3. Add dependency using package manager's workspace syntax\n4. Verify symlinks created in consumer's `node_modules/`\n\n---\n\n## pnpm\n\nUses `workspace:` protocol - symlinks only created when explicitly declared.\n\n```bash\n# From consumer directory\npnpm add @org/ui --workspace\n\n# Or with --filter from anywhere\npnpm add @org/ui --filter @org/app --workspace\n```\n\nResult in `package.json`:\n\n```json\n{ \"dependencies\": { \"@org/ui\": \"workspace:*\" } }\n```\n\n---\n\n## yarn (v2+/berry)\n\nAlso uses `workspace:` protocol.\n\n```bash\nyarn workspace @org/app add @org/ui\n```\n\nResult in `package.json`:\n\n```json\n{ \"dependencies\": { \"@org/ui\": \"workspace:^\" } }\n```\n\n---\n\n## npm\n\nNo `workspace:` protocol. npm auto-symlinks workspace packages.\n\n```bash\nnpm install @org/ui --workspace @org/app\n```\n\nResult in `package.json`:\n\n```json\n{ \"dependencies\": { \"@org/ui\": \"*\" } }\n```\n\nnpm resolves to local workspace automatically during install.\n\n---\n\n## bun\n\nSupports `workspace:` protocol (pnpm-compatible).\n\n```bash\ncd packages/app && bun add @org/ui\n```\n\nResult in `package.json`:\n\n```json\n{ \"dependencies\": { \"@org/ui\": \"workspace:*\" } }\n```\n\n---\n\n## Examples\n\n**Example 1: pnpm - link ui lib to app**\n\n```bash\npnpm add @org/ui --filter @org/app --workspace\n```\n\n**Example 2: npm - link multiple packages**\n\n```bash\nnpm install @org/data-access @org/ui --workspace @org/dashboard\n```\n\n**Example 3: Debug \"Cannot find module\"**\n\n1. Check if dependency is declared in consumer's `package.json`\n2. If not, add it using appropriate command above\n3. Run install (`pnpm install`, `npm install`, etc.)\n\n## Notes\n\n- Symlinks appear in `<consumer>/node_modules/@org/<package>`\n- **Hoisting differs by manager:**\n  - npm/bun: hoist shared deps to root `node_modules`\n  - pnpm: no hoisting (strict isolation, prevents phantom deps)\n  - yarn berry: uses Plug'n'Play by default (no `node_modules`)\n- Root `package.json` should have `\"private\": true` to prevent accidental publish\n","frontmatter":{"name":"link-workspace-packages","description":"Link workspace packages in monorepos (npm, yarn, pnpm, bun). USE WHEN: (1) you just created or generated new packages and need to wire up their dependencies, (2) user imports from a sibling package and needs to add it as a dependency, (3) you get resolution errors for workspace packages (@org/*) like \"cannot find module\", \"failed to resolve import\", \"TS2307\", or \"cannot resolve\". DO NOT patch around with tsconfig paths or manual package.json edits - use the package manager's workspace commands to fix actual linking."},"isInternal":false,"tokens":772,"sizeBytes":3046},{"name":"SKILL.md","path":".agents/skills/nx-generate/SKILL.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/.agents/skills/nx-generate/SKILL.md","title":"nx-generate","category":"anthropic-skill","format":"markdown","content":"---\nname: nx-generate\ndescription: Generate code using nx generators. INVOKE IMMEDIATELY when user mentions scaffolding, setup, structure, creating apps/libs, or setting up project structure. Trigger words - scaffold, setup, create a ... app, create a ... lib, project structure, generate, add a new project. ALWAYS use this BEFORE calling nx_docs or exploring - this skill handles discovery internally.\nsubagent: general-purpose\ncontext: fork\n---\n\n# Run Nx Generator\n\nNx generators are powerful tools that scaffold projects, make automated code migrations or automate repetitive tasks in a monorepo. They ensure consistency across the codebase and reduce boilerplate work.\n\nThis skill applies when the user wants to:\n\n- Create new projects like libraries or applications\n- Scaffold features or boilerplate code\n- Run workspace-specific or custom generators\n- Do anything else that an nx generator exists for\n\n## Key Principles\n\n1. **Always use `--no-interactive`** - Prevents prompts that would hang execution\n2. **Read the generator source code** - The schema alone is not enough; understand what the generator actually does\n3. **Match existing repo patterns** - Study similar artifacts in the repo and follow their conventions\n4. **Verify with lint/test/build/typecheck etc.** - Generated code must pass verification. The listed targets are just an example, use what's appropriate for this workspace.\n\n## Steps\n\n### 1. Discover Available Generators\n\nUse the Nx CLI to discover available generators:\n\n- List all generators for a plugin: `npx nx list @nx/react`\n- View available plugins: `npx nx list`\n\nThis includes plugin generators (e.g., `@nx/react:library`) and local workspace generators.\n\n### 2. Match Generator to User Request\n\nIdentify which generator(s) could fulfill the user's needs. Consider what artifact type they want, which framework is relevant, and any specific generator names mentioned.\n\n**IMPORTANT**: When both a local workspace generator and an external plugin generator could satisfy the request, **always prefer the local workspace generator**. Local generators are customized for the specific repo's patterns.\n\nIf no suitable generator exists, you can stop using this skill. However, the burden of proof is high—carefully consider all available generators before deciding none apply.\n\n### 3. Get Generator Options\n\nUse the `--help` flag to understand available options:\n\n```bash\nnpx nx g @nx/react:library --help\n```\n\nPay attention to required options, defaults that might need overriding, and options relevant to the user's request.\n\n### Library Buildability\n\n**Default to non-buildable libraries** unless there's a specific reason for buildable.\n\n| Type                        | When to use                                                       | Generator flags                     |\n| --------------------------- | ----------------------------------------------------------------- | ----------------------------------- |\n| **Non-buildable** (default) | Internal monorepo libs consumed by apps                           | No `--bundler` flag                 |\n| **Buildable**               | Publishing to npm, cross-repo sharing, stable libs for cache hits | `--bundler=vite` or `--bundler=swc` |\n\nNon-buildable libs:\n\n- Export `.ts`/`.tsx` source directly\n- Consumer's bundler compiles them\n- Faster dev experience, less config\n\nBuildable libs:\n\n- Have their own build target\n- Useful for stable libs that rarely change (cache hits)\n- Required for npm publishing\n\n**If unclear, ask the user:** \"Should this library be buildable (own build step, better caching) or non-buildable (source consumed directly, simpler setup)?\"\n\n### 4. Read Generator Source Code\n\n**This step is critical.** The schema alone does not tell you everything. Reading the source code helps you:\n\n- Know exactly what files will be created/modified and where\n- Understand side effects (updating configs, installing deps, etc.)\n- Identify behaviors and options not obvious from the schema\n- Understand how options interact with each other\n\nTo find generator source code:\n\n- For plugin generators: Use `node -e \"console.log(require.resolve('@nx/<plugin>/generators.json'));\"` to find the generators.json, then locate the source from there\n- If that fails, read directly from `node_modules/<plugin>/generators.json`\n- For local generators: Typically in `tools/generators/` or a local plugin directory. Search the repo for the generator name.\n\nAfter reading the source, reconsider: Is this the right generator? If not, go back to step 2.\n\n> **⚠️ `--directory` flag behavior can be misleading.**\n> It should specify the full path of the generated library or component, not the parent path that it will be generated in.\n>\n> ```bash\n> # ✅ Correct - directory is the full path for the library\n> nx g @nx/react:library --directory=libs/my-lib\n> # generates libs/my-lib/package.json and more\n>\n> # ❌ Wrong - this will create files at libs and libs/src/...\n> nx g @nx/react:library --name=my-lib --directory=libs\n> # generates libs/package.json and more\n> ```\n\n### 5. Examine Existing Patterns\n\nBefore generating, examine the target area of the codebase:\n\n- Look at similar existing artifacts (other libraries, applications, etc.)\n- Identify naming conventions, file structures, and configuration patterns\n- Note which test runners, build tools, and linters are used\n- Configure the generator to match these patterns\n\n### 6. Dry-Run to Verify File Placement\n\n**Always run with `--dry-run` first** to verify files will be created in the correct location:\n\n```bash\nnpx nx g @nx/react:library --name=my-lib --dry-run --no-interactive\n```\n\nReview the output carefully. If files would be created in the wrong location, adjust your options based on what you learned from the generator source code.\n\nNote: Some generators don't support dry-run (e.g., if they install npm packages). If dry-run fails for this reason, proceed to running the generator for real.\n\n### 7. Run the Generator\n\nExecute the generator:\n\n```bash\nnx generate <generator-name> <options> --no-interactive\n```\n\n> **Tip:** New packages often need workspace dependencies wired up (e.g., importing shared types, being consumed by apps). The `link-workspace-packages` skill can help add these correctly.\n\n### 8. Modify Generated Code (If Needed)\n\nGenerators provide a starting point. Modify the output as needed to:\n\n- Add or modify functionality as requested\n- Adjust imports, exports, or configurations\n- Integrate with existing code patterns\n\n**Important:** If you replace or delete generated test files (e.g., `*.spec.ts`), either write meaningful replacement tests or remove the `test` target from the project configuration. Empty test suites will cause `nx test` to fail.\n\n### 9. Format and Verify\n\nFormat all generated/modified files:\n\n```bash\nnx format --fix\n```\n\nThis example is for built-in nx formatting with prettier. There might be other formatting tools for this workspace, use these when appropriate.\n\nThen verify the generated code works. Keep in mind that the changes you make with a generator or subsequent modifications might impact various projects so it's usually not enough to only run targets for the artifact you just created.\n\n```bash\n# these targets are just an example!\nnx run-many -t build,lint,test,typecheck\n```\n\nThese targets are common examples used across many workspaces. You should do research into other targets available for this workspace and its projects. CI configuration is usually a good guide for what the critical targets are that have to pass.\n\nIf verification fails with manageable issues (a few lint errors, minor type issues), fix them. If issues are extensive, attempt obvious fixes first, then escalate to the user with details about what was generated, what's failing, and what you've attempted.\n","frontmatter":{"name":"nx-generate","description":"Generate code using nx generators. INVOKE IMMEDIATELY when user mentions scaffolding, setup, structure, creating apps/libs, or setting up project structure. Trigger words - scaffold, setup, create a ... app, create a ... lib, project structure, generate, add a new project. ALWAYS use this BEFORE calling nx_docs or exploring - this skill handles discovery internally.","subagent":"general-purpose","context":"fork"},"isInternal":false,"tokens":1645,"sizeBytes":7806},{"name":"ESLINT.md","path":".agents/skills/nx-import/references/ESLINT.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/.agents/skills/nx-import/references/ESLINT.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"## ESLint\n\nESLint-specific guidance for `nx import`. For generic import issues (root deps, pnpm globs, project references), see `SKILL.md`.\n\n---\n\n### How `@nx/eslint/plugin` Works\n\n`@nx/eslint/plugin` scans for ESLint config files and creates a lint target for each project. It detects **both** flat config files (`eslint.config.{js,mjs,cjs,ts,mts,cts}`) and legacy config files (`.eslintrc.{json,js,cjs,mjs,yml,yaml}`).\n\n**Plugin options (set during `nx add @nx/eslint`):**\n\n```json\n{\n  \"plugin\": \"@nx/eslint/plugin\",\n  \"options\": {\n    \"targetName\": \"eslint:lint\"\n  }\n}\n```\n\n**Auto-installation**: `nx import` auto-detects ESLint config files and offers to install `@nx/eslint`. Accept the offer — it registers the plugin and updates `namedInputs.production` to exclude ESLint config files.\n\n---\n\n### Duplicate `lint` and `eslint:lint` Targets\n\nAfter import, projects will have **two** lint-related targets if the source `package.json` has a `\"lint\"` npm script:\n\n- `eslint:lint` — inferred by `@nx/eslint/plugin`; has proper caching and input/output tracking\n- `lint` — created by Nx from the npm script via `nx:run-script`; no caching intelligence, just wraps `npm run lint`\n\n**Fix**: Remove the `\"lint\"` script from each project's `package.json`. Keep `\"lint:fix\"` if present — there is no plugin-inferred equivalent for auto-fixing.\n\n---\n\n### Legacy `.eslintrc.*` Configs Linting Generated Files\n\nWhen `@nx/eslint/plugin` runs `eslint .` on a project with a legacy `.eslintrc.*` config that uses `parserOptions.project`, it tries to lint **all** files in the project directory including:\n\n- Generated `dist/**/*.d.ts` files (not in tsconfig `include`)\n- The `.eslintrc.js` config file itself (not in tsconfig `include`)\n\nThis causes `Parsing error: ESLint was configured to run on X using parserOptions.project, however that TSConfig does not include this file`.\n\n**Fix**: Add `ignorePatterns` to the `.eslintrc.*` config:\n\n```json\n// .eslintrc.json\n{\n  \"ignorePatterns\": [\"dist/**\"]\n}\n```\n\n```js\n// .eslintrc.js — also ignore the config file itself since module.exports isn't in tsconfig\nmodule.exports = {\n  ignorePatterns: ['dist/**', '.eslintrc.js'],\n  // ...\n}\n```\n\n---\n\n### Flat Config `.cjs` Files Self-Linting\n\nWhen a project uses `eslint.config.cjs` (CJS flat config), `eslint .` lints the config file itself. The `require()` call on line 1 triggers `@typescript-eslint/no-require-imports`.\n\n**Fix**: Add the config filename to the top-level `ignores` array:\n\n```js\nmodule.exports = tseslint.config(\n  {\n    ignores: ['dist/**', 'node_modules/**', 'eslint.config.cjs'],\n  }\n  // ...\n)\n```\n\nThe same applies to `eslint.config.js` in a CJS project (no `\"type\": \"module\"`) if it uses `require()`.\n\n---\n\n### `typescript-eslint` Version Conflict With ESLint 9\n\n`typescript-eslint@7.x` declares `peerDependencies: { \"eslint\": \"^8.56.0\" }`, but it is commonly used alongside `\"eslint\": \"^9.0.0\"`. npm treats this as a hard peer dep conflict and refuses to install.\n\n**Root cause**: `@nx/eslint` init adds `eslint@~8.57.0` at the workspace root (for its own peer deps). Workspace packages that request `eslint@^9.0.0` + `typescript-eslint@^7.0.0` trigger the conflict when npm resolves their deps.\n\n**Fix**: Upgrade `typescript-eslint` from `^7.0.0` to `^8.0.0` directly in the affected workspace package's `package.json`. The `tseslint.config()` API and `tseslint.configs.recommended` are identical between v7 and v8 — no config changes needed.\n\n```json\n// packages/my-package/package.json\n{\n  \"devDependencies\": {\n    \"typescript-eslint\": \"^8.0.0\"\n  }\n}\n```\n\n**Note**: npm's root-level `\"overrides\"` field does not force versions for workspace packages' direct dependencies — update each package.json individually.\n\n---\n\n### Mixed ESLint v8 and v9 in One Workspace\n\nLegacy v8 and flat-config v9 packages can coexist in the same workspace. Each package resolves its own `eslint` version. The root `eslint@~8.57.0` (added by `@nx/eslint` init) is used by legacy v8 packages; v9 packages get their own hoisted `eslint@9`.\n\n`@nx/eslint/plugin` infers `eslint:lint` targets for **both** config formats. Legacy packages run ESLint v8 with `.eslintrc.*`; flat-config packages run ESLint v9 with `eslint.config.*`. No special nx.json configuration is needed to support both simultaneously.\n","isInternal":false,"tokens":1139,"sizeBytes":4305},{"name":"JEST.md","path":".agents/skills/nx-import/references/JEST.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/.agents/skills/nx-import/references/JEST.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"## Jest\n\nJest-specific guidance for `nx import`. For the basic \"Jest Preset Missing\" fix (create `jest.preset.js`, install deps), see `SKILL.md`. This file covers deeper Jest integration issues.\n\n---\n\n### How `@nx/jest` Works\n\n`@nx/jest/plugin` scans for `jest.config.{ts,js,cjs,mjs,cts,mts}` and creates a `test` target for each project.\n\n**Plugin options:**\n\n```json\n{\n  \"plugin\": \"@nx/jest/plugin\",\n  \"options\": {\n    \"targetName\": \"test\"\n  }\n}\n```\n\n`npx nx add @nx/jest` does two things:\n\n1. **Registers `@nx/jest/plugin` in `nx.json`** — without this, no `test` targets are inferred\n2. Updates `namedInputs.production` to exclude test files\n\n**Gotcha**: `nx add @nx/jest` does NOT create `jest.preset.js` — that file is only generated when you run a generator (e.g. `@nx/jest:configuration`). For imports, you must create it manually (see \"Jest Preset\" section below).\n\n**Other gotcha**: If you create `jest.preset.js` manually but skip `npx nx add @nx/jest`, the plugin won't be registered and `nx run PROJECT:test` will fail with \"Cannot find target 'test'\". You need both.\n\n---\n\n### Jest Preset\n\nThe preset provides shared Jest configuration (test patterns, ts-jest transform, resolver, jsdom environment).\n\n**Root `jest.preset.js`:**\n\n```js\nconst nxPreset = require('@nx/jest/preset').default\nmodule.exports = { ...nxPreset }\n```\n\n**Project `jest.config.ts`:**\n\n```ts\nexport default {\n  displayName: 'my-lib',\n  preset: '../../jest.preset.js',\n  // project-specific overrides\n}\n```\n\nThe `preset` path is relative from the project root to the workspace root. Subdirectory imports preserve the original relative path (e.g. `../../jest.preset.js`), which resolves correctly if the import destination matches the source directory depth.\n\n---\n\n### Testing Dependencies\n\n#### Core (always needed)\n\n```\npnpm add -wD jest ts-jest @types/jest @nx/jest\n```\n\n#### Environment-specific\n\n- **DOM testing** (React, Vue, browser libs): `jest-environment-jsdom`\n- **Node testing** (APIs, CLIs): no extra deps (Jest defaults to `node` env, but Nx preset defaults to `jsdom`)\n\n#### React testing\n\n```\npnpm add -wD @testing-library/react @testing-library/jest-dom\n```\n\n#### React with Babel (non-ts-jest transform)\n\nSome React projects use Babel instead of ts-jest for JSX transformation:\n\n```\npnpm add -wD babel-jest @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript\n```\n\n**When**: Project `jest.config` has `transform` using `babel-jest` instead of `ts-jest`. Common in older Nx workspaces and CRA migrations.\n\n#### Vue testing\n\n```\npnpm add -wD @vue/test-utils\n```\n\nVue projects typically use Vitest (not Jest) — see VITE.md.\n\n---\n\n### `tsconfig.spec.json`\n\nJest projects need a `tsconfig.spec.json` that includes test files:\n\n```json\n{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../../dist/out-tsc\",\n    \"module\": \"commonjs\",\n    \"types\": [\"jest\", \"node\"]\n  },\n  \"include\": [\"jest.config.ts\", \"src/**/*.test.ts\", \"src/**/*.spec.ts\", \"src/**/*.d.ts\"]\n}\n```\n\n**Common issues after import:**\n\n- Missing `\"types\": [\"jest\", \"node\"]` — causes `describe`/`it`/`expect` to be unrecognized\n- Missing `\"module\": \"commonjs\"` — Jest doesn't support ESM by default (ts-jest transpiles to CJS)\n- `include` array missing test patterns — TypeScript won't check test files\n\n---\n\n### Jest vs Vitest Coexistence\n\nWorkspaces can have both:\n\n- **Jest**: Next.js apps, older React libs, Node libraries\n- **Vitest**: Vite-based React/Vue apps and libs\n\nBoth `@nx/jest/plugin` and `@nx/vite/plugin` (which infers Vitest targets) coexist without conflicts — they detect different config files (`jest.config.*` vs `vite.config.*`).\n\n**Target naming**: Both default to `test`. If a project somehow has both config files, rename one:\n\n```json\n{\n  \"plugin\": \"@nx/jest/plugin\",\n  \"options\": { \"targetName\": \"jest-test\" }\n}\n```\n\n---\n\n### `@testing-library/jest-dom` — Jest vs Vitest\n\nProjects migrating from Jest to Vitest (or workspaces with both) need different imports:\n\n**Jest** (in `test-setup.ts`):\n\n```ts\nimport '@testing-library/jest-dom'\n```\n\n**Vitest** (in `test-setup.ts`):\n\n```ts\nimport '@testing-library/jest-dom/vitest'\n```\n\nIf the source used Jest but the dest workspace uses Vitest for that project type, update the import path. Also add `@testing-library/jest-dom` to tsconfig `types` array.\n\n---\n\n### Non-Nx Source: Test Script Rewriting\n\nNx rewrites `package.json` scripts during init. Test scripts get broken:\n\n- `\"test\": \"jest\"` → `\"test\": \"nx test\"` (circular if no executor configured)\n- `\"test\": \"vitest run\"` → `\"test\": \"nx test run\"` (broken — `run` becomes an argument)\n\n**Fix**: Remove all rewritten test scripts. `@nx/jest/plugin` and `@nx/vite/plugin` infer test targets from config files.\n\n---\n\n### CI Atomization\n\n`@nx/jest/plugin` supports splitting tests per-file for CI parallelism:\n\n```json\n{\n  \"plugin\": \"@nx/jest/plugin\",\n  \"options\": {\n    \"targetName\": \"test\",\n    \"ciTargetName\": \"test-ci\"\n  }\n}\n```\n\nThis creates `test-ci--src/lib/foo.spec.ts` targets for each test file, enabling Nx Cloud distribution. Not relevant during import, but useful for post-import CI setup.\n\n---\n\n### Common Post-Import Issues\n\n1. **\"Cannot find target 'test'\"**: `@nx/jest/plugin` not registered in `nx.json`. Run `npx nx add @nx/jest` or manually add the plugin entry.\n\n2. **\"Cannot find module 'jest-preset'\"**: `jest.preset.js` missing at workspace root. Create it (see SKILL.md).\n\n3. **\"Cannot find type definition file for 'jest'\"**: Missing `@types/jest` or `tsconfig.spec.json` doesn't have `\"types\": [\"jest\", \"node\"]`.\n\n4. **Tests fail with \"Cannot use import statement outside a module\"**: `ts-jest` not installed or not configured as transform. Check `jest.config.ts` transform section.\n\n5. **Snapshot path mismatches**: After import, `__snapshots__` directories may have paths baked in. Run tests once with `--updateSnapshot` to regenerate.\n\n---\n\n## Fix Order\n\n### Subdirectory Import (Nx Source)\n\n1. `npx nx add @nx/jest` — registers plugin in `nx.json` (does NOT create `jest.preset.js`)\n2. Create `jest.preset.js` manually (see \"Jest Preset\" section above)\n3. Install deps: `pnpm add -wD jest jest-environment-jsdom ts-jest @types/jest`\n4. Install framework test deps: `@testing-library/react @testing-library/jest-dom` (React), `@vue/test-utils` (Vue)\n5. Verify `tsconfig.spec.json` has `\"types\": [\"jest\", \"node\"]`\n6. `nx run-many -t test`\n\n### Whole-Repo Import (Non-Nx Source)\n\n1. Remove rewritten test scripts from `package.json`\n2. `npx nx add @nx/jest` — registers plugin (does NOT create preset)\n3. Create `jest.preset.js` manually\n4. Install deps (same as above)\n5. Verify/fix `jest.config.*` — ensure `preset` path points to root `jest.preset.js`\n6. Verify/fix `tsconfig.spec.json` — add `types`, `module`, `include` if missing\n7. `nx run-many -t test`\n","isInternal":false,"tokens":1847,"sizeBytes":6842},{"name":"VITE.md","path":".agents/skills/nx-import/references/VITE.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/.agents/skills/nx-import/references/VITE.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"## Vite\n\nVite-specific guidance for `nx import`. For generic import issues (pnpm globs, root deps, project references, name collisions, ESLint, frontend tsconfig base settings, `@nx/react` typings, Jest preset, non-Nx source handling), see `SKILL.md`.\n\n---\n\n### `@nx/vite/plugin` Typecheck Target\n\n`@nx/vite/plugin` defaults `typecheckTargetName` to `\"vite:typecheck\"`. If the workspace expects `\"typecheck\"`, set it explicitly in `nx.json`. If `@nx/js/typescript` is also registered, rename one target to avoid conflicts (e.g. `\"tsc-typecheck\"` for the JS plugin).\n\nKeep both plugins only if the workspace has non-Vite pure TS libraries — `@nx/js/typescript` handles those while `@nx/vite/plugin` handles Vite projects.\n\n### @nx/vite Plugin Install Failure\n\nPlugin init loads `vite.config.ts` before deps are available. **Fix**: `pnpm add -wD vite @vitejs/plugin-react` (or `@vitejs/plugin-vue`) first, then `pnpm exec nx add @nx/vite`.\n\n### Vite `resolve.alias` and `__dirname` (Non-Nx Sources)\n\n**`__dirname` undefined** (CJS-only): Replace with `fileURLToPath(new URL('./src', import.meta.url))` from `'node:url'`.\n\n**`@/` path alias**: Vite's `resolve.alias` works at runtime but TS needs matching `\"paths\"`. Set `\"baseUrl\": \".\"` in project tsconfig.\n\n**PostCSS/Tailwind**: Verify `content` globs resolve correctly after import.\n\n### Missing TypeScript `types` (Non-Nx Sources)\n\nNon-Nx tsconfigs may not declare all needed types. Ensure Vite projects include `\"types\": [\"node\", \"vite/client\"]` in their tsconfig.\n\n### `noEmit` Fix: Vite-Specific Notes\n\nSee SKILL.md for the generic noEmit→composite fix. Vite-specific additions:\n\n- Non-Nx Vite projects often have **both** `tsconfig.app.json` and `tsconfig.node.json` with `noEmit` — fix both\n- Solution-style tsconfigs (`\"files\": [], \"references\": [...]`) may lack `extends`. Add `extends` pointing to the dest root `tsconfig.base.json` so base settings (`moduleResolution`, `lib`) apply.\n- This is safe — Vite/Vitest ignore TypeScript emit settings.\n\n### Dependency Version Conflicts\n\n**Shared Vite deps (both frameworks):** `vite`, `vitest`, `jsdom`, `@types/node`, `typescript` (dev)\n\n**Vite 6→7**: Typecheck fails (`Plugin<any>` type mismatch); build/serve still works. Fix: align versions.\n**Vitest 3→4**: Usually works; type conflicts may surface in shared test utils.\n\n---\n\n## React Router 7 (Vite-Based)\n\nReact Router 7 (`@react-router/dev`) uses Vite under the hood with a `vite.config.ts` and a `react-router.config.ts`. The `@nx/vite/plugin` detects `vite.config.ts` and creates inferred targets.\n\n### Targets\n\n`@nx/vite/plugin` creates `build`, `dev`, `serve` targets. The `build` target invokes the script defined in `package.json` (usually `react-router build`), not `vite build` directly.\n\n**No separate typecheck target from `@nx/vite/plugin`** — React Router 7 typegen is run as part of `typecheck` (e.g. `react-router typegen && tsc`). The `typecheck` target is inferred from the tsconfig. Keep the `typecheck` script in `package.json` if present; it is not rewritten.\n\n### tsconfig Notes\n\nReact Router 7 uses a single `tsconfig.json` (no `tsconfig.app.json`/`tsconfig.node.json` split). It includes:\n\n- `\"rootDirs\": [\".\", \"./.react-router/types\"]` — for generated type files; keep as-is\n- `\"paths\": { \"~/*\": [\"./app/*\"] }` — self-referential alias; keep as-is\n- `\"noEmit\": true` — replace with composite settings per SKILL.md\n\n### Build Output\n\nReact Router 7 outputs to `build/` (not `dist/`). Add `build` to the dest root `.gitignore`.\n\n### Generated Types Directory\n\nReact Router 7 generates `.react-router/` at the project root for route type generation. Add `.react-router` to the dest root `.gitignore`.\n\n---\n\n## TanStack Start (Vite-Based)\n\nTanStack Start uses Vinxi under the hood, which wraps Vite. Projects have a standard `vite.config.ts` that `@nx/vite/plugin` detects normally.\n\n### Targets\n\n`@nx/vite/plugin` creates `build`, `dev`, `preview`, `serve-static`, `typecheck` targets. The `build` target runs `vite build` which invokes the TanStack Start Vinxi pipeline (produces both client and SSR bundles).\n\n### tsconfig Notes\n\nTanStack Start uses a single `tsconfig.json` with `\"allowImportingTsExtensions\": true` and `\"noEmit\": true`. Apply the standard noEmit → composite fix. `allowImportingTsExtensions` is compatible with `emitDeclarationOnly: true` — no change needed.\n\n### `paths` Aliases\n\nTanStack Start commonly uses `\"#/*\": [\"./src/*\"]` and `\"@/*\": [\"./src/*\"]`. These are self-referential — keep as-is for a single-project app.\n\n### Uncommitted Source Repo\n\n`create-tan-stack` initializes a git repo but does NOT make an initial commit. Before importing, commit first:\n\n```bash\ngit -C /path/to/source add . && git -C /path/to/source commit -m \"Initial commit\"\n```\n\n### Generated and Build Directories\n\nTanStack Start / Vinxi / Nitro generate several directories that must be added to the dest root `.gitignore`:\n\n- `.vinxi` — Vinxi build cache\n- `.tanstack` — TanStack generated files\n- `.nitro` — Nitro build artifacts\n- `.output` — server-side build output (SSR/edge)\n\nThese are not covered by `dist` or `build`.\n\n---\n\n## React-Specific\n\n### React Dependencies\n\n**Production:** `react`, `react-dom`\n**Dev:** `@types/react`, `@types/react-dom`, `@vitejs/plugin-react`, `@testing-library/react`, `@testing-library/jest-dom`, `jsdom`\n**ESLint (Nx sources):** `eslint-plugin-import`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`, `eslint-plugin-react-hooks`\n**ESLint (`create-vite`):** `eslint-plugin-react-refresh`, `eslint-plugin-react-hooks` — self-contained flat configs can be left as-is\n**Nx plugins:** `@nx/react` (generators), `@nx/vite`, `@nx/vitest`, `@nx/eslint`\n\n### React TypeScript Configuration\n\nAdd `\"jsx\": \"react-jsx\"` — in `tsconfig.base.json` for single-framework workspaces, per-project for mixed (see Mixed section).\n\n### React ESLint Config\n\n```js\nimport nx from '@nx/eslint-plugin'\nimport baseConfig from '../../eslint.config.mjs'\nexport default [\n  ...baseConfig,\n  ...nx.configs['flat/react'],\n  { files: ['**/*.ts', '**/*.tsx'], rules: {} },\n]\n```\n\n### React Version Conflicts\n\nReact 18 (source) + React 19 (dest): pnpm may hoist mismatched `react-dom`, causing `TypeError: Cannot read properties of undefined (reading 'S')`. **Fix**: Align versions with `pnpm.overrides`.\n\n### `@testing-library/jest-dom` with Vitest\n\nIf source used Jest: change import to `@testing-library/jest-dom/vitest` in test-setup.ts, add to tsconfig `types`.\n\n---\n\n## Vue-Specific\n\n### Vue Dependencies\n\n**Production:** `vue` (plus `vue-router`, `pinia` if used)\n**Dev:** `@vitejs/plugin-vue`, `vue-tsc`, `@vue/test-utils`, `jsdom`\n**ESLint:** `eslint-plugin-vue`, `vue-eslint-parser`, `@vue/eslint-config-typescript`, `@vue/eslint-config-prettier`\n**Nx plugins:** `@nx/vue` (generators), `@nx/vite`, `@nx/vitest`, `@nx/eslint` (install AFTER deps — see below)\n\n### Vue TypeScript Configuration\n\nAdd to `tsconfig.base.json` (single-framework) or per-project (mixed):\n\n```json\n{ \"jsx\": \"preserve\", \"jsxImportSource\": \"vue\", \"resolveJsonModule\": true }\n```\n\n### `vue-shims.d.ts`\n\nVue SFC files need a type declaration. Usually exists in each project's `src/` and imports cleanly. If missing:\n\n```ts\ndeclare module '*.vue' {\n  import { defineComponent } from 'vue'\n  const component: ReturnType<typeof defineComponent>\n  export default component\n}\n```\n\n### `vue-tsc` Auto-Detection\n\nBoth `@nx/js/typescript` and `@nx/vite/plugin` auto-detect `vue-tsc` when installed — no manual config needed. Remove source scripts like `\"typecheck\": \"vue-tsc --noEmit\"`.\n\n### ESLint Plugin Installation Order (Critical)\n\n`@nx/eslint` init **crashes** if Vue ESLint deps aren't installed first (it loads all config files).\n\n**Correct order:**\n\n1. `pnpm add -wD eslint@^9 eslint-plugin-vue vue-eslint-parser @vue/eslint-config-typescript @typescript-eslint/parser @nx/eslint-plugin typescript-eslint`\n2. Create root `eslint.config.mjs`\n3. Then `npx nx add @nx/eslint`\n\n### Vue ESLint Config Pattern\n\n```js\nimport vue from 'eslint-plugin-vue'\nimport vueParser from 'vue-eslint-parser'\nimport tsParser from '@typescript-eslint/parser'\nimport baseConfig from '../../eslint.config.mjs'\nexport default [\n  ...baseConfig,\n  ...vue.configs['flat/recommended'],\n  {\n    files: ['**/*.vue'],\n    languageOptions: { parser: vueParser, parserOptions: { parser: tsParser } },\n  },\n  {\n    files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.vue'],\n    rules: { 'vue/multi-word-component-names': 'off' },\n  },\n]\n```\n\n**Important**: `vue-eslint-parser` override must come **AFTER** base config — `flat/typescript` sets the TS parser globally without a `files` filter, breaking `.vue` parsing.\n\n`vue-eslint-parser` must be an explicit pnpm dependency (strict resolution prevents transitive import).\n\n**Known issue**: Some generated Vue ESLint configs omit `vue-eslint-parser`. Use the pattern above instead.\n\n---\n\n## Mixed React + Vue\n\nWhen both frameworks coexist, several settings become per-project.\n\n### tsconfig `jsx` — Per-Project Only\n\n- React: `\"jsx\": \"react-jsx\"` in project tsconfig\n- Vue: `\"jsx\": \"preserve\"`, `\"jsxImportSource\": \"vue\"` in project tsconfig\n- Root: **NO** `jsx` setting\n\n### Typecheck — Auto-Detects Framework\n\n`@nx/vite/plugin` uses `vue-tsc` for Vue projects and `tsc` for React automatically.\n\n```json\n{\n  \"plugins\": [\n    { \"plugin\": \"@nx/eslint/plugin\", \"options\": { \"targetName\": \"lint\" } },\n    {\n      \"plugin\": \"@nx/vite/plugin\",\n      \"options\": {\n        \"buildTargetName\": \"build\",\n        \"typecheckTargetName\": \"typecheck\",\n        \"testTargetName\": \"test\"\n      }\n    }\n  ]\n}\n```\n\nRemove `@nx/js/typescript` if all projects use Vite. Keep it (renamed to `\"tsc-typecheck\"`) only for non-Vite pure TS libs.\n\n### ESLint — Three-Tier Config\n\n1. **Root**: Base rules only, no framework-specific rules\n2. **React projects**: Extend root + `nx.configs['flat/react']`\n3. **Vue projects**: Extend root + `vue.configs['flat/recommended']` + `vue-eslint-parser`\n\n**Required packages**: Shared (`eslint@^9`, `@nx/eslint-plugin`, `typescript-eslint`, `@typescript-eslint/parser`), React (`eslint-plugin-import`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`, `eslint-plugin-react-hooks`), Vue (`eslint-plugin-vue`, `vue-eslint-parser`)\n\n`@nx/react`/`@nx/vue` are for generators only — no target conflicts.\n\n---\n\n## Redundant npm Scripts After Import\n\n`nx import` copies `package.json` verbatim, so npm scripts come along. For Vite-based projects `@nx/vite/plugin` already infers the same targets from `vite.config.ts` — the npm scripts just shadow the plugin with weaker `nx:run-script` wrappers (no first-class caching inputs/outputs). Remove them after import.\n\n### Standalone Vite App (`create-vite`)\n\nRemove the following scripts — every one is redundant:\n\n| Script                        | Plugin replacement                                                           |\n| ----------------------------- | ---------------------------------------------------------------------------- |\n| `dev: vite`                   | `@nx/vite/plugin` → `dev`                                                    |\n| `build: tsc -b && vite build` | `@nx/vite/plugin` → `build`; `typecheck` via `@nx/js/typescript` handles tsc |\n| `preview: vite preview`       | `@nx/vite/plugin` → `preview`                                                |\n| `lint: eslint .`              | `@nx/eslint/plugin` → `eslint:lint`                                          |\n\n### TanStack Start\n\nRemove `build`, `dev`, `preview`, and `test` scripts, but move any hardcoded `--port` flag to `vite.config.ts` first:\n\n```ts\n// vite.config.ts\nexport default defineConfig({\n  server: { port: 3000 },  // replaces `vite dev --port 3000`\n  ...\n})\n```\n\n### React Router 7 — Keep ALL scripts\n\nDo **not** remove React Router 7 scripts. They use the framework CLI (`react-router build`, `react-router dev`, `react-router-serve`) which is not interchangeable with plain `vite`:\n\n- `typecheck` runs `react-router typegen && tsc` — typegen must precede `tsc` or it fails on missing route types\n- `start` serves the SSR bundle — no plugin equivalent\n\n---\n\n## Fix Orders\n\n### Nx Source\n\n1. Generic fixes from SKILL.md (pnpm globs, root deps, executor paths, frontend tsconfig base settings, `@nx/react` typings)\n2. Configure `@nx/vite/plugin` typecheck target\n3. **React**: `jsx: \"react-jsx\"` (root or per-project)\n4. **Vue**: `jsx: \"preserve\"` + `jsxImportSource: \"vue\"`; verify `vue-shims.d.ts`; install ESLint deps before `@nx/eslint`\n5. **Mixed**: `jsx` per-project; remove/rename `@nx/js/typescript`\n6. `nx sync --yes && nx reset && nx run-many -t typecheck,build,test,lint`\n\n### Non-Nx Source (additional steps)\n\n0. Import into `apps/<name>` (see SKILL.md: \"Application vs Library Detection\")\n1. Generic fixes from SKILL.md (stale files cleanup, pnpm globs, rewritten scripts, target name prefixing, noEmit→composite, ESLint handling)\n2. Fix `noEmit` in **all** tsconfigs (app, node, etc. — non-Nx projects often have multiple)\n3. Add `extends` to solution-style tsconfigs so root settings apply\n4. Fix `resolve.alias` / `__dirname` / `baseUrl`\n5. Ensure `types` include `vite/client` and `node`\n6. Install `@nx/vite` manually if it failed during import\n7. Remove redundant npm scripts so `@nx/vite/plugin` infers them natively (see \"Redundant npm Scripts\" section)\n8. **Vue**: Add `outDir` + `**/*.vue.d.ts` to ESLint ignores\n9. Full verification\n\n### Multiple-Source Imports\n\nSee SKILL.md for generic multi-import (name collisions, dep refs). Vite-specific: fix tsconfig `references` paths for alternate directories (`../../libs/` → `../../libs-beta/`).\n\n### Non-Nx Source: React Router 7\n\n1. Ensure source has at least one commit (see SKILL.md: \"Source Repo Has No Commits\")\n2. `nx import` whole-repo into `apps/<name>` (see SKILL.md: \"Application vs Library Detection\") → auto-installs `@nx/vite`, `@nx/react`\n3. Stale file cleanup: `node_modules/`, `package-lock.json`, `.gitignore`\n4. Fix `tsconfig.json`: `noEmit` → `composite + emitDeclarationOnly + outDir + tsBuildInfoFile`\n5. Add `build` and `.react-router` to dest root `.gitignore`\n6. **Keep all npm scripts** — React Router 7 uses framework CLI (`react-router build/dev`), not plain vite (see \"Redundant npm Scripts\" above)\n7. `npm install && nx reset && nx sync --yes`\n\n### Non-Nx Source: TanStack Start\n\n1. Ensure source has at least one commit — `create-tan-stack` does NOT auto-commit (see SKILL.md)\n2. `nx import` whole-repo into `apps/<name>` (see SKILL.md: \"Application vs Library Detection\") → auto-installs `@nx/vite`, `@nx/vitest`\n3. Stale file cleanup: `node_modules/`, `package-lock.json`, `.gitignore`\n4. Fix `tsconfig.json`: `noEmit` → `composite + emitDeclarationOnly + outDir + tsBuildInfoFile`\n5. Keep `allowImportingTsExtensions` — compatible with `emitDeclarationOnly: true`\n6. Add `.vinxi`, `.tanstack`, `.nitro`, `.output` to dest root `.gitignore`\n7. Move hardcoded `--port` from `dev` script into `vite.config.ts` (`server: { port: N }`)\n8. Remove redundant npm scripts — `@nx/vite/plugin` infers `build`, `dev`, `preview`, `test` (see \"Redundant npm Scripts\" above)\n9. `npm install && nx reset && nx sync --yes`\n\n### Quick Reference: React vs Vue\n\n| Aspect        | React                    | Vue                                       |\n| ------------- | ------------------------ | ----------------------------------------- |\n| Vite plugin   | `@vitejs/plugin-react`   | `@vitejs/plugin-vue`                      |\n| Type checker  | `tsc`                    | `vue-tsc` (auto-detected)                 |\n| SFC support   | N/A                      | `vue-shims.d.ts` needed                   |\n| tsconfig jsx  | `\"react-jsx\"`            | `\"preserve\"` + `\"jsxImportSource\": \"vue\"` |\n| ESLint parser | Standard TS              | `vue-eslint-parser` + TS sub-parser       |\n| ESLint setup  | Straightforward          | Must install deps before `@nx/eslint`     |\n| Test utils    | `@testing-library/react` | `@vue/test-utils`                         |\n\n### Quick Reference: Vite-Based React Frameworks\n\n| Aspect             | Vite (standalone) | React Router 7          | TanStack Start           |\n| ------------------ | ----------------- | ----------------------- | ------------------------ |\n| Build config       | `vite.config.ts`  | `vite.config.ts`        | `vite.config.ts`         |\n| Build output       | `dist/`           | `build/`                | `dist/`                  |\n| SSR bundle         | No                | Yes (`build/server/`)   | Yes (`dist/server/`)     |\n| tsconfig layout    | app + node split  | Single tsconfig         | Single tsconfig          |\n| Auto-committed     | Depends on tool   | Usually yes             | **No — commit first**    |\n| `nx import` plugin | `@nx/vite`        | `@nx/vite`, `@nx/react` | `@nx/vite`, `@nx/vitest` |\n\n---\n\n## Iteration Log\n\n### Scenario 6: Multiple non-Nx React apps (CRA, Next.js, React Router 7, TanStack Start, Vite) → TS preset (PASS)\n\n- Sources: 5 standalone non-Nx repos with different build tools\n- Dest: CNW ts preset (Nx 22.5.1), npm workspaces, `packages/*`\n- Import: whole-repo for each, sequential into `packages/<name>`\n- Pre-import fixes:\n  1. Removed `packages/.gitkeep` and committed\n  2. `git init && git add . && git commit` in Vite app (no git at all)\n  3. `git add . && git commit` in TanStack app (git init'd but no commits)\n- Import: `npm exec nx -- import <source> packages/<name> --source=. --ref=main --no-interactive`\n  - Next.js import auto-installed `@nx/eslint`, `@nx/next`\n  - React Router 7 import auto-installed `@nx/vite`, `@nx/react`, `@nx/docker` (Dockerfile present)\n  - TanStack import auto-installed `@nx/vitest`\n- Post-import fixes:\n  1. Removed stale `node_modules/`, `package-lock.json`, `.gitignore` from each package\n  2. Removed Nx-rewritten scripts from `board-games-nextjs/package.json` (had `\"build\": \"nx next:build\"`, etc.)\n  3. Updated root `tsconfig.base.json`: `nodenext` → `bundler`, added `dom`/`dom.iterable` to lib, added `jsx: react-jsx`\n  4. Added `build` to dest root `.gitignore` (CRA and React Router 7 output there)\n  5. Fixed `noEmit` → `composite + emitDeclarationOnly` in: `board-games-vite/tsconfig.app.json`, `board-games-vite/tsconfig.node.json`, `board-games-react-router/tsconfig.json`, `board-games-tanstack/tsconfig.json`\n  6. Fixed `tsBuildInfoFile` paths from `./node_modules/.tmp/...` to `./dist/...`\n  7. Installed root `@types/react`, `@types/react-dom`, `@types/node`\n- All targets green: `build` for all 5 projects; `typecheck` for Vite/React Router/TanStack; `next:build` for Next.js\n","isInternal":false,"tokens":4973,"sizeBytes":18680},{"name":"SKILL.md","path":".agents/skills/nx-import/SKILL.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/.agents/skills/nx-import/SKILL.md","title":"nx-import","category":"anthropic-skill","format":"markdown","content":"---\nname: nx-import\ndescription: Import, merge, or combine repositories into an Nx workspace using nx import. USE WHEN the user asks to adopt Nx across repos, move projects into a monorepo, or bring code/history from another repository.\n---\n\n## Quick Start\n\n- `nx import` brings code from a source repository or folder into the current workspace, preserving commit history.\n- After nx `22.6.0`, `nx import` responds with .ndjson outputs and follow-up questions. For earlier versions, always run with `--no-interactive` and specify all flags directly.\n- Run `nx import --help` for available options.\n- Make sure the destination directory is empty before importing.\n  EXAMPLE: target has `libs/utils` and `libs/models`; source has `libs/ui` and `libs/data-access` — you cannot import `libs/` into `libs/` directly. Import each source library individually.\n\nPrimary docs:\n\n- https://nx.dev/docs/guides/adopting-nx/import-project\n- https://nx.dev/docs/guides/adopting-nx/preserving-git-histories\n\nRead the nx docs if you have the tools for it.\n\n## Import Strategy\n\n**Subdirectory-at-a-time** (`nx import <source> apps --source=apps`):\n\n- **Recommended for monorepo sources** — files land at top level, no redundant config\n- Caveats: multiple import commands (separate merge commits each); dest must not have conflicting directories; root configs (deps, plugins, targetDefaults) not imported\n- **Directory conflicts**: Import into alternate-named dir (e.g. `imported-apps/`), then rename\n\n**Whole repo** (`nx import <source> imported --source=.`):\n\n- **Only for non-monorepo sources** (single-project repos)\n- For monorepos, creates messy nested config (`imported/nx.json`, `imported/tsconfig.base.json`, etc.)\n- If you must: keep imported `tsconfig.base.json` (projects extend it), prefix workspace globs and executor paths\n\n### Directory Conventions\n\n- **Always prefer the destination's existing conventions.** Source uses `libs/`but dest uses `packages/`? Import into `packages/` (`nx import <source> packages/foo --source=libs/foo`).\n- If dest has no convention (empty workspace), ask the user.\n\n### Application vs Library Detection\n\nBefore importing, identify whether the source is an **application** or a **library**:\n\n- **Applications**: Deployable end products. Common indicators:\n  - _Frontend_: `next.config.*`, `vite.config.*` with a build entry point, framework-specific app scaffolding (CRA, Angular CLI app, etc.)\n  - _Backend (Node.js)_: Express/Fastify/NestJS server entrypoint, no `\"exports\"` field in `package.json`\n  - _JVM_: Maven `pom.xml` with `<packaging>jar</packaging>` or `<packaging>war</packaging>` and a `main` class; Gradle `application` plugin or `mainClass` setting\n  - _.NET_: `.csproj`/`.fsproj` with `<OutputType>Exe</OutputType>` or `<OutputType>WinExe</OutputType>`\n  - _General_: Dockerfile, a runnable entrypoint, no public API surface intended for import by other projects\n- **Libraries**: Reusable packages consumed by other projects. Common indicators: `\"main\"`/`\"exports\"` in `package.json`, Maven/Gradle packaging as a library jar, .NET `<OutputType>Library</OutputType>`, named exports intended for import by other packages.\n\n**Destination directory rules**:\n\n- Applications → `apps/<name>`. Check workspace globs (e.g. `pnpm-workspace.yaml`, `workspaces` in root `package.json`) for an existing `apps/*` entry.\n  - If `apps/*` is **not** present, add it before importing: update the workspace glob config and commit (or stage) the change.\n  - Example: `nx import <source> apps/my-app --source=packages/my-app`\n- Libraries → follow the dest's existing convention (`packages/`, `libs/`, etc.).\n\n## Common Issues\n\n### pnpm Workspace Globs (Critical)\n\n`nx import` adds the imported directory itself (e.g. `apps`) to `pnpm-workspace.yaml`, **NOT** glob patterns for packages within it. Cross-package imports will fail with `Cannot find module`.\n\n**Fix**: Replace with proper globs from the source config (e.g. `apps/*`, `libs/shared/*`), then `pnpm install`.\n\n### Root Dependencies and Config Not Imported (Critical)\n\n`nx import` does **NOT** merge from the source's root:\n\n- `dependencies`/`devDependencies` from `package.json`\n- `targetDefaults` from `nx.json` (e.g. `\"@nx/esbuild:esbuild\": { \"dependsOn\": [\"^build\"] }` — critical for build ordering)\n- `namedInputs` from `nx.json` (e.g. `production` exclusion patterns for test files)\n- Plugin configurations from `nx.json`\n\n**Fix**: Diff source and dest `package.json` + `nx.json`. Add missing deps, merge relevant `targetDefaults` and `namedInputs`.\n\n### TypeScript Project References\n\nAfter import, run `nx sync --yes`. If it reports nothing but typecheck still fails, `nx reset` first, then `nx sync --yes` again.\n\n### Explicit Executor Path Fixups\n\nInferred targets (via Nx plugins) resolve config relative to project root — no changes needed. Explicit executor targets (e.g. `@nx/esbuild:esbuild`) have workspace-root-relative paths (`main`, `outputPath`, `tsConfig`, `assets`, `sourceRoot`) that must be prefixed with the import destination directory.\n\n### Plugin Detection\n\n- **Whole-repo import**: `nx import` detects and offers to install plugins. Accept them.\n- **Subdirectory import**: Plugins NOT auto-detected. Manually add with `npx nx add @nx/PLUGIN`. Check `include`/`exclude` patterns — defaults won't match alternate directories (e.g. `apps-beta/`).\n- Run `npx nx reset` after any plugin config changes.\n\n### Redundant Root Files (Whole-Repo Only)\n\nWhole-repo import brings ALL source root files into the dest subdirectory. Clean up:\n\n- `pnpm-lock.yaml` — stale; dest has its own lockfile\n- `pnpm-workspace.yaml` — source workspace config; conflicts with dest\n- `node_modules/` — stale symlinks pointing to source filesystem\n- `.gitignore` — redundant with dest root `.gitignore`\n- `nx.json` — source Nx config; dest has its own\n- `README.md` — optional; keep or remove\n\n**Don't blindly delete** `tsconfig.base.json` — imported projects may extend it via relative paths.\n\n### Root ESLint Config Missing (Subdirectory Import)\n\nSubdirectory import doesn't bring the source's root `eslint.config.mjs`, but project configs reference `../../eslint.config.mjs`.\n\n**Fix order**:\n\n1. Install ESLint deps first: `pnpm add -wD eslint@^9 @nx/eslint-plugin typescript-eslint` (plus framework-specific plugins)\n2. Create root `eslint.config.mjs` (copy from source or create with `@nx/eslint-plugin` base rules)\n3. Then `npx nx add @nx/eslint` to register the plugin in `nx.json`\n\nInstall `typescript-eslint` explicitly — pnpm's strict hoisting won't auto-resolve this transitive dep of `@nx/eslint-plugin`.\n\n### ESLint Version Pinning (Critical)\n\n**Pin ESLint to v9** (`eslint@^9.0.0`). ESLint 10 breaks `@nx/eslint` and many plugins with cryptic errors like `Cannot read properties of undefined (reading 'version')`.\n\n`@nx/eslint` may peer-depend on ESLint 8, causing the wrong version to resolve. If lint fails with `Cannot read properties of undefined (reading 'allow')`, add `pnpm.overrides`:\n\n```json\n{ \"pnpm\": { \"overrides\": { \"eslint\": \"^9.0.0\" } } }\n```\n\n### Dependency Version Conflicts\n\nAfter import, compare key deps (`typescript`, `eslint`, framework-specific). If dest uses newer versions, upgrade imported packages to match (usually safe). If source is newer, may need to upgrade dest first. Use `pnpm.overrides` to enforce single-version policy if desired.\n\n### Module Boundaries\n\nImported projects may lack `tags`. Add tags or update `@nx/enforce-module-boundaries` rules.\n\n### Project Name Collisions (Multi-Import)\n\nSame `name` in `package.json` across source and dest causes `MultipleProjectsWithSameNameError`. **Fix**: Rename conflicting names (e.g. `@org/api` → `@org/teama-api`), update all dep references and import statements, `pnpm install`. The root `package.json` of each imported repo also becomes a project — rename those too.\n\n### Workspace Dep Import Ordering\n\n`pnpm install` fails during `nx import` if a `\"workspace:*\"` dependency hasn't been imported yet. File operations still succeed. **Fix**: Import all projects first, then `pnpm install --no-frozen-lockfile`.\n\n### `.gitkeep` Blocking Subdirectory Import\n\nThe TS preset creates `packages/.gitkeep`. Remove it and commit before importing.\n\n### Frontend tsconfig Base Settings (Critical)\n\nThe TS preset defaults (`module: \"nodenext\"`, `moduleResolution: \"nodenext\"`, `lib: [\"es2022\"]`) are incompatible with frontend frameworks (React, Next.js, Vue, Vite). After importing frontend projects, verify the dest root `tsconfig.base.json`:\n\n- **`moduleResolution`**: Must be `\"bundler\"` (not `\"nodenext\"`)\n- **`module`**: Must be `\"esnext\"` (not `\"nodenext\"`)\n- **`lib`**: Must include `\"dom\"` and `\"dom.iterable\"` (frontend projects need these)\n- **`jsx`**: `\"react-jsx\"` for React-only workspaces, per-project for mixed frameworks\n\nFor **subdirectory imports**, the dest root tsconfig is authoritative — update it. For **whole-repo imports**, imported projects may extend their own nested `tsconfig.base.json`, making this less critical.\n\nIf the dest also has backend projects needing `nodenext`, use per-project overrides instead of changing the root.\n\n**Gotcha**: TypeScript does NOT merge `lib` arrays — a project-level override **replaces** the base array entirely. Always include all needed entries (e.g. `es2022`, `dom`, `dom.iterable`) in any project-level `lib`.\n\n### `@nx/react` Typings for Libraries\n\nReact libraries generated with `@nx/react:library` reference `@nx/react/typings/cssmodule.d.ts` and `@nx/react/typings/image.d.ts` in their tsconfig `types`. These fail with `Cannot find type definition file` unless `@nx/react` is installed in the dest workspace.\n\n**Fix**: `pnpm add -wD @nx/react`\n\n### Jest Preset Missing (Subdirectory Import)\n\nNx presets create `jest.preset.js` at the workspace root, and project jest configs reference it (e.g. `../../jest.preset.js`). Subdirectory import does NOT bring this file.\n\n**Fix**:\n\n1. Run `npx nx add @nx/jest` — registers `@nx/jest/plugin` in `nx.json` and updates `namedInputs`\n2. Create `jest.preset.js` at workspace root (see `references/JEST.md` for content) — `nx add` only creates this when a generator runs, not on bare `nx add`\n3. Install test runner deps: `pnpm add -wD jest jest-environment-jsdom ts-jest @types/jest`\n4. Install framework-specific test deps as needed (see `references/JEST.md`)\n\nFor deeper Jest issues (tsconfig.spec.json, Babel transforms, CI atomization, Jest vs Vitest coexistence), see `references/JEST.md`.\n\n### Target Name Prefixing (Whole-Repo Import)\n\nWhen importing a project with existing npm scripts (`build`, `dev`, `start`, `lint`), Nx plugins auto-prefix inferred target names to avoid conflicts: e.g. `next:build`, `vite:build`, `eslint:lint`.\n\n**Fix**: Remove the Nx-rewritten npm scripts from the imported `package.json`, then either:\n\n- Accept the prefixed names (e.g. `nx run app:next:build`)\n- Rename plugin target names in `nx.json` to use unprefixed names\n\n## Non-Nx Source Issues\n\nWhen the source is a plain pnpm/npm workspace without `nx.json`.\n\n### npm Script Rewriting (Critical)\n\nNx rewrites `package.json` scripts during init, creating broken commands (e.g. `vitest run` → `nx test run`). **Fix**: Remove all rewritten scripts — Nx plugins infer targets from config files.\n\n### `noEmit` → `composite` + `emitDeclarationOnly` (Critical)\n\nPlain TS projects use `\"noEmit\": true`, incompatible with Nx project references.\n\n**Symptoms**: \"typecheck target is disabled because one or more project references set 'noEmit: true'\" or TS6310.\n\n**Fix** in **all** imported tsconfigs:\n\n1. Remove `\"noEmit\": true`. If inherited via extends chain, set `\"noEmit\": false` explicitly.\n2. Add `\"composite\": true`, `\"emitDeclarationOnly\": true`, `\"declarationMap\": true`\n3. Add `\"outDir\": \"dist\"` and `\"tsBuildInfoFile\": \"dist/tsconfig.tsbuildinfo\"`\n4. Add `\"extends\": \"../../tsconfig.base.json\"` if missing. Remove settings now inherited from base.\n\n### Stale node_modules and Lockfiles\n\n`nx import` may bring `node_modules/` (pnpm symlinks pointing to the source filesystem) and `pnpm-lock.yaml` from the source. Both are stale.\n\n**Fix**: `rm -rf imported/node_modules imported/pnpm-lock.yaml imported/pnpm-workspace.yaml imported/.gitignore`, then `pnpm install`.\n\n### ESLint Config Handling\n\n- **Legacy `.eslintrc.json` (ESLint 8)**: Delete all `.eslintrc.*`, remove v8 deps, create flat `eslint.config.mjs`.\n- **Flat config (`eslint.config.js`)**: Self-contained configs can often be left as-is.\n- **No ESLint**: Create both root and project-level configs from scratch.\n\n### TypeScript `paths` Aliases\n\nNx uses `package.json` `\"exports\"` + pnpm workspace linking instead of tsconfig `\"paths\"`. If packages have proper `\"exports\"`, paths are redundant. Otherwise, update paths for the new directory structure.\n\n## Technology-specific Guidance\n\nIdentify technologies in the source repo, then read and apply the matching reference file(s).\n\nAvailable references:\n\n- `references/ESLINT.md` — ESLint projects: duplicate `lint`/`eslint:lint` targets, legacy `.eslintrc.*` linting generated files, flat config `.cjs` self-linting, `typescript-eslint` v7/v9 peer dep conflict, mixed ESLint v8+v9 in one workspace.\n- `references/GRADLE.md`\n- `references/JEST.md` — Jest testing: `@nx/jest/plugin` setup, jest.preset.js, testing deps by framework, tsconfig.spec.json, Jest vs Vitest coexistence, Babel transforms, CI atomization.\n- `references/NEXT.md` — Next.js projects: `@nx/next/plugin` targets, `withNx`, Next.js TS config (`noEmit`, `jsx: \"preserve\"`), auto-installing deps via wrong PM, non-Nx `create-next-app` imports, mixed Next.js+Vite coexistence.\n- `references/TURBOREPO.md`\n- `references/VITE.md` — Vite projects (React, Vue, or both): `@nx/vite/plugin` typecheck target, `resolve.alias`/`__dirname` fixes, framework deps, Vue-specific setup, mixed React+Vue coexistence.\n","frontmatter":{"name":"nx-import","description":"Import, merge, or combine repositories into an Nx workspace using nx import. USE WHEN the user asks to adopt Nx across repos, move projects into a monorepo, or bring code/history from another repository."},"isInternal":false,"tokens":3470,"sizeBytes":13914},{"name":"SKILL.md","path":".agents/skills/nx-plugins/SKILL.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/.agents/skills/nx-plugins/SKILL.md","title":"nx-plugins","category":"anthropic-skill","format":"markdown","content":"---\nname: nx-plugins\ndescription: Find and add Nx plugins. USE WHEN user wants to discover available plugins, install a new plugin, or add support for a specific framework or technology to the workspace.\n---\n\n## Finding and Installing new plugins\n\n- List plugins: `pnpm nx list`\n- Install plugins `pnpm nx add <plugin>`. Example: `pnpm nx add @nx/react`.\n","frontmatter":{"name":"nx-plugins","description":"Find and add Nx plugins. USE WHEN user wants to discover available plugins, install a new plugin, or add support for a specific framework or technology to the workspace."},"isInternal":false,"tokens":82,"sizeBytes":355},{"name":"SKILL.md","path":".agents/skills/nx-run-tasks/SKILL.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/.agents/skills/nx-run-tasks/SKILL.md","title":"nx-run-tasks","category":"anthropic-skill","format":"markdown","content":"---\nname: nx-run-tasks\ndescription: Helps with running tasks in an Nx workspace. USE WHEN the user wants to execute build, test, lint, serve, or run any other tasks defined in the workspace.\n---\n\nYou can run tasks with Nx in the following way.\n\nKeep in mind that you might have to prefix things with npx/pnpx/yarn if the user doesn't have nx installed globally. Look at the package.json or lockfile to determine which package manager is in use.\n\nFor more details on any command, run it with `--help` (e.g. `nx run-many --help`, `nx affected --help`).\n\n## Understand which tasks can be run\n\nYou can check those via `nx show project <projectname> --json`, for example `nx show project myapp --json`. It contains a `targets` section which has information about targets that can be run. You can also just look at the `package.json` scripts or `project.json` targets, but you might miss out on inferred tasks by Nx plugins.\n\n## Run a single task\n\n```\nnx run <project>:<task>\n```\n\nwhere `project` is the project name defined in `package.json` or `project.json` (if present).\n\n## Run multiple tasks\n\n```\nnx run-many -t build test lint typecheck\n```\n\nYou can pass a `-p` flag to filter to specific projects, otherwise it runs on all projects. You can also use `--exclude` to exclude projects, and `--parallel` to control the number of parallel processes (default is 3).\n\nExamples:\n\n- `nx run-many -t test -p proj1 proj2` — test specific projects\n- `nx run-many -t test --projects=*-app --exclude=excluded-app` — test projects matching a pattern\n- `nx run-many -t test --projects=tag:api-*` — test projects by tag\n\n## Run tasks for affected projects\n\nUse `nx affected` to only run tasks on projects that have been changed and projects that depend on changed projects. This is especially useful in CI and for large workspaces.\n\n```\nnx affected -t build test lint\n```\n\nBy default it compares against the base branch. You can customize this:\n\n- `nx affected -t test --base=main --head=HEAD` — compare against a specific base and head\n- `nx affected -t test --files=libs/mylib/src/index.ts` — specify changed files directly\n\n## Useful flags\n\nThese flags work with `run`, `run-many`, and `affected`:\n\n- `--skipNxCache` — rerun tasks even when results are cached\n- `--verbose` — print additional information such as stack traces\n- `--nxBail` — stop execution after the first failed task\n- `--configuration=<name>` — use a specific configuration (e.g. `production`)\n","frontmatter":{"name":"nx-run-tasks","description":"Helps with running tasks in an Nx workspace. USE WHEN the user wants to execute build, test, lint, serve, or run any other tasks defined in the workspace."},"isInternal":false,"tokens":601,"sizeBytes":2468},{"name":"AFFECTED.md","path":".agents/skills/nx-workspace/references/AFFECTED.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/.agents/skills/nx-workspace/references/AFFECTED.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"## Affected Projects\n\nFind projects affected by changes in the current branch.\n\n```bash\n# Affected since base branch (auto-detected)\nnx show projects --affected\n\n# Affected with explicit base\nnx show projects --affected --base=main\nnx show projects --affected --base=origin/main\n\n# Affected between two commits\nnx show projects --affected --base=abc123 --head=def456\n\n# Affected apps only\nnx show projects --affected --type app\n\n# Affected excluding e2e projects\nnx show projects --affected --exclude=\"*-e2e\"\n\n# Affected by uncommitted changes\nnx show projects --affected --uncommitted\n\n# Affected by untracked files\nnx show projects --affected --untracked\n```\n","isInternal":false,"tokens":159,"sizeBytes":661},{"name":"SKILL.md","path":".agents/skills/nx-workspace/SKILL.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/.agents/skills/nx-workspace/SKILL.md","title":"nx-workspace","category":"anthropic-skill","format":"markdown","content":"---\nname: nx-workspace\ndescription: \"Explore and understand Nx workspaces. USE WHEN answering questions about the workspace, projects, or tasks. ALSO USE WHEN an nx command fails or you need to check available targets/configuration before running a task. EXAMPLES: 'What projects are in this workspace?', 'How is project X configured?', 'What depends on library Y?', 'What targets can I run?', 'Cannot find configuration for task', 'debug nx task failure'.\"\n---\n\n# Nx Workspace Exploration\n\nThis skill provides read-only exploration of Nx workspaces. Use it to understand workspace structure, project configuration, available targets, and dependencies.\n\nKeep in mind that you might have to prefix commands with `npx`/`pnpx`/`yarn` if nx isn't installed globally. Check the lockfile to determine the package manager in use.\n\n## Listing Projects\n\nUse `nx show projects` to list projects in the workspace.\n\nThe project filtering syntax (`-p`/`--projects`) works across many Nx commands including `nx run-many`, `nx release`, `nx show projects`, and more. Filters support explicit names, glob patterns, tag references (e.g. `tag:name`), directories, and negation (e.g. `!project-name`).\n\n```bash\n# List all projects\nnx show projects\n\n# Filter by pattern (glob)\nnx show projects --projects \"apps/*\"\nnx show projects --projects \"shared-*\"\n\n# Filter by tag\nnx show projects --projects \"tag:publishable\"\nnx show projects -p 'tag:publishable,!tag:internal'\n\n# Filter by target (projects that have a specific target)\nnx show projects --withTarget build\n\n# Combine filters\nnx show projects --type lib --withTarget test\nnx show projects --affected --exclude=\"*-e2e\"\nnx show projects -p \"tag:scope:client,packages/*\"\n\n# Negate patterns\nnx show projects -p '!tag:private'\nnx show projects -p '!*-e2e'\n\n# Output as JSON\nnx show projects --json\n```\n\n## Project Configuration\n\nUse `nx show project <name> --json` to get the full resolved configuration for a project.\n\n**Important**: Do NOT read `project.json` directly - it only contains partial configuration. The `nx show project --json` command returns the full resolved config including inferred targets from plugins.\n\nYou can read the full project schema at `node_modules/nx/schemas/project-schema.json` to understand nx project configuration options.\n\n```bash\n# Get full project configuration\nnx show project my-app --json\n\n# Extract specific parts from the JSON\nnx show project my-app --json | jq '.targets'\nnx show project my-app --json | jq '.targets.build'\nnx show project my-app --json | jq '.targets | keys'\n\n# Check project metadata\nnx show project my-app --json | jq '{name, root, sourceRoot, projectType, tags}'\n```\n\n## Target Information\n\nTargets define what tasks can be run on a project.\n\n```bash\n# List all targets for a project\nnx show project my-app --json | jq '.targets | keys'\n\n# Get full target configuration\nnx show project my-app --json | jq '.targets.build'\n\n# Check target executor/command\nnx show project my-app --json | jq '.targets.build.executor'\nnx show project my-app --json | jq '.targets.build.command'\n\n# View target options\nnx show project my-app --json | jq '.targets.build.options'\n\n# Check target inputs/outputs (for caching)\nnx show project my-app --json | jq '.targets.build.inputs'\nnx show project my-app --json | jq '.targets.build.outputs'\n\n# Find projects with a specific target\nnx show projects --withTarget serve\nnx show projects --withTarget e2e\n```\n\n## Workspace Configuration\n\nRead `nx.json` directly for workspace-level configuration.\nYou can read the full project schema at `node_modules/nx/schemas/nx-schema.json` to understand nx project configuration options.\n\n```bash\n# Read the full nx.json\ncat nx.json\n\n# Or use jq for specific sections\ncat nx.json | jq '.targetDefaults'\ncat nx.json | jq '.namedInputs'\ncat nx.json | jq '.plugins'\ncat nx.json | jq '.generators'\n```\n\nKey nx.json sections:\n\n- `targetDefaults` - Default configuration applied to all targets of a given name\n- `namedInputs` - Reusable input definitions for caching\n- `plugins` - Nx plugins and their configuration\n- ...and much more, read the schema or nx.json for details\n\n## Affected Projects\n\nIf the user is asking about affected projects, read the [affected projects reference](references/AFFECTED.md) for detailed commands and examples.\n\n## Common Exploration Patterns\n\n### \"What's in this workspace?\"\n\n```bash\nnx show projects\nnx show projects --type app\nnx show projects --type lib\n```\n\n### \"How do I build/test/lint project X?\"\n\n```bash\nnx show project X --json | jq '.targets | keys'\nnx show project X --json | jq '.targets.build'\n```\n\n### \"What depends on library Y?\"\n\n```bash\n# Use the project graph to find dependents\nnx graph --print | jq '.graph.dependencies | to_entries[] | select(.value[].target == \"Y\") | .key'\n```\n\n## Programmatic Answers\n\nWhen processing nx CLI results, use command-line tools to compute the answer programmatically rather than counting or parsing output manually. Always use `--json` flags to get structured output that can be processed with `jq`, `grep`, or other tools you have installed locally.\n\n### Listing Projects\n\n```bash\nnx show projects --json\n```\n\nExample output:\n\n```json\n[\"my-app\", \"my-app-e2e\", \"shared-ui\", \"shared-utils\", \"api\"]\n```\n\nCommon operations:\n\n```bash\n# Count projects\nnx show projects --json | jq 'length'\n\n# Filter by pattern\nnx show projects --json | jq '.[] | select(startswith(\"shared-\"))'\n\n# Get affected projects as array\nnx show projects --affected --json | jq '.'\n```\n\n### Project Details\n\n```bash\nnx show project my-app --json\n```\n\nExample output:\n\n```json\n{\n  \"root\": \"apps/my-app\",\n  \"name\": \"my-app\",\n  \"sourceRoot\": \"apps/my-app/src\",\n  \"projectType\": \"application\",\n  \"tags\": [\"type:app\", \"scope:client\"],\n  \"targets\": {\n    \"build\": {\n      \"executor\": \"@nx/vite:build\",\n      \"options\": { \"outputPath\": \"dist/apps/my-app\" }\n    },\n    \"serve\": {\n      \"executor\": \"@nx/vite:dev-server\",\n      \"options\": { \"buildTarget\": \"my-app:build\" }\n    },\n    \"test\": {\n      \"executor\": \"@nx/vite:test\",\n      \"options\": {}\n    }\n  },\n  \"implicitDependencies\": []\n}\n```\n\nCommon operations:\n\n```bash\n# Get target names\nnx show project my-app --json | jq '.targets | keys'\n\n# Get specific target config\nnx show project my-app --json | jq '.targets.build'\n\n# Get tags\nnx show project my-app --json | jq '.tags'\n\n# Get project root\nnx show project my-app --json | jq -r '.root'\n```\n\n### Project Graph\n\n```bash\nnx graph --print\n```\n\nExample output:\n\n```json\n{\n  \"graph\": {\n    \"nodes\": {\n      \"my-app\": {\n        \"name\": \"my-app\",\n        \"type\": \"app\",\n        \"data\": { \"root\": \"apps/my-app\", \"tags\": [\"type:app\"] }\n      },\n      \"shared-ui\": {\n        \"name\": \"shared-ui\",\n        \"type\": \"lib\",\n        \"data\": { \"root\": \"libs/shared-ui\", \"tags\": [\"type:ui\"] }\n      }\n    },\n    \"dependencies\": {\n      \"my-app\": [{ \"source\": \"my-app\", \"target\": \"shared-ui\", \"type\": \"static\" }],\n      \"shared-ui\": []\n    }\n  }\n}\n```\n\nCommon operations:\n\n```bash\n# Get all project names from graph\nnx graph --print | jq '.graph.nodes | keys'\n\n# Find dependencies of a project\nnx graph --print | jq '.graph.dependencies[\"my-app\"]'\n\n# Find projects that depend on a library\nnx graph --print | jq '.graph.dependencies | to_entries[] | select(.value[].target == \"shared-ui\") | .key'\n```\n\n## Troubleshooting\n\n### \"Cannot find configuration for task X:target\"\n\n```bash\n# Check what targets exist on the project\nnx show project X --json | jq '.targets | keys'\n\n# Check if any projects have that target\nnx show projects --withTarget target\n```\n\n### \"The workspace is out of sync\"\n\n```bash\nnx sync\nnx reset  # if sync doesn't fix stale cache\n```\n","frontmatter":{"name":"nx-workspace","description":"Explore and understand Nx workspaces. USE WHEN answering questions about the workspace, projects, or tasks. ALSO USE WHEN an nx command fails or you need to check available targets/configuration before running a task. EXAMPLES: 'What projects are in this workspace?', 'How is project X configured?', 'What depends on library Y?', 'What targets can I run?', 'Cannot find configuration for task', 'debug nx task failure'."},"isInternal":false,"tokens":1885,"sizeBytes":7653},{"name":"AGENTS.md","path":"packages/core/auth-js/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/auth-js/AGENTS.md","title":"Auth-js Skill","category":"anthropic-skill","format":"markdown","content":"# Agent instructions for `@supabase/auth-js`\n\nSupabase Auth client SDK for JavaScript. Handles sign-in, sign-up, sessions, OAuth, MFA, and related auth flows.\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n","isInternal":false,"tokens":223,"sizeBytes":904},{"name":"AGENTS.md","path":"packages/core/functions-js/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/functions-js/AGENTS.md","title":"Functions-js Skill","category":"anthropic-skill","format":"markdown","content":"# Agent instructions for `@supabase/functions-js`\n\nJavaScript SDK for invoking Supabase Edge Functions.\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n","isInternal":false,"tokens":205,"sizeBytes":849},{"name":"AGENTS.md","path":"packages/core/postgrest-js/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/postgrest-js/AGENTS.md","title":"Postgrest-js Skill","category":"anthropic-skill","format":"markdown","content":"# Agent instructions for `@supabase/postgrest-js`\n\nIsomorphic PostgREST client for database operations (select, insert, update, upsert, delete, filters, RPC).\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n","isInternal":false,"tokens":222,"sizeBytes":904},{"name":"AGENTS.md","path":"packages/core/realtime-js/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/realtime-js/AGENTS.md","title":"Realtime-js Skill","category":"anthropic-skill","format":"markdown","content":"# Agent instructions for `@supabase/realtime-js`\n\nListen to realtime updates from a Supabase PostgreSQL database. Handles channels, presence, broadcast, and Postgres CDC subscriptions.\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n","isInternal":false,"tokens":222,"sizeBytes":930},{"name":"AGENTS.md","path":"packages/core/storage-js/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/storage-js/AGENTS.md","title":"Storage-js Skill","category":"anthropic-skill","format":"markdown","content":"# Agent instructions for `@supabase/storage-js`\n\nIsomorphic storage client for Supabase. Handles bucket and object operations: upload, download, list, signed URLs, transformations.\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n","isInternal":false,"tokens":221,"sizeBytes":926},{"name":"AGENTS.md","path":"packages/core/supabase-js/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/supabase-js/AGENTS.md","title":"Supabase-js Skill","category":"anthropic-skill","format":"markdown","content":"# Agent instructions for `@supabase/supabase-js`\n\nMain isomorphic Supabase client for JavaScript. Aggregates `@supabase/auth-js`, `@supabase/postgrest-js`, `@supabase/realtime-js`, `@supabase/storage-js`, and `@supabase/functions-js` into one client.\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n","isInternal":false,"tokens":260,"sizeBytes":996},{"name":"mcp.json","path":".cursor/mcp.json","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/.cursor/mcp.json","title":"Model Context Protocol (MCP) Configuration","category":"mcp-config","format":"json","content":"{\n  \"mcpServers\": {}\n}\n","frontmatter":{"mcpServers":{}},"isInternal":false,"tokens":9,"sizeBytes":23},{"name":"README.md","path":"packages/core/auth-js/example/react/README.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/auth-js/example/react/README.md","title":"react Documentation","category":"plugin-manifest","format":"markdown","content":"# Supabase `auth-js` example\n\n- Created based on the [Quickstart example](https://supabase.com/docs/guides/auth/quickstarts/react) in the Supabase docs.\n- Bootstrapped with Vite CLI\n\n## Setup\n\n### With a Supabase project\n\n### 1. Create new project\n\nSign up to Supabase - [https://supabase.com/dashboard](https://supabase.com/dashboard) and create a new project. Wait for your database to start.\n\n### 2. Get the URL and Key\n\nCreate a copy of `.env.local.example`:\n\n```bash\ncp .env.local.example .env.local\n```\n\n1. Go to the Project Settings (the cog icon)\n2. Open the Data API tab, and find your API URL\n3. Open the API Keys tab and create a new Publishable key\n4. Set them both in your newly created `.env.local` file.O\n\n### 3. Enable Auth providers\n\n1. From the sidenav, go to Authentication -> Configuration -> Sign In/Providers (https://supabase.com/dashboard/project/<YOUR_PROJECT_ID>/auth/providers)\n2. Enable providers as needed (for this example: Anonymous, Email, Phone, GitHub, Google)\n\n## Run\n\n### Install root dependencies and build `auth-js`\n\n```bash\nnpm i\n```\n\n```bash\nnpx nx build auth-js\n```\n\n### Install the dependencies and run the example\n\n```bash\ncd example/react\n```\n\n```bash\nnpm i; npm run dev\n```\n","isInternal":false,"tokens":325,"sizeBytes":1219},{"name":"README.md","path":"packages/core/auth-js/migrations/README.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/auth-js/migrations/README.md","title":"migrations Documentation","category":"plugin-manifest","format":"markdown","content":"# Migration notes for `@supabase/auth-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/auth-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/auth-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/auth-js`:\n\n1. Read the migration files in `node_modules/@supabase/auth-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/auth-js` only.\n","isInternal":false,"tokens":333,"sizeBytes":1496},{"name":"README.md","path":"packages/core/auth-js/README.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/auth-js/README.md","title":"auth-js Documentation","category":"plugin-manifest","format":"markdown","content":"<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase Auth JS SDK</h1>\n\n  <h3 align=\"center\">An isomorphic JavaScript SDK for the <a href=\"https://github.com/supabase/auth\">Supabase Auth</a> API.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/auth\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript/auth-signup\">Reference Docs</a>\n    ·\n    <a href=\"https://supabase.github.io/supabase-js/auth-js/v2/spec.json\">TypeDoc</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/auth-js)](https://www.npmjs.com/package/@supabase/auth-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/auth-js)](https://pkg.pr.new/~/supabase/auth-js)\n\n</div>\n\n## Requirements\n\n- **Node.js 22 or later** (Node.js 20 support dropped in v2.110.0)\n- For browser support, all modern browsers are supported\n\n> ⚠️ **Node.js 18 Deprecation Notice**\n>\n> Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped on October 31, 2025.\n\n> ⚠️ **Node.js 20 Deprecation Notice**\n>\n> Node.js 20 reached end-of-life on April 30, 2026. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/45715), support for Node.js 20 was dropped in v2.110.0.\n\n## Quick start\n\nInstall\n\n```bash\nnpm install --save @supabase/auth-js\n```\n\nUsage\n\n```js\nimport { AuthClient } from '@supabase/auth-js'\n\nconst GOTRUE_URL = 'http://localhost:9999'\n\nconst auth = new AuthClient({ url: GOTRUE_URL })\n```\n\n- `signUp()`: https://supabase.com/docs/reference/javascript/auth-signup\n- `signIn()`: https://supabase.com/docs/reference/javascript/auth-signin\n- `signOut()`: https://supabase.com/docs/reference/javascript/auth-signout\n\n### Custom `fetch` implementation\n\n`auth-js` uses the runtime's global `fetch` to make HTTP requests, but an alternative `fetch` implementation can be provided as an option. This is useful in environments where the global `fetch` is unavailable or where you want to customize request behavior:\n\n```js\nimport { AuthClient } from '@supabase/auth-js'\n\nconst AUTH_URL = 'http://localhost:9999'\n\nconst auth = new AuthClient({ url: AUTH_URL, fetch: fetch })\n```\n\n## Development\n\nThis package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:\n\n### Building\n\n```bash\n# Complete build (from monorepo root)\npnpm nx build auth-js\n\n# Build with watch mode for development\npnpm nx build auth-js --watch\n\n# Individual build targets\npnpm nx build:main auth-js    # CommonJS build (dist/main/)\npnpm nx build:module auth-js  # ES Modules build (dist/module/)\n\n# Other useful commands\npnpm nx lint auth-js          # Run ESLint\npnpm nx typecheck auth-js     # TypeScript type checking\npnpm nx docs auth-js          # Generate documentation\n```\n\n#### Build Outputs\n\n- **CommonJS (`dist/main/`)** - For Node.js environments\n- **ES Modules (`dist/module/`)** - For modern bundlers (Webpack, Vite, Rollup)\n- **TypeScript definitions (`dist/module/index.d.ts`)** - Type definitions for TypeScript projects\n\n### Testing\n\nThe auth-js package has two test suites:\n\n1. **CLI Tests** - Main test suite using Supabase CLI (331 tests)\n2. **Docker Tests** - Edge case tests requiring specific GoTrue configurations (11 tests)\n\n#### Prerequisites\n\n- **Supabase CLI** - Required for main test suite ([installation guide](https://supabase.com/docs/guides/cli))\n- **Docker** - Required for edge case tests\n\n#### Running Tests\n\n```bash\n# Run main test suite with Supabase CLI (recommended)\npnpm nx test:auth auth-js\n\n# Run Docker-only edge case tests\npnpm nx test:docker auth-js\n\n# Run both test suites\npnpm nx test:auth auth-js && pnpm nx test:docker auth-js\n```\n\n#### Main Test Suite (Supabase CLI)\n\nThe `test:auth` command automatically:\n\n1. Stops any existing Supabase instance\n2. Starts a local Supabase instance via CLI\n3. Runs the test suite (excludes `docker-tests/` folder)\n4. Cleans up after tests complete\n\n```bash\n# Individual commands for manual control\npnpm nx test:infra auth-js    # Start Supabase CLI\npnpm nx test:suite auth-js    # Run tests only\npnpm nx test:clean-post auth-js  # Stop Supabase CLI\n```\n\n#### Docker Tests (Edge Cases)\n\nThe `test:docker` target runs tests that require specific GoTrue configurations not possible with a single Supabase CLI instance:\n\n- **Signup disabled** - Tests for disabled signup functionality\n- **Asymmetric JWT (RS256)** - Tests for RS256 JWT verification\n- **Phone OTP / SMS** - Tests requiring Twilio SMS provider\n- **Anonymous sign-in disabled** - Tests for disabled anonymous auth\n\nThese tests are located in `test/docker-tests/` and use the Docker Compose setup in `infra/docker-compose.yml`.\n\n```bash\n# Individual commands for manual control\npnpm nx test:docker:infra auth-js    # Start Docker containers\npnpm nx test:docker:suite auth-js    # Run Docker tests only\npnpm nx test:docker:clean-post auth-js  # Stop Docker containers\n```\n\n#### Development Testing\n\nFor actively developing and debugging tests:\n\n```bash\n# Start Supabase CLI once\npnpm nx test:infra auth-js\n\n# Run tests multiple times (faster since instance stays up)\npnpm nx test:suite auth-js\n\n# Clean up when done\npnpm nx test:clean-post auth-js\n```\n\n#### Test Infrastructure\n\n| Suite        | Infrastructure | Configuration               |\n| ------------ | -------------- | --------------------------- |\n| CLI Tests    | Supabase CLI   | `test/supabase/config.toml` |\n| Docker Tests | Docker Compose | `infra/docker-compose.yml`  |\n\n### Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n","isInternal":false,"tokens":1765,"sizeBytes":6690},{"name":"README.md","path":"packages/core/auth-js/test/README.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/auth-js/test/README.md","title":"test Documentation","category":"plugin-manifest","format":"markdown","content":"# Testing\n\n## Prerequisites\n\n- Docker & docker compose\n\n### Basic testing\n\nRun all tests:\n\n```sh\nnpm run test\n```\n\n> Note: If tests fail due to connection issues, your tests may be running too soon and the infra is not yet ready.\n> If that's the case, adjust the `sleep 10` duration in:\n> `\"test:infra\": \"cd infra && docker-compose down && docker-compose pull && docker-compose up -d && sleep 10\",`\n> to a value that works for your system setup.\n\n### Advanced\n\n**Start all the infrastructure:**\n\n```sh\nnpm run test:infra\n```\n\nYou can now open the mock mail server on `http://localhost:9000`\n\n**Run the tests only:**\n\n```sh\nnpm run test:suite\n```\n\nAll emails will appear in the mock mail server.\n\n## Passkey (WebAuthn) Tests\n\nPasskey coverage is split across two files:\n\n- `passkey.methods.test.ts` — unit tests for all `auth.passkey.*`, `signInWithPasskey()`,\n  `registerPasskey()` and `admin.passkey.*` methods with mocked `fetch` and a simulated\n  browser environment (no infra needed)\n- `passkey.e2e.test.ts` — full registration/authentication ceremonies against the\n  Supabase CLI Auth server\n\nThe e2e tests rely on:\n\n- `[auth.passkey]` and `[auth.webauthn]` in `test/supabase/config.toml` (requires\n  Supabase CLI >= 2.105.0)\n- `test/lib/software-authenticator.ts`, a minimal software WebAuthn authenticator\n  (ES256, \"none\" attestation, discoverable credentials) that stands in for\n  `navigator.credentials` since the tests run in Node\n\n## RSA Signing Keys\n\n### Security Model\n\nThe auth-js tests require RSA signing keys to verify RS256 JWT tokens. **These keys are NEVER committed to the repository** for security reasons.\n\n### Key Generation\n\nKeys are automatically generated before tests run:\n\n- **Locally**: `nx test:auth auth-js` or `nx test:docker auth-js` automatically generates keys via the `test:generate-keys` target\n- **CI**: GitHub Actions generates fresh keys before each test run\n\n### Manual Key Generation\n\nIf you need to generate keys manually:\n\n```bash\ncd packages/core/auth-js/test\nnode generate-signing-keys.js\n```\n\nThis creates `test/supabase/signing_keys.json` (gitignored).\n\n### JWT Token Generation\n\nJWT tokens (anon, service_role, admin) are **automatically generated** at runtime from the signing keys in `test/lib/clients.ts`. No manual updates needed!\n\nFor debugging/inspection only:\n\n```bash\ncd packages/core/auth-js/test\nnode generate-jwt.js\n```\n\nThis displays the tokens but you don't need to copy them anywhere - they're generated automatically.\n\n## Important Notes\n\n⚠️ **NEVER commit `signing_keys.json`** - It's in `.gitignore` for security\n\n⚠️ **These are TEST KEYS only** - Never use in production\n\n✅ **Fresh keys per test run** - CI generates new keys every time for maximum security\n","isInternal":false,"tokens":680,"sizeBytes":2741},{"name":"README.md","path":"packages/core/functions-js/migrations/README.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/functions-js/migrations/README.md","title":"migrations Documentation","category":"plugin-manifest","format":"markdown","content":"# Migration notes for `@supabase/functions-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/functions-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/functions-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/functions-js`:\n\n1. Read the migration files in `node_modules/@supabase/functions-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/functions-js` only.\n","isInternal":false,"tokens":333,"sizeBytes":1526},{"name":"README.md","path":"packages/core/functions-js/README.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/functions-js/README.md","title":"functions-js Documentation","category":"plugin-manifest","format":"markdown","content":"<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase Functions JS SDK</h1>\n\n  <h3 align=\"center\">JavaScript SDK to interact with Supabase Edge Functions.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/functions\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript/functions-invoke\">Reference Docs</a>\n    ·\n    <a href=\"https://supabase.github.io/supabase-js/functions-js/v2/spec.json\">TypeDoc</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/functions-js)](https://www.npmjs.com/package/@supabase/functions-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/functions-js)](https://pkg.pr.new/~/supabase/functions-js)\n\n</div>\n\n## Requirements\n\n- **Node.js 22 or later** (Node.js 20 support dropped in v2.110.0)\n- For browser support, all modern browsers are supported\n\n> ⚠️ **Node.js 18 Deprecation Notice**\n>\n> Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped on October 31, 2025.\n\n> ⚠️ **Node.js 20 Deprecation Notice**\n>\n> Node.js 20 reached end-of-life on April 30, 2026. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/45715), support for Node.js 20 was dropped in v2.110.0.\n\n## Quick Start\n\n### Installation\n\n```bash\nnpm install @supabase/functions-js\n```\n\n### Usage\n\n```js\nimport { FunctionsClient } from '@supabase/functions-js'\n\nconst functionsUrl = 'https://<project_ref>.supabase.co/functions/v1'\nconst publishableKey = '<publishable_key>'\n\nconst functions = new FunctionsClient(functionsUrl, {\n  headers: {\n    Authorization: `Bearer ${publishableKey}`,\n  },\n})\n\n// Invoke a function\nconst { data, error } = await functions.invoke('hello-world', {\n  body: { name: 'Functions' },\n})\n```\n\n## Development\n\nThis package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:\n\n### Building\n\n```bash\n# Complete build (from monorepo root)\npnpm nx build functions-js\n\n# Build with watch mode for development\npnpm nx build functions-js --watch\n\n# Individual build targets\npnpm nx build:main functions-js    # CommonJS build (dist/main/)\npnpm nx build:module functions-js  # ES Modules build (dist/module/)\n\n# Other useful commands\npnpm nx clean functions-js         # Clean build artifacts\npnpm nx typecheck functions-js     # TypeScript type checking\npnpm nx docs functions-js          # Generate documentation\n```\n\n#### Build Outputs\n\n- **CommonJS (`dist/main/`)** - For Node.js environments\n- **ES Modules (`dist/module/`)** - For modern bundlers (Webpack, Vite, Rollup)\n- **TypeScript definitions (`dist/module/index.d.ts`)** - Type definitions for TypeScript projects\n\n### Testing\n\n**Docker Required** for relay tests. The functions-js tests use testcontainers to spin up a Deno relay server for testing Edge Function invocations.\n\n```bash\n# Run all tests (from monorepo root)\npnpm nx test functions-js\n\n# Run tests with coverage report\npnpm nx test functions-js --coverage\n\n# Run tests in watch mode during development\npnpm nx test functions-js --watch\n\n# CI test command (runs with coverage)\npnpm nx test:ci functions-js\n```\n\n#### Test Requirements\n\n- **Node.js 22+** - Required for testcontainers\n- **Docker** - Must be installed and running for relay tests\n- No Supabase instance needed - Tests use mocked services and testcontainers\n\n#### What Gets Tested\n\n- **Function invocation** - Testing the `invoke()` method with various options\n- **Relay functionality** - Using a containerized Deno relay to test real Edge Function scenarios\n- **Error handling** - Ensuring proper error responses and retries\n- **Request/response models** - Validating headers, body, and response formats\n\n### Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n","isInternal":false,"tokens":1275,"sizeBytes":4909},{"name":"README.md","path":"packages/core/postgrest-js/migrations/README.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/postgrest-js/migrations/README.md","title":"migrations Documentation","category":"plugin-manifest","format":"markdown","content":"# Migration notes for `@supabase/postgrest-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/postgrest-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/postgrest-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/postgrest-js`:\n\n1. Read the migration files in `node_modules/@supabase/postgrest-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/postgrest-js` only.\n","isInternal":false,"tokens":345,"sizeBytes":1526},{"name":"README.md","path":"packages/core/postgrest-js/README.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/postgrest-js/README.md","title":"postgrest-js Documentation","category":"plugin-manifest","format":"markdown","content":"<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase PostgREST JS SDK</h1>\n\n  <h3 align=\"center\">Isomorphic JavaScript SDK for <a href=\"https://postgrest.org\">PostgREST</a> with an ORM-like interface.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/database\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript/select\">Reference Docs</a>\n    ·\n    <a href=\"https://supabase.github.io/supabase-js/postgrest-js/v2/spec.json\">TypeDoc</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/postgrest-js)](https://www.npmjs.com/package/@supabase/postgrest-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/postgrest-js)](https://pkg.pr.new/~/supabase/postgrest-js)\n\n</div>\n\n### Quick start\n\nInstall\n\n```bash\nnpm install @supabase/postgrest-js\n```\n\nUsage\n\n```js\nimport { PostgrestClient } from '@supabase/postgrest-js'\n\nconst REST_URL = 'http://localhost:3000'\nconst postgrest = new PostgrestClient(REST_URL)\n```\n\n- [select()](https://supabase.com/docs/reference/javascript/select)\n- [insert()](https://supabase.com/docs/reference/javascript/insert)\n- [update()](https://supabase.com/docs/reference/javascript/update)\n- [delete()](https://supabase.com/docs/reference/javascript/delete)\n\n#### Custom `fetch` implementation\n\n`postgrest-js` uses the runtime's global `fetch` to make HTTP requests, but an alternative `fetch` implementation can be provided as an option. This is useful in environments where the global `fetch` is unavailable or where you want to customize request behavior:\n\n```js\nimport { PostgrestClient } from '@supabase/postgrest-js'\n\nconst REST_URL = 'http://localhost:3000'\nconst postgrest = new PostgrestClient(REST_URL, {\n  fetch: (...args) => fetch(...args),\n})\n```\n\n## Development\n\nThis package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:\n\n### Building\n\n```bash\n# Build (from monorepo root)\npnpm nx build postgrest-js\n\n# Build with watch mode for development\npnpm nx build:watch postgrest-js\n\n# TypeScript type checking\npnpm nx type-check postgrest-js\n\n# Generate documentation\npnpm nx docs postgrest-js\n```\n\n### Testing\n\n**Supabase CLI Required!** The `postgrest-js` tests use the [Supabase CLI](https://supabase.com/docs/guides/local-development/cli/getting-started) to run a local PostgreSQL database and PostgREST server.\n\n#### Quick Start\n\n```bash\n# Run all tests (from monorepo root)\npnpm nx test:ci:postgrest postgrest-js\n```\n\nThis single command automatically:\n\n1. Stops any existing Supabase CLI containers\n2. Starts PostgreSQL database and PostgREST server via Supabase CLI\n3. Resets and seeds the database\n4. Runs all Jest unit tests with coverage\n5. Cleans up containers\n\n#### Individual Test Commands\n\n```bash\n# Run Jest tests with coverage (requires infrastructure running)\npnpm nx test:run postgrest-js\n\n# Run type tests with tstyche\npnpm nx test:types postgrest-js\n\n# Run smoke tests (CommonJS and ESM imports)\npnpm nx test:smoke postgrest-js\n\n# Format code\npnpm nx format postgrest-js\n\n# Check formatting\npnpm nx format:check postgrest-js\n```\n\n#### Test Infrastructure\n\nThe tests use Supabase CLI to spin up:\n\n- **PostgreSQL** - Database with test schema and seed data (port 54322)\n- **PostgREST** - REST API server that the client connects to (port 54321)\n\n```bash\n# Manually manage test infrastructure (from monorepo root)\npnpm nx test:infra postgrest-js      # Start containers\npnpm nx test:clean-pre postgrest-js  # Stop and remove containers\n```\n\nOr directly via Supabase CLI:\n\n```bash\ncd packages/core/postgrest-js\nnpx supabase --workdir ./test start        # Start all services\nnpx supabase --workdir ./test db reset     # Reset and seed database\nnpx supabase --workdir ./test stop         # Stop all services\n```\n\n#### Regenerating TypeScript Types\n\nWhen the database schema changes, regenerate TypeScript types from the actual database:\n\n```bash\n# From the monorepo root\npnpm run codegen:postgrest\n```\n\nThis command automatically:\n\n1. Cleans up any existing Supabase containers\n2. Starts Supabase (PostgreSQL, PostgREST, and all services)\n3. Generates TypeScript types from the database schema\n4. Post-processes the generated types (updates JSON type definitions)\n5. Formats the generated file with Prettier\n6. Cleans up Supabase containers\n\nThe generated types are written to `test/types.generated.ts`.\n\n#### Test Types Explained\n\n- **Unit Tests** - Jest tests covering all client functionality (`pnpm nx test:run postgrest-js`)\n- **Type Tests** - Validates TypeScript types using tstyche (`pnpm nx test:types postgrest-js`)\n- **Smoke Tests** - Basic import/require tests for CommonJS and ESM (`pnpm nx test:smoke postgrest-js`)\n\n#### Prerequisites\n\n- **Supabase CLI** must be installed ([instructions](https://supabase.com/docs/guides/local-development/cli/getting-started)) or can be used through `npx` (`npx supabase`)\n- **Docker** must be installed and running (Supabase CLI uses Docker under the hood)\n- **Port 54321** - PostgREST API\n- **Port 54322** - PostgreSQL database\n- **Port 54323** - Supabase Studio (used for type generation)\n\n#### PostgREST v12 Backward Compatibility Tests\n\nWe maintain backward compatibility tests for PostgREST v12 (the current Supabase CLI uses v14+). These tests ensure the SDK works correctly for users still running older PostgREST versions.\n\n```bash\n# Run v12 compatibility tests (requires Docker)\npnpm nx test:ci:v12 postgrest-js\n```\n\nThis command:\n\n1. Starts PostgREST v12 + PostgreSQL in Docker (ports 3012/5433)\n2. Runs runtime tests that verify v12-specific behavior\n3. Cleans up containers\n\n**Type-only tests** for v12 compatibility also run as part of the regular type tests:\n\n```bash\npnpm nx test:types postgrest-js  # Includes v12-compat.test-d.ts\n```\n\n**Note:** These v12 tests will be removed when v3 ships (sometime in 2026).\n\n### Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n\n## License\n\nThis repo is licensed under MIT License.\n","isInternal":false,"tokens":1860,"sizeBytes":7021},{"name":"README.md","path":"packages/core/realtime-js/example/README.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/realtime-js/example/README.md","title":"example Documentation","category":"plugin-manifest","format":"markdown","content":"# Realtime Chat Example\n\nA minimal anonymous chat app showcasing Supabase Realtime features:\n\n- **Broadcast** - Real-time message delivery\n- **Presence** - Online user indicators\n- **Database** - Message persistence\n\n## Features\n\n- Anonymous users with random usernames (stored in localStorage)\n- 4 chat rooms: General, Random, Tech, Off-Topic\n- Real-time messages\n- Online users per room\n- Message history on join\n\n## Setup\n\n### 1. Create a Supabase Project\n\nCreate a new project at [database.new](https://database.new)\n\n### 2. Run the Database Migration\n\nGo to the [SQL Editor](https://supabase.com/dashboard/project/_/sql) in your Supabase dashboard and run the migration you find in [supabase/migrations/001_create_messages_table.sql](./supabase/migrations/001_create_messages_table.sql).\n\n### 3. Configure Environment Variables\n\nCopy `.env.example` to `.env` and fill in your Supabase credentials:\n\n```bash\ncp .env.example .env\n```\n\nUpdate the values:\n\n```env\nNEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co\nNEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=your-publishable-key\n```\n\nFind these in your [Supabase project settings](https://supabase.com/dashboard/project/_/settings/api).\n\n### 4. Install Dependencies\n\n```bash\nnpm install\n```\n\n### 5. Run the App\n\n```bash\nnpm run dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000) to start chatting.\n\n## How It Works\n\n### Broadcast\n\nMessages are instantly delivered to all connected clients via Supabase Realtime Broadcast:\n\n```typescript\nchannel.send({\n  type: 'broadcast',\n  event: 'message',\n  payload: message,\n})\n```\n\n### Presence\n\nOnline users are tracked using Supabase Realtime Presence:\n\n```typescript\nchannel.on('presence', { event: 'sync' }, () => {\n  const users = Object.values(channel.presenceState()).flat()\n  setOnlineUsers(users)\n})\n```\n\n### Persistence\n\nMessages are also stored in the database so users see history when joining:\n\n```typescript\nconst { data } = await supabase\n  .from('messages')\n  .select('*')\n  .eq('room', room)\n  .order('created_at', { ascending: true })\n  .limit(50)\n```\n\n## Local Development\n\nYou can run Supabase locally using the Supabase CLI and Docker.\n\n### Prerequisites\n\n- [Docker](https://docs.docker.com/get-docker/) installed and running\n- [Supabase CLI](https://supabase.com/docs/guides/cli) (installed or used through `npx`)\n\n### 1. Start Supabase\n\n```bash\nnpx supabase start\n```\n\nThis will start all Supabase services locally. Once started, you'll see output with your local credentials:\n\n```\n╭──────────────────────────────────────╮\n│ 🔧 Development Tools                 │\n├─────────┬────────────────────────────┤\n│ Studio  │ http://127.0.0.1:54323     │\n│ ...     │ ...                        │\n╰─────────┴────────────────────────────╯\n\n╭──────────────────────────────────────────────╮\n│ 🌐 APIs                                      │\n├────────────────┬─────────────────────────────┤\n│ Project URL    │ http://127.0.0.1:54321      │\n│ ...            │ ...                         │\n╰────────────────┴─────────────────────────────╯\n...\n╭──────────────────────────────────────────────────╮\n│ 🔑 Authentication Keys                           │\n├─────────────┬────────────────────────────────────┤\n│ Publishable │ sb_publishable_...                 │\n│ Secret      │ sb_secret_...                      │\n╰─────────────┴────────────────────────────────────╯\n...\n```\n\n### 2. Configure Environment\n\nCopy `.env.example` to `.env.local`:\n\n```bash\ncp .env.example .env.local\n```\n\nUpdate the values:\n\n```env\nNEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321\nNEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_....\n```\n\n### 3. Run Migrations\n\nApply the database migration:\n\n```bash\nnpx supabase db reset\n```\n\nThis will apply all migrations from `supabase/migrations/`.\n\n### 5. Access Local Dashboard\n\nOpen [http://127.0.0.1:54323](http://127.0.0.1:54323) to access Supabase Studio locally. Here you can:\n\n- View and edit data in the Table Editor\n- Run SQL queries\n- Monitor Realtime connections\n- Check logs\n\n### Stopping Supabase\n\n```bash\nnpx supabase stop\n```\n","isInternal":false,"tokens":1062,"sizeBytes":4959},{"name":"README.md","path":"packages/core/realtime-js/migrations/README.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/realtime-js/migrations/README.md","title":"migrations Documentation","category":"plugin-manifest","format":"markdown","content":"# Migration notes for `@supabase/realtime-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/realtime-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/realtime-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/realtime-js`:\n\n1. Read the migration files in `node_modules/@supabase/realtime-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/realtime-js` only.\n","isInternal":false,"tokens":345,"sizeBytes":1520},{"name":"README.md","path":"packages/core/realtime-js/README.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/realtime-js/README.md","title":"realtime-js Documentation","category":"plugin-manifest","format":"markdown","content":"<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase Realtime JS SDK</h1>\n\n  <h3 align=\"center\">Send ephemeral messages with <b>Broadcast</b>, track and synchronize state with <b>Presence</b>, and listen to database changes with <b>Postgres Change Data Capture (CDC)</b>.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/realtime\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript\">Reference Docs</a>\n    ·\n    <a href=\"https://multiplayer.dev\">Multiplayer Demo</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/realtime-js)](https://www.npmjs.com/package/@supabase/realtime-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/realtime-js)](https://pkg.pr.new/~/supabase/realtime-js)\n\n</div>\n\n# Overview\n\nThis SDK enables you to use the following Supabase Realtime's features:\n\n- **Broadcast**: send ephemeral messages from client to clients with minimal latency. Use cases include sharing cursor positions between users.\n- **Presence**: track and synchronize shared state across clients with the help of CRDTs. Use cases include tracking which users are currently viewing a specific webpage.\n- **Postgres Change Data Capture (CDC)**: listen for changes in your PostgreSQL database and send them to clients.\n\n# Usage\n\n## Installing the Package\n\n```bash\nnpm install @supabase/realtime-js\n```\n\n## Creating a Channel\n\n```js\nimport { RealtimeClient } from '@supabase/realtime-js'\n\nconst client = new RealtimeClient(REALTIME_URL, {\n  params: {\n    apikey: API_KEY,\n  },\n})\n\nconst channel = client.channel('test-channel', {})\n\nchannel.subscribe((status, err) => {\n  if (status === 'SUBSCRIBED') {\n    console.log('Connected!')\n  }\n\n  if (status === 'CHANNEL_ERROR') {\n    console.log(`There was an error subscribing to channel: ${err.message}`)\n  }\n\n  if (status === 'TIMED_OUT') {\n    console.log('Realtime server did not respond in time.')\n  }\n\n  if (status === 'CLOSED') {\n    console.log('Realtime channel was unexpectedly closed.')\n  }\n})\n```\n\n### Notes:\n\n- `REALTIME_URL` is `'ws://localhost:4000/socket'` when developing locally and `'wss://<project_ref>.supabase.co/realtime/v1'` when connecting to your Supabase project.\n- `API_KEY` is a JWT whose claims must contain `exp` and `role` (existing database role).\n- Channel name can be any `string`.\n- Setting `private` to `true` means that the client will use RLS to determine if the user can connect or not to a given channel.\n\n## Broadcast\n\nYour client can send and receive messages based on the `event`.\n\n```js\n// Setup...\n\nconst channel = client.channel('broadcast-test', { broadcast: { ack: false, self: false } })\n\nchannel.on('broadcast', { event: 'some-event' }, (payload) => console.log(payload))\n\nchannel.subscribe(async (status) => {\n  if (status === 'SUBSCRIBED') {\n    // Send message to other clients listening to 'broadcast-test' channel\n    await channel.send({\n      type: 'broadcast',\n      event: 'some-event',\n      payload: { hello: 'world' },\n    })\n  }\n})\n```\n\n### Notes:\n\n- Setting `ack` to `true` means that the `channel.send` promise will resolve once server replies with acknowledgment that it received the broadcast message request.\n- Setting `self` to `true` means that the client will receive the broadcast message it sent out.\n\n### Broadcast Replay\n\nBroadcast Replay enables **private** channels to access messages that were sent earlier. Only messages published via [Broadcast From the Database](https://supabase.com/docs/guides/realtime/broadcast#trigger-broadcast-messages-from-your-database) are available for replay.\n\nYou can configure replay with the following options:\n\n- **`since`** (Required): The epoch timestamp in milliseconds, specifying the earliest point from which messages should be retrieved.\n- **`limit`** (Optional): The number of messages to return. This must be a positive integer, with a maximum value of 25.\n\nExample:\n\n```typescript\nconst twelveHours = 12 * 60 * 60 * 1000\nconst twelveHoursAgo = Date.now() - twelveHours\n\nconst config = { private: true, broadcast: { replay: { since: twelveHoursAgo, limit: 10 } } }\n\nsupabase\n  .channel('main:room', { config })\n  .on('broadcast', { event: 'my_event' }, (payload) => {\n    if (payload?.meta?.replayed) {\n      console.log('This message was sent earlier:', payload)\n    } else {\n      console.log('This is a new message', payload)\n    }\n    // ...\n  })\n  .subscribe()\n```\n\n## Presence\n\nYour client can track and sync state that's stored in the channel.\n\n```js\n// Setup...\n\nconst channel = client.channel('presence-test', {\n  config: {\n    presence: {\n      key: '',\n    },\n  },\n})\n\nchannel.on('presence', { event: 'sync' }, () => {\n  console.log('Online users: ', channel.presenceState())\n})\n\nchannel.on('presence', { event: 'join' }, ({ newPresences }) => {\n  console.log('New users have joined: ', newPresences)\n})\n\nchannel.on('presence', { event: 'leave' }, ({ leftPresences }) => {\n  console.log('Users have left: ', leftPresences)\n})\n\nchannel.subscribe(async (status) => {\n  if (status === 'SUBSCRIBED') {\n    const status = await channel.track({ user_id: 1 })\n    console.log(status)\n  }\n})\n```\n\n> `config.presence.enabled` (set automatically if you add an `.on('presence', ...)` listener)\n> controls whether _this_ client receives presence state and updates from other clients —\n> without it, `presenceState()` stays empty for you. It does not affect whether other clients\n> see you: calling `track()` always makes you visible to subscribers that do have presence\n> enabled. On RLS-protected channels, receiving presence updates additionally requires the\n> `presence.read` policy to authorize this client.\n\n## Postgres CDC\n\nReceive database changes on the client.\n\n```js\n// Setup...\n\nconst channel = client.channel('db-changes')\n\nchannel.on('postgres_changes', { event: '*', schema: 'public' }, (payload) => {\n  console.log('All changes in public schema: ', payload)\n})\n\nchannel.on(\n  'postgres_changes',\n  { event: 'INSERT', schema: 'public', table: 'messages' },\n  (payload) => {\n    console.log('All inserts in messages table: ', payload)\n  }\n)\n\nchannel.on(\n  'postgres_changes',\n  { event: 'UPDATE', schema: 'public', table: 'users', filter: 'username=eq.Realtime' },\n  (payload) => {\n    console.log('All updates on users table when username is Realtime: ', payload)\n  }\n)\n\nchannel.subscribe(async (status) => {\n  if (status === 'SUBSCRIBED') {\n    console.log('Ready to receive database changes!')\n  }\n})\n```\n\n### Filters\n\nThe `filter` option accepts **either** a raw string **or** a\n`postgresChangesFilter()` builder — both produce the exact same wire format, so\nyou can mix and match and existing string filters keep working unchanged:\n\n```js\n// Raw string — always supported, fully backward compatible\n{ event: 'UPDATE', schema: 'public', table: 'users', filter: 'id=eq.1' }\n\n// Builder — type-checked, ergonomic; the SDK serializes it for you\n{ event: 'UPDATE', schema: 'public', table: 'users', filter: postgresChangesFilter().eq('id', 1) }\n```\n\nA filter is a `column=operator.value` expression evaluated server-side. The\nfollowing operators are supported:\n\n| Operator              | String form                  | Builder                                | Meaning                           |\n| --------------------- | ---------------------------- | -------------------------------------- | --------------------------------- |\n| `eq`                  | `id=eq.1`                    | `.eq('id', 1)`                         | equal                             |\n| `neq`                 | `id=neq.1`                   | `.neq('id', 1)`                        | not equal                         |\n| `lt` `lte` `gt` `gte` | `age=gte.18`                 | `.gte('age', 18)`                      | comparison                        |\n| `in`                  | `status=in.(active,pending)` | `.in('status', ['active', 'pending'])` | in list                           |\n| `like` `ilike`        | `title=like.%foo%`           | `.like('title', '%foo%')`              | pattern match (case in/sensitive) |\n| `is`                  | `deleted_at=is.null`         | `.is('deleted_at', null)`              | `IS null/true/false/unknown`      |\n| `match` `imatch`      | `title=match.^foo`           | `.match('title', '^foo')`              | POSIX regex match (`~` / `~*`)    |\n| `isdistinct`          | `value=isdistinct.1`         | `.isDistinct('value', 1)`              | NULL-safe inequality              |\n\n**Negation** — prefix any operator with `not.` (string) or use\n`.not(column, operator, value)` (builder):\n\n```js\n// String\n{ event: '*', schema: 'public', table: 'posts', filter: 'status=not.in.(draft,archived)' }\n\n// Builder\n{\n  event: '*',\n  schema: 'public',\n  table: 'posts',\n  filter: postgresChangesFilter().not('status', 'in', ['draft', 'archived']),\n}\n```\n\n**AND composition** — multiple conditions are combined with commas and applied\nas an `AND`. With the builder you just chain calls:\n\n```js\n// String\n{ event: 'UPDATE', schema: 'public', table: 'orders', filter: 'amount=gt.100,status=in.(open,pending)' }\n\n// Builder — equivalent, chained\n{\n  event: 'UPDATE',\n  schema: 'public',\n  table: 'orders',\n  filter: postgresChangesFilter().gt('amount', 100).in('status', ['open', 'pending']),\n}\n```\n\n#### Building filters with `postgresChangesFilter()`\n\nThe builder (modeled on the `postgrest-js` filter methods) is the recommended,\ntype-checked way to compose filters — but it is entirely optional; raw strings\nremain fully supported.\n\n```js\nimport { postgresChangesFilter } from '@supabase/realtime-js'\n\nchannel.on(\n  'postgres_changes',\n  {\n    event: 'UPDATE',\n    schema: 'public',\n    table: 'orders',\n    // → 'amount=gt.100,status=not.in.(draft,archived)'\n    filter: postgresChangesFilter().gt('amount', 100).not('status', 'in', ['draft', 'archived']),\n  },\n  (payload) => console.log(payload)\n)\n```\n\nThe builder exposes `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `in`, `like`,\n`ilike`, `match`, `imatch`, `is`, `isDistinct` and `not`. Call `.build()` if you\nneed the raw string yourself (e.g. to log it or store it).\n\n**Values are sent verbatim** — the server has no quoting/escaping, so spaces and\nquotes are preserved as-is. The server separates conditions by commas outside\nparentheses, so a literal comma in a scalar value can't be expressed (commas\ninside `in.(…)` are fine); the builder throws on such values rather than\nsilently producing a broken filter.\n\n> **Note for PostgREST users:** Realtime evaluates filters server-side over a\n> single table's WAL — there is no resource embedding (`!inner`, embedded\n> filters) and no `or()` grouping. Use `%` (not `*`) for `like`/`ilike`\n> wildcards, since filters travel in the WebSocket payload rather than a URL.\n\n### Selecting columns\n\nUse `select` to receive only a subset of columns instead of the full row. This\nreduces payload size (helpful for large `bytea`/`jsonb` columns). The selected\ncolumns must be selectable by the subscribing role:\n\n```js\nchannel.on(\n  'postgres_changes',\n  { event: '*', schema: 'public', table: 'users', select: ['id', 'first_name'] },\n  (payload) => {\n    // payload.new only contains { id, first_name }\n    console.log(payload)\n  }\n)\n```\n\n## Get All Channels\n\nYou can see all the channels that your client has instantiatied.\n\n```js\n// Setup...\n\nclient.getChannels()\n```\n\n## Cleanup\n\nIt is highly recommended that you clean up your channels after you're done with them.\n\n- Remove a single channel\n\n```js\n// Setup...\n\nconst channel = client.channel('some-channel-to-remove')\n\nchannel.unsubscribe()\nclient.removeChannel(channel)\n```\n\n- Remove all channels and close the connection\n\n```js\n// Setup...\n\nclient.removeAllChannels()\nclient.disconnect()\n```\n\n## Development\n\nThis package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:\n\n### Building\n\n```bash\n# Complete build (from monorepo root)\npnpm nx build realtime-js\n\n# Build with watch mode for development\npnpm nx build realtime-js --watch\n\n# Individual build targets\npnpm nx build:main realtime-js    # CommonJS build (dist/main/)\npnpm nx build:module realtime-js  # ES Modules build (dist/module/)\n\n# Other useful commands\npnpm nx clean realtime-js         # Clean build artifacts\npnpm nx lint realtime-js          # Run ESLint\npnpm nx typecheck realtime-js     # TypeScript type checking\n```\n\n#### Build Outputs\n\n- **CommonJS (`dist/main/`)** - For Node.js environments\n- **ES Modules (`dist/module/`)** - For modern bundlers (Webpack, Vite, Rollup)\n- **TypeScript definitions (`dist/module/index.d.ts`)** - Type definitions for TypeScript projects\n\nNote: Unlike some other packages, realtime-js doesn't include a UMD build since it's primarily used in Node.js or bundled applications.\n\n#### Validating Package Exports\n\n```bash\n# Check if package exports are correctly configured\npnpm nx check-exports realtime-js\n```\n\nThis command uses [\"Are the types wrong?\"](https://github.com/arethetypeswrong/arethetypeswrong.github.io) to verify that the package exports work correctly in different environments. Run this before publishing to ensure your package can be imported correctly by all consumers.\n\n### Testing\n\n**No Docker or Supabase instance required!** The realtime-js tests use mocked WebSocket connections, so they're completely self-contained.\n\n```bash\n# Run unit tests (from monorepo root)\npnpm nx test realtime-js\n\n# Run tests with coverage report\npnpm nx test:coverage realtime-js\n\n# Run tests in watch mode during development\npnpm nx test:watch realtime-js\n```\n\n#### Test Scripts Explained\n\n- **test** - Runs all unit tests once using Vitest\n- **test:coverage** - Runs tests and generates coverage report with terminal output\n- **test:watch** - Runs tests in interactive watch mode for development\n\nThe tests mock WebSocket connections using `mock-socket`, so you can run them anytime without any external dependencies.\n\n### Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n\n## Credits\n\nThis repo draws heavily from [phoenix-js](https://github.com/phoenixframework/phoenix/tree/master/assets/js/phoenix).\n\n## License\n\nMIT.\n","isInternal":false,"tokens":3751,"sizeBytes":15172},{"name":"README.md","path":"packages/core/storage-js/migrations/README.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/storage-js/migrations/README.md","title":"migrations Documentation","category":"plugin-manifest","format":"markdown","content":"# Migration notes for `@supabase/storage-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/storage-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/storage-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/storage-js`:\n\n1. Read the migration files in `node_modules/@supabase/storage-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/storage-js` only.\n","isInternal":false,"tokens":333,"sizeBytes":1514},{"name":"README.md","path":"packages/core/storage-js/README.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/storage-js/README.md","title":"storage-js Documentation","category":"plugin-manifest","format":"markdown","content":"<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase Storage JS SDK</h1>\n\n  <h3 align=\"center\">JavaScript SDK to interact with Supabase Storage, including file storage and vector embeddings.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/storage\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript/storage-createbucket\">Reference Docs</a>\n    ·\n    <a href=\"https://supabase.github.io/supabase-js/storage-js/v2/spec.json\">TypeDoc</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/storage-js)](https://www.npmjs.com/package/@supabase/storage-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/storage-js)](https://pkg.pr.new/~/supabase/storage-js)\n\n</div>\n\n## Requirements\n\n- **Node.js 22 or later** (Node.js 20 support dropped in v2.110.0)\n- For browser support, all modern browsers are supported\n\n> ⚠️ **Node.js 18 Deprecation Notice**\n>\n> Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped on October 31, 2025.\n\n> ⚠️ **Node.js 20 Deprecation Notice**\n>\n> Node.js 20 reached end-of-life on April 30, 2026. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/45715), support for Node.js 20 was dropped in v2.110.0.\n\n## Features\n\n- **File Storage**: Upload, download, list, move, and delete files\n- **Access Control**: Public and private buckets with fine-grained permissions\n- **Signed URLs**: Generate time-limited URLs for secure file access\n- **Image Transformations**: On-the-fly image resizing and optimization\n- **Vector Embeddings**: Store and query high-dimensional embeddings with similarity search\n- **Analytics Buckets**: Iceberg table-based buckets optimized for analytical queries and data processing\n- **Lifecycle**: Expire previous versions of objects after a number of days\n\n## Quick Start Guide\n\n### Installing the module\n\n```bash\nnpm install @supabase/storage-js\n```\n\n### Connecting to the storage backend\n\nThere are two ways to use the Storage SDK:\n\n#### Option 1: Via Supabase Client (Recommended)\n\nIf you're already using `@supabase/supabase-js`, access storage through the client:\n\n```js\nimport { createClient } from '@supabase/supabase-js'\n\n// Use publishable key for frontend applications\nconst supabase = createClient('https://<project_ref>.supabase.co', '<your-publishable-key>')\n\n// Access storage\nconst storage = supabase.storage\n\n// Access different bucket types\nconst regularBucket = storage.from('my-bucket')\nconst vectorBucket = storage.vectors.from('embeddings-bucket')\nconst analyticsBucket = storage.analytics // Analytics API\n```\n\n#### Option 2: Standalone StorageClient\n\nFor backend applications or when you need to bypass Row Level Security:\n\n```js\nimport { StorageClient } from '@supabase/storage-js'\n\nconst STORAGE_URL = 'https://<project_ref>.supabase.co/storage/v1'\nconst SERVICE_KEY = '<your-secret-key>' // Use secret key for backend operations\n\nconst storageClient = new StorageClient(STORAGE_URL, {\n  apikey: SERVICE_KEY,\n  Authorization: `Bearer ${SERVICE_KEY}`,\n})\n\n// Access different bucket types\nconst regularBucket = storageClient.from('my-bucket')\nconst vectorBucket = storageClient.vectors.from('embeddings-bucket')\nconst analyticsBucket = storageClient.analytics // Analytics API\n```\n\n> **When to use each approach:**\n>\n> - Use `supabase.storage` when working with other Supabase features (auth, database, etc.) in frontend applications\n> - Use `new StorageClient()` for backend applications, Edge Functions, or when you need to bypass RLS policies\n\n> **Note:** Refer to the [Storage Access Control guide](https://supabase.com/docs/guides/storage/access-control) for detailed information on creating RLS policies.\n\n### Understanding Bucket Types\n\nSupabase Storage supports three types of buckets, each optimized for different use cases:\n\n#### 1. Regular Storage Buckets (File Storage)\n\nStandard buckets for storing files, images, videos, and other assets.\n\n```js\n// Create regular storage bucket\nconst { data, error } = await storageClient.createBucket('my-files', {\n  public: false,\n})\n\n// Upload files\nawait storageClient.from('my-files').upload('avatar.png', file)\n```\n\n**Use cases:** User uploads, media assets, documents, backups\n\n#### 2. Vector Buckets (Embeddings Storage)\n\nSpecialized buckets for storing and querying high-dimensional vector embeddings.\n\n```js\n// Create vector bucket\nawait storageClient.vectors.createBucket('embeddings-prod')\n\n// Create index and insert vectors\nconst bucket = storageClient.vectors.from('embeddings-prod')\nawait bucket.createIndex({\n  indexName: 'documents',\n  dimension: 1536,\n  distanceMetric: 'cosine',\n})\n```\n\n**Use cases:** Semantic search, AI-powered recommendations, similarity matching\n\n**[See full Vector Embeddings documentation below](#vector-embeddings)**\n\n#### 3. Analytics Buckets\n\nSpecialized buckets using Apache Iceberg table format, optimized for analytical queries and large-scale data processing.\n\n```js\n// Create analytics bucket\nawait storageClient.analytics.createBucket('analytics-data')\n\n// List analytics buckets\nconst { data, error } = await storageClient.analytics.listBuckets()\n\n// Delete analytics bucket\nawait storageClient.analytics.deleteBucket('analytics-data')\n```\n\n**Use cases:** Time-series data, analytical queries, data lakes, large-scale data processing, business intelligence\n\n**[See full Analytics Buckets documentation below](#analytics-buckets)**\n\n---\n\n### Handling resources\n\n#### Handling Storage Buckets\n\n- Create a new Storage bucket:\n\n  ```js\n  const { data, error } = await storageClient.createBucket(\n    'test_bucket', // Bucket name (must be unique)\n    { public: false } // Bucket options\n  )\n  ```\n\n- Retrieve the details of an existing Storage bucket:\n\n  ```js\n  const { data, error } = await storageClient.getBucket('test_bucket')\n  ```\n\n- Update a new Storage bucket:\n\n  ```js\n  const { data, error } = await storageClient.updateBucket(\n    'test_bucket', // Bucket name\n    { public: false } // Bucket options\n  )\n  ```\n\n- Remove all objects inside a single bucket:\n\n  ```js\n  const { data, error } = await storageClient.emptyBucket('test_bucket')\n  ```\n\n- Delete an existing bucket (a bucket can't be deleted with existing objects inside it):\n\n  ```js\n  const { data, error } = await storageClient.deleteBucket('test_bucket')\n  ```\n\n- Retrieve the details of all Storage buckets within an existing project:\n\n  ```js\n  // List all buckets\n  const { data, error } = await storageClient.listBuckets()\n\n  // List buckets with options (pagination, sorting, search)\n  const { data, error } = await storageClient.listBuckets({\n    limit: 10,\n    offset: 0,\n    sortColumn: 'created_at',\n    sortOrder: 'desc',\n    search: 'prod',\n  })\n  ```\n\n- Manage a bucket's lifecycle policy. Rules expire **previous versions** of objects after a number of days, so versioning needs to be enabled or the policy has nothing to act on. This is Standard buckets only, and the project must have lifecycle enabled.\n\n  ```js\n  // Replaces every existing rule\n  const { data, error } = await storageClient.updateBucketLifecycle('test_bucket', {\n    rules: [\n      {\n        id: 'expire-old-versions',\n        status: 'Enabled',\n        filter: {},\n        noncurrentVersionExpiration: { noncurrentDays: 30 },\n      },\n    ],\n  })\n\n  // Fails with NoSuchLifecycleConfiguration when the bucket has no policy\n  const { data: config, error: configError } = await storageClient.getBucketLifecycle('test_bucket')\n\n  await storageClient.deleteBucketLifecycle('test_bucket')\n  ```\n\n#### Handling Files\n\n- Upload a file to an existing bucket:\n\n  ```js\n  const fileBody = ... // load your file here\n\n  const { data, error } = await storageClient.from('bucket').upload('path/to/file', fileBody)\n  ```\n\n  > Note:  \n  > The path in `data.Key` is prefixed by the bucket ID and is not the value which should be passed to the `download` method in order to fetch the file.  \n  > To fetch the file via the `download` method, use `data.path` and `data.bucketId` as follows:\n  >\n  > ```javascript\n  > const { data, error } = await storageClient.from('bucket').upload('/folder/file.txt', fileBody)\n  > // check for errors\n  > const { data2, error2 } = await storageClient.from(data.bucketId).download(data.path)\n  > ```\n\n  > Note: The `upload` method also accepts a map of optional parameters. For a complete list see the [Supabase API reference](https://supabase.com/docs/reference/javascript/storage-from-upload).\n\n- Download a file from an exisiting bucket:\n\n  ```js\n  const { data, error } = await storageClient.from('bucket').download('path/to/file')\n  ```\n\n- List all the files within a bucket:\n\n  ```js\n  const { data, error } = await storageClient.from('bucket').list('folder')\n  ```\n\n  > Note: The `list` method also accepts a map of optional parameters. For a complete list see the [Supabase API reference](https://supabase.com/docs/reference/javascript/storage-from-list).\n\n- Replace an existing file at the specified path with a new one:\n\n  ```js\n  const fileBody = ... // load your file here\n\n  const { data, error } = await storageClient\n    .from('bucket')\n    .update('path/to/file', fileBody)\n  ```\n\n  > Note: The `upload` method also accepts a map of optional parameters. For a complete list see the [Supabase API reference](https://supabase.com/docs/reference/javascript/storage-from-upload).\n\n- Move an existing file:\n\n  ```js\n  const { data, error } = await storageClient\n    .from('bucket')\n    .move('old/path/to/file', 'new/path/to/file')\n  ```\n\n- Delete files within the same bucket:\n\n  ```js\n  const { data, error } = await storageClient.from('bucket').remove(['path/to/file'])\n  ```\n\n- Create signed URL to download file without requiring permissions:\n\n  ```js\n  const expireIn = 60\n\n  const { data, error } = await storageClient\n    .from('bucket')\n    .createSignedUrl('path/to/file', expireIn)\n  ```\n\n- Retrieve URLs for assets in public buckets:\n\n  ```js\n  const { data, error } = await storageClient.from('public-bucket').getPublicUrl('path/to/file')\n  ```\n\n## Analytics Buckets\n\nSupabase Storage provides specialized analytics buckets using Apache Iceberg table format, optimized for analytical workloads and large-scale data processing. These buckets are designed for data lake architectures, time-series data, and business intelligence applications.\n\n### What are Analytics Buckets?\n\nAnalytics buckets use the Apache Iceberg open table format, providing:\n\n- **ACID transactions** for data consistency\n- **Schema evolution** without data rewrites\n- **Time travel** to query historical data\n- **Efficient metadata management** for large datasets\n- **Optimized for analytical queries** rather than individual file operations\n\n### When to Use Analytics Buckets\n\n**Use analytics buckets for:**\n\n- Time-series data (logs, metrics, events)\n- Data lake architectures\n- Business intelligence and reporting\n- Large-scale batch processing\n- Analytical workloads requiring ACID guarantees\n\n**Use regular storage buckets for:**\n\n- User file uploads (images, documents, videos)\n- Individual file management\n- Content delivery\n- Simple object storage needs\n\n### Quick Start\n\nYou can access analytics functionality through the `analytics` property on your storage client:\n\n#### Via Supabase Client\n\n```typescript\nimport { createClient } from '@supabase/supabase-js'\n\nconst supabase = createClient('https://your-project.supabase.co', 'your-publishable-key')\n\n// Access analytics operations\nconst analytics = supabase.storage.analytics\n\n// Create an analytics bucket\nconst { data, error } = await analytics.createBucket('analytics-data')\nif (error) {\n  console.error('Failed to create analytics bucket:', error.message)\n} else {\n  console.log('Created bucket:', data.name)\n}\n```\n\n#### Via StorageClient\n\n```typescript\nimport { StorageClient } from '@supabase/storage-js'\n\nconst storageClient = new StorageClient('https://your-project.supabase.co/storage/v1', {\n  apikey: 'YOUR_API_KEY',\n  Authorization: 'Bearer YOUR_TOKEN',\n})\n\n// Access analytics operations\nconst analytics = storageClient.analytics\n\n// Create an analytics bucket\nawait analytics.createBucket('analytics-data')\n```\n\n### API Reference\n\n#### Create Analytics Bucket\n\nCreates a new analytics bucket using Iceberg table format:\n\n```typescript\nconst { data, error } = await analytics.createBucket('my-analytics-bucket')\n\nif (error) {\n  console.error('Error:', error.message)\n} else {\n  console.log('Created bucket:', data)\n}\n```\n\n**Returns:**\n\n```typescript\n{\n  data: {\n    id: string\n    type: 'ANALYTICS'\n    format: string\n    created_at: string\n    updated_at: string\n  } | null\n  error: StorageError | null\n}\n```\n\n#### List Analytics Buckets\n\nRetrieves all analytics buckets in your project with optional filtering and pagination:\n\n```typescript\nconst { data, error } = await analytics.listBuckets({\n  limit: 10,\n  offset: 0,\n  sortColumn: 'created_at',\n  sortOrder: 'desc',\n  search: 'prod',\n})\n\nif (data) {\n  console.log(`Found ${data.length} analytics buckets`)\n  data.forEach((bucket) => {\n    console.log(`- ${bucket.id} (created: ${bucket.created_at})`)\n  })\n}\n```\n\n**Parameters:**\n\n- `limit?: number` - Maximum number of buckets to return\n- `offset?: number` - Number of buckets to skip (for pagination)\n- `sortColumn?: 'id' | 'name' | 'created_at' | 'updated_at'` - Column to sort by\n- `sortOrder?: 'asc' | 'desc'` - Sort direction\n- `search?: string` - Search term to filter bucket names\n\n**Returns:**\n\n```typescript\n{\n  data: AnalyticBucket[] | null\n  error: StorageError | null\n}\n```\n\n**Example with Pagination:**\n\n```typescript\n// Fetch first page\nconst firstPage = await analytics.listBuckets({\n  limit: 100,\n  offset: 0,\n  sortColumn: 'created_at',\n  sortOrder: 'desc',\n})\n\n// Fetch second page\nconst secondPage = await analytics.listBuckets({\n  limit: 100,\n  offset: 100,\n  sortColumn: 'created_at',\n  sortOrder: 'desc',\n})\n```\n\n#### Delete Analytics Bucket\n\nDeletes an analytics bucket. The bucket must be empty before deletion.\n\n```typescript\nconst { data, error } = await analytics.deleteBucket('old-analytics-bucket')\n\nif (error) {\n  console.error('Failed to delete:', error.message)\n} else {\n  console.log('Bucket deleted:', data.message)\n}\n```\n\n**Returns:**\n\n```typescript\n{\n  data: { message: string } | null\n  error: StorageError | null\n}\n```\n\n> **Note:** A bucket cannot be deleted if it contains data. You must empty the bucket first.\n\n#### Get Iceberg Catalog for Advanced Operations\n\nFor advanced operations like creating tables, namespaces, and querying Iceberg metadata, use the `from()` method to get a configured [iceberg-js](https://github.com/supabase/iceberg-js) client:\n\n```typescript\n// Get an Iceberg REST Catalog client for your analytics bucket\nconst catalog = analytics.from('analytics-data')\n\n// Create a namespace\nawait catalog.createNamespace({ namespace: ['default'] }, { properties: { owner: 'data-team' } })\n\n// Create a table with schema\nawait catalog.createTable(\n  { namespace: ['default'] },\n  {\n    name: 'events',\n    schema: {\n      type: 'struct',\n      fields: [\n        { id: 1, name: 'id', type: 'long', required: true },\n        { id: 2, name: 'timestamp', type: 'timestamp', required: true },\n        { id: 3, name: 'user_id', type: 'string', required: false },\n      ],\n      'schema-id': 0,\n      'identifier-field-ids': [1],\n    },\n    'partition-spec': {\n      'spec-id': 0,\n      fields: [],\n    },\n    'write-order': {\n      'order-id': 0,\n      fields: [],\n    },\n    properties: {\n      'write.format.default': 'parquet',\n    },\n  }\n)\n\n// List tables in namespace\nconst tables = await catalog.listTables({ namespace: ['default'] })\nconsole.log(tables) // [{ namespace: ['default'], name: 'events' }]\n\n// Load table metadata\nconst table = await catalog.loadTable({ namespace: ['default'], name: 'events' })\n\n// Update table properties\nawait catalog.updateTable(\n  { namespace: ['default'], name: 'events' },\n  { properties: { 'read.split.target-size': '134217728' } }\n)\n\n// Drop table\nawait catalog.dropTable({ namespace: ['default'], name: 'events' })\n\n// Drop namespace\nawait catalog.dropNamespace({ namespace: ['default'] })\n```\n\n**Returns:** `IcebergRestCatalog` instance from [iceberg-js](https://github.com/supabase/iceberg-js)\n\n> **Note:** The `from()` method returns an Iceberg REST Catalog client that provides full access to the Apache Iceberg REST API. For complete documentation of available operations, see the [iceberg-js documentation](https://supabase.github.io/iceberg-js/).\n\n### Error Handling\n\nAnalytics buckets use the same error handling pattern as the rest of the Storage SDK:\n\n```typescript\nconst { data, error } = await analytics.createBucket('my-bucket')\n\nif (error) {\n  console.error('Error:', error.message)\n  console.error('Status:', error.status)\n  console.error('Status Code:', error.statusCode)\n  // Handle error appropriately\n}\n```\n\n#### Throwing Errors\n\nYou can configure the client to throw errors instead of returning them:\n\n```typescript\nconst analytics = storageClient.analytics\nanalytics.throwOnError()\n\ntry {\n  const { data } = await analytics.createBucket('my-bucket')\n  // data is guaranteed to be present\n  console.log('Success:', data)\n} catch (error) {\n  if (error instanceof StorageApiError) {\n    console.error('API Error:', error.statusCode, error.message)\n  }\n}\n```\n\n### TypeScript Types\n\nThe library exports TypeScript types for analytics buckets:\n\n```typescript\nimport type { AnalyticBucket, BucketType, StorageError } from '@supabase/storage-js'\n\n// AnalyticBucket type\ninterface AnalyticBucket {\n  id: string\n  type: 'ANALYTICS'\n  format: string\n  created_at: string\n  updated_at: string\n}\n```\n\n### Common Patterns\n\n#### Checking if a Bucket Exists\n\n```typescript\nasync function bucketExists(bucketName: string): Promise<boolean> {\n  const { data, error } = await analytics.listBuckets({\n    search: bucketName,\n  })\n\n  if (error) {\n    console.error('Error checking bucket:', error.message)\n    return false\n  }\n\n  return data?.some((bucket) => bucket.id === bucketName) ?? false\n}\n```\n\n#### Creating Bucket with Error Handling\n\n```typescript\nasync function ensureAnalyticsBucket(bucketName: string) {\n  // Try to create the bucket\n  const { data, error } = await analytics.createBucket(bucketName)\n\n  if (error) {\n    // Check if bucket already exists (conflict error)\n    if (error.statusCode === '409') {\n      console.log(`Bucket '${bucketName}' already exists`)\n      return { success: true, created: false }\n    }\n\n    // Other error occurred\n    console.error('Failed to create bucket:', error.message)\n    return { success: false, error }\n  }\n\n  console.log(`Created new bucket: '${bucketName}'`)\n  return { success: true, created: true, data }\n}\n```\n\n#### Listing All Buckets with Pagination\n\n```typescript\nasync function getAllAnalyticsBuckets() {\n  const allBuckets: AnalyticBucket[] = []\n  let offset = 0\n  const limit = 100\n\n  while (true) {\n    const { data, error } = await analytics.listBuckets({\n      limit,\n      offset,\n      sortColumn: 'created_at',\n      sortOrder: 'desc',\n    })\n\n    if (error) {\n      console.error('Error fetching buckets:', error.message)\n      break\n    }\n\n    if (!data || data.length === 0) {\n      break\n    }\n\n    allBuckets.push(...data)\n\n    // If we got fewer results than the limit, we've reached the end\n    if (data.length < limit) {\n      break\n    }\n\n    offset += limit\n  }\n\n  return allBuckets\n}\n```\n\n## Vector Embeddings\n\nSupabase Storage provides built-in support for storing and querying high-dimensional vector embeddings, powered by S3 Vectors. This enables semantic search, similarity matching, and AI-powered applications without needing a separate vector database.\n\n> **Note:** Vector embeddings functionality is available in `@supabase/storage-js` v2.76 and later.\n\n### Features\n\n- **Vector Buckets**: Organize vector indexes into logical containers\n- **Vector Indexes**: Define schemas with configurable dimensions and distance metrics\n- **Batch Operations**: Insert/update/delete up to 500 vectors per request\n- **Similarity Search**: Query for nearest neighbors using cosine, euclidean, or dot product distance\n- **Metadata Filtering**: Store and filter vectors by arbitrary JSON metadata\n- **Pagination**: Efficiently scan large vector datasets\n- **Parallel Scanning**: Distribute scans across multiple workers for high throughput\n- **Cross-platform**: Works in Node.js, browsers, and edge runtimes\n\n### Quick Start\n\nYou can access vector functionality in three ways, depending on your use case:\n\n#### Option 1: Via Supabase Client (Most Common)\n\nIf you're using the full Supabase client:\n\n```typescript\nimport { createClient } from '@supabase/supabase-js'\n\nconst supabase = createClient('https://your-project.supabase.co', 'your-publishable-key')\n\n// Access vector operations through storage\nconst vectors = supabase.storage.vectors\n\n// Create a vector bucket\nawait vectors.createBucket('embeddings-prod')\n\n// Create an index\nconst bucket = vectors.from('embeddings-prod')\nawait bucket.createIndex({\n  indexName: 'documents-openai',\n  dataType: 'float32',\n  dimension: 1536,\n  distanceMetric: 'cosine',\n})\n\n// Insert vectors\nconst index = bucket.index('documents-openai')\nawait index.putVectors({\n  vectors: [\n    {\n      key: 'doc-1',\n      data: { float32: [0.1, 0.2, 0.3 /* ...1536 dimensions */] },\n      metadata: { title: 'Introduction', category: 'docs' },\n    },\n  ],\n})\n\n// Query similar vectors\nconst { data, error } = await index.queryVectors({\n  queryVector: { float32: [0.15, 0.25, 0.35 /* ...1536 dimensions */] },\n  topK: 5,\n  returnDistance: true,\n  returnMetadata: true,\n})\n\nif (data) {\n  data.vectors.forEach((match) => {\n    console.log(`${match.key}: distance=${match.distance}`)\n    console.log('Metadata:', match.metadata)\n  })\n}\n```\n\n#### Option 2: Via StorageClient\n\nIf you're using the standalone `StorageClient` for storage operations, access vectors through the `vectors` property:\n\n```typescript\nimport { StorageClient } from '@supabase/storage-js'\n\nconst storageClient = new StorageClient('https://your-project.supabase.co/storage/v1', {\n  apikey: 'YOUR_API_KEY',\n  Authorization: 'Bearer YOUR_TOKEN',\n})\n\n// Access vector operations\nconst vectors = storageClient.vectors\n\n// Use the same API as shown in Option 1\nawait vectors.createBucket('embeddings-prod')\nconst bucket = vectors.from('embeddings-prod')\n// ... rest of operations\n```\n\n#### Option 3: Standalone Vector Client\n\nFor vector-only applications that don't need regular file storage operations:\n\n```typescript\nimport { StorageVectorsClient } from '@supabase/storage-js'\n\n// Initialize standalone vector client\nconst vectorClient = new StorageVectorsClient('https://your-project.supabase.co/storage/v1', {\n  headers: { Authorization: 'Bearer YOUR_TOKEN' },\n})\n\n// Use the same API as shown in Option 1\nawait vectorClient.createBucket('embeddings-prod')\nconst bucket = vectorClient.from('embeddings-prod')\n// ... rest of operations\n```\n\n> **When to use each approach:**\n>\n> - **Option 1**: When using other Supabase features (auth, database, realtime)\n> - **Option 2**: When working with both file storage and vectors\n> - **Option 3**: For dedicated vector-only applications without file storage\n\n### API Reference\n\n#### Client Initialization\n\n```typescript\nconst vectorClient = new StorageVectorsClient(url, options?)\n```\n\n**Options:**\n\n- `headers?: Record<string, string>` - Custom HTTP headers (e.g., Authorization)\n- `fetch?: Fetch` - Custom fetch implementation\n\n#### Vector Buckets\n\nVector buckets are top-level containers for organizing vector indexes.\n\n##### Create Bucket\n\n```typescript\nconst { data, error } = await vectorClient.createBucket('my-bucket')\n```\n\n##### Get Bucket\n\n```typescript\nconst { data, error } = await vectorClient.getBucket('my-bucket')\nconsole.log('Created at:', new Date(data.vectorBucket.creationTime! * 1000))\n```\n\n##### List Buckets\n\n```typescript\nconst { data, error } = await vectorClient.listBuckets({\n  prefix: 'prod-',\n  maxResults: 100,\n})\n\n// Pagination\nif (data?.nextToken) {\n  const next = await vectorClient.listBuckets({ nextToken: data.nextToken })\n}\n```\n\n##### Delete Bucket\n\n```typescript\n// Bucket must be empty (all indexes deleted first)\nconst { error } = await vectorClient.deleteBucket('my-bucket')\n```\n\n#### Vector Indexes\n\nVector indexes define the schema for embeddings including dimension and distance metric.\n\n##### Create Index\n\n```typescript\nconst bucket = vectorClient.from('my-bucket')\n\nawait bucket.createIndex({\n  indexName: 'my-index',\n  dataType: 'float32',\n  dimension: 1536,\n  distanceMetric: 'cosine', // 'cosine' | 'euclidean' | 'dotproduct'\n  metadataConfiguration: {\n    nonFilterableMetadataKeys: ['raw_text', 'internal_id'],\n  },\n})\n```\n\n**Distance Metrics:**\n\n- `cosine` - Cosine similarity (normalized dot product)\n- `euclidean` - Euclidean distance (L2 norm)\n- `dotproduct` - Dot product similarity\n\n##### Get Index\n\n```typescript\nconst { data, error } = await bucket.getIndex('my-index')\nconsole.log('Dimension:', data?.index.dimension)\nconsole.log('Distance metric:', data?.index.distanceMetric)\n```\n\n##### List Indexes\n\n```typescript\nconst { data, error } = await bucket.listIndexes({\n  prefix: 'documents-',\n  maxResults: 100,\n})\n```\n\n##### Delete Index\n\n```typescript\n// Deletes index and all its vectors\nawait bucket.deleteIndex('my-index')\n```\n\n#### Vector Operations\n\n##### Insert/Update Vectors (Upsert)\n\n```typescript\nconst index = vectorClient.from('my-bucket').index('my-index')\n\nawait index.putVectors({\n  vectors: [\n    {\n      key: 'unique-id-1',\n      data: {\n        float32: [\n          /* 1536 numbers */\n        ],\n      },\n      metadata: {\n        title: 'Document Title',\n        category: 'technical',\n        page: 1,\n      },\n    },\n    // ... up to 500 vectors per request\n  ],\n})\n```\n\n**Limitations:**\n\n- 1-500 vectors per request\n- Vectors must match index dimension\n- Keys must be unique within index\n\n##### Get Vectors by Key\n\n```typescript\nconst { data, error } = await index.getVectors({\n  keys: ['doc-1', 'doc-2', 'doc-3'],\n  returnData: true, // Include embeddings\n  returnMetadata: true, // Include metadata\n})\n\ndata?.vectors.forEach((v) => {\n  console.log(v.key, v.metadata)\n})\n```\n\n##### Query Similar Vectors (ANN Search)\n\n```typescript\nconst { data, error } = await index.queryVectors({\n  queryVector: {\n    float32: [\n      /* 1536 numbers */\n    ],\n  },\n  topK: 10,\n  filter: {\n    category: 'technical',\n    published: true,\n  },\n  returnDistance: true,\n  returnMetadata: true,\n})\n\n// Results ordered by similarity\ndata?.vectors.forEach((match) => {\n  console.log(`${match.key}: distance=${match.distance}`)\n})\n```\n\nS3 vector buckets support deep queries with `topK` up to 10,000, returning at most 100 vectors per response. Pass the response's `nextToken` with the same query to retrieve the next page:\n\n```typescript\nconst query = {\n  queryVector: { float32: embedding },\n  topK: 1000,\n  returnDistance: true,\n}\n\nlet nextToken: string | undefined\n\ndo {\n  const { data, error } = await index.queryVectors({ ...query, nextToken })\n  if (error) throw error\n\n  for (const vector of data.vectors) {\n    console.log(`${vector.key}: distance=${vector.distance}`)\n  }\n\n  nextToken = data.nextToken\n} while (nextToken)\n```\n\nThe pgvector backend supports `topK` up to 100 and does not support `nextToken` pagination.\n\n**Filter Syntax:**\nThe `filter` parameter accepts arbitrary JSON for metadata filtering. Non-filterable keys (configured at index creation) cannot be used in filters but can still be returned.\n\n##### List/Scan Vectors\n\n```typescript\n// Simple pagination\nlet nextToken: string | undefined\ndo {\n  const { data } = await index.listVectors({\n    maxResults: 500,\n    nextToken,\n    returnMetadata: true,\n  })\n\n  console.log('Batch:', data?.vectors.length)\n  nextToken = data?.nextToken\n} while (nextToken)\n\n// Parallel scanning (4 workers)\nconst workers = [0, 1, 2, 3].map(async (segmentIndex) => {\n  const { data } = await index.listVectors({\n    segmentCount: 4,\n    segmentIndex,\n    returnMetadata: true,\n  })\n  return data?.vectors || []\n})\n\nconst results = await Promise.all(workers)\nconst allVectors = results.flat()\n```\n\n**Limitations:**\n\n- `maxResults`: 1-1000 (default: 500)\n- `segmentCount`: 1-16\n- Response may be limited by 1MB size\n\n##### Delete Vectors\n\n```typescript\nawait index.deleteVectors({\n  keys: ['doc-1', 'doc-2', 'doc-3'],\n  // ... up to 500 keys per request\n})\n```\n\n### Error Handling\n\nThe library uses a consistent error handling pattern:\n\n```typescript\nconst { data, error } = await vectorClient.createBucket('my-bucket')\n\nif (error) {\n  console.error('Error:', error.message)\n  console.error('Status:', error.status)\n  console.error('Code:', error.statusCode)\n}\n```\n\n#### Error Codes\n\n| Code                         | HTTP | Description             |\n| ---------------------------- | ---- | ----------------------- |\n| `InternalError`              | 500  | Internal server error   |\n| `S3VectorConflictException`  | 409  | Resource already exists |\n| `S3VectorNotFoundException`  | 404  | Resource not found      |\n| `S3VectorBucketNotEmpty`     | 400  | Bucket contains indexes |\n| `S3VectorMaxBucketsExceeded` | 400  | Bucket quota exceeded   |\n| `S3VectorMaxIndexesExceeded` | 400  | Index quota exceeded    |\n\n#### Throwing Errors\n\nYou can configure the client to throw errors instead:\n\n```typescript\nconst vectorClient = new StorageVectorsClient(url, options)\nvectorClient.throwOnError()\n\ntry {\n  const { data } = await vectorClient.createBucket('my-bucket')\n  // data is guaranteed to be present\n} catch (error) {\n  if (error instanceof StorageVectorsApiError) {\n    console.error('API Error:', error.statusCode)\n  }\n}\n```\n\n### Advanced Usage\n\n#### Scoped Clients\n\nCreate scoped clients for cleaner code:\n\n```typescript\n// Bucket-scoped operations\nconst bucket = vectorClient.from('embeddings-prod')\nawait bucket.createIndex({\n  /* ... */\n})\nawait bucket.listIndexes()\n\n// Index-scoped operations\nconst index = bucket.index('documents-openai')\nawait index.putVectors({\n  /* ... */\n})\nawait index.queryVectors({\n  /* ... */\n})\n```\n\n#### Custom Fetch\n\nProvide a custom fetch implementation:\n\n```typescript\nimport { StorageVectorsClient } from '@supabase/storage-js'\n\nconst vectorClient = new StorageVectorsClient(url, {\n  fetch: customFetch,\n  headers: {\n    /* ... */\n  },\n})\n```\n\n#### Batch Processing\n\nProcess large datasets in batches:\n\n```typescript\nasync function insertLargeDataset(vectors: VectorObject[]) {\n  const batchSize = 500\n\n  for (let i = 0; i < vectors.length; i += batchSize) {\n    const batch = vectors.slice(i, i + batchSize)\n    await index.putVectors({ vectors: batch })\n    console.log(`Inserted ${i + batch.length}/${vectors.length}`)\n  }\n}\n```\n\n#### Float32 Validation\n\nEnsure vectors are properly normalized to float32:\n\n```typescript\nimport { normalizeToFloat32 } from '@supabase/storage-js'\n\nconst vector = normalizeToFloat32([0.1, 0.2, 0.3 /* ... */])\n```\n\n### Type Definitions\n\nThe library exports comprehensive TypeScript types:\n\n```typescript\nimport type {\n  VectorBucket,\n  VectorIndex,\n  VectorData,\n  VectorObject,\n  VectorMatch,\n  VectorMetadata,\n  DistanceMetric,\n  ApiResponse,\n  StorageVectorsError,\n} from '@supabase/storage-js'\n```\n\n## Development\n\nThis package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:\n\n### Building\n\n#### Build Scripts Overview\n\n```bash\n# Build the package\npnpm nx build storage-js\n\n# Watch mode for development\npnpm nx build storage-js --watch\n\n# Generate documentation\npnpm nx docs storage-js\n```\n\n### Testing\n\n**Important:** The storage-js tests require a local Supabase stack running via the Supabase CLI. Docker must be running since the Supabase CLI uses it internally.\n\n#### Prerequisites\n\n1. **Docker** must be installed and running (used by Supabase CLI internally)\n2. **Supabase CLI** — installed automatically via `pnpm exec supabase`\n\n#### Test Scripts Overview\n\n| Script            | Description                       | What it does                                                      |\n| ----------------- | --------------------------------- | ----------------------------------------------------------------- |\n| `test:storage`    | **Complete test workflow**        | Runs the full test cycle: clean → start infra → run tests → clean |\n| `test:suite`      | **Jest tests only**               | Runs Jest tests with coverage (requires infra to be running)      |\n| `test:infra`      | **Start test infrastructure**     | Starts Supabase CLI stack (PostgreSQL, Storage API, Kong, etc.)   |\n| `test:clean-post` | **Stop and clean infrastructure** | Stops the Supabase CLI stack                                      |\n\n#### Running Tests\n\n##### Option 1: Complete Test Run (Recommended)\n\nThis handles everything automatically - starting infrastructure, running tests, and cleaning up:\n\n```bash\n# From monorepo root\npnpm nx test:storage storage-js\n```\n\nThis command will:\n\n1. Stop any existing test containers\n2. Build and start fresh test infrastructure\n3. Wait for services to be ready\n4. Run all Jest tests with coverage\n5. Clean up all containers after tests complete\n\n##### Option 2: Manual Infrastructure Management\n\nUseful for development when you want to run tests multiple times without restarting Docker:\n\n```bash\n# Step 1: Start the test infrastructure\n# From root\npnpm nx test:infra storage-js\n# This starts: PostgreSQL, Storage API, Kong Gateway, and imgproxy\n\n# Step 2: Run tests (can run multiple times)\npnpm nx test:suite storage-js\n\n# Step 3: When done, clean up the infrastructure\npnpm nx test:clean-post storage-js\n```\n\n##### Option 3: Development Mode\n\nFor actively developing and debugging tests:\n\n```bash\n# Start infrastructure once (from root)\npnpm nx test:infra storage-js\n\n# Run tests in watch mode\npnpm nx test:suite storage-js --watch\n\n# Clean up when done\npnpm nx test:clean-post storage-js\n```\n\n#### Test Infrastructure Details\n\nThe test infrastructure is managed via the Supabase CLI (`pnpm exec supabase start --workdir test`), which starts a local Supabase stack defined by the config in `test/`. This includes PostgreSQL, the Storage API, Kong Gateway, and supporting services.\n\n#### Common Issues and Solutions\n\n| Issue                             | Solution                                                                                          |\n| --------------------------------- | ------------------------------------------------------------------------------------------------- |\n| Port conflicts                    | Another service is using a required port. Run `pnpm nx test:clean-post storage-js` then try again |\n| \"request failed, reason:\" errors  | Infrastructure isn't running. Run `pnpm nx test:infra storage-js` first                           |\n| Tests fail with connection errors | Ensure Docker is running (Supabase CLI requires Docker)                                           |\n| Stack already running             | Run `pnpm nx test:clean-post storage-js` to stop it before restarting                             |\n\n#### Understanding Test Failures\n\n- **StorageUnknownError with \"request failed\"**: Infrastructure not running\n- **Snapshot failures**: Expected test data has changed — review and update snapshots if needed\n\n### Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n","isInternal":false,"tokens":8683,"sizeBytes":36527},{"name":"README.md","path":"packages/core/supabase-js/migrations/README.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/supabase-js/migrations/README.md","title":"migrations Documentation","category":"plugin-manifest","format":"markdown","content":"# Migration notes for `@supabase/supabase-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/supabase-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/supabase-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/supabase-js`:\n\n1. Read the migration files in `node_modules/@supabase/supabase-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/supabase-js` only.\n","isInternal":false,"tokens":351,"sizeBytes":1520},{"name":"README.md","path":"packages/core/supabase-js/README.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/supabase-js/README.md","title":"supabase-js Documentation","category":"plugin-manifest","format":"markdown","content":"<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase JS SDK</h1>\n\n  <h3 align=\"center\">Isomorphic JavaScript SDK for Supabase - combining Auth, Database, Storage, Functions, and Realtime.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/getting-started\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript/start\">Reference Docs</a>\n    ·\n    <a href=\"https://supabase.github.io/supabase-js/supabase-js/v2/spec.json\">TypeDoc</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/supabase-js)](https://www.npmjs.com/package/@supabase/supabase-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/supabase-js)](https://pkg.pr.new/~/supabase/supabase-js)\n\n</div>\n\n## Usage\n\nFirst of all, you need to install the library:\n\n```sh\nnpm install @supabase/supabase-js\n```\n\nThen you're able to import the library and establish the connection with the database:\n\n```js\nimport { createClient } from '@supabase/supabase-js'\n\n// Create a single supabase client for interacting with your database\nconst supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')\n```\n\n### UMD\n\nYou can use plain `<script>`s to import supabase-js from CDNs, like:\n\n```html\n<script src=\"https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2\"></script>\n```\n\nor even:\n\n```html\n<script src=\"https://unpkg.com/@supabase/supabase-js@2\"></script>\n```\n\nThen you can use it from a global `supabase` variable:\n\n```html\n<script>\n  const { createClient } = supabase\n  const _supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')\n\n  console.log('Supabase Instance: ', _supabase)\n  // ...\n</script>\n```\n\n### ESM\n\nYou can use `<script type=\"module\">` to import supabase-js from CDNs, like:\n\n```html\n<script type=\"module\">\n  import { createClient } from 'https://cdn.jsdelivr.net/npm/@supabase/supabase-js/+esm'\n  const supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')\n\n  console.log('Supabase Instance: ', supabase)\n  // ...\n</script>\n```\n\n### Deno\n\nYou can use supabase-js in the Deno runtime via [JSR](https://jsr.io/@supabase/supabase-js):\n\n```js\nimport { createClient } from 'jsr:@supabase/supabase-js@2'\n```\n\n### Custom `fetch` implementation\n\n`supabase-js` uses the runtime's global `fetch` to make HTTP requests, but an alternative `fetch` implementation can be provided as an option. This is useful in environments where the global `fetch` is unavailable or where you want to customize request behavior:\n\n```js\nimport { createClient } from '@supabase/supabase-js'\n\n// Provide a custom `fetch` implementation as an option\nconst supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key', {\n  global: {\n    fetch: (...args) => fetch(...args),\n  },\n})\n```\n\n### Distributed Tracing with OpenTelemetry\n\nThe Supabase JS SDK can attach W3C/OpenTelemetry trace context headers (`traceparent`, `tracestate`, `baggage`) to outgoing requests, enabling end-to-end request tracing from your client application through Supabase services.\n\nTrace propagation is **opt-in** and disabled by default. When enabled, headers are only attached to requests targeting Supabase domains (`*.supabase.co`, `*.supabase.in`, `localhost`).\n\n#### Enable trace propagation\n\nOpting in takes two steps: install `@opentelemetry/api`, and load the tracing runtime by importing the `@supabase/supabase-js/tracing` subpath once at your application entry point. The main bundle contains no OpenTelemetry code — the subpath import is what wires it up.\n\n```js\nimport '@supabase/supabase-js/tracing'\nimport { createClient } from '@supabase/supabase-js'\nimport { trace } from '@opentelemetry/api'\n\nconst supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key', {\n  tracePropagation: true,\n})\n\nconst tracer = trace.getTracer('my-app')\nawait tracer.startActiveSpan('fetch-users', async (span) => {\n  // This request now includes the active trace context.\n  const { data, error } = await supabase.from('users').select('*')\n  span.end()\n})\n```\n\nThe subpath imports `@opentelemetry/api` directly, so module resolution fails loudly if it is not installed. If `tracePropagation` is enabled without the subpath import, the SDK logs a one-time warning and sends requests without trace headers; if no active context exists at request time, it silently no-ops.\n\nTrace propagation is not available via the CDN/UMD build (`https://cdn.jsdelivr.net/.../supabase.js`) — there is no way to load the tracing runtime there.\n\n#### Advanced configuration\n\n```typescript\ninterface TracePropagationOptions {\n  // Enable trace propagation (default: false).\n  enabled?: boolean\n\n  // Respect upstream sampling decisions (default: true).\n  // When true, non-sampled requests carry only `traceparent` (flag preserved,\n  // so nothing is recorded downstream) — Supabase logs still get a trace_id,\n  // while `tracestate` and `baggage` are withheld.\n  respectSamplingDecision?: boolean\n}\n```\n\n```js\n// Always propagate the full trace context, even for non-sampled traces.\nconst supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key', {\n  tracePropagation: { enabled: true, respectSamplingDecision: false },\n})\n```\n\n## Support Policy\n\nThis section outlines the scope of support for various runtime environments in Supabase JavaScript client.\n\n### Node.js\n\nWe only support Node.js versions that are in **Active LTS** or **Maintenance** status as defined by the [official Node.js release schedule](https://nodejs.org/en/about/previous-releases#release-schedule). This means we support versions that are currently receiving long-term support and critical bug fixes.\n\nWhen a Node.js version reaches end-of-life and is no longer in Active LTS or Maintenance status, Supabase will drop it in a **minor release**, and **this won't be considered a breaking change**.\n\n> ⚠️ **Node.js 18 Deprecation Notice**\n>\n> Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped in version `2.79.0`.\n>\n> If you must use Node.js 18, please use version `2.78.0`, which is the last version that supported Node.js 18.\n\n> ⚠️ **Node.js 20 Deprecation Notice**\n>\n> Node.js 20 reached end-of-life on April 30, 2026. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/45715), support for Node.js 20 was dropped in version `2.110.0`.\n>\n> If you must use Node.js 20, please use version `2.109.0`, which is the last version that supported Node.js 20.\n\n### Deno\n\nWe support Deno versions that are currently receiving active development and security updates. We follow the [official Deno release schedule](https://docs.deno.com/runtime/fundamentals/stability_and_releases/) and only support versions from the `stable` and `lts` release channels.\n\nWhen a Deno version reaches end-of-life and is no longer receiving security updates, Supabase will drop it in a **minor release**, and **this won't be considered a breaking change**.\n\n### Browsers\n\nAll modern browsers are supported. We support browsers that provide native `fetch` API. For Realtime features, browsers must also support native `WebSocket` API.\n\n### Bun\n\nWe support Bun runtime environments. Bun provides native fetch support and is compatible with Node.js APIs. Since Bun does not follow a structured release schedule like Node.js or Deno, we support current stable versions of Bun and may drop support for older versions in minor releases without considering it a breaking change.\n\n### React Native\n\nWe support React Native environments with fetch polyfills provided by the framework. Since React Native does not follow a structured release schedule, we support current stable versions and may drop support for older versions in minor releases without considering it a breaking change.\n\n### Cloudflare Workers\n\nWe support Cloudflare Workers runtime environments. Cloudflare Workers provides native fetch support. Since Cloudflare Workers does not follow a structured release schedule, we support current stable versions and may drop support for older versions in minor releases without considering it a breaking change.\n\n### Important Notes\n\n- **Experimental features**: Features marked as experimental may be removed or changed without notice\n\n## Known Build Warnings\n\n### `UNUSED_EXTERNAL_IMPORT` in Vite / Rollup / Nuxt\n\nWhen bundling your app, you may see warnings like:\n\n```\n\"PostgrestError\" is imported from external module \"@supabase/postgrest-js\" but never used in \"...supabase-js/dist/index.mjs\".\n\"FunctionRegion\", \"FunctionsError\", \"FunctionsFetchError\", \"FunctionsHttpError\" and \"FunctionsRelayError\" are imported from external module \"@supabase/functions-js\" but never used in \"...\".\n```\n\n**This is a false positive — your bundle is fine.** Here is why it happens:\n\n`@supabase/supabase-js` re-exports `PostgrestError`, `FunctionsError`, and related symbols so you can import them directly from `@supabase/supabase-js`. However, our build tool merges all imports from the same package into a single import statement in the built output:\n\n```js\n// dist/index.mjs (simplified)\nimport { PostgrestClient, PostgrestError } from '@supabase/postgrest-js'\n//       ^ used internally    ^ re-exported for you\n```\n\nYour bundler checks which names from that import are used _in the code body_, and flags `PostgrestError` as unused because it only appears in an `export` statement — not called or assigned. The export itself is the usage, but downstream bundlers don't track this correctly. This is a known Rollup/Vite limitation with re-exported external imports.\n\n**Nothing is broken.** Tree-shaking and bundle size are unaffected.\n\nTo suppress the warning:\n\n**Vite / Rollup (`vite.config.js` or `rollup.config.js`):**\n\n```js\nexport default {\n  build: {\n    rollupOptions: {\n      onwarn(warning, warn) {\n        if (warning.code === 'UNUSED_EXTERNAL_IMPORT' && warning.exporter?.includes('@supabase/'))\n          return\n        warn(warning)\n      },\n    },\n  },\n}\n```\n\n**Nuxt (`nuxt.config.ts`):**\n\n```ts\nexport default defineNuxtConfig({\n  vite: {\n    build: {\n      rollupOptions: {\n        onwarn(warning, warn) {\n          if (warning.code === 'UNUSED_EXTERNAL_IMPORT' && warning.exporter?.includes('@supabase/'))\n            return\n          warn(warning)\n        },\n      },\n    },\n  },\n})\n```\n\n## Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n\n### Building\n\n```bash\n# From the monorepo root\npnpm nx build supabase-js\n\n# Or with watch mode for development\npnpm nx build supabase-js --watch\n```\n\n### Testing\n\nThere's a complete guide on how to set up your environment for running locally the `supabase-js` integration tests. Please refer to [TESTING.md](./TESTING.md).\n\n## Badges\n\n[![Coverage Status](https://coveralls.io/repos/github/supabase/supabase-js/badge.svg?branch=master)](https://coveralls.io/github/supabase/supabase-js?branch=master)\n","isInternal":false,"tokens":3007,"sizeBytes":12014},{"name":"README.md","path":"packages/core/supabase-js/test/integration/expo/README.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/supabase-js/test/integration/expo/README.md","title":"expo Documentation","category":"plugin-manifest","format":"markdown","content":"# supabase-js Expo integration test\n\nAn Expo SDK 53 app used as an integration target for `@supabase/supabase-js`. The test suite under `__tests__/` is exercised by:\n\n```bash\nnx test:expo supabase-js\n```\n\nfrom the repository root. CI runs it as part of the `integration-tests` workflow against pkg.pr.new preview builds of `@supabase/supabase-js`.\n\n## Local development\n\n```bash\ncd packages/core/supabase-js/test/integration/expo\nnpm install --legacy-peer-deps --ignore-scripts\nnpm test\n```\n\n`--legacy-peer-deps` is required because preview packages are published with version `0.0.0-automated`, which does not satisfy peer-dependency ranges like `^2.76.1`.\n\n## Why jest is pinned to 29 here\n\nThe rest of the monorepo runs jest 30 (declared at the workspace root). This subdir pins `jest@29.7.0` directly.\n\n`jest-expo` — at every published version including the current latest `jest-expo@56` — depends on jest 29.x internals: `@jest/globals@^29.2.1`, `@jest/create-cache-key-function@^29.2.1`, `babel-jest@^29.2.1`, `jest-environment-jsdom@^29.2.1`, `jest-snapshot@^29.2.1`. The Expo team has not migrated jest-expo to jest 30 yet.\n\nWithout an explicit pin here, `npm install --legacy-peer-deps` lets npm treat the root-hoisted `jest@30` as satisfying `jest-expo`'s optional `jest >=29` peer, so jest is not installed locally. At test time, Node's module resolution then walks up to the root `jest-runtime@30` while `jest-environment-jsdom@29` (a hard dep of jest-expo, installed locally) creates the moduleMocker via `jest-mock@29`. jest 30's runtime calls `_moduleMocker.clearMocksOnScope`, a method that only exists in jest-mock 30 — so CI fails with:\n\n```\nTypeError: this._moduleMocker.clearMocksOnScope is not a function\n```\n\nPinning `jest@29.7.0` in this subdir's `package.json` forces npm to install a complete jest 29 toolchain locally (since the root's jest 30 no longer satisfies the explicit `29.7.0` request). Node's lookup from this dir finds the local v29 internals before walking up. Root and every other package keep jest 30; only this expo test runs on jest 29.\n\n**Remove the pin** when jest-expo ships a jest-30-compatible release — at which point this subdir can fall back to whatever the workspace root provides.\n","isInternal":false,"tokens":608,"sizeBytes":2241},{"name":"README.md","path":"packages/core/supabase-js/test/integration/next/README.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/core/supabase-js/test/integration/next/README.md","title":"next Documentation","category":"plugin-manifest","format":"markdown","content":"<a href=\"https://demo-nextjs-with-supabase.vercel.app/\">\n  <img alt=\"Next.js and Supabase Starter Kit - the fastest way to build apps with Next.js and Supabase\" src=\"https://demo-nextjs-with-supabase.vercel.app/opengraph-image.png\">\n  <h1 align=\"center\">Next.js and Supabase Starter Kit</h1>\n</a>\n\n<p align=\"center\">\n The fastest way to build apps with Next.js and Supabase\n</p>\n\n<p align=\"center\">\n  <a href=\"#features\"><strong>Features</strong></a> ·\n  <a href=\"#demo\"><strong>Demo</strong></a> ·\n  <a href=\"#deploy-to-vercel\"><strong>Deploy to Vercel</strong></a> ·\n  <a href=\"#clone-and-run-locally\"><strong>Clone and run locally</strong></a> ·\n  <a href=\"#feedback-and-issues\"><strong>Feedback and issues</strong></a>\n  <a href=\"#more-supabase-examples\"><strong>More Examples</strong></a>\n</p>\n<br/>\n\n## Features\n\n- Works across the entire [Next.js](https://nextjs.org) stack\n  - App Router\n  - Pages Router\n  - Middleware\n  - Client\n  - Server\n  - It just works!\n- supabase-ssr. A package to configure Supabase Auth to use cookies\n- Password-based authentication block installed via the [Supabase UI Library](https://supabase.com/ui/docs/nextjs/password-based-auth)\n- Styling with [Tailwind CSS](https://tailwindcss.com)\n- Components with [shadcn/ui](https://ui.shadcn.com/)\n- Optional deployment with [Supabase Vercel Integration and Vercel deploy](#deploy-your-own)\n  - Environment variables automatically assigned to Vercel project\n\n## Demo\n\nYou can view a fully working demo at [demo-nextjs-with-supabase.vercel.app](https://demo-nextjs-with-supabase.vercel.app/).\n\n## Deploy to Vercel\n\nVercel deployment will guide you through creating a Supabase account and project.\n\nAfter installation of the Supabase integration, all relevant environment variables will be assigned to the project so the deployment is fully functioning.\n\n[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fnext.js%2Ftree%2Fcanary%2Fexamples%2Fwith-supabase&project-name=nextjs-with-supabase&repository-name=nextjs-with-supabase&demo-title=nextjs-with-supabase&demo-description=This+starter+configures+Supabase+Auth+to+use+cookies%2C+making+the+user%27s+session+available+throughout+the+entire+Next.js+app+-+Client+Components%2C+Server+Components%2C+Route+Handlers%2C+Server+Actions+and+Middleware.&demo-url=https%3A%2F%2Fdemo-nextjs-with-supabase.vercel.app%2F&external-id=https%3A%2F%2Fgithub.com%2Fvercel%2Fnext.js%2Ftree%2Fcanary%2Fexamples%2Fwith-supabase&demo-image=https%3A%2F%2Fdemo-nextjs-with-supabase.vercel.app%2Fopengraph-image.png)\n\nThe above will also clone the Starter kit to your GitHub, you can clone that locally and develop locally.\n\nIf you wish to just develop locally and not deploy to Vercel, [follow the steps below](#clone-and-run-locally).\n\n## Clone and run locally\n\n1. You'll first need a Supabase project which can be made [via the Supabase dashboard](https://database.new)\n\n2. Create a Next.js app using the Supabase Starter template npx command\n\n   ```bash\n   npx create-next-app --example with-supabase with-supabase-app\n   ```\n\n   ```bash\n   yarn create next-app --example with-supabase with-supabase-app\n   ```\n\n   ```bash\n   pnpm create next-app --example with-supabase with-supabase-app\n   ```\n\n3. Use `cd` to change into the app's directory\n\n   ```bash\n   cd with-supabase-app\n   ```\n\n4. Rename `.env.example` to `.env.local` and update the following:\n\n   ```\n   NEXT_PUBLIC_SUPABASE_URL=[INSERT SUPABASE PROJECT URL]\n   NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=[INSERT SUPABASE PROJECT API PUBLISHABLE KEY]\n   ```\n\n   Both `NEXT_PUBLIC_SUPABASE_URL` and `NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY` can be found in [your Supabase project's API settings](https://supabase.com/dashboard/project/_?showConnect=true)\n\n5. You can now run the Next.js local development server:\n\n   ```bash\n   npm run dev\n   ```\n\n   The starter kit should now be running on [localhost:3000](http://localhost:3000/).\n\n6. This template comes with the default shadcn/ui style initialized. If you instead want other ui.shadcn styles, delete `components.json` and [re-install shadcn/ui](https://ui.shadcn.com/docs/installation/next)\n\n> Check out [the docs for Local Development](https://supabase.com/docs/guides/getting-started/local-development) to also run Supabase locally.\n\n## Feedback and issues\n\nPlease file feedback and issues over on the [Supabase GitHub org](https://github.com/supabase/supabase/issues/new/choose).\n\n## More Supabase examples\n\n- [Next.js Subscription Payments Starter](https://github.com/vercel/nextjs-subscription-payments)\n- [Cookie-based Auth and the Next.js 13 App Router (free course)](https://youtube.com/playlist?list=PL5S4mPUpp4OtMhpnp93EFSo42iQ40XjbF)\n- [Supabase Auth and the Next.js App Router](https://github.com/supabase/supabase/tree/master/examples/auth/nextjs)\n","isInternal":false,"tokens":1381,"sizeBytes":4865},{"name":"README.md","path":"packages/shared/tracing/README.md","rawUrl":"https://raw.githubusercontent.com/supabase/supabase-js/HEAD/packages/shared/tracing/README.md","title":"tracing Documentation","category":"plugin-manifest","format":"markdown","content":"# @supabase/tracing\n\nW3C/OpenTelemetry trace context propagation utilities for the Supabase JS SDK.\n\nThis package provides utilities for extracting, parsing, validating, and propagating trace context headers according to the [W3C Trace Context](https://www.w3.org/TR/trace-context/) specification.\n\n## Features\n\n- Build a trace context extractor from a caller-supplied OpenTelemetry API object\n- Parse and validate W3C `traceparent` headers\n- Validate target URLs for trace propagation\n- Default Supabase domain allowlist\n- TypeScript type definitions\n- Zero dependencies — this package never imports `@opentelemetry/api`; callers pass the API object in\n\n## Installation\n\nThis package is typically used internally by `@supabase/supabase-js` and does not need to be installed directly.\n\n## Usage\n\n### Create a Trace Context Extractor\n\n```typescript\nimport { createTraceContextExtractor } from '@supabase/tracing'\nimport { propagation, context } from '@opentelemetry/api'\n\n// The caller owns the OpenTelemetry dependency and passes it in.\nconst extract = createTraceContextExtractor({ propagation, context })\n\nconst traceContext = extract()\n// { traceparent, tracestate, baggage } or null when there is no active trace\n```\n\n### Parse Traceparent Header\n\n```typescript\nimport { parseTraceParent } from '@supabase/tracing'\n\nconst parsed = parseTraceParent('00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01')\n\nconsole.log(parsed)\n// {\n//   version: '00',\n//   traceId: '0af7651916cd43dd8448eb211c80319c',\n//   parentId: 'b7ad6b7169203331',\n//   traceFlags: '01',\n//   isSampled: true\n// }\n```\n\n### Validate Target URLs\n\n```typescript\nimport { shouldPropagateToTarget } from '@supabase/tracing'\n\nconst targets = [\n  'myproject.supabase.co',\n  /.*\\.supabase\\.co$/,\n  (url) => url.hostname === 'localhost',\n]\n\nconst shouldPropagate = shouldPropagateToTarget(\n  'https://myproject.supabase.co/rest/v1/table',\n  targets\n)\n// true\n```\n\n### Get Default Targets\n\n```typescript\nimport { getDefaultPropagationTargets } from '@supabase/tracing'\n\nconst targets = getDefaultPropagationTargets('https://myproject.supabase.co')\n// Returns array of default Supabase domains\n```\n\n## Type Definitions\n\n```typescript\ninterface TraceContext {\n  traceparent?: string\n  tracestate?: string\n  baggage?: string\n}\n\ninterface ParsedTraceParent {\n  version: string\n  traceId: string\n  parentId: string\n  traceFlags: string\n  isSampled: boolean\n}\n\ntype TracePropagationTarget = string | RegExp | ((url: URL) => boolean)\n```\n\n## License\n\nMIT\n","isInternal":false,"tokens":632,"sizeBytes":2517}],"systemPromptSnippet":"<yakaai_skills repo=\"supabase/supabase-js\">\n<!-- File: AGENTS.md (Tokens: ~1154 | Category: root-instruction) -->\n# Agent instructions\n\nEntry point for AI/LLM agents working in or with this repository. Pointers below; nothing canonical lives in this file.\n\n## Repository overview\n\n- [`README.md`](./README.md) — what this repo is, package list, quick start\n- [`CONTRIBUTING.md`](./CONTRIBUTING.md) — contribution guidelines, commit format, PR process\n- [`.claude/CLAUDE.md`](./.claude/CLAUDE.md) — development conventions, Nx commands, testing matrix, library-specific notes (read by Claude Code; the canonical development-conventions doc)\n- [`.cursor/.cursorrules`](./.cursor/.cursorrules) — same conventions for Cursor (read by Cursor IDE)\n\n## Agent skills\n\nReusable agent skills for working in this Nx workspace (Nx-related: `nx-workspace`, `nx-generate`, `nx-import`, `nx-plugins`, `nx-run-tasks`, `link-workspace-packages`) live at:\n\n- [`.agents/skills/`](./.agents/skills/) — vendor-neutral location (Agent Skills spec)\n- [`.claude/skills/`](./.claude/skills/) — mirrored copy read by Claude Code by literal path\n\nBoth directories currently hold the same content. Treat `.agents/skills/` as the source of truth; the `.claude/skills/` copy is kept in sync until Claude Code can discover skills from `.agents/skills/` directly.\n\n## Per-package usage\n\nEach package has its own README with usage examples and API notes:\n\n- [`packages/core/supabase-js/README.md`](./packages/core/supabase-js/README.md) — `@supabase/supabase-js` (main isomorphic client)\n- [`packages/core/auth-js/README.md`](./packages/core/auth-js/README.md) — `@supabase/auth-js`\n- [`packages/core/postgrest-js/README.md`](./packages/core/postgrest-js/README.md) — `@supabase/postgrest-js`\n- [`packages/core/realtime-js/README.md`](./packages/core/realtime-js/README.md) — `@supabase/realtime-js`\n- [`packages/core/storage-js/README.md`](./packages/core/storage-js/README.md) — `@supabase/storage-js`\n- [`packages/core/functions-js/README.md`](./packages/core/functions-js/README.md) — `@supabase/functions-js`\n\n## Helping users of a published `@supabase/*` package\n\nThe published npm tarball for each package ships everything an agent needs to give a correct, version-pinned answer. After `npm install @supabase/<package>`, an agent helping with that package should look inside `node_modules/@supabase/<package>/`:\n\n- `AGENTS.md` — per-package agent entry point (read this first; it points at the resources below).\n- `README.md` — usage and quick-start.\n- `src/` — full API source with TSDoc. Every public method and type has JSDoc, most have `@example` blocks. Read source here for the canonical, version-pinned answer instead of guessing from training data.\n- `migrations/` — per-theme migration notes for changes that need caller action.\n\nSource files ship via npm because every package's `files` array in `package.json` includes `\"src\"`. Migration notes ship via `\"migrations\"`. Per-package `AGENTS.md` ships via `\"AGENTS.md\"`. All three are version-pinned by virtue of being inside the installed package.\n\nWe deliberately do NOT ship per-package skills or duplicate docs-site content. The TSDoc-in-source IS the canonical API documentation for the SDK packages.\n\nFor higher-level Supabase guidance (the documentation site, MCP tools, schema management workflows, project setup), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills):\n\n```bash\nnpx skills add supabase/agent-skills\n```\n\nOr use the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins) to install the agent skills together with the Supabase MCP server in one step. See also: [Agent Skills documentation](https://agentskills.io/home).\n\n## Migration notes\n\nMigration notes live close to the code they describe, so they ship via npm alongside the package.\n\n- **Per-package migrations**: `packages/core/<package>/migrations/<theme>.md` — one file per migration theme (e.g. `<new-feature-adoption>.md`). Each file describes what changed, who is affected, and what callers need to do.\n- **Cross-cutting migrations** (affecting the whole repo or all packages): [`docs/MIGRATION.md`](./docs/MIGRATION.md) — one H2 section per theme (e.g. Node.js version drops). Low-frequency by design; split into a directory only if the file grows past a handful of themes.\n\n## Other documentation\n\n- [`docs/TESTING.md`](./docs/TESTING.md) — testing guide with Docker requirements per package\n- [`docs/RELEASE.md`](./docs/RELEASE.md) — release workflows and versioning strategy\n- [Security Policy](https://github.com/supabase/supabase-js/security/policy) — security policies and responsible disclosure\n- [`docs/JSR_PUBLISHING.md`](./docs/JSR_PUBLISHING.md) — JSR registry publishing\n\n<!-- File: .claude/CLAUDE.md (Tokens: ~7581 | Category: claude-rule) -->\n# Claude AI Instructions for Supabase JS Libraries Monorepo\n\nYou are assisting with development in a unified Nx monorepo that consolidates all Supabase JavaScript SDKs, built with Nx for optimal developer experience and maintainability. This strategic migration from 6 separate repositories addresses critical maintenance overhead, dependency duplication, and release coordination challenges while maintaining **zero breaking changes** for consumers.\n\n> **📚 Essential Documentation**: Always refer to these guides for detailed information:\n>\n> - **[CONTRIBUTING.md](../CONTRIBUTING.md)** - Development guidelines, commit format, PR process\n> - **[TESTING.md](../docs/TESTING.md)** - Complete testing guide with Docker requirements\n> - **[RELEASE.md](../docs/RELEASE.md)** - Release workflows and versioning strategy\n> - **[MIGRATION.md](../docs/MIGRATION.md)** - Cross-cutting migration notes (one H2 per theme). Per-package migrations live at `packages/core/<package>/migrations/`.\n> - **[Security Policy](https://github.com/supabase/supabase-js/security/policy)** - Security policies and responsible disclosure\n\n## Repository Architecture\n\n### Monorepo Structure\n\n```text\nsupabase-js/\n├── packages/core/\n│   ├── supabase-js/      # @supabase/supabase-js - Main isomorphic client for Supabase\n│   ├── auth-js/          # @supabase/auth-js - Authentication client\n│   ├── postgrest-js/     # @supabase/postgrest-js - PostgREST client for database operations\n│   ├── realtime-js/      # @supabase/realtime-js - Real-time subscriptions client\n│   ├── storage-js/       # @supabase/storage-js - File storage client\n│   └── functions-js/     # @supabase/functions-js - Edge Functions client\n├── CONTRIBUTING.md       # Contribution guidelines\n├── docs/                 # Comprehensive documentation guides\n│   ├── TESTING.md        # Testing guide\n│   ├── RELEASE.md        # Release workflows\n│   ├── MIGRATION.md      # Migration guide\n│   └── JSR_PUBLISHING.md # JSR publishing guide\n├── scripts/              # Automation scripts\n│   ├── release-canary.ts # Canary release automation\n│   ├── release-stable.ts # Stable release automation\n│   └── update-version-files.ts # Version management\n├── nx.json               # Nx workspace configuration\n├── tsconfig.base.json    # Base TypeScript configuration\n├── package.json          # Root package with workspace scripts\n└── commitlint.config.js  # Commit message validation\n```\n\n### Migration Benefits\n\n- **Dependency Consolidation**: 22 previously duplicated dependencies now centrally managed\n- **Atomic Changes**: Cross-library fixes in single PRs\n- **Immediate Integration Testing**: No manual release coordination needed\n- **Unified Versioning**: Fixed version mode with automated releases using `nx release`\n- **Intelligent Building**: Nx only rebuilds/tests what actually changed\n\n## Core Development Principles\n\n### 1. Zero Breaking Changes\n\nEvery change must maintain full backward compatibility. The migration itself introduces no breaking changes - all packages maintain their original npm names and APIs.\n\n### 2. Hybrid Release Model with Fixed Versioning\n\nUses automated canary releases with batched stable releases:\n\n- **Canary**: Every commit to master → prerelease (e.g., `2.80.1-canary.0`) with `canary` dist-tag\n- **Stable**: Manual promotion of validated canary to `latest` dist-tag\n- **Fixed Versioning**: All packages share identical version numbers (e.g., all at 2.80.0)\n- **Version Line**: Continuing with v2.x.x to maintain ecosystem stability\n\n**Three Release Workflows:**\n\n1. **Canary** (`.github/workflows/main-ci-release.yml`) - Automated on every master commit\n2. **Stable** (`.github/workflows/release-stable.yml`) - Manual by repository owners\n3. **Preview** (`.github/workflows/preview-release.yml`) - PR-based testing via pkg.pr.new\n\n> **📖 See [RELEASE.md](../docs/RELEASE.md) for complete release documentation**\n\n### 3. Workspace Dependencies\n\nInternal dependencies use the `*` protocol:\n\n```json\n// packages/core/supabase-js/package.json\n{\n  \"dependencies\": {\n    \"@supabase/auth-js\": \"*\",\n    \"@supabase/realtime-js\": \"*\",\n    \"@supabase/functions-js\": \"*\",\n    \"@supabase/storage-js\": \"*\",\n    \"@supabase/postgrest-js\": \"*\"\n  }\n}\n```\n\nNx automatically replaces `*` with the actual version during release.\n\n### 4. Affected-First Development\n\nAlways use `nx affected` commands to build/test only what changed, leveraging Nx's dependency graph intelligence.\n\n### 5. Conventional Commits\n\nUse conventional commit format for automated versioning:\n\n- `fix(auth-js): resolve token refresh race condition` → Patch release\n- `feat(realtime-js): add presence support` → Minor release\n- `feat(auth)!: remove deprecated method` → Major release\n- `chore(deps): update TypeScript to 5.8` → No version bump\n\n**Always use the interactive commit tool:**\n\n```bash\npnpm commit\n```\n\n> **📖 See [CONTRIBUTING.md](../CONTRIBUTING.md#commit-guidelines) for complete commit guidelines**\n\n## Essential Commands Reference\n\n### Building\n\n```bash\nnx run-many --target=build --all        # Build all packages\nnx build auth-js                         # Build specific package\nnx affected --target=build               # Build only affected\nnx build auth-js --watch                 # Development mode\n```\n\n### Testing\n\n```bash\n# Test specific packages (complete test suites with Docker setup/cleanup)\nnx test:auth auth-js                    # Complete auth-js test suite (handles Docker)\nnx test:storage storage-js              # Complete storage-js test suite (handles Docker)\nnx test:ci:postgrest postgrest-js      # Complete postgrest-js test suite (handles Docker)\nnx test functions-js                    # Standard test (uses testcontainers)\nnx test realtime-js                     # Standard test (no Docker needed)\nnx test supabase-js                     # Standard test (unit tests only)\n\n# Coverage reports\nnx test supabase-js --coverage\nnx test:coverage realtime-js\nnx test:ci functions-js                 # Includes coverage\n```\n\n**Docker Requirements:**\n\n| Package      | Docker Required | Infrastructure                  | Complete Test Command               | Individual Commands                                                                       |\n| ------------ | --------------- | ------------------------------- | ----------------------------------- | ----------------------------------------------------------------------------------------- |\n| auth-js      | ✅ Yes          | Auth Server + Postgres          | `nx test:auth auth-js`              | `nx test:suite auth-js`, `nx test:infra auth-js`, `nx test:clean-post auth-js`            |\n| storage-js   | ✅ Yes          | Storage API + PostgreSQL + Kong | `nx test:storage storage-js`        | `nx test:suite storage-js`, `nx test:infra storage-js`, `nx test:clean-post storage-js`   |\n| postgrest-js | ✅ Yes          | PostgREST + PostgreSQL          | `nx test:ci:postgrest postgrest-js` | `nx test:run postgrest-js`, `nx test:types postgrest-js`                                  |\n| functions-js | ✅ Yes          | Deno relay (testcontainers)     | `nx test functions-js`              | `nx test:ci functions-js` (with coverage)                                                 |\n| realtime-js  | ❌ No           | Mock WebSockets                 | `nx test realtime-js`               | `nx test:coverage realtime-js`, `nx test:watch realtime-js`                               |\n| supabase-js  | ❌ No           | Unit tests only                 | `nx test supabase-js`               | `nx test:all`, `nx test:unit`, `nx test:integration`, `nx test:coverage`, `nx test:watch` |\n\n**supabase-js Additional Test Commands:**\n\n```bash\nnx test:all supabase-js                  # Unit + integration + browser tests\nnx test:unit supabase-js                # Jest unit tests only\nnx test:integration supabase-js         # Node.js integration tests\nnx test:integration:browser supabase-js # Browser tests (requires Deno)\nnx test:edge-functions supabase-js      # Edge Functions tests\nnx test:deno supabase-js                # Deno runtime tests\nnx test:bun supabase-js                 # Bun runtime tests\nnx test:expo supabase-js                # React Native/Expo tests\nnx test:next supabase-js                # Next.js SSR tests\nnx test:node:playwright supabase-js     # WebSocket browser tests\nnx test:types supabase-js               # TypeScript type checking\nnx test:coverage supabase-js            # Coverage report\nnx test:watch supabase-js               # Watch mode\n```\n\n> **📖 See [TESTING.md](../docs/TESTING.md) for complete testing guide and troubleshooting**\n\n### Code Quality\n\n```bash\nnx run-many --target=lint --all          # Lint all packages\nnx lint storage-js                       # Lint specific package\nnx format                                 # Auto-format all code\nnx format:check                           # Check formatting\n```\n\n### Analysis\n\n```bash\nnx graph                                  # Interactive dependency graph\nnx show projects                          # List all projects\nnx affected --graph                       # Visualize affected projects\n```\n\n## Development Workflows\n\n### Cross-Library Bug Fix Example\n\n**Scenario**: Bug in supabase-js caused by realtime-js\n\n**Monorepo Solution**:\n\n1. Fix root cause in `packages/core/realtime-js/src/`\n2. Add unit test in `packages/core/realtime-js/test/`\n3. Add integration test in `packages/core/supabase-js/test/`\n4. Run complete test suites for both packages to verify impacts\n5. Commit: `fix(realtime-js): resolve reconnection logic affecting supabase-js`\n6. Single PR, single review, single release - all packages version together\n\n### Adding New Features\n\n1. Implement in appropriate library under `packages/core/[library]/src/`\n2. Write comprehensive unit tests in `packages/core/[library]/test/`\n3. If feature affects supabase-js, add integration tests there\n4. Update TypeScript types if needed\n5. Run complete test suite for the package before committing\n6. Use conventional commit: `feat(storage-js): add resumable uploads`\n\n### Quick Fix Workflow\n\n```bash\n# Even for single-library fixes:\ngit add .\ngit commit -m \"fix(auth-js): correct session expiry calculation\"\n# → Automatic canary: 2.80.1-canary.0 published to 'canary' dist-tag\n# Run complete test suite for the package:\nnx test:auth auth-js\n# After validation, manual promotion:\nnx release --tag=latest --yes  # Promotes to stable with same version for ALL packages\n```\n\n## TypeScript Configuration\n\n### Workspace Settings\n\n- **Target**: ES2022\n- **Module**: NodeNext\n- **Strict**: true\n- **Isolated Modules**: true (faster compilation)\n- **Composite**: true (incremental builds)\n\n### Per-Library Configs\n\nEach library has its own `tsconfig.json` extending the base configuration, allowing for library-specific adjustments while maintaining consistency.\n\n### TypeScript Project References Setup\n\nThis repository uses TypeScript project references for incremental builds and better type checking across packages.\n\n**What's Configured:**\n\n1. **tsconfig.base.json** - Base configuration inherited by all projects:\n   - `composite: true` - Enables project references\n   - `declaration: true` - Required by composite\n   - `moduleResolution: \"bundler\"` - Works with workspaces\n   - `isolatedModules: true` - Inherited but overridden in core packages\n   - `noImplicitOverride: true` - Inherited but overridden in core packages\n   - **No `customConditions`** - Removed to avoid conflicts with CommonJS packages\n\n2. **Root tsconfig.json** - References all projects in the monorepo:\n\n   ```json\n   {\n     \"extends\": \"./tsconfig.base.json\",\n     \"files\": [],\n     \"references\": [\n       { \"path\": \"./packages/core/auth-js\" },\n       { \"path\": \"./packages/core/realtime-js\" }\n       // ... all other packages\n     ]\n   }\n   ```\n\n3. **Core packages** (auth-js, realtime-js, postgrest-js, functions-js, storage-js):\n   - Keep `module: \"CommonJS\"` for backward compatibility\n   - Override `moduleResolution: \"Node\"` (required for CommonJS)\n   - Override `isolatedModules: false` (existing code doesn't use `export type`)\n   - Override `noImplicitOverride: false` (existing code doesn't use `override` keyword)\n   - Add `references` array pointing to dependencies (managed by `nx sync`)\n\n4. **Utils packages** (utils-fetch):\n   - Inherit `moduleResolution: \"bundler\"` from base\n   - Can optionally add `customConditions: [\"@supabase-js/source\"]` for source preference\n\n**Key Principles:**\n\n- ✅ **No Breaking Changes**: Build output is identical - only type-checking is affected\n- ✅ **Incremental Builds**: TypeScript only recompiles changed projects\n- ✅ **Better Performance**: Reduced memory usage during builds\n- ✅ **Automatic References**: Nx sync automatically maintains project references\n- ⚠️ **No `customConditions` in base**: Would conflict with `moduleResolution: \"Node\"`\n\n**When Adding New Packages:**\n\n1. Ensure `composite: true` and `declaration: true` are set\n2. Add `references` array pointing to dependencies\n3. If using CommonJS, override `moduleResolution: \"Node\"` and disable strict options\n4. Run `nx sync` to update root tsconfig.json automatically\n\n**Important Notes:**\n\n- TypeScript project references work WITHOUT `customConditions` - it's optional\n- `customConditions` only optimizes source file resolution during development\n- Core packages use `moduleResolution: \"Node\"` which is incompatible with `customConditions`\n- The `isolatedModules: false` override avoids requiring `export type` for type re-exports\n- All build outputs remain identical to pre-project-references setup\n\n## Testing Infrastructure\n\n### Unit Tests (Jest)\n\n- Location: `packages/core/[library]/test/`\n- Pattern: Mirror source structure\n- Principle: Test public APIs thoroughly\n- Mocking: Mock external dependencies\n\n### Integration Tests (Docker-based)\n\n**Complete Test Suites (Recommended)**:\n\n```bash\n# Auth-js: Complete test suite (handles Docker setup/cleanup automatically)\nnx test:auth auth-js\n\n# Storage-js: Complete test suite (handles Docker setup/cleanup automatically)\nnx test:storage storage-js\n\n# Postgrest-js: Complete test suite (handles Docker setup/cleanup automatically)\nnx test:ci:postgrest postgrest-js\n```\n\n**Manual Infrastructure Management** (for development):\n\n```bash\n# Auth-js\nnx test:infra auth-js        # Start Supabase CLI infrastructure\nnx test:suite auth-js        # Run tests (can run multiple times)\nnx test:clean-post auth-js   # Cleanup\n\n# Storage-js\nnx test:infra storage-js        # Start Supabase CLI infrastructure\nnx test:suite storage-js        # Run tests (can run multiple times)\nnx test:clean-post storage-js   # Cleanup\n\n# Postgrest-js\nnx test:infra postgrest-js        # Start Supabase CLI infrastructure\nnx test:run postgrest-js          # Run tests\nnx test:clean-post postgrest-js   # Cleanup\n```\n\n### Cross-Platform Tests (supabase-js)\n\nTests run against multiple environments:\n\n- Node.js (native)\n- Next.js (SSR/React)\n- Expo (React Native)\n- Bun (alternative runtime)\n- Deno (secure runtime)\n- Browser (via Puppeteer)\n\n## Library-Specific Considerations\n\n### supabase-js\n\n- Aggregates all other libraries\n- Primary integration testing location\n- Most complex cross-platform test suite (Node.js, Next.js, Expo, Bun, Deno, Browser)\n- Users typically interact through this package\n- Default branch: **master**\n\n### auth-js\n\n- Requires Docker for integration tests (GoTrue + PostgreSQL)\n- Complex session management logic\n- Security-critical - extra review care needed\n- See [auth-js README](../packages/core/auth-js/README.md) for details\n\n### realtime-js\n\n- WebSocket-based, timing-sensitive\n- Mock time in tests when possible\n- No Docker required (uses mock WebSockets)\n- See [realtime-js README](../packages/core/realtime-js/README.md) for details\n\n### storage-js\n\n- Requires Docker for integration tests (Storage API + PostgreSQL + Kong)\n- File handling varies by platform\n- See [storage-js README](../packages/core/storage-js/README.md) for details\n\n### postgrest-js\n\n- Pure HTTP client, easiest to test\n- Requires Docker for integration tests (PostgREST + PostgreSQL)\n- See [postgrest-js README](../packages/core/postgrest-js/README.md) for details\n\n### functions-js\n\n- Simplest library, minimal dependencies\n- Uses testcontainers for Deno relay\n- See [functions-js README](../packages/core/functions-js/README.md) for details\n\n## Code Style Guidelines\n\n### Formatting\n\n- Prettier handles all formatting (configured in `.prettierrc`)\n- Run `nx format` before committing\n- No formatting debates - Prettier decides\n\n### Patterns\n\n- Follow existing patterns in each library\n- Extract shared code to packages/shared/ when identified\n- Maintain consistency across monorepo\n\n### Documentation\n\n- JSDoc for all public APIs\n- README per package with examples\n- Update docs when changing APIs\n\n## Important Context\n\n### Branch Information\n\n**Current Repository:**\n\n- **Default branch**: `master` (v2 active development; all PRs land here by default; auto-publishes `@canary` on every push, stable releases are manual `workflow_dispatch` from this branch)\n- **Long-lived feature branch**: `v3` (v3-only breaking changes; `@next` prereleases are **manual `workflow_dispatch` only** — never auto-published; kept in sync with `master` by periodic `git merge master`)\n- **Repository URL**: `github.com/supabase/supabase-js`\n\n**Original Repository Branches** (for historical reference):\n\n- **master**: auth-js, postgrest-js, realtime-js, supabase-js\n- **main**: functions-js, storage-js\n\nWhen referencing original repository history or comparing changes, be aware of these branch name differences.\n\n### Package Publishing\n\n- All packages publish to npm under `@supabase` scope\n- Versions synchronized via fixed release mode (all packages always have same version)\n- Changelogs generated per package from conventional commits\n- \"No user-facing changes\" message for unchanged packages\n- Three dist-tags: `latest` (stable), `canary` (pre-release), `next` (legacy)\n\n### Docker Requirements\n\nIntegration tests for auth-js, functions-js, postgrest-js, and storage-js require Docker running locally:\n\n- **macOS/Windows**: Ensure Docker Desktop is installed and running\n- **Linux**: Ensure Docker daemon is running\n- **CI**: Docker is automatically available in GitHub Actions\n\nCheck [TESTING.md](../docs/TESTING.md) for port requirements and troubleshooting.\n\n### Commit Message Validation\n\nAll commits are validated using commitlint with strict rules:\n\n- **Type**: Required (feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert)\n- **Scope**: Required (auth, functions, postgrest, realtime, storage, supabase, repo, deps, ci, release, docs, scripts, misc)\n- **Subject**: Required, imperative mood, no period at end, max 100 characters\n- **Interactive Tool**: Use `pnpm commit` to ensure compliance\n\nSee [CONTRIBUTING.md](../CONTRIBUTING.md#commit-guidelines) for complete details.\n\n## Common Pitfalls & Solutions\n\n### Pitfall 1: Hardcoding Internal Versions\n\n❌ Wrong:\n\n```json\n\"@supabase/auth-js\": \"3.5.0\"\n```\n\n✅ Correct:\n\n```json\n\"@supabase/auth-js\": \"*\"\n```\n\n### Pitfall 2: Running npm Directly\n\n❌ Wrong:\n\n```bash\ncd packages/core/auth-js && npm test\n```\n\n✅ Correct:\n\n```bash\nnx test:auth auth-js\n```\n\n### Pitfall 3: Testing Everything\n\n❌ Wrong:\n\n```bash\nnx run-many --target=test --all  # Won't work - no standard test target for all packages\n```\n\n✅ Correct:\n\n```bash\n# Run complete test suite for the specific package\nnx test:auth auth-js\nnx test:storage storage-js\nnx test:ci:postgrest postgrest-js\nnx test functions-js\nnx test realtime-js\nnx test supabase-js\n```\n\n### Pitfall 4: Breaking Changes\n\n❌ Wrong: Changing public API signatures without proper process\n\n```typescript\n// Don't just change existing method signatures\n- signIn(email: string): Promise<void>\n+ signIn(credentials: Credentials): Promise<void>\n```\n\n✅ Correct: Add new methods, deprecate old ones gradually, use proper commit format\n\n```typescript\n// Add new method\nsignIn(credentials: Credentials): Promise<void>\n\n// Deprecate old method with backward compatibility\n/** @deprecated Use signIn(credentials) instead */\nsignInWithEmail(email: string): Promise<void> {\n  return this.signIn({ email })\n}\n```\n\nUse breaking change commit format when necessary:\n\n```bash\nfeat(auth)!: remove deprecated signInWithEmail method\n\nBREAKING CHANGE: The deprecated signInWithEmail method has been removed.\nUse signIn({ email }) instead.\n```\n\n### Pitfall 5: Running Commands Incorrectly\n\n❌ Wrong: Running npm commands directly in library directories\n\n```bash\ncd packages/core/auth-js\nnpm test\nnpm run build\n```\n\n✅ Correct: Use Nx commands from repository root\n\n```bash\nnx test:auth auth-js\nnx build auth-js --watch\n```\n\n### Pitfall 6: Not Using the Commit Tool\n\n❌ Wrong: Using git commit directly\n\n```bash\ngit commit -m \"fix auth bug\"  # Missing scope, will fail validation\n```\n\n✅ Correct: Use the interactive commit tool\n\n```bash\npnpm commit  # Guides you through proper format\n```\n\n### Pitfall 7: Not Checking Documentation\n\n❌ Wrong: Assuming you know how to run tests without checking\n\n```bash\nnx test storage-js  # Wrong - should use nx test:storage storage-js\n```\n\n✅ Correct: Check library README and TESTING.md first\n\n```bash\n# Read docs first\ncat packages/core/storage-js/README.md\ncat docs/TESTING.md\n# Then run tests with proper setup\n```\n\n## Pull Request Best Practices\n\n> **📖 See [CONTRIBUTING.md](../CONTRIBUTING.md#pull-request-process) for complete PR guidelines**\n\n### Before Creating PR\n\n1. **Ensure branch is up to date** with the PR's target branch (typically `master`; `v3` only for v3-only breaking changes):\n\n   ```bash\n   git checkout <target-branch>     # master or v3\n   git pull upstream <target-branch>\n   git checkout your-feature-branch\n   git rebase <target-branch>\n   ```\n\n2. **Run all necessary checks:**\n\n   ```bash\n   nx format                    # Format code\n   # Run complete test suite for affected packages individually\n   nx test:auth auth-js         # If auth-js changed\n   nx test:storage storage-js   # If storage-js changed\n   # ... etc for other packages\n   nx affected --target=build   # Build affected packages\n   ```\n\n3. **Use interactive commit tool:**\n\n   ```bash\n   pnpm commit\n   ```\n\n### PR Requirements\n\n- ✅ At least 1 approving review from a code owner\n- ✅ All status checks passing (CI/CD pipeline)\n- ✅ No merge conflicts with the base branch\n- ✅ Squash merge only (enforced by repository settings)\n\n### PR Description Template\n\n```markdown\n## Description\n\nBrief description of what this PR does\n\n## Type of Change\n\n- [ ] Bug fix (fix)\n- [ ] New feature (feat)\n- [ ] Breaking change (feat! or fix!)\n- [ ] Documentation update (docs)\n- [ ] Other (chore, refactor, etc.)\n\n## Testing\n\n- [ ] Unit tests added/updated\n- [ ] Integration tests added/updated (if applicable)\n- [ ] All tests passing locally\n\n## Checklist\n\n- [ ] Code formatted (`nx format`)\n- [ ] Tests passing (run complete test suites for affected packages)\n- [ ] Builds passing (`nx affected --target=build`)\n- [ ] Used conventional commits\n- [ ] Documentation updated (if needed)\n```\n\n### Requesting Preview Releases\n\nIf you need to test your changes before merging:\n\n1. Create your PR\n2. Comment: \"Can a maintainer add the preview label for testing?\"\n3. Wait for maintainer to add `trigger: preview` label\n4. Follow instructions in automated comment to install preview packages\n\n## Helpful Commands Reference\n\n### Analysis & Debugging\n\n```bash\n# Visualize dependency graph\nnx graph\n\n# Show what's affected by changes\nnx affected --graph\n\n# List all projects\nnx show projects\n\n# See project details\nnx show project auth-js --web\n\n# Clear Nx cache\nnx reset\n```\n\n### Development Workflow\n\n```bash\n# 1. Create feature branch\ngit checkout -b feat/your-feature\n\n# 2. Make changes in packages/core/[library]/\n\n# 3. Test continuously\nnx test [library] --watch\n\n# 4. Format before committing\nnx format\n\n# 5. Commit with tool\npnpm commit\n\n# 6. Before pushing\n# Run complete test suite for the package you changed\nnx test:auth auth-js         # If auth-js changed\nnx test:storage storage-js   # If storage-js changed\n# ... etc\nnx affected --target=build\nnx format:check\n\n# 7. Push and create PR\ngit push origin feat/your-feature\n```\n\n### Troubleshooting\n\n```bash\n# Clear cache and rebuild\nnx reset\nnx run-many --target=build --all\n\n# Clean install\nrm -rf node_modules\npnpm install\n\n# Check for errors\nnx run-many --target=lint --all\n\n# Run specific test file (for packages with standard test target)\nnx test realtime-js --testFile=RealtimeClient.test.ts\nnx test supabase-js --testFile=client.test.ts\n```\n\n## Additional Resources\n\n- **[README.md](../README.md)** - Repository overview and quick start\n- **[CONTRIBUTING.md](../CONTRIBUTING.md)** - Complete contribution guide\n- **[TESTING.md](../docs/TESTING.md)** - Comprehensive testing documentation\n- **[RELEASE.md](../docs/RELEASE.md)** - Release workflows and automation\n- **[MIGRATION.md](../docs/MIGRATION.md)** - Cross-cutting migration notes; per-package migrations live at `packages/core/<package>/migrations/`\n- **[Security Policy](https://github.com/supabase/supabase-js/security/policy)** - Security policy and reporting\n- **[Supabase Documentation](https://supabase.com/docs)** - Official Supabase docs\n- **[Nx Documentation](https://nx.dev)** - Nx monorepo documentation\n- **[Conventional Commits](https://www.conventionalcommits.org/)** - Commit format specification\n\n### Pitfall 5: Incomplete Cross-Library Testing\n\n❌ Wrong: Only testing in source library\n✅ Correct: Test in source library AND integration tests in supabase-js\n\n## Release Process\n\n### Hybrid Release Flow\n\n**Canary Releases (Automated)**:\n\n```bash\n# Triggered automatically on every commit to master\ngit commit -m \"fix(auth): resolve token issue\"\n# → Automatic CI: nx release --tag=canary --yes\n# → Published: 2.80.1-canary.0 to 'canary' dist-tag\n```\n\n**Stable Releases (Manual)**:\n\n```bash\n# 1. Validate canary version\n# Run complete test suites for packages individually\n\n# 2. Preview stable promotion\nnx release --dry-run\n\n# 3. Promote canary to stable\nnx release --tag=latest --yes\n\n# Alternative: Promote specific canary\nnx release --specifier=2.80.1 --tag=latest --yes\n```\n\n### What Happens During Canary Release\n\n1. CI detects conventional commits\n2. Determines version bump (patch/minor/major)\n3. Generates prerelease version (e.g., 2.80.1-canary.0)\n4. Updates all package.json files\n5. Replaces `*` with actual versions\n6. Publishes all packages to npm with `canary` dist-tag\n7. Triggers dogfooding workflows (when configured)\n\n### What Happens During Stable Release\n\n1. Promotes validated canary to `latest` dist-tag\n2. Generates curated per-package changelogs\n3. Creates GitHub release with notes\n4. All packages get identical stable version\n\n### Nx Release Configuration\n\nThe workspace is configured for hybrid releases in `nx.json`:\n\n```json\n{\n  \"release\": {\n    \"projectsRelationship\": \"fixed\",\n    \"version\": {\n      \"conventionalCommits\": true\n    },\n    \"changelog\": {\n      \"projectChangelogs\": true,\n      \"workspaceChangelog\": true\n    }\n  }\n}\n```\n\n### Release Command Reference\n\n```bash\n# Canary releases (automated in CI)\nnx release --tag=canary --yes                    # Publish to 'canary' dist-tag\nnx release --specifier=prerelease --tag=canary   # Force prerelease bump\n\n# Stable releases (manual promotion)\nnx release --tag=latest --yes                  # Promote to 'latest' dist-tag\nnx release --specifier=2.80.1 --tag=latest     # Promote specific version\n\n# Preview and debugging\nnx release --dry-run                           # Preview changes\nnx release --dry-run --verbose                 # Detailed preview\nnx release --first-release --dry-run           # First release preview\n\n# Version-specific releases\nnx release --specifier=patch --tag=latest      # Force patch bump\nnx release --specifier=minor --tag=latest      # Force minor bump\nnx release --specifier=major --tag=latest      # Force major bump\n```\n\n### Changelog Example\n\n```markdown\n## @supabase/realtime-js 2.80.1 (2025-09-16)\n\n- fix: correct reconnection logic (#123)\n\n## @supabase/auth-js 2.80.1 (2025-09-16)\n\n_No user-facing changes in this release._\n\n## @supabase/supabase-js 2.80.1 (2025-09-16)\n\n_No user-facing changes in this release._\n```\n\n## When Providing Code Suggestions\n\n1. **Consider Monorepo Impact**: Changes might affect multiple packages - always check dependencies\n2. **Use Nx Commands**: Always prefer `nx` over direct `npm` for workspace operations\n3. **Suggest Complete Test Suites**: Use complete test suites (`nx test:auth auth-js`, `nx test:storage storage-js`, etc.) for packages individually\n4. **Respect Fixed Versioning**: All packages version together - no independent versioning\n5. **Maintain Compatibility**: Never introduce breaking changes without proper process\n6. **Check Testing Requirements**: Be aware of Docker requirements for integration tests\n7. **Extract Shared Code**: Identify patterns that could be shared across packages\n8. **Follow Conventions**: Use existing patterns and structures within each library\n9. **Document Changes**: Update JSDoc and READMEs when changing public APIs\n10. **Use Conventional Commits**: Always suggest proper commit format with scope\n\n## Quick Decision Tree\n\n**Q: Where does this code belong?**\n\n- Authentication logic → auth-js\n- Database queries → postgrest-js\n- Real-time subscriptions → realtime-js\n- File operations → storage-js\n- Edge function calls → functions-js\n- Integration of above → supabase-js\n- Shared utilities → packages/shared/ (create if needed)\n\n**Q: How to test this change?**\n\n1. Unit test in source library\n2. Integration test in supabase-js if affects it\n3. Run complete test suite for the package:\n   - `nx test:auth auth-js` (handles Docker automatically)\n   - `nx test:storage storage-js` (handles Docker automatically)\n   - `nx test:ci:postgrest postgrest-js` (handles Docker automatically)\n   - `nx test functions-js` (uses testcontainers)\n   - `nx test realtime-js` (no Docker needed)\n   - `nx test supabase-js` (unit tests only)\n4. Run complete test suites for all affected packages individually\n\n**Q: How will this release?**\n\n- All packages version together in fixed mode\n- Your commit triggers automatic canary release for ALL packages\n- Weekly promotion of validated canary to stable\n- Unchanged packages show \"No user-facing changes\"\n- Single npm install updates entire SDK suite\n\nRemember: This monorepo optimizes for developer experience and maintenance efficiency while ensuring zero breaking changes for the millions of developers using Supabase SDKs.\n\n<!-- nx configuration start-->\n<!-- Leave the start & end comments to automatically receive updates. -->\n\n## General Guidelines for working with Nx\n\n- For navigating/exploring the workspace, invoke the `nx-workspace` skill first - it has patterns for querying projects, targets, and dependencies\n- When running tasks (for example build, lint, test, e2e, etc.), always prefer running the task through `nx` (i.e. `nx run`, `nx run-many`, `nx affected`) instead of using the underlying tooling directly\n- Prefix nx commands with the workspace's package manager (e.g., `pnpm nx build`, `npm exec nx test`) - avoids using globally installed CLI\n- You have access to the Nx MCP server and its tools, use them to help the user\n- For Nx plugin best practices, check `node_modules/@nx/<plugin>/PLUGIN.md`. Not all plugins have this file - proceed without it if unavailable.\n- NEVER guess CLI flags - always check nx_docs or `--help` first when unsure\n\n## Scaffolding & Generators\n\n- For scaffolding tasks (creating apps, libs, project structure, setup), ALWAYS invoke the `nx-generate` skill FIRST before exploring or calling MCP tools\n\n## When to use nx_docs\n\n- USE for: advanced config options, unfamiliar flags, migration guides, plugin configuration, edge cases\n- DON'T USE for: basic generator syntax (`nx g @nx/react:app`), standard commands, things you already know\n- The `nx-generate` skill handles generator discovery internally - don't call nx_docs just to look up generator syntax\n\n<!-- nx configuration end-->\n\n<!-- File: .agents/skills/link-workspace-packages/SKILL.md (Tokens: ~772 | Category: anthropic-skill) -->\n---\nname: link-workspace-packages\ndescription: 'Link workspace packages in monorepos (npm, yarn, pnpm, bun). USE WHEN: (1) you just created or generated new packages and need to wire up their dependencies, (2) user imports from a sibling package and needs to add it as a dependency, (3) you get resolution errors for workspace packages (@org/*) like \"cannot find module\", \"failed to resolve import\", \"TS2307\", or \"cannot resolve\". DO NOT patch around with tsconfig paths or manual package.json edits - use the package manager''s workspace commands to fix actual linking.'\n---\n\n# Link Workspace Packages\n\nAdd dependencies between packages in a monorepo. All package managers support workspaces but with different syntax.\n\n## Detect Package Manager\n\nCheck whether there's a `packageManager` field in the root-level `package.json`.\n\nAlternatively check lockfile in repo root:\n\n- `pnpm-lock.yaml` → pnpm\n- `yarn.lock` → yarn\n- `bun.lock` / `bun.lockb` → bun\n- `package-lock.json` → npm\n\n## Workflow\n\n1. Identify consumer package (the one importing)\n2. Identify provider package(s) (being imported)\n3. Add dependency using package manager's workspace syntax\n4. Verify symlinks created in consumer's `node_modules/`\n\n---\n\n## pnpm\n\nUses `workspace:` protocol - symlinks only created when explicitly declared.\n\n```bash\n# From consumer directory\npnpm add @org/ui --workspace\n\n# Or with --filter from anywhere\npnpm add @org/ui --filter @org/app --workspace\n```\n\nResult in `package.json`:\n\n```json\n{ \"dependencies\": { \"@org/ui\": \"workspace:*\" } }\n```\n\n---\n\n## yarn (v2+/berry)\n\nAlso uses `workspace:` protocol.\n\n```bash\nyarn workspace @org/app add @org/ui\n```\n\nResult in `package.json`:\n\n```json\n{ \"dependencies\": { \"@org/ui\": \"workspace:^\" } }\n```\n\n---\n\n## npm\n\nNo `workspace:` protocol. npm auto-symlinks workspace packages.\n\n```bash\nnpm install @org/ui --workspace @org/app\n```\n\nResult in `package.json`:\n\n```json\n{ \"dependencies\": { \"@org/ui\": \"*\" } }\n```\n\nnpm resolves to local workspace automatically during install.\n\n---\n\n## bun\n\nSupports `workspace:` protocol (pnpm-compatible).\n\n```bash\ncd packages/app && bun add @org/ui\n```\n\nResult in `package.json`:\n\n```json\n{ \"dependencies\": { \"@org/ui\": \"workspace:*\" } }\n```\n\n---\n\n## Examples\n\n**Example 1: pnpm - link ui lib to app**\n\n```bash\npnpm add @org/ui --filter @org/app --workspace\n```\n\n**Example 2: npm - link multiple packages**\n\n```bash\nnpm install @org/data-access @org/ui --workspace @org/dashboard\n```\n\n**Example 3: Debug \"Cannot find module\"**\n\n1. Check if dependency is declared in consumer's `package.json`\n2. If not, add it using appropriate command above\n3. Run install (`pnpm install`, `npm install`, etc.)\n\n## Notes\n\n- Symlinks appear in `<consumer>/node_modules/@org/<package>`\n- **Hoisting differs by manager:**\n  - npm/bun: hoist shared deps to root `node_modules`\n  - pnpm: no hoisting (strict isolation, prevents phantom deps)\n  - yarn berry: uses Plug'n'Play by default (no `node_modules`)\n- Root `package.json` should have `\"private\": true` to prevent accidental publish\n\n<!-- File: .agents/skills/nx-generate/SKILL.md (Tokens: ~1645 | Category: anthropic-skill) -->\n---\nname: nx-generate\ndescription: Generate code using nx generators. INVOKE IMMEDIATELY when user mentions scaffolding, setup, structure, creating apps/libs, or setting up project structure. Trigger words - scaffold, setup, create a ... app, create a ... lib, project structure, generate, add a new project. ALWAYS use this BEFORE calling nx_docs or exploring - this skill handles discovery internally.\nsubagent: general-purpose\ncontext: fork\n---\n\n# Run Nx Generator\n\nNx generators are powerful tools that scaffold projects, make automated code migrations or automate repetitive tasks in a monorepo. They ensure consistency across the codebase and reduce boilerplate work.\n\nThis skill applies when the user wants to:\n\n- Create new projects like libraries or applications\n- Scaffold features or boilerplate code\n- Run workspace-specific or custom generators\n- Do anything else that an nx generator exists for\n\n## Key Principles\n\n1. **Always use `--no-interactive`** - Prevents prompts that would hang execution\n2. **Read the generator source code** - The schema alone is not enough; understand what the generator actually does\n3. **Match existing repo patterns** - Study similar artifacts in the repo and follow their conventions\n4. **Verify with lint/test/build/typecheck etc.** - Generated code must pass verification. The listed targets are just an example, use what's appropriate for this workspace.\n\n## Steps\n\n### 1. Discover Available Generators\n\nUse the Nx CLI to discover available generators:\n\n- List all generators for a plugin: `npx nx list @nx/react`\n- View available plugins: `npx nx list`\n\nThis includes plugin generators (e.g., `@nx/react:library`) and local workspace generators.\n\n### 2. Match Generator to User Request\n\nIdentify which generator(s) could fulfill the user's needs. Consider what artifact type they want, which framework is relevant, and any specific generator names mentioned.\n\n**IMPORTANT**: When both a local workspace generator and an external plugin generator could satisfy the request, **always prefer the local workspace generator**. Local generators are customized for the specific repo's patterns.\n\nIf no suitable generator exists, you can stop using this skill. However, the burden of proof is high—carefully consider all available generators before deciding none apply.\n\n### 3. Get Generator Options\n\nUse the `--help` flag to understand available options:\n\n```bash\nnpx nx g @nx/react:library --help\n```\n\nPay attention to required options, defaults that might need overriding, and options relevant to the user's request.\n\n### Library Buildability\n\n**Default to non-buildable libraries** unless there's a specific reason for buildable.\n\n| Type                        | When to use                                                       | Generator flags                     |\n| --------------------------- | ----------------------------------------------------------------- | ----------------------------------- |\n| **Non-buildable** (default) | Internal monorepo libs consumed by apps                           | No `--bundler` flag                 |\n| **Buildable**               | Publishing to npm, cross-repo sharing, stable libs for cache hits | `--bundler=vite` or `--bundler=swc` |\n\nNon-buildable libs:\n\n- Export `.ts`/`.tsx` source directly\n- Consumer's bundler compiles them\n- Faster dev experience, less config\n\nBuildable libs:\n\n- Have their own build target\n- Useful for stable libs that rarely change (cache hits)\n- Required for npm publishing\n\n**If unclear, ask the user:** \"Should this library be buildable (own build step, better caching) or non-buildable (source consumed directly, simpler setup)?\"\n\n### 4. Read Generator Source Code\n\n**This step is critical.** The schema alone does not tell you everything. Reading the source code helps you:\n\n- Know exactly what files will be created/modified and where\n- Understand side effects (updating configs, installing deps, etc.)\n- Identify behaviors and options not obvious from the schema\n- Understand how options interact with each other\n\nTo find generator source code:\n\n- For plugin generators: Use `node -e \"console.log(require.resolve('@nx/<plugin>/generators.json'));\"` to find the generators.json, then locate the source from there\n- If that fails, read directly from `node_modules/<plugin>/generators.json`\n- For local generators: Typically in `tools/generators/` or a local plugin directory. Search the repo for the generator name.\n\nAfter reading the source, reconsider: Is this the right generator? If not, go back to step 2.\n\n> **⚠️ `--directory` flag behavior can be misleading.**\n> It should specify the full path of the generated library or component, not the parent path that it will be generated in.\n>\n> ```bash\n> # ✅ Correct - directory is the full path for the library\n> nx g @nx/react:library --directory=libs/my-lib\n> # generates libs/my-lib/package.json and more\n>\n> # ❌ Wrong - this will create files at libs and libs/src/...\n> nx g @nx/react:library --name=my-lib --directory=libs\n> # generates libs/package.json and more\n> ```\n\n### 5. Examine Existing Patterns\n\nBefore generating, examine the target area of the codebase:\n\n- Look at similar existing artifacts (other libraries, applications, etc.)\n- Identify naming conventions, file structures, and configuration patterns\n- Note which test runners, build tools, and linters are used\n- Configure the generator to match these patterns\n\n### 6. Dry-Run to Verify File Placement\n\n**Always run with `--dry-run` first** to verify files will be created in the correct location:\n\n```bash\nnpx nx g @nx/react:library --name=my-lib --dry-run --no-interactive\n```\n\nReview the output carefully. If files would be created in the wrong location, adjust your options based on what you learned from the generator source code.\n\nNote: Some generators don't support dry-run (e.g., if they install npm packages). If dry-run fails for this reason, proceed to running the generator for real.\n\n### 7. Run the Generator\n\nExecute the generator:\n\n```bash\nnx generate <generator-name> <options> --no-interactive\n```\n\n> **Tip:** New packages often need workspace dependencies wired up (e.g., importing shared types, being consumed by apps). The `link-workspace-packages` skill can help add these correctly.\n\n### 8. Modify Generated Code (If Needed)\n\nGenerators provide a starting point. Modify the output as needed to:\n\n- Add or modify functionality as requested\n- Adjust imports, exports, or configurations\n- Integrate with existing code patterns\n\n**Important:** If you replace or delete generated test files (e.g., `*.spec.ts`), either write meaningful replacement tests or remove the `test` target from the project configuration. Empty test suites will cause `nx test` to fail.\n\n### 9. Format and Verify\n\nFormat all generated/modified files:\n\n```bash\nnx format --fix\n```\n\nThis example is for built-in nx formatting with prettier. There might be other formatting tools for this workspace, use these when appropriate.\n\nThen verify the generated code works. Keep in mind that the changes you make with a generator or subsequent modifications might impact various projects so it's usually not enough to only run targets for the artifact you just created.\n\n```bash\n# these targets are just an example!\nnx run-many -t build,lint,test,typecheck\n```\n\nThese targets are common examples used across many workspaces. You should do research into other targets available for this workspace and its projects. CI configuration is usually a good guide for what the critical targets are that have to pass.\n\nIf verification fails with manageable issues (a few lint errors, minor type issues), fix them. If issues are extensive, attempt obvious fixes first, then escalate to the user with details about what was generated, what's failing, and what you've attempted.\n\n<!-- File: .agents/skills/nx-import/references/ESLINT.md (Tokens: ~1139 | Category: anthropic-skill) -->\n## ESLint\n\nESLint-specific guidance for `nx import`. For generic import issues (root deps, pnpm globs, project references), see `SKILL.md`.\n\n---\n\n### How `@nx/eslint/plugin` Works\n\n`@nx/eslint/plugin` scans for ESLint config files and creates a lint target for each project. It detects **both** flat config files (`eslint.config.{js,mjs,cjs,ts,mts,cts}`) and legacy config files (`.eslintrc.{json,js,cjs,mjs,yml,yaml}`).\n\n**Plugin options (set during `nx add @nx/eslint`):**\n\n```json\n{\n  \"plugin\": \"@nx/eslint/plugin\",\n  \"options\": {\n    \"targetName\": \"eslint:lint\"\n  }\n}\n```\n\n**Auto-installation**: `nx import` auto-detects ESLint config files and offers to install `@nx/eslint`. Accept the offer — it registers the plugin and updates `namedInputs.production` to exclude ESLint config files.\n\n---\n\n### Duplicate `lint` and `eslint:lint` Targets\n\nAfter import, projects will have **two** lint-related targets if the source `package.json` has a `\"lint\"` npm script:\n\n- `eslint:lint` — inferred by `@nx/eslint/plugin`; has proper caching and input/output tracking\n- `lint` — created by Nx from the npm script via `nx:run-script`; no caching intelligence, just wraps `npm run lint`\n\n**Fix**: Remove the `\"lint\"` script from each project's `package.json`. Keep `\"lint:fix\"` if present — there is no plugin-inferred equivalent for auto-fixing.\n\n---\n\n### Legacy `.eslintrc.*` Configs Linting Generated Files\n\nWhen `@nx/eslint/plugin` runs `eslint .` on a project with a legacy `.eslintrc.*` config that uses `parserOptions.project`, it tries to lint **all** files in the project directory including:\n\n- Generated `dist/**/*.d.ts` files (not in tsconfig `include`)\n- The `.eslintrc.js` config file itself (not in tsconfig `include`)\n\nThis causes `Parsing error: ESLint was configured to run on X using parserOptions.project, however that TSConfig does not include this file`.\n\n**Fix**: Add `ignorePatterns` to the `.eslintrc.*` config:\n\n```json\n// .eslintrc.json\n{\n  \"ignorePatterns\": [\"dist/**\"]\n}\n```\n\n```js\n// .eslintrc.js — also ignore the config file itself since module.exports isn't in tsconfig\nmodule.exports = {\n  ignorePatterns: ['dist/**', '.eslintrc.js'],\n  // ...\n}\n```\n\n---\n\n### Flat Config `.cjs` Files Self-Linting\n\nWhen a project uses `eslint.config.cjs` (CJS flat config), `eslint .` lints the config file itself. The `require()` call on line 1 triggers `@typescript-eslint/no-require-imports`.\n\n**Fix**: Add the config filename to the top-level `ignores` array:\n\n```js\nmodule.exports = tseslint.config(\n  {\n    ignores: ['dist/**', 'node_modules/**', 'eslint.config.cjs'],\n  }\n  // ...\n)\n```\n\nThe same applies to `eslint.config.js` in a CJS project (no `\"type\": \"module\"`) if it uses `require()`.\n\n---\n\n### `typescript-eslint` Version Conflict With ESLint 9\n\n`typescript-eslint@7.x` declares `peerDependencies: { \"eslint\": \"^8.56.0\" }`, but it is commonly used alongside `\"eslint\": \"^9.0.0\"`. npm treats this as a hard peer dep conflict and refuses to install.\n\n**Root cause**: `@nx/eslint` init adds `eslint@~8.57.0` at the workspace root (for its own peer deps). Workspace packages that request `eslint@^9.0.0` + `typescript-eslint@^7.0.0` trigger the conflict when npm resolves their deps.\n\n**Fix**: Upgrade `typescript-eslint` from `^7.0.0` to `^8.0.0` directly in the affected workspace package's `package.json`. The `tseslint.config()` API and `tseslint.configs.recommended` are identical between v7 and v8 — no config changes needed.\n\n```json\n// packages/my-package/package.json\n{\n  \"devDependencies\": {\n    \"typescript-eslint\": \"^8.0.0\"\n  }\n}\n```\n\n**Note**: npm's root-level `\"overrides\"` field does not force versions for workspace packages' direct dependencies — update each package.json individually.\n\n---\n\n### Mixed ESLint v8 and v9 in One Workspace\n\nLegacy v8 and flat-config v9 packages can coexist in the same workspace. Each package resolves its own `eslint` version. The root `eslint@~8.57.0` (added by `@nx/eslint` init) is used by legacy v8 packages; v9 packages get their own hoisted `eslint@9`.\n\n`@nx/eslint/plugin` infers `eslint:lint` targets for **both** config formats. Legacy packages run ESLint v8 with `.eslintrc.*`; flat-config packages run ESLint v9 with `eslint.config.*`. No special nx.json configuration is needed to support both simultaneously.\n\n<!-- File: .agents/skills/nx-import/references/JEST.md (Tokens: ~1847 | Category: anthropic-skill) -->\n## Jest\n\nJest-specific guidance for `nx import`. For the basic \"Jest Preset Missing\" fix (create `jest.preset.js`, install deps), see `SKILL.md`. This file covers deeper Jest integration issues.\n\n---\n\n### How `@nx/jest` Works\n\n`@nx/jest/plugin` scans for `jest.config.{ts,js,cjs,mjs,cts,mts}` and creates a `test` target for each project.\n\n**Plugin options:**\n\n```json\n{\n  \"plugin\": \"@nx/jest/plugin\",\n  \"options\": {\n    \"targetName\": \"test\"\n  }\n}\n```\n\n`npx nx add @nx/jest` does two things:\n\n1. **Registers `@nx/jest/plugin` in `nx.json`** — without this, no `test` targets are inferred\n2. Updates `namedInputs.production` to exclude test files\n\n**Gotcha**: `nx add @nx/jest` does NOT create `jest.preset.js` — that file is only generated when you run a generator (e.g. `@nx/jest:configuration`). For imports, you must create it manually (see \"Jest Preset\" section below).\n\n**Other gotcha**: If you create `jest.preset.js` manually but skip `npx nx add @nx/jest`, the plugin won't be registered and `nx run PROJECT:test` will fail with \"Cannot find target 'test'\". You need both.\n\n---\n\n### Jest Preset\n\nThe preset provides shared Jest configuration (test patterns, ts-jest transform, resolver, jsdom environment).\n\n**Root `jest.preset.js`:**\n\n```js\nconst nxPreset = require('@nx/jest/preset').default\nmodule.exports = { ...nxPreset }\n```\n\n**Project `jest.config.ts`:**\n\n```ts\nexport default {\n  displayName: 'my-lib',\n  preset: '../../jest.preset.js',\n  // project-specific overrides\n}\n```\n\nThe `preset` path is relative from the project root to the workspace root. Subdirectory imports preserve the original relative path (e.g. `../../jest.preset.js`), which resolves correctly if the import destination matches the source directory depth.\n\n---\n\n### Testing Dependencies\n\n#### Core (always needed)\n\n```\npnpm add -wD jest ts-jest @types/jest @nx/jest\n```\n\n#### Environment-specific\n\n- **DOM testing** (React, Vue, browser libs): `jest-environment-jsdom`\n- **Node testing** (APIs, CLIs): no extra deps (Jest defaults to `node` env, but Nx preset defaults to `jsdom`)\n\n#### React testing\n\n```\npnpm add -wD @testing-library/react @testing-library/jest-dom\n```\n\n#### React with Babel (non-ts-jest transform)\n\nSome React projects use Babel instead of ts-jest for JSX transformation:\n\n```\npnpm add -wD babel-jest @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript\n```\n\n**When**: Project `jest.config` has `transform` using `babel-jest` instead of `ts-jest`. Common in older Nx workspaces and CRA migrations.\n\n#### Vue testing\n\n```\npnpm add -wD @vue/test-utils\n```\n\nVue projects typically use Vitest (not Jest) — see VITE.md.\n\n---\n\n### `tsconfig.spec.json`\n\nJest projects need a `tsconfig.spec.json` that includes test files:\n\n```json\n{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../../dist/out-tsc\",\n    \"module\": \"commonjs\",\n    \"types\": [\"jest\", \"node\"]\n  },\n  \"include\": [\"jest.config.ts\", \"src/**/*.test.ts\", \"src/**/*.spec.ts\", \"src/**/*.d.ts\"]\n}\n```\n\n**Common issues after import:**\n\n- Missing `\"types\": [\"jest\", \"node\"]` — causes `describe`/`it`/`expect` to be unrecognized\n- Missing `\"module\": \"commonjs\"` — Jest doesn't support ESM by default (ts-jest transpiles to CJS)\n- `include` array missing test patterns — TypeScript won't check test files\n\n---\n\n### Jest vs Vitest Coexistence\n\nWorkspaces can have both:\n\n- **Jest**: Next.js apps, older React libs, Node libraries\n- **Vitest**: Vite-based React/Vue apps and libs\n\nBoth `@nx/jest/plugin` and `@nx/vite/plugin` (which infers Vitest targets) coexist without conflicts — they detect different config files (`jest.config.*` vs `vite.config.*`).\n\n**Target naming**: Both default to `test`. If a project somehow has both config files, rename one:\n\n```json\n{\n  \"plugin\": \"@nx/jest/plugin\",\n  \"options\": { \"targetName\": \"jest-test\" }\n}\n```\n\n---\n\n### `@testing-library/jest-dom` — Jest vs Vitest\n\nProjects migrating from Jest to Vitest (or workspaces with both) need different imports:\n\n**Jest** (in `test-setup.ts`):\n\n```ts\nimport '@testing-library/jest-dom'\n```\n\n**Vitest** (in `test-setup.ts`):\n\n```ts\nimport '@testing-library/jest-dom/vitest'\n```\n\nIf the source used Jest but the dest workspace uses Vitest for that project type, update the import path. Also add `@testing-library/jest-dom` to tsconfig `types` array.\n\n---\n\n### Non-Nx Source: Test Script Rewriting\n\nNx rewrites `package.json` scripts during init. Test scripts get broken:\n\n- `\"test\": \"jest\"` → `\"test\": \"nx test\"` (circular if no executor configured)\n- `\"test\": \"vitest run\"` → `\"test\": \"nx test run\"` (broken — `run` becomes an argument)\n\n**Fix**: Remove all rewritten test scripts. `@nx/jest/plugin` and `@nx/vite/plugin` infer test targets from config files.\n\n---\n\n### CI Atomization\n\n`@nx/jest/plugin` supports splitting tests per-file for CI parallelism:\n\n```json\n{\n  \"plugin\": \"@nx/jest/plugin\",\n  \"options\": {\n    \"targetName\": \"test\",\n    \"ciTargetName\": \"test-ci\"\n  }\n}\n```\n\nThis creates `test-ci--src/lib/foo.spec.ts` targets for each test file, enabling Nx Cloud distribution. Not relevant during import, but useful for post-import CI setup.\n\n---\n\n### Common Post-Import Issues\n\n1. **\"Cannot find target 'test'\"**: `@nx/jest/plugin` not registered in `nx.json`. Run `npx nx add @nx/jest` or manually add the plugin entry.\n\n2. **\"Cannot find module 'jest-preset'\"**: `jest.preset.js` missing at workspace root. Create it (see SKILL.md).\n\n3. **\"Cannot find type definition file for 'jest'\"**: Missing `@types/jest` or `tsconfig.spec.json` doesn't have `\"types\": [\"jest\", \"node\"]`.\n\n4. **Tests fail with \"Cannot use import statement outside a module\"**: `ts-jest` not installed or not configured as transform. Check `jest.config.ts` transform section.\n\n5. **Snapshot path mismatches**: After import, `__snapshots__` directories may have paths baked in. Run tests once with `--updateSnapshot` to regenerate.\n\n---\n\n## Fix Order\n\n### Subdirectory Import (Nx Source)\n\n1. `npx nx add @nx/jest` — registers plugin in `nx.json` (does NOT create `jest.preset.js`)\n2. Create `jest.preset.js` manually (see \"Jest Preset\" section above)\n3. Install deps: `pnpm add -wD jest jest-environment-jsdom ts-jest @types/jest`\n4. Install framework test deps: `@testing-library/react @testing-library/jest-dom` (React), `@vue/test-utils` (Vue)\n5. Verify `tsconfig.spec.json` has `\"types\": [\"jest\", \"node\"]`\n6. `nx run-many -t test`\n\n### Whole-Repo Import (Non-Nx Source)\n\n1. Remove rewritten test scripts from `package.json`\n2. `npx nx add @nx/jest` — registers plugin (does NOT create preset)\n3. Create `jest.preset.js` manually\n4. Install deps (same as above)\n5. Verify/fix `jest.config.*` — ensure `preset` path points to root `jest.preset.js`\n6. Verify/fix `tsconfig.spec.json` — add `types`, `module`, `include` if missing\n7. `nx run-many -t test`\n\n<!-- File: .agents/skills/nx-import/references/VITE.md (Tokens: ~4973 | Category: anthropic-skill) -->\n## Vite\n\nVite-specific guidance for `nx import`. For generic import issues (pnpm globs, root deps, project references, name collisions, ESLint, frontend tsconfig base settings, `@nx/react` typings, Jest preset, non-Nx source handling), see `SKILL.md`.\n\n---\n\n### `@nx/vite/plugin` Typecheck Target\n\n`@nx/vite/plugin` defaults `typecheckTargetName` to `\"vite:typecheck\"`. If the workspace expects `\"typecheck\"`, set it explicitly in `nx.json`. If `@nx/js/typescript` is also registered, rename one target to avoid conflicts (e.g. `\"tsc-typecheck\"` for the JS plugin).\n\nKeep both plugins only if the workspace has non-Vite pure TS libraries — `@nx/js/typescript` handles those while `@nx/vite/plugin` handles Vite projects.\n\n### @nx/vite Plugin Install Failure\n\nPlugin init loads `vite.config.ts` before deps are available. **Fix**: `pnpm add -wD vite @vitejs/plugin-react` (or `@vitejs/plugin-vue`) first, then `pnpm exec nx add @nx/vite`.\n\n### Vite `resolve.alias` and `__dirname` (Non-Nx Sources)\n\n**`__dirname` undefined** (CJS-only): Replace with `fileURLToPath(new URL('./src', import.meta.url))` from `'node:url'`.\n\n**`@/` path alias**: Vite's `resolve.alias` works at runtime but TS needs matching `\"paths\"`. Set `\"baseUrl\": \".\"` in project tsconfig.\n\n**PostCSS/Tailwind**: Verify `content` globs resolve correctly after import.\n\n### Missing TypeScript `types` (Non-Nx Sources)\n\nNon-Nx tsconfigs may not declare all needed types. Ensure Vite projects include `\"types\": [\"node\", \"vite/client\"]` in their tsconfig.\n\n### `noEmit` Fix: Vite-Specific Notes\n\nSee SKILL.md for the generic noEmit→composite fix. Vite-specific additions:\n\n- Non-Nx Vite projects often have **both** `tsconfig.app.json` and `tsconfig.node.json` with `noEmit` — fix both\n- Solution-style tsconfigs (`\"files\": [], \"references\": [...]`) may lack `extends`. Add `extends` pointing to the dest root `tsconfig.base.json` so base settings (`moduleResolution`, `lib`) apply.\n- This is safe — Vite/Vitest ignore TypeScript emit settings.\n\n### Dependency Version Conflicts\n\n**Shared Vite deps (both frameworks):** `vite`, `vitest`, `jsdom`, `@types/node`, `typescript` (dev)\n\n**Vite 6→7**: Typecheck fails (`Plugin<any>` type mismatch); build/serve still works. Fix: align versions.\n**Vitest 3→4**: Usually works; type conflicts may surface in shared test utils.\n\n---\n\n## React Router 7 (Vite-Based)\n\nReact Router 7 (`@react-router/dev`) uses Vite under the hood with a `vite.config.ts` and a `react-router.config.ts`. The `@nx/vite/plugin` detects `vite.config.ts` and creates inferred targets.\n\n### Targets\n\n`@nx/vite/plugin` creates `build`, `dev`, `serve` targets. The `build` target invokes the script defined in `package.json` (usually `react-router build`), not `vite build` directly.\n\n**No separate typecheck target from `@nx/vite/plugin`** — React Router 7 typegen is run as part of `typecheck` (e.g. `react-router typegen && tsc`). The `typecheck` target is inferred from the tsconfig. Keep the `typecheck` script in `package.json` if present; it is not rewritten.\n\n### tsconfig Notes\n\nReact Router 7 uses a single `tsconfig.json` (no `tsconfig.app.json`/`tsconfig.node.json` split). It includes:\n\n- `\"rootDirs\": [\".\", \"./.react-router/types\"]` — for generated type files; keep as-is\n- `\"paths\": { \"~/*\": [\"./app/*\"] }` — self-referential alias; keep as-is\n- `\"noEmit\": true` — replace with composite settings per SKILL.md\n\n### Build Output\n\nReact Router 7 outputs to `build/` (not `dist/`). Add `build` to the dest root `.gitignore`.\n\n### Generated Types Directory\n\nReact Router 7 generates `.react-router/` at the project root for route type generation. Add `.react-router` to the dest root `.gitignore`.\n\n---\n\n## TanStack Start (Vite-Based)\n\nTanStack Start uses Vinxi under the hood, which wraps Vite. Projects have a standard `vite.config.ts` that `@nx/vite/plugin` detects normally.\n\n### Targets\n\n`@nx/vite/plugin` creates `build`, `dev`, `preview`, `serve-static`, `typecheck` targets. The `build` target runs `vite build` which invokes the TanStack Start Vinxi pipeline (produces both client and SSR bundles).\n\n### tsconfig Notes\n\nTanStack Start uses a single `tsconfig.json` with `\"allowImportingTsExtensions\": true` and `\"noEmit\": true`. Apply the standard noEmit → composite fix. `allowImportingTsExtensions` is compatible with `emitDeclarationOnly: true` — no change needed.\n\n### `paths` Aliases\n\nTanStack Start commonly uses `\"#/*\": [\"./src/*\"]` and `\"@/*\": [\"./src/*\"]`. These are self-referential — keep as-is for a single-project app.\n\n### Uncommitted Source Repo\n\n`create-tan-stack` initializes a git repo but does NOT make an initial commit. Before importing, commit first:\n\n```bash\ngit -C /path/to/source add . && git -C /path/to/source commit -m \"Initial commit\"\n```\n\n### Generated and Build Directories\n\nTanStack Start / Vinxi / Nitro generate several directories that must be added to the dest root `.gitignore`:\n\n- `.vinxi` — Vinxi build cache\n- `.tanstack` — TanStack generated files\n- `.nitro` — Nitro build artifacts\n- `.output` — server-side build output (SSR/edge)\n\nThese are not covered by `dist` or `build`.\n\n---\n\n## React-Specific\n\n### React Dependencies\n\n**Production:** `react`, `react-dom`\n**Dev:** `@types/react`, `@types/react-dom`, `@vitejs/plugin-react`, `@testing-library/react`, `@testing-library/jest-dom`, `jsdom`\n**ESLint (Nx sources):** `eslint-plugin-import`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`, `eslint-plugin-react-hooks`\n**ESLint (`create-vite`):** `eslint-plugin-react-refresh`, `eslint-plugin-react-hooks` — self-contained flat configs can be left as-is\n**Nx plugins:** `@nx/react` (generators), `@nx/vite`, `@nx/vitest`, `@nx/eslint`\n\n### React TypeScript Configuration\n\nAdd `\"jsx\": \"react-jsx\"` — in `tsconfig.base.json` for single-framework workspaces, per-project for mixed (see Mixed section).\n\n### React ESLint Config\n\n```js\nimport nx from '@nx/eslint-plugin'\nimport baseConfig from '../../eslint.config.mjs'\nexport default [\n  ...baseConfig,\n  ...nx.configs['flat/react'],\n  { files: ['**/*.ts', '**/*.tsx'], rules: {} },\n]\n```\n\n### React Version Conflicts\n\nReact 18 (source) + React 19 (dest): pnpm may hoist mismatched `react-dom`, causing `TypeError: Cannot read properties of undefined (reading 'S')`. **Fix**: Align versions with `pnpm.overrides`.\n\n### `@testing-library/jest-dom` with Vitest\n\nIf source used Jest: change import to `@testing-library/jest-dom/vitest` in test-setup.ts, add to tsconfig `types`.\n\n---\n\n## Vue-Specific\n\n### Vue Dependencies\n\n**Production:** `vue` (plus `vue-router`, `pinia` if used)\n**Dev:** `@vitejs/plugin-vue`, `vue-tsc`, `@vue/test-utils`, `jsdom`\n**ESLint:** `eslint-plugin-vue`, `vue-eslint-parser`, `@vue/eslint-config-typescript`, `@vue/eslint-config-prettier`\n**Nx plugins:** `@nx/vue` (generators), `@nx/vite`, `@nx/vitest`, `@nx/eslint` (install AFTER deps — see below)\n\n### Vue TypeScript Configuration\n\nAdd to `tsconfig.base.json` (single-framework) or per-project (mixed):\n\n```json\n{ \"jsx\": \"preserve\", \"jsxImportSource\": \"vue\", \"resolveJsonModule\": true }\n```\n\n### `vue-shims.d.ts`\n\nVue SFC files need a type declaration. Usually exists in each project's `src/` and imports cleanly. If missing:\n\n```ts\ndeclare module '*.vue' {\n  import { defineComponent } from 'vue'\n  const component: ReturnType<typeof defineComponent>\n  export default component\n}\n```\n\n### `vue-tsc` Auto-Detection\n\nBoth `@nx/js/typescript` and `@nx/vite/plugin` auto-detect `vue-tsc` when installed — no manual config needed. Remove source scripts like `\"typecheck\": \"vue-tsc --noEmit\"`.\n\n### ESLint Plugin Installation Order (Critical)\n\n`@nx/eslint` init **crashes** if Vue ESLint deps aren't installed first (it loads all config files).\n\n**Correct order:**\n\n1. `pnpm add -wD eslint@^9 eslint-plugin-vue vue-eslint-parser @vue/eslint-config-typescript @typescript-eslint/parser @nx/eslint-plugin typescript-eslint`\n2. Create root `eslint.config.mjs`\n3. Then `npx nx add @nx/eslint`\n\n### Vue ESLint Config Pattern\n\n```js\nimport vue from 'eslint-plugin-vue'\nimport vueParser from 'vue-eslint-parser'\nimport tsParser from '@typescript-eslint/parser'\nimport baseConfig from '../../eslint.config.mjs'\nexport default [\n  ...baseConfig,\n  ...vue.configs['flat/recommended'],\n  {\n    files: ['**/*.vue'],\n    languageOptions: { parser: vueParser, parserOptions: { parser: tsParser } },\n  },\n  {\n    files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.vue'],\n    rules: { 'vue/multi-word-component-names': 'off' },\n  },\n]\n```\n\n**Important**: `vue-eslint-parser` override must come **AFTER** base config — `flat/typescript` sets the TS parser globally without a `files` filter, breaking `.vue` parsing.\n\n`vue-eslint-parser` must be an explicit pnpm dependency (strict resolution prevents transitive import).\n\n**Known issue**: Some generated Vue ESLint configs omit `vue-eslint-parser`. Use the pattern above instead.\n\n---\n\n## Mixed React + Vue\n\nWhen both frameworks coexist, several settings become per-project.\n\n### tsconfig `jsx` — Per-Project Only\n\n- React: `\"jsx\": \"react-jsx\"` in project tsconfig\n- Vue: `\"jsx\": \"preserve\"`, `\"jsxImportSource\": \"vue\"` in project tsconfig\n- Root: **NO** `jsx` setting\n\n### Typecheck — Auto-Detects Framework\n\n`@nx/vite/plugin` uses `vue-tsc` for Vue projects and `tsc` for React automatically.\n\n```json\n{\n  \"plugins\": [\n    { \"plugin\": \"@nx/eslint/plugin\", \"options\": { \"targetName\": \"lint\" } },\n    {\n      \"plugin\": \"@nx/vite/plugin\",\n      \"options\": {\n        \"buildTargetName\": \"build\",\n        \"typecheckTargetName\": \"typecheck\",\n        \"testTargetName\": \"test\"\n      }\n    }\n  ]\n}\n```\n\nRemove `@nx/js/typescript` if all projects use Vite. Keep it (renamed to `\"tsc-typecheck\"`) only for non-Vite pure TS libs.\n\n### ESLint — Three-Tier Config\n\n1. **Root**: Base rules only, no framework-specific rules\n2. **React projects**: Extend root + `nx.configs['flat/react']`\n3. **Vue projects**: Extend root + `vue.configs['flat/recommended']` + `vue-eslint-parser`\n\n**Required packages**: Shared (`eslint@^9`, `@nx/eslint-plugin`, `typescript-eslint`, `@typescript-eslint/parser`), React (`eslint-plugin-import`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`, `eslint-plugin-react-hooks`), Vue (`eslint-plugin-vue`, `vue-eslint-parser`)\n\n`@nx/react`/`@nx/vue` are for generators only — no target conflicts.\n\n---\n\n## Redundant npm Scripts After Import\n\n`nx import` copies `package.json` verbatim, so npm scripts come along. For Vite-based projects `@nx/vite/plugin` already infers the same targets from `vite.config.ts` — the npm scripts just shadow the plugin with weaker `nx:run-script` wrappers (no first-class caching inputs/outputs). Remove them after import.\n\n### Standalone Vite App (`create-vite`)\n\nRemove the following scripts — every one is redundant:\n\n| Script                        | Plugin replacement                                                           |\n| ----------------------------- | ---------------------------------------------------------------------------- |\n| `dev: vite`                   | `@nx/vite/plugin` → `dev`                                                    |\n| `build: tsc -b && vite build` | `@nx/vite/plugin` → `build`; `typecheck` via `@nx/js/typescript` handles tsc |\n| `preview: vite preview`       | `@nx/vite/plugin` → `preview`                                                |\n| `lint: eslint .`              | `@nx/eslint/plugin` → `eslint:lint`                                          |\n\n### TanStack Start\n\nRemove `build`, `dev`, `preview`, and `test` scripts, but move any hardcoded `--port` flag to `vite.config.ts` first:\n\n```ts\n// vite.config.ts\nexport default defineConfig({\n  server: { port: 3000 },  // replaces `vite dev --port 3000`\n  ...\n})\n```\n\n### React Router 7 — Keep ALL scripts\n\nDo **not** remove React Router 7 scripts. They use the framework CLI (`react-router build`, `react-router dev`, `react-router-serve`) which is not interchangeable with plain `vite`:\n\n- `typecheck` runs `react-router typegen && tsc` — typegen must precede `tsc` or it fails on missing route types\n- `start` serves the SSR bundle — no plugin equivalent\n\n---\n\n## Fix Orders\n\n### Nx Source\n\n1. Generic fixes from SKILL.md (pnpm globs, root deps, executor paths, frontend tsconfig base settings, `@nx/react` typings)\n2. Configure `@nx/vite/plugin` typecheck target\n3. **React**: `jsx: \"react-jsx\"` (root or per-project)\n4. **Vue**: `jsx: \"preserve\"` + `jsxImportSource: \"vue\"`; verify `vue-shims.d.ts`; install ESLint deps before `@nx/eslint`\n5. **Mixed**: `jsx` per-project; remove/rename `@nx/js/typescript`\n6. `nx sync --yes && nx reset && nx run-many -t typecheck,build,test,lint`\n\n### Non-Nx Source (additional steps)\n\n0. Import into `apps/<name>` (see SKILL.md: \"Application vs Library Detection\")\n1. Generic fixes from SKILL.md (stale files cleanup, pnpm globs, rewritten scripts, target name prefixing, noEmit→composite, ESLint handling)\n2. Fix `noEmit` in **all** tsconfigs (app, node, etc. — non-Nx projects often have multiple)\n3. Add `extends` to solution-style tsconfigs so root settings apply\n4. Fix `resolve.alias` / `__dirname` / `baseUrl`\n5. Ensure `types` include `vite/client` and `node`\n6. Install `@nx/vite` manually if it failed during import\n7. Remove redundant npm scripts so `@nx/vite/plugin` infers them natively (see \"Redundant npm Scripts\" section)\n8. **Vue**: Add `outDir` + `**/*.vue.d.ts` to ESLint ignores\n9. Full verification\n\n### Multiple-Source Imports\n\nSee SKILL.md for generic multi-import (name collisions, dep refs). Vite-specific: fix tsconfig `references` paths for alternate directories (`../../libs/` → `../../libs-beta/`).\n\n### Non-Nx Source: React Router 7\n\n1. Ensure source has at least one commit (see SKILL.md: \"Source Repo Has No Commits\")\n2. `nx import` whole-repo into `apps/<name>` (see SKILL.md: \"Application vs Library Detection\") → auto-installs `@nx/vite`, `@nx/react`\n3. Stale file cleanup: `node_modules/`, `package-lock.json`, `.gitignore`\n4. Fix `tsconfig.json`: `noEmit` → `composite + emitDeclarationOnly + outDir + tsBuildInfoFile`\n5. Add `build` and `.react-router` to dest root `.gitignore`\n6. **Keep all npm scripts** — React Router 7 uses framework CLI (`react-router build/dev`), not plain vite (see \"Redundant npm Scripts\" above)\n7. `npm install && nx reset && nx sync --yes`\n\n### Non-Nx Source: TanStack Start\n\n1. Ensure source has at least one commit — `create-tan-stack` does NOT auto-commit (see SKILL.md)\n2. `nx import` whole-repo into `apps/<name>` (see SKILL.md: \"Application vs Library Detection\") → auto-installs `@nx/vite`, `@nx/vitest`\n3. Stale file cleanup: `node_modules/`, `package-lock.json`, `.gitignore`\n4. Fix `tsconfig.json`: `noEmit` → `composite + emitDeclarationOnly + outDir + tsBuildInfoFile`\n5. Keep `allowImportingTsExtensions` — compatible with `emitDeclarationOnly: true`\n6. Add `.vinxi`, `.tanstack`, `.nitro`, `.output` to dest root `.gitignore`\n7. Move hardcoded `--port` from `dev` script into `vite.config.ts` (`server: { port: N }`)\n8. Remove redundant npm scripts — `@nx/vite/plugin` infers `build`, `dev`, `preview`, `test` (see \"Redundant npm Scripts\" above)\n9. `npm install && nx reset && nx sync --yes`\n\n### Quick Reference: React vs Vue\n\n| Aspect        | React                    | Vue                                       |\n| ------------- | ------------------------ | ----------------------------------------- |\n| Vite plugin   | `@vitejs/plugin-react`   | `@vitejs/plugin-vue`                      |\n| Type checker  | `tsc`                    | `vue-tsc` (auto-detected)                 |\n| SFC support   | N/A                      | `vue-shims.d.ts` needed                   |\n| tsconfig jsx  | `\"react-jsx\"`            | `\"preserve\"` + `\"jsxImportSource\": \"vue\"` |\n| ESLint parser | Standard TS              | `vue-eslint-parser` + TS sub-parser       |\n| ESLint setup  | Straightforward          | Must install deps before `@nx/eslint`     |\n| Test utils    | `@testing-library/react` | `@vue/test-utils`                         |\n\n### Quick Reference: Vite-Based React Frameworks\n\n| Aspect             | Vite (standalone) | React Router 7          | TanStack Start           |\n| ------------------ | ----------------- | ----------------------- | ------------------------ |\n| Build config       | `vite.config.ts`  | `vite.config.ts`        | `vite.config.ts`         |\n| Build output       | `dist/`           | `build/`                | `dist/`                  |\n| SSR bundle         | No                | Yes (`build/server/`)   | Yes (`dist/server/`)     |\n| tsconfig layout    | app + node split  | Single tsconfig         | Single tsconfig          |\n| Auto-committed     | Depends on tool   | Usually yes             | **No — commit first**    |\n| `nx import` plugin | `@nx/vite`        | `@nx/vite`, `@nx/react` | `@nx/vite`, `@nx/vitest` |\n\n---\n\n## Iteration Log\n\n### Scenario 6: Multiple non-Nx React apps (CRA, Next.js, React Router 7, TanStack Start, Vite) → TS preset (PASS)\n\n- Sources: 5 standalone non-Nx repos with different build tools\n- Dest: CNW ts preset (Nx 22.5.1), npm workspaces, `packages/*`\n- Import: whole-repo for each, sequential into `packages/<name>`\n- Pre-import fixes:\n  1. Removed `packages/.gitkeep` and committed\n  2. `git init && git add . && git commit` in Vite app (no git at all)\n  3. `git add . && git commit` in TanStack app (git init'd but no commits)\n- Import: `npm exec nx -- import <source> packages/<name> --source=. --ref=main --no-interactive`\n  - Next.js import auto-installed `@nx/eslint`, `@nx/next`\n  - React Router 7 import auto-installed `@nx/vite`, `@nx/react`, `@nx/docker` (Dockerfile present)\n  - TanStack import auto-installed `@nx/vitest`\n- Post-import fixes:\n  1. Removed stale `node_modules/`, `package-lock.json`, `.gitignore` from each package\n  2. Removed Nx-rewritten scripts from `board-games-nextjs/package.json` (had `\"build\": \"nx next:build\"`, etc.)\n  3. Updated root `tsconfig.base.json`: `nodenext` → `bundler`, added `dom`/`dom.iterable` to lib, added `jsx: react-jsx`\n  4. Added `build` to dest root `.gitignore` (CRA and React Router 7 output there)\n  5. Fixed `noEmit` → `composite + emitDeclarationOnly` in: `board-games-vite/tsconfig.app.json`, `board-games-vite/tsconfig.node.json`, `board-games-react-router/tsconfig.json`, `board-games-tanstack/tsconfig.json`\n  6. Fixed `tsBuildInfoFile` paths from `./node_modules/.tmp/...` to `./dist/...`\n  7. Installed root `@types/react`, `@types/react-dom`, `@types/node`\n- All targets green: `build` for all 5 projects; `typecheck` for Vite/React Router/TanStack; `next:build` for Next.js\n\n<!-- File: .agents/skills/nx-import/SKILL.md (Tokens: ~3470 | Category: anthropic-skill) -->\n---\nname: nx-import\ndescription: Import, merge, or combine repositories into an Nx workspace using nx import. USE WHEN the user asks to adopt Nx across repos, move projects into a monorepo, or bring code/history from another repository.\n---\n\n## Quick Start\n\n- `nx import` brings code from a source repository or folder into the current workspace, preserving commit history.\n- After nx `22.6.0`, `nx import` responds with .ndjson outputs and follow-up questions. For earlier versions, always run with `--no-interactive` and specify all flags directly.\n- Run `nx import --help` for available options.\n- Make sure the destination directory is empty before importing.\n  EXAMPLE: target has `libs/utils` and `libs/models`; source has `libs/ui` and `libs/data-access` — you cannot import `libs/` into `libs/` directly. Import each source library individually.\n\nPrimary docs:\n\n- https://nx.dev/docs/guides/adopting-nx/import-project\n- https://nx.dev/docs/guides/adopting-nx/preserving-git-histories\n\nRead the nx docs if you have the tools for it.\n\n## Import Strategy\n\n**Subdirectory-at-a-time** (`nx import <source> apps --source=apps`):\n\n- **Recommended for monorepo sources** — files land at top level, no redundant config\n- Caveats: multiple import commands (separate merge commits each); dest must not have conflicting directories; root configs (deps, plugins, targetDefaults) not imported\n- **Directory conflicts**: Import into alternate-named dir (e.g. `imported-apps/`), then rename\n\n**Whole repo** (`nx import <source> imported --source=.`):\n\n- **Only for non-monorepo sources** (single-project repos)\n- For monorepos, creates messy nested config (`imported/nx.json`, `imported/tsconfig.base.json`, etc.)\n- If you must: keep imported `tsconfig.base.json` (projects extend it), prefix workspace globs and executor paths\n\n### Directory Conventions\n\n- **Always prefer the destination's existing conventions.** Source uses `libs/`but dest uses `packages/`? Import into `packages/` (`nx import <source> packages/foo --source=libs/foo`).\n- If dest has no convention (empty workspace), ask the user.\n\n### Application vs Library Detection\n\nBefore importing, identify whether the source is an **application** or a **library**:\n\n- **Applications**: Deployable end products. Common indicators:\n  - _Frontend_: `next.config.*`, `vite.config.*` with a build entry point, framework-specific app scaffolding (CRA, Angular CLI app, etc.)\n  - _Backend (Node.js)_: Express/Fastify/NestJS server entrypoint, no `\"exports\"` field in `package.json`\n  - _JVM_: Maven `pom.xml` with `<packaging>jar</packaging>` or `<packaging>war</packaging>` and a `main` class; Gradle `application` plugin or `mainClass` setting\n  - _.NET_: `.csproj`/`.fsproj` with `<OutputType>Exe</OutputType>` or `<OutputType>WinExe</OutputType>`\n  - _General_: Dockerfile, a runnable entrypoint, no public API surface intended for import by other projects\n- **Libraries**: Reusable packages consumed by other projects. Common indicators: `\"main\"`/`\"exports\"` in `package.json`, Maven/Gradle packaging as a library jar, .NET `<OutputType>Library</OutputType>`, named exports intended for import by other packages.\n\n**Destination directory rules**:\n\n- Applications → `apps/<name>`. Check workspace globs (e.g. `pnpm-workspace.yaml`, `workspaces` in root `package.json`) for an existing `apps/*` entry.\n  - If `apps/*` is **not** present, add it before importing: update the workspace glob config and commit (or stage) the change.\n  - Example: `nx import <source> apps/my-app --source=packages/my-app`\n- Libraries → follow the dest's existing convention (`packages/`, `libs/`, etc.).\n\n## Common Issues\n\n### pnpm Workspace Globs (Critical)\n\n`nx import` adds the imported directory itself (e.g. `apps`) to `pnpm-workspace.yaml`, **NOT** glob patterns for packages within it. Cross-package imports will fail with `Cannot find module`.\n\n**Fix**: Replace with proper globs from the source config (e.g. `apps/*`, `libs/shared/*`), then `pnpm install`.\n\n### Root Dependencies and Config Not Imported (Critical)\n\n`nx import` does **NOT** merge from the source's root:\n\n- `dependencies`/`devDependencies` from `package.json`\n- `targetDefaults` from `nx.json` (e.g. `\"@nx/esbuild:esbuild\": { \"dependsOn\": [\"^build\"] }` — critical for build ordering)\n- `namedInputs` from `nx.json` (e.g. `production` exclusion patterns for test files)\n- Plugin configurations from `nx.json`\n\n**Fix**: Diff source and dest `package.json` + `nx.json`. Add missing deps, merge relevant `targetDefaults` and `namedInputs`.\n\n### TypeScript Project References\n\nAfter import, run `nx sync --yes`. If it reports nothing but typecheck still fails, `nx reset` first, then `nx sync --yes` again.\n\n### Explicit Executor Path Fixups\n\nInferred targets (via Nx plugins) resolve config relative to project root — no changes needed. Explicit executor targets (e.g. `@nx/esbuild:esbuild`) have workspace-root-relative paths (`main`, `outputPath`, `tsConfig`, `assets`, `sourceRoot`) that must be prefixed with the import destination directory.\n\n### Plugin Detection\n\n- **Whole-repo import**: `nx import` detects and offers to install plugins. Accept them.\n- **Subdirectory import**: Plugins NOT auto-detected. Manually add with `npx nx add @nx/PLUGIN`. Check `include`/`exclude` patterns — defaults won't match alternate directories (e.g. `apps-beta/`).\n- Run `npx nx reset` after any plugin config changes.\n\n### Redundant Root Files (Whole-Repo Only)\n\nWhole-repo import brings ALL source root files into the dest subdirectory. Clean up:\n\n- `pnpm-lock.yaml` — stale; dest has its own lockfile\n- `pnpm-workspace.yaml` — source workspace config; conflicts with dest\n- `node_modules/` — stale symlinks pointing to source filesystem\n- `.gitignore` — redundant with dest root `.gitignore`\n- `nx.json` — source Nx config; dest has its own\n- `README.md` — optional; keep or remove\n\n**Don't blindly delete** `tsconfig.base.json` — imported projects may extend it via relative paths.\n\n### Root ESLint Config Missing (Subdirectory Import)\n\nSubdirectory import doesn't bring the source's root `eslint.config.mjs`, but project configs reference `../../eslint.config.mjs`.\n\n**Fix order**:\n\n1. Install ESLint deps first: `pnpm add -wD eslint@^9 @nx/eslint-plugin typescript-eslint` (plus framework-specific plugins)\n2. Create root `eslint.config.mjs` (copy from source or create with `@nx/eslint-plugin` base rules)\n3. Then `npx nx add @nx/eslint` to register the plugin in `nx.json`\n\nInstall `typescript-eslint` explicitly — pnpm's strict hoisting won't auto-resolve this transitive dep of `@nx/eslint-plugin`.\n\n### ESLint Version Pinning (Critical)\n\n**Pin ESLint to v9** (`eslint@^9.0.0`). ESLint 10 breaks `@nx/eslint` and many plugins with cryptic errors like `Cannot read properties of undefined (reading 'version')`.\n\n`@nx/eslint` may peer-depend on ESLint 8, causing the wrong version to resolve. If lint fails with `Cannot read properties of undefined (reading 'allow')`, add `pnpm.overrides`:\n\n```json\n{ \"pnpm\": { \"overrides\": { \"eslint\": \"^9.0.0\" } } }\n```\n\n### Dependency Version Conflicts\n\nAfter import, compare key deps (`typescript`, `eslint`, framework-specific). If dest uses newer versions, upgrade imported packages to match (usually safe). If source is newer, may need to upgrade dest first. Use `pnpm.overrides` to enforce single-version policy if desired.\n\n### Module Boundaries\n\nImported projects may lack `tags`. Add tags or update `@nx/enforce-module-boundaries` rules.\n\n### Project Name Collisions (Multi-Import)\n\nSame `name` in `package.json` across source and dest causes `MultipleProjectsWithSameNameError`. **Fix**: Rename conflicting names (e.g. `@org/api` → `@org/teama-api`), update all dep references and import statements, `pnpm install`. The root `package.json` of each imported repo also becomes a project — rename those too.\n\n### Workspace Dep Import Ordering\n\n`pnpm install` fails during `nx import` if a `\"workspace:*\"` dependency hasn't been imported yet. File operations still succeed. **Fix**: Import all projects first, then `pnpm install --no-frozen-lockfile`.\n\n### `.gitkeep` Blocking Subdirectory Import\n\nThe TS preset creates `packages/.gitkeep`. Remove it and commit before importing.\n\n### Frontend tsconfig Base Settings (Critical)\n\nThe TS preset defaults (`module: \"nodenext\"`, `moduleResolution: \"nodenext\"`, `lib: [\"es2022\"]`) are incompatible with frontend frameworks (React, Next.js, Vue, Vite). After importing frontend projects, verify the dest root `tsconfig.base.json`:\n\n- **`moduleResolution`**: Must be `\"bundler\"` (not `\"nodenext\"`)\n- **`module`**: Must be `\"esnext\"` (not `\"nodenext\"`)\n- **`lib`**: Must include `\"dom\"` and `\"dom.iterable\"` (frontend projects need these)\n- **`jsx`**: `\"react-jsx\"` for React-only workspaces, per-project for mixed frameworks\n\nFor **subdirectory imports**, the dest root tsconfig is authoritative — update it. For **whole-repo imports**, imported projects may extend their own nested `tsconfig.base.json`, making this less critical.\n\nIf the dest also has backend projects needing `nodenext`, use per-project overrides instead of changing the root.\n\n**Gotcha**: TypeScript does NOT merge `lib` arrays — a project-level override **replaces** the base array entirely. Always include all needed entries (e.g. `es2022`, `dom`, `dom.iterable`) in any project-level `lib`.\n\n### `@nx/react` Typings for Libraries\n\nReact libraries generated with `@nx/react:library` reference `@nx/react/typings/cssmodule.d.ts` and `@nx/react/typings/image.d.ts` in their tsconfig `types`. These fail with `Cannot find type definition file` unless `@nx/react` is installed in the dest workspace.\n\n**Fix**: `pnpm add -wD @nx/react`\n\n### Jest Preset Missing (Subdirectory Import)\n\nNx presets create `jest.preset.js` at the workspace root, and project jest configs reference it (e.g. `../../jest.preset.js`). Subdirectory import does NOT bring this file.\n\n**Fix**:\n\n1. Run `npx nx add @nx/jest` — registers `@nx/jest/plugin` in `nx.json` and updates `namedInputs`\n2. Create `jest.preset.js` at workspace root (see `references/JEST.md` for content) — `nx add` only creates this when a generator runs, not on bare `nx add`\n3. Install test runner deps: `pnpm add -wD jest jest-environment-jsdom ts-jest @types/jest`\n4. Install framework-specific test deps as needed (see `references/JEST.md`)\n\nFor deeper Jest issues (tsconfig.spec.json, Babel transforms, CI atomization, Jest vs Vitest coexistence), see `references/JEST.md`.\n\n### Target Name Prefixing (Whole-Repo Import)\n\nWhen importing a project with existing npm scripts (`build`, `dev`, `start`, `lint`), Nx plugins auto-prefix inferred target names to avoid conflicts: e.g. `next:build`, `vite:build`, `eslint:lint`.\n\n**Fix**: Remove the Nx-rewritten npm scripts from the imported `package.json`, then either:\n\n- Accept the prefixed names (e.g. `nx run app:next:build`)\n- Rename plugin target names in `nx.json` to use unprefixed names\n\n## Non-Nx Source Issues\n\nWhen the source is a plain pnpm/npm workspace without `nx.json`.\n\n### npm Script Rewriting (Critical)\n\nNx rewrites `package.json` scripts during init, creating broken commands (e.g. `vitest run` → `nx test run`). **Fix**: Remove all rewritten scripts — Nx plugins infer targets from config files.\n\n### `noEmit` → `composite` + `emitDeclarationOnly` (Critical)\n\nPlain TS projects use `\"noEmit\": true`, incompatible with Nx project references.\n\n**Symptoms**: \"typecheck target is disabled because one or more project references set 'noEmit: true'\" or TS6310.\n\n**Fix** in **all** imported tsconfigs:\n\n1. Remove `\"noEmit\": true`. If inherited via extends chain, set `\"noEmit\": false` explicitly.\n2. Add `\"composite\": true`, `\"emitDeclarationOnly\": true`, `\"declarationMap\": true`\n3. Add `\"outDir\": \"dist\"` and `\"tsBuildInfoFile\": \"dist/tsconfig.tsbuildinfo\"`\n4. Add `\"extends\": \"../../tsconfig.base.json\"` if missing. Remove settings now inherited from base.\n\n### Stale node_modules and Lockfiles\n\n`nx import` may bring `node_modules/` (pnpm symlinks pointing to the source filesystem) and `pnpm-lock.yaml` from the source. Both are stale.\n\n**Fix**: `rm -rf imported/node_modules imported/pnpm-lock.yaml imported/pnpm-workspace.yaml imported/.gitignore`, then `pnpm install`.\n\n### ESLint Config Handling\n\n- **Legacy `.eslintrc.json` (ESLint 8)**: Delete all `.eslintrc.*`, remove v8 deps, create flat `eslint.config.mjs`.\n- **Flat config (`eslint.config.js`)**: Self-contained configs can often be left as-is.\n- **No ESLint**: Create both root and project-level configs from scratch.\n\n### TypeScript `paths` Aliases\n\nNx uses `package.json` `\"exports\"` + pnpm workspace linking instead of tsconfig `\"paths\"`. If packages have proper `\"exports\"`, paths are redundant. Otherwise, update paths for the new directory structure.\n\n## Technology-specific Guidance\n\nIdentify technologies in the source repo, then read and apply the matching reference file(s).\n\nAvailable references:\n\n- `references/ESLINT.md` — ESLint projects: duplicate `lint`/`eslint:lint` targets, legacy `.eslintrc.*` linting generated files, flat config `.cjs` self-linting, `typescript-eslint` v7/v9 peer dep conflict, mixed ESLint v8+v9 in one workspace.\n- `references/GRADLE.md`\n- `references/JEST.md` — Jest testing: `@nx/jest/plugin` setup, jest.preset.js, testing deps by framework, tsconfig.spec.json, Jest vs Vitest coexistence, Babel transforms, CI atomization.\n- `references/NEXT.md` — Next.js projects: `@nx/next/plugin` targets, `withNx`, Next.js TS config (`noEmit`, `jsx: \"preserve\"`), auto-installing deps via wrong PM, non-Nx `create-next-app` imports, mixed Next.js+Vite coexistence.\n- `references/TURBOREPO.md`\n- `references/VITE.md` — Vite projects (React, Vue, or both): `@nx/vite/plugin` typecheck target, `resolve.alias`/`__dirname` fixes, framework deps, Vue-specific setup, mixed React+Vue coexistence.\n\n<!-- File: .agents/skills/nx-plugins/SKILL.md (Tokens: ~82 | Category: anthropic-skill) -->\n---\nname: nx-plugins\ndescription: Find and add Nx plugins. USE WHEN user wants to discover available plugins, install a new plugin, or add support for a specific framework or technology to the workspace.\n---\n\n## Finding and Installing new plugins\n\n- List plugins: `pnpm nx list`\n- Install plugins `pnpm nx add <plugin>`. Example: `pnpm nx add @nx/react`.\n\n<!-- File: .agents/skills/nx-run-tasks/SKILL.md (Tokens: ~601 | Category: anthropic-skill) -->\n---\nname: nx-run-tasks\ndescription: Helps with running tasks in an Nx workspace. USE WHEN the user wants to execute build, test, lint, serve, or run any other tasks defined in the workspace.\n---\n\nYou can run tasks with Nx in the following way.\n\nKeep in mind that you might have to prefix things with npx/pnpx/yarn if the user doesn't have nx installed globally. Look at the package.json or lockfile to determine which package manager is in use.\n\nFor more details on any command, run it with `--help` (e.g. `nx run-many --help`, `nx affected --help`).\n\n## Understand which tasks can be run\n\nYou can check those via `nx show project <projectname> --json`, for example `nx show project myapp --json`. It contains a `targets` section which has information about targets that can be run. You can also just look at the `package.json` scripts or `project.json` targets, but you might miss out on inferred tasks by Nx plugins.\n\n## Run a single task\n\n```\nnx run <project>:<task>\n```\n\nwhere `project` is the project name defined in `package.json` or `project.json` (if present).\n\n## Run multiple tasks\n\n```\nnx run-many -t build test lint typecheck\n```\n\nYou can pass a `-p` flag to filter to specific projects, otherwise it runs on all projects. You can also use `--exclude` to exclude projects, and `--parallel` to control the number of parallel processes (default is 3).\n\nExamples:\n\n- `nx run-many -t test -p proj1 proj2` — test specific projects\n- `nx run-many -t test --projects=*-app --exclude=excluded-app` — test projects matching a pattern\n- `nx run-many -t test --projects=tag:api-*` — test projects by tag\n\n## Run tasks for affected projects\n\nUse `nx affected` to only run tasks on projects that have been changed and projects that depend on changed projects. This is especially useful in CI and for large workspaces.\n\n```\nnx affected -t build test lint\n```\n\nBy default it compares against the base branch. You can customize this:\n\n- `nx affected -t test --base=main --head=HEAD` — compare against a specific base and head\n- `nx affected -t test --files=libs/mylib/src/index.ts` — specify changed files directly\n\n## Useful flags\n\nThese flags work with `run`, `run-many`, and `affected`:\n\n- `--skipNxCache` — rerun tasks even when results are cached\n- `--verbose` — print additional information such as stack traces\n- `--nxBail` — stop execution after the first failed task\n- `--configuration=<name>` — use a specific configuration (e.g. `production`)\n\n<!-- File: .agents/skills/nx-workspace/references/AFFECTED.md (Tokens: ~159 | Category: anthropic-skill) -->\n## Affected Projects\n\nFind projects affected by changes in the current branch.\n\n```bash\n# Affected since base branch (auto-detected)\nnx show projects --affected\n\n# Affected with explicit base\nnx show projects --affected --base=main\nnx show projects --affected --base=origin/main\n\n# Affected between two commits\nnx show projects --affected --base=abc123 --head=def456\n\n# Affected apps only\nnx show projects --affected --type app\n\n# Affected excluding e2e projects\nnx show projects --affected --exclude=\"*-e2e\"\n\n# Affected by uncommitted changes\nnx show projects --affected --uncommitted\n\n# Affected by untracked files\nnx show projects --affected --untracked\n```\n\n<!-- File: .agents/skills/nx-workspace/SKILL.md (Tokens: ~1885 | Category: anthropic-skill) -->\n---\nname: nx-workspace\ndescription: \"Explore and understand Nx workspaces. USE WHEN answering questions about the workspace, projects, or tasks. ALSO USE WHEN an nx command fails or you need to check available targets/configuration before running a task. EXAMPLES: 'What projects are in this workspace?', 'How is project X configured?', 'What depends on library Y?', 'What targets can I run?', 'Cannot find configuration for task', 'debug nx task failure'.\"\n---\n\n# Nx Workspace Exploration\n\nThis skill provides read-only exploration of Nx workspaces. Use it to understand workspace structure, project configuration, available targets, and dependencies.\n\nKeep in mind that you might have to prefix commands with `npx`/`pnpx`/`yarn` if nx isn't installed globally. Check the lockfile to determine the package manager in use.\n\n## Listing Projects\n\nUse `nx show projects` to list projects in the workspace.\n\nThe project filtering syntax (`-p`/`--projects`) works across many Nx commands including `nx run-many`, `nx release`, `nx show projects`, and more. Filters support explicit names, glob patterns, tag references (e.g. `tag:name`), directories, and negation (e.g. `!project-name`).\n\n```bash\n# List all projects\nnx show projects\n\n# Filter by pattern (glob)\nnx show projects --projects \"apps/*\"\nnx show projects --projects \"shared-*\"\n\n# Filter by tag\nnx show projects --projects \"tag:publishable\"\nnx show projects -p 'tag:publishable,!tag:internal'\n\n# Filter by target (projects that have a specific target)\nnx show projects --withTarget build\n\n# Combine filters\nnx show projects --type lib --withTarget test\nnx show projects --affected --exclude=\"*-e2e\"\nnx show projects -p \"tag:scope:client,packages/*\"\n\n# Negate patterns\nnx show projects -p '!tag:private'\nnx show projects -p '!*-e2e'\n\n# Output as JSON\nnx show projects --json\n```\n\n## Project Configuration\n\nUse `nx show project <name> --json` to get the full resolved configuration for a project.\n\n**Important**: Do NOT read `project.json` directly - it only contains partial configuration. The `nx show project --json` command returns the full resolved config including inferred targets from plugins.\n\nYou can read the full project schema at `node_modules/nx/schemas/project-schema.json` to understand nx project configuration options.\n\n```bash\n# Get full project configuration\nnx show project my-app --json\n\n# Extract specific parts from the JSON\nnx show project my-app --json | jq '.targets'\nnx show project my-app --json | jq '.targets.build'\nnx show project my-app --json | jq '.targets | keys'\n\n# Check project metadata\nnx show project my-app --json | jq '{name, root, sourceRoot, projectType, tags}'\n```\n\n## Target Information\n\nTargets define what tasks can be run on a project.\n\n```bash\n# List all targets for a project\nnx show project my-app --json | jq '.targets | keys'\n\n# Get full target configuration\nnx show project my-app --json | jq '.targets.build'\n\n# Check target executor/command\nnx show project my-app --json | jq '.targets.build.executor'\nnx show project my-app --json | jq '.targets.build.command'\n\n# View target options\nnx show project my-app --json | jq '.targets.build.options'\n\n# Check target inputs/outputs (for caching)\nnx show project my-app --json | jq '.targets.build.inputs'\nnx show project my-app --json | jq '.targets.build.outputs'\n\n# Find projects with a specific target\nnx show projects --withTarget serve\nnx show projects --withTarget e2e\n```\n\n## Workspace Configuration\n\nRead `nx.json` directly for workspace-level configuration.\nYou can read the full project schema at `node_modules/nx/schemas/nx-schema.json` to understand nx project configuration options.\n\n```bash\n# Read the full nx.json\ncat nx.json\n\n# Or use jq for specific sections\ncat nx.json | jq '.targetDefaults'\ncat nx.json | jq '.namedInputs'\ncat nx.json | jq '.plugins'\ncat nx.json | jq '.generators'\n```\n\nKey nx.json sections:\n\n- `targetDefaults` - Default configuration applied to all targets of a given name\n- `namedInputs` - Reusable input definitions for caching\n- `plugins` - Nx plugins and their configuration\n- ...and much more, read the schema or nx.json for details\n\n## Affected Projects\n\nIf the user is asking about affected projects, read the [affected projects reference](references/AFFECTED.md) for detailed commands and examples.\n\n## Common Exploration Patterns\n\n### \"What's in this workspace?\"\n\n```bash\nnx show projects\nnx show projects --type app\nnx show projects --type lib\n```\n\n### \"How do I build/test/lint project X?\"\n\n```bash\nnx show project X --json | jq '.targets | keys'\nnx show project X --json | jq '.targets.build'\n```\n\n### \"What depends on library Y?\"\n\n```bash\n# Use the project graph to find dependents\nnx graph --print | jq '.graph.dependencies | to_entries[] | select(.value[].target == \"Y\") | .key'\n```\n\n## Programmatic Answers\n\nWhen processing nx CLI results, use command-line tools to compute the answer programmatically rather than counting or parsing output manually. Always use `--json` flags to get structured output that can be processed with `jq`, `grep`, or other tools you have installed locally.\n\n### Listing Projects\n\n```bash\nnx show projects --json\n```\n\nExample output:\n\n```json\n[\"my-app\", \"my-app-e2e\", \"shared-ui\", \"shared-utils\", \"api\"]\n```\n\nCommon operations:\n\n```bash\n# Count projects\nnx show projects --json | jq 'length'\n\n# Filter by pattern\nnx show projects --json | jq '.[] | select(startswith(\"shared-\"))'\n\n# Get affected projects as array\nnx show projects --affected --json | jq '.'\n```\n\n### Project Details\n\n```bash\nnx show project my-app --json\n```\n\nExample output:\n\n```json\n{\n  \"root\": \"apps/my-app\",\n  \"name\": \"my-app\",\n  \"sourceRoot\": \"apps/my-app/src\",\n  \"projectType\": \"application\",\n  \"tags\": [\"type:app\", \"scope:client\"],\n  \"targets\": {\n    \"build\": {\n      \"executor\": \"@nx/vite:build\",\n      \"options\": { \"outputPath\": \"dist/apps/my-app\" }\n    },\n    \"serve\": {\n      \"executor\": \"@nx/vite:dev-server\",\n      \"options\": { \"buildTarget\": \"my-app:build\" }\n    },\n    \"test\": {\n      \"executor\": \"@nx/vite:test\",\n      \"options\": {}\n    }\n  },\n  \"implicitDependencies\": []\n}\n```\n\nCommon operations:\n\n```bash\n# Get target names\nnx show project my-app --json | jq '.targets | keys'\n\n# Get specific target config\nnx show project my-app --json | jq '.targets.build'\n\n# Get tags\nnx show project my-app --json | jq '.tags'\n\n# Get project root\nnx show project my-app --json | jq -r '.root'\n```\n\n### Project Graph\n\n```bash\nnx graph --print\n```\n\nExample output:\n\n```json\n{\n  \"graph\": {\n    \"nodes\": {\n      \"my-app\": {\n        \"name\": \"my-app\",\n        \"type\": \"app\",\n        \"data\": { \"root\": \"apps/my-app\", \"tags\": [\"type:app\"] }\n      },\n      \"shared-ui\": {\n        \"name\": \"shared-ui\",\n        \"type\": \"lib\",\n        \"data\": { \"root\": \"libs/shared-ui\", \"tags\": [\"type:ui\"] }\n      }\n    },\n    \"dependencies\": {\n      \"my-app\": [{ \"source\": \"my-app\", \"target\": \"shared-ui\", \"type\": \"static\" }],\n      \"shared-ui\": []\n    }\n  }\n}\n```\n\nCommon operations:\n\n```bash\n# Get all project names from graph\nnx graph --print | jq '.graph.nodes | keys'\n\n# Find dependencies of a project\nnx graph --print | jq '.graph.dependencies[\"my-app\"]'\n\n# Find projects that depend on a library\nnx graph --print | jq '.graph.dependencies | to_entries[] | select(.value[].target == \"shared-ui\") | .key'\n```\n\n## Troubleshooting\n\n### \"Cannot find configuration for task X:target\"\n\n```bash\n# Check what targets exist on the project\nnx show project X --json | jq '.targets | keys'\n\n# Check if any projects have that target\nnx show projects --withTarget target\n```\n\n### \"The workspace is out of sync\"\n\n```bash\nnx sync\nnx reset  # if sync doesn't fix stale cache\n```\n\n<!-- File: packages/core/auth-js/AGENTS.md (Tokens: ~223 | Category: anthropic-skill) -->\n# Agent instructions for `@supabase/auth-js`\n\nSupabase Auth client SDK for JavaScript. Handles sign-in, sign-up, sessions, OAuth, MFA, and related auth flows.\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n\n<!-- File: packages/core/functions-js/AGENTS.md (Tokens: ~205 | Category: anthropic-skill) -->\n# Agent instructions for `@supabase/functions-js`\n\nJavaScript SDK for invoking Supabase Edge Functions.\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n\n<!-- File: packages/core/postgrest-js/AGENTS.md (Tokens: ~222 | Category: anthropic-skill) -->\n# Agent instructions for `@supabase/postgrest-js`\n\nIsomorphic PostgREST client for database operations (select, insert, update, upsert, delete, filters, RPC).\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n\n<!-- File: packages/core/realtime-js/AGENTS.md (Tokens: ~222 | Category: anthropic-skill) -->\n# Agent instructions for `@supabase/realtime-js`\n\nListen to realtime updates from a Supabase PostgreSQL database. Handles channels, presence, broadcast, and Postgres CDC subscriptions.\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n\n<!-- File: packages/core/storage-js/AGENTS.md (Tokens: ~221 | Category: anthropic-skill) -->\n# Agent instructions for `@supabase/storage-js`\n\nIsomorphic storage client for Supabase. Handles bucket and object operations: upload, download, list, signed URLs, transformations.\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n\n<!-- File: packages/core/supabase-js/AGENTS.md (Tokens: ~260 | Category: anthropic-skill) -->\n# Agent instructions for `@supabase/supabase-js`\n\nMain isomorphic Supabase client for JavaScript. Aggregates `@supabase/auth-js`, `@supabase/postgrest-js`, `@supabase/realtime-js`, `@supabase/storage-js`, and `@supabase/functions-js` into one client.\n\nWhen helping a user work with this package:\n\n- **Usage and quick start**: [`README.md`](./README.md)\n- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.\n- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.\n\nFor broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).\n\n<!-- File: .cursor/mcp.json (Tokens: ~9 | Category: mcp-config) -->\n{\n  \"mcpServers\": {}\n}\n\n<!-- File: packages/core/auth-js/example/react/README.md (Tokens: ~325 | Category: plugin-manifest) -->\n# Supabase `auth-js` example\n\n- Created based on the [Quickstart example](https://supabase.com/docs/guides/auth/quickstarts/react) in the Supabase docs.\n- Bootstrapped with Vite CLI\n\n## Setup\n\n### With a Supabase project\n\n### 1. Create new project\n\nSign up to Supabase - [https://supabase.com/dashboard](https://supabase.com/dashboard) and create a new project. Wait for your database to start.\n\n### 2. Get the URL and Key\n\nCreate a copy of `.env.local.example`:\n\n```bash\ncp .env.local.example .env.local\n```\n\n1. Go to the Project Settings (the cog icon)\n2. Open the Data API tab, and find your API URL\n3. Open the API Keys tab and create a new Publishable key\n4. Set them both in your newly created `.env.local` file.O\n\n### 3. Enable Auth providers\n\n1. From the sidenav, go to Authentication -> Configuration -> Sign In/Providers (https://supabase.com/dashboard/project/<YOUR_PROJECT_ID>/auth/providers)\n2. Enable providers as needed (for this example: Anonymous, Email, Phone, GitHub, Google)\n\n## Run\n\n### Install root dependencies and build `auth-js`\n\n```bash\nnpm i\n```\n\n```bash\nnpx nx build auth-js\n```\n\n### Install the dependencies and run the example\n\n```bash\ncd example/react\n```\n\n```bash\nnpm i; npm run dev\n```\n\n<!-- File: packages/core/auth-js/migrations/README.md (Tokens: ~333 | Category: plugin-manifest) -->\n# Migration notes for `@supabase/auth-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/auth-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/auth-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/auth-js`:\n\n1. Read the migration files in `node_modules/@supabase/auth-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/auth-js` only.\n\n<!-- File: packages/core/auth-js/README.md (Tokens: ~1765 | Category: plugin-manifest) -->\n<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase Auth JS SDK</h1>\n\n  <h3 align=\"center\">An isomorphic JavaScript SDK for the <a href=\"https://github.com/supabase/auth\">Supabase Auth</a> API.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/auth\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript/auth-signup\">Reference Docs</a>\n    ·\n    <a href=\"https://supabase.github.io/supabase-js/auth-js/v2/spec.json\">TypeDoc</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/auth-js)](https://www.npmjs.com/package/@supabase/auth-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/auth-js)](https://pkg.pr.new/~/supabase/auth-js)\n\n</div>\n\n## Requirements\n\n- **Node.js 22 or later** (Node.js 20 support dropped in v2.110.0)\n- For browser support, all modern browsers are supported\n\n> ⚠️ **Node.js 18 Deprecation Notice**\n>\n> Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped on October 31, 2025.\n\n> ⚠️ **Node.js 20 Deprecation Notice**\n>\n> Node.js 20 reached end-of-life on April 30, 2026. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/45715), support for Node.js 20 was dropped in v2.110.0.\n\n## Quick start\n\nInstall\n\n```bash\nnpm install --save @supabase/auth-js\n```\n\nUsage\n\n```js\nimport { AuthClient } from '@supabase/auth-js'\n\nconst GOTRUE_URL = 'http://localhost:9999'\n\nconst auth = new AuthClient({ url: GOTRUE_URL })\n```\n\n- `signUp()`: https://supabase.com/docs/reference/javascript/auth-signup\n- `signIn()`: https://supabase.com/docs/reference/javascript/auth-signin\n- `signOut()`: https://supabase.com/docs/reference/javascript/auth-signout\n\n### Custom `fetch` implementation\n\n`auth-js` uses the runtime's global `fetch` to make HTTP requests, but an alternative `fetch` implementation can be provided as an option. This is useful in environments where the global `fetch` is unavailable or where you want to customize request behavior:\n\n```js\nimport { AuthClient } from '@supabase/auth-js'\n\nconst AUTH_URL = 'http://localhost:9999'\n\nconst auth = new AuthClient({ url: AUTH_URL, fetch: fetch })\n```\n\n## Development\n\nThis package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:\n\n### Building\n\n```bash\n# Complete build (from monorepo root)\npnpm nx build auth-js\n\n# Build with watch mode for development\npnpm nx build auth-js --watch\n\n# Individual build targets\npnpm nx build:main auth-js    # CommonJS build (dist/main/)\npnpm nx build:module auth-js  # ES Modules build (dist/module/)\n\n# Other useful commands\npnpm nx lint auth-js          # Run ESLint\npnpm nx typecheck auth-js     # TypeScript type checking\npnpm nx docs auth-js          # Generate documentation\n```\n\n#### Build Outputs\n\n- **CommonJS (`dist/main/`)** - For Node.js environments\n- **ES Modules (`dist/module/`)** - For modern bundlers (Webpack, Vite, Rollup)\n- **TypeScript definitions (`dist/module/index.d.ts`)** - Type definitions for TypeScript projects\n\n### Testing\n\nThe auth-js package has two test suites:\n\n1. **CLI Tests** - Main test suite using Supabase CLI (331 tests)\n2. **Docker Tests** - Edge case tests requiring specific GoTrue configurations (11 tests)\n\n#### Prerequisites\n\n- **Supabase CLI** - Required for main test suite ([installation guide](https://supabase.com/docs/guides/cli))\n- **Docker** - Required for edge case tests\n\n#### Running Tests\n\n```bash\n# Run main test suite with Supabase CLI (recommended)\npnpm nx test:auth auth-js\n\n# Run Docker-only edge case tests\npnpm nx test:docker auth-js\n\n# Run both test suites\npnpm nx test:auth auth-js && pnpm nx test:docker auth-js\n```\n\n#### Main Test Suite (Supabase CLI)\n\nThe `test:auth` command automatically:\n\n1. Stops any existing Supabase instance\n2. Starts a local Supabase instance via CLI\n3. Runs the test suite (excludes `docker-tests/` folder)\n4. Cleans up after tests complete\n\n```bash\n# Individual commands for manual control\npnpm nx test:infra auth-js    # Start Supabase CLI\npnpm nx test:suite auth-js    # Run tests only\npnpm nx test:clean-post auth-js  # Stop Supabase CLI\n```\n\n#### Docker Tests (Edge Cases)\n\nThe `test:docker` target runs tests that require specific GoTrue configurations not possible with a single Supabase CLI instance:\n\n- **Signup disabled** - Tests for disabled signup functionality\n- **Asymmetric JWT (RS256)** - Tests for RS256 JWT verification\n- **Phone OTP / SMS** - Tests requiring Twilio SMS provider\n- **Anonymous sign-in disabled** - Tests for disabled anonymous auth\n\nThese tests are located in `test/docker-tests/` and use the Docker Compose setup in `infra/docker-compose.yml`.\n\n```bash\n# Individual commands for manual control\npnpm nx test:docker:infra auth-js    # Start Docker containers\npnpm nx test:docker:suite auth-js    # Run Docker tests only\npnpm nx test:docker:clean-post auth-js  # Stop Docker containers\n```\n\n#### Development Testing\n\nFor actively developing and debugging tests:\n\n```bash\n# Start Supabase CLI once\npnpm nx test:infra auth-js\n\n# Run tests multiple times (faster since instance stays up)\npnpm nx test:suite auth-js\n\n# Clean up when done\npnpm nx test:clean-post auth-js\n```\n\n#### Test Infrastructure\n\n| Suite        | Infrastructure | Configuration               |\n| ------------ | -------------- | --------------------------- |\n| CLI Tests    | Supabase CLI   | `test/supabase/config.toml` |\n| Docker Tests | Docker Compose | `infra/docker-compose.yml`  |\n\n### Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n\n<!-- File: packages/core/auth-js/test/README.md (Tokens: ~680 | Category: plugin-manifest) -->\n# Testing\n\n## Prerequisites\n\n- Docker & docker compose\n\n### Basic testing\n\nRun all tests:\n\n```sh\nnpm run test\n```\n\n> Note: If tests fail due to connection issues, your tests may be running too soon and the infra is not yet ready.\n> If that's the case, adjust the `sleep 10` duration in:\n> `\"test:infra\": \"cd infra && docker-compose down && docker-compose pull && docker-compose up -d && sleep 10\",`\n> to a value that works for your system setup.\n\n### Advanced\n\n**Start all the infrastructure:**\n\n```sh\nnpm run test:infra\n```\n\nYou can now open the mock mail server on `http://localhost:9000`\n\n**Run the tests only:**\n\n```sh\nnpm run test:suite\n```\n\nAll emails will appear in the mock mail server.\n\n## Passkey (WebAuthn) Tests\n\nPasskey coverage is split across two files:\n\n- `passkey.methods.test.ts` — unit tests for all `auth.passkey.*`, `signInWithPasskey()`,\n  `registerPasskey()` and `admin.passkey.*` methods with mocked `fetch` and a simulated\n  browser environment (no infra needed)\n- `passkey.e2e.test.ts` — full registration/authentication ceremonies against the\n  Supabase CLI Auth server\n\nThe e2e tests rely on:\n\n- `[auth.passkey]` and `[auth.webauthn]` in `test/supabase/config.toml` (requires\n  Supabase CLI >= 2.105.0)\n- `test/lib/software-authenticator.ts`, a minimal software WebAuthn authenticator\n  (ES256, \"none\" attestation, discoverable credentials) that stands in for\n  `navigator.credentials` since the tests run in Node\n\n## RSA Signing Keys\n\n### Security Model\n\nThe auth-js tests require RSA signing keys to verify RS256 JWT tokens. **These keys are NEVER committed to the repository** for security reasons.\n\n### Key Generation\n\nKeys are automatically generated before tests run:\n\n- **Locally**: `nx test:auth auth-js` or `nx test:docker auth-js` automatically generates keys via the `test:generate-keys` target\n- **CI**: GitHub Actions generates fresh keys before each test run\n\n### Manual Key Generation\n\nIf you need to generate keys manually:\n\n```bash\ncd packages/core/auth-js/test\nnode generate-signing-keys.js\n```\n\nThis creates `test/supabase/signing_keys.json` (gitignored).\n\n### JWT Token Generation\n\nJWT tokens (anon, service_role, admin) are **automatically generated** at runtime from the signing keys in `test/lib/clients.ts`. No manual updates needed!\n\nFor debugging/inspection only:\n\n```bash\ncd packages/core/auth-js/test\nnode generate-jwt.js\n```\n\nThis displays the tokens but you don't need to copy them anywhere - they're generated automatically.\n\n## Important Notes\n\n⚠️ **NEVER commit `signing_keys.json`** - It's in `.gitignore` for security\n\n⚠️ **These are TEST KEYS only** - Never use in production\n\n✅ **Fresh keys per test run** - CI generates new keys every time for maximum security\n\n<!-- File: packages/core/functions-js/migrations/README.md (Tokens: ~333 | Category: plugin-manifest) -->\n# Migration notes for `@supabase/functions-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/functions-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/functions-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/functions-js`:\n\n1. Read the migration files in `node_modules/@supabase/functions-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/functions-js` only.\n\n<!-- File: packages/core/functions-js/README.md (Tokens: ~1275 | Category: plugin-manifest) -->\n<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase Functions JS SDK</h1>\n\n  <h3 align=\"center\">JavaScript SDK to interact with Supabase Edge Functions.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/functions\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript/functions-invoke\">Reference Docs</a>\n    ·\n    <a href=\"https://supabase.github.io/supabase-js/functions-js/v2/spec.json\">TypeDoc</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/functions-js)](https://www.npmjs.com/package/@supabase/functions-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/functions-js)](https://pkg.pr.new/~/supabase/functions-js)\n\n</div>\n\n## Requirements\n\n- **Node.js 22 or later** (Node.js 20 support dropped in v2.110.0)\n- For browser support, all modern browsers are supported\n\n> ⚠️ **Node.js 18 Deprecation Notice**\n>\n> Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped on October 31, 2025.\n\n> ⚠️ **Node.js 20 Deprecation Notice**\n>\n> Node.js 20 reached end-of-life on April 30, 2026. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/45715), support for Node.js 20 was dropped in v2.110.0.\n\n## Quick Start\n\n### Installation\n\n```bash\nnpm install @supabase/functions-js\n```\n\n### Usage\n\n```js\nimport { FunctionsClient } from '@supabase/functions-js'\n\nconst functionsUrl = 'https://<project_ref>.supabase.co/functions/v1'\nconst publishableKey = '<publishable_key>'\n\nconst functions = new FunctionsClient(functionsUrl, {\n  headers: {\n    Authorization: `Bearer ${publishableKey}`,\n  },\n})\n\n// Invoke a function\nconst { data, error } = await functions.invoke('hello-world', {\n  body: { name: 'Functions' },\n})\n```\n\n## Development\n\nThis package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:\n\n### Building\n\n```bash\n# Complete build (from monorepo root)\npnpm nx build functions-js\n\n# Build with watch mode for development\npnpm nx build functions-js --watch\n\n# Individual build targets\npnpm nx build:main functions-js    # CommonJS build (dist/main/)\npnpm nx build:module functions-js  # ES Modules build (dist/module/)\n\n# Other useful commands\npnpm nx clean functions-js         # Clean build artifacts\npnpm nx typecheck functions-js     # TypeScript type checking\npnpm nx docs functions-js          # Generate documentation\n```\n\n#### Build Outputs\n\n- **CommonJS (`dist/main/`)** - For Node.js environments\n- **ES Modules (`dist/module/`)** - For modern bundlers (Webpack, Vite, Rollup)\n- **TypeScript definitions (`dist/module/index.d.ts`)** - Type definitions for TypeScript projects\n\n### Testing\n\n**Docker Required** for relay tests. The functions-js tests use testcontainers to spin up a Deno relay server for testing Edge Function invocations.\n\n```bash\n# Run all tests (from monorepo root)\npnpm nx test functions-js\n\n# Run tests with coverage report\npnpm nx test functions-js --coverage\n\n# Run tests in watch mode during development\npnpm nx test functions-js --watch\n\n# CI test command (runs with coverage)\npnpm nx test:ci functions-js\n```\n\n#### Test Requirements\n\n- **Node.js 22+** - Required for testcontainers\n- **Docker** - Must be installed and running for relay tests\n- No Supabase instance needed - Tests use mocked services and testcontainers\n\n#### What Gets Tested\n\n- **Function invocation** - Testing the `invoke()` method with various options\n- **Relay functionality** - Using a containerized Deno relay to test real Edge Function scenarios\n- **Error handling** - Ensuring proper error responses and retries\n- **Request/response models** - Validating headers, body, and response formats\n\n### Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n\n<!-- File: packages/core/postgrest-js/migrations/README.md (Tokens: ~345 | Category: plugin-manifest) -->\n# Migration notes for `@supabase/postgrest-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/postgrest-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/postgrest-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/postgrest-js`:\n\n1. Read the migration files in `node_modules/@supabase/postgrest-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/postgrest-js` only.\n\n<!-- File: packages/core/postgrest-js/README.md (Tokens: ~1860 | Category: plugin-manifest) -->\n<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase PostgREST JS SDK</h1>\n\n  <h3 align=\"center\">Isomorphic JavaScript SDK for <a href=\"https://postgrest.org\">PostgREST</a> with an ORM-like interface.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/database\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript/select\">Reference Docs</a>\n    ·\n    <a href=\"https://supabase.github.io/supabase-js/postgrest-js/v2/spec.json\">TypeDoc</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/postgrest-js)](https://www.npmjs.com/package/@supabase/postgrest-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/postgrest-js)](https://pkg.pr.new/~/supabase/postgrest-js)\n\n</div>\n\n### Quick start\n\nInstall\n\n```bash\nnpm install @supabase/postgrest-js\n```\n\nUsage\n\n```js\nimport { PostgrestClient } from '@supabase/postgrest-js'\n\nconst REST_URL = 'http://localhost:3000'\nconst postgrest = new PostgrestClient(REST_URL)\n```\n\n- [select()](https://supabase.com/docs/reference/javascript/select)\n- [insert()](https://supabase.com/docs/reference/javascript/insert)\n- [update()](https://supabase.com/docs/reference/javascript/update)\n- [delete()](https://supabase.com/docs/reference/javascript/delete)\n\n#### Custom `fetch` implementation\n\n`postgrest-js` uses the runtime's global `fetch` to make HTTP requests, but an alternative `fetch` implementation can be provided as an option. This is useful in environments where the global `fetch` is unavailable or where you want to customize request behavior:\n\n```js\nimport { PostgrestClient } from '@supabase/postgrest-js'\n\nconst REST_URL = 'http://localhost:3000'\nconst postgrest = new PostgrestClient(REST_URL, {\n  fetch: (...args) => fetch(...args),\n})\n```\n\n## Development\n\nThis package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:\n\n### Building\n\n```bash\n# Build (from monorepo root)\npnpm nx build postgrest-js\n\n# Build with watch mode for development\npnpm nx build:watch postgrest-js\n\n# TypeScript type checking\npnpm nx type-check postgrest-js\n\n# Generate documentation\npnpm nx docs postgrest-js\n```\n\n### Testing\n\n**Supabase CLI Required!** The `postgrest-js` tests use the [Supabase CLI](https://supabase.com/docs/guides/local-development/cli/getting-started) to run a local PostgreSQL database and PostgREST server.\n\n#### Quick Start\n\n```bash\n# Run all tests (from monorepo root)\npnpm nx test:ci:postgrest postgrest-js\n```\n\nThis single command automatically:\n\n1. Stops any existing Supabase CLI containers\n2. Starts PostgreSQL database and PostgREST server via Supabase CLI\n3. Resets and seeds the database\n4. Runs all Jest unit tests with coverage\n5. Cleans up containers\n\n#### Individual Test Commands\n\n```bash\n# Run Jest tests with coverage (requires infrastructure running)\npnpm nx test:run postgrest-js\n\n# Run type tests with tstyche\npnpm nx test:types postgrest-js\n\n# Run smoke tests (CommonJS and ESM imports)\npnpm nx test:smoke postgrest-js\n\n# Format code\npnpm nx format postgrest-js\n\n# Check formatting\npnpm nx format:check postgrest-js\n```\n\n#### Test Infrastructure\n\nThe tests use Supabase CLI to spin up:\n\n- **PostgreSQL** - Database with test schema and seed data (port 54322)\n- **PostgREST** - REST API server that the client connects to (port 54321)\n\n```bash\n# Manually manage test infrastructure (from monorepo root)\npnpm nx test:infra postgrest-js      # Start containers\npnpm nx test:clean-pre postgrest-js  # Stop and remove containers\n```\n\nOr directly via Supabase CLI:\n\n```bash\ncd packages/core/postgrest-js\nnpx supabase --workdir ./test start        # Start all services\nnpx supabase --workdir ./test db reset     # Reset and seed database\nnpx supabase --workdir ./test stop         # Stop all services\n```\n\n#### Regenerating TypeScript Types\n\nWhen the database schema changes, regenerate TypeScript types from the actual database:\n\n```bash\n# From the monorepo root\npnpm run codegen:postgrest\n```\n\nThis command automatically:\n\n1. Cleans up any existing Supabase containers\n2. Starts Supabase (PostgreSQL, PostgREST, and all services)\n3. Generates TypeScript types from the database schema\n4. Post-processes the generated types (updates JSON type definitions)\n5. Formats the generated file with Prettier\n6. Cleans up Supabase containers\n\nThe generated types are written to `test/types.generated.ts`.\n\n#### Test Types Explained\n\n- **Unit Tests** - Jest tests covering all client functionality (`pnpm nx test:run postgrest-js`)\n- **Type Tests** - Validates TypeScript types using tstyche (`pnpm nx test:types postgrest-js`)\n- **Smoke Tests** - Basic import/require tests for CommonJS and ESM (`pnpm nx test:smoke postgrest-js`)\n\n#### Prerequisites\n\n- **Supabase CLI** must be installed ([instructions](https://supabase.com/docs/guides/local-development/cli/getting-started)) or can be used through `npx` (`npx supabase`)\n- **Docker** must be installed and running (Supabase CLI uses Docker under the hood)\n- **Port 54321** - PostgREST API\n- **Port 54322** - PostgreSQL database\n- **Port 54323** - Supabase Studio (used for type generation)\n\n#### PostgREST v12 Backward Compatibility Tests\n\nWe maintain backward compatibility tests for PostgREST v12 (the current Supabase CLI uses v14+). These tests ensure the SDK works correctly for users still running older PostgREST versions.\n\n```bash\n# Run v12 compatibility tests (requires Docker)\npnpm nx test:ci:v12 postgrest-js\n```\n\nThis command:\n\n1. Starts PostgREST v12 + PostgreSQL in Docker (ports 3012/5433)\n2. Runs runtime tests that verify v12-specific behavior\n3. Cleans up containers\n\n**Type-only tests** for v12 compatibility also run as part of the regular type tests:\n\n```bash\npnpm nx test:types postgrest-js  # Includes v12-compat.test-d.ts\n```\n\n**Note:** These v12 tests will be removed when v3 ships (sometime in 2026).\n\n### Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n\n## License\n\nThis repo is licensed under MIT License.\n\n<!-- File: packages/core/realtime-js/example/README.md (Tokens: ~1062 | Category: plugin-manifest) -->\n# Realtime Chat Example\n\nA minimal anonymous chat app showcasing Supabase Realtime features:\n\n- **Broadcast** - Real-time message delivery\n- **Presence** - Online user indicators\n- **Database** - Message persistence\n\n## Features\n\n- Anonymous users with random usernames (stored in localStorage)\n- 4 chat rooms: General, Random, Tech, Off-Topic\n- Real-time messages\n- Online users per room\n- Message history on join\n\n## Setup\n\n### 1. Create a Supabase Project\n\nCreate a new project at [database.new](https://database.new)\n\n### 2. Run the Database Migration\n\nGo to the [SQL Editor](https://supabase.com/dashboard/project/_/sql) in your Supabase dashboard and run the migration you find in [supabase/migrations/001_create_messages_table.sql](./supabase/migrations/001_create_messages_table.sql).\n\n### 3. Configure Environment Variables\n\nCopy `.env.example` to `.env` and fill in your Supabase credentials:\n\n```bash\ncp .env.example .env\n```\n\nUpdate the values:\n\n```env\nNEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co\nNEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=your-publishable-key\n```\n\nFind these in your [Supabase project settings](https://supabase.com/dashboard/project/_/settings/api).\n\n### 4. Install Dependencies\n\n```bash\nnpm install\n```\n\n### 5. Run the App\n\n```bash\nnpm run dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000) to start chatting.\n\n## How It Works\n\n### Broadcast\n\nMessages are instantly delivered to all connected clients via Supabase Realtime Broadcast:\n\n```typescript\nchannel.send({\n  type: 'broadcast',\n  event: 'message',\n  payload: message,\n})\n```\n\n### Presence\n\nOnline users are tracked using Supabase Realtime Presence:\n\n```typescript\nchannel.on('presence', { event: 'sync' }, () => {\n  const users = Object.values(channel.presenceState()).flat()\n  setOnlineUsers(users)\n})\n```\n\n### Persistence\n\nMessages are also stored in the database so users see history when joining:\n\n```typescript\nconst { data } = await supabase\n  .from('messages')\n  .select('*')\n  .eq('room', room)\n  .order('created_at', { ascending: true })\n  .limit(50)\n```\n\n## Local Development\n\nYou can run Supabase locally using the Supabase CLI and Docker.\n\n### Prerequisites\n\n- [Docker](https://docs.docker.com/get-docker/) installed and running\n- [Supabase CLI](https://supabase.com/docs/guides/cli) (installed or used through `npx`)\n\n### 1. Start Supabase\n\n```bash\nnpx supabase start\n```\n\nThis will start all Supabase services locally. Once started, you'll see output with your local credentials:\n\n```\n╭──────────────────────────────────────╮\n│ 🔧 Development Tools                 │\n├─────────┬────────────────────────────┤\n│ Studio  │ http://127.0.0.1:54323     │\n│ ...     │ ...                        │\n╰─────────┴────────────────────────────╯\n\n╭──────────────────────────────────────────────╮\n│ 🌐 APIs                                      │\n├────────────────┬─────────────────────────────┤\n│ Project URL    │ http://127.0.0.1:54321      │\n│ ...            │ ...                         │\n╰────────────────┴─────────────────────────────╯\n...\n╭──────────────────────────────────────────────────╮\n│ 🔑 Authentication Keys                           │\n├─────────────┬────────────────────────────────────┤\n│ Publishable │ sb_publishable_...                 │\n│ Secret      │ sb_secret_...                      │\n╰─────────────┴────────────────────────────────────╯\n...\n```\n\n### 2. Configure Environment\n\nCopy `.env.example` to `.env.local`:\n\n```bash\ncp .env.example .env.local\n```\n\nUpdate the values:\n\n```env\nNEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321\nNEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_....\n```\n\n### 3. Run Migrations\n\nApply the database migration:\n\n```bash\nnpx supabase db reset\n```\n\nThis will apply all migrations from `supabase/migrations/`.\n\n### 5. Access Local Dashboard\n\nOpen [http://127.0.0.1:54323](http://127.0.0.1:54323) to access Supabase Studio locally. Here you can:\n\n- View and edit data in the Table Editor\n- Run SQL queries\n- Monitor Realtime connections\n- Check logs\n\n### Stopping Supabase\n\n```bash\nnpx supabase stop\n```\n\n<!-- File: packages/core/realtime-js/migrations/README.md (Tokens: ~345 | Category: plugin-manifest) -->\n# Migration notes for `@supabase/realtime-js`\n\nEach file in this directory describes one migration theme — what changed in `@supabase/realtime-js`, who is affected, and what callers need to do.\n\nFiles are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/realtime-js` you have installed. Upgrading the package brings the relevant migration notes along with it.\n\n## How agents should use this directory\n\nWhen helping a developer upgrade `@supabase/realtime-js`:\n\n1. Read the migration files in `node_modules/@supabase/realtime-js/migrations/` for the version they have installed.\n2. Cross-reference against the version they are upgrading to.\n3. Apply the migration steps described in each relevant file.\n\n## How humans should use this directory\n\nBrowse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.\n\n## File naming\n\nOne file per migration theme, named by topic rather than version (e.g. `<theme>.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.\n\n## Cross-cutting migration notes\n\nMigrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/realtime-js` only.\n\n<!-- File: packages/core/realtime-js/README.md (Tokens: ~3751 | Category: plugin-manifest) -->\n<br />\n<p align=\"center\">\n  <a href=\"https://supabase.io\">\n        <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n      <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\">\n    </picture>\n  </a>\n\n  <h1 align=\"center\">Supabase Realtime JS SDK</h1>\n\n  <h3 align=\"center\">Send ephemeral messages with <b>Broadcast</b>, track and synchronize state with <b>Presence</b>, and listen to database changes with <b>Postgres Change Data Capture (CDC)</b>.</h3>\n\n  <p align=\"center\">\n    <a href=\"https://supabase.com/docs/guides/realtime\">Guides</a>\n    ·\n    <a href=\"https://supabase.com/docs/reference/javascript\">Reference Docs</a>\n    ·\n    <a href=\"https://multiplayer.dev\">Multiplayer Demo</a>\n  </p>\n</p>\n\n<div align=\"center\">\n\n[![Build](https://github.com/supabase/supabase-js/workflows/CI/badge.svg)](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)\n[![Package](https://img.shields.io/npm/v/@supabase/realtime-js)](https://www.npmjs.com/package/@supabase/realtime-js)\n[![License: MIT](https://img.shields.io/npm/l/@supabase/supabase-js)](#license)\n[![pkg.pr.new](https://pkg.pr.new/badge/supabase/realtime-js)](https://pkg.pr.new/~/supabase/realtime-js)\n\n</div>\n\n# Overview\n\nThis SDK enables you to use the following Supabase Realtime's features:\n\n- **Broadcast**: send ephemeral messages from client to clients with minimal latency. Use cases include sharing cursor positions between users.\n- **Presence**: track and synchronize shared state across clients with the help of CRDTs. Use cases include tracking which users are currently viewing a specific webpage.\n- **Postgres Change Data Capture (CDC)**: listen for changes in your PostgreSQL database and send them to clients.\n\n# Usage\n\n## Installing the Package\n\n```bash\nnpm install @supabase/realtime-js\n```\n\n## Creating a Channel\n\n```js\nimport { RealtimeClient } from '@supabase/realtime-js'\n\nconst client = new RealtimeClient(REALTIME_URL, {\n  params: {\n    apikey: API_KEY,\n  },\n})\n\nconst channel = client.channel('test-channel', {})\n\nchannel.subscribe((status, err) => {\n  if (status === 'SUBSCRIBED') {\n    console.log('Connected!')\n  }\n\n  if (status === 'CHANNEL_ERROR') {\n    console.log(`There was an error subscribing to channel: ${err.message}`)\n  }\n\n  if (status === 'TIMED_OUT') {\n    console.log('Realtime server did not respond in time.')\n  }\n\n  if (status === 'CLOSED') {\n    console.log('Realtime channel was unexpectedly closed.')\n  }\n})\n```\n\n### Notes:\n\n- `REALTIME_URL` is `'ws://localhost:4000/socket'` when developing locally and `'wss://<project_ref>.supabase.co/realtime/v1'` when connecting to your Supabase project.\n- `API_KEY` is a JWT whose claims must contain `exp` and `role` (existing database role).\n- Channel name can be any `string`.\n- Setting `private` to `true` means that the client will use RLS to determine if the user can connect or not to a given channel.\n\n## Broadcast\n\nYour client can send and receive messages based on the `event`.\n\n```js\n// Setup...\n\nconst channel = client.channel('broadcast-test', { broadcast: { ack: false, self: false } })\n\nchannel.on('broadcast', { event: 'some-event' }, (payload) => console.log(payload))\n\nchannel.subscribe(async (status) => {\n  if (status === 'SUBSCRIBED') {\n    // Send message to other clients listening to 'broadcast-test' channel\n    await channel.send({\n      type: 'broadcast',\n      event: 'some-event',\n      payload: { hello: 'world' },\n    })\n  }\n})\n```\n\n### Notes:\n\n- Setting `ack` to `true` means that the `channel.send` promise will resolve once server replies with acknowledgment that it received the broadcast message request.\n- Setting `self` to `true` means that the client will receive the broadcast message it sent out.\n\n### Broadcast Replay\n\nBroadcast Replay enables **private** channels to access messages that were sent earlier. Only messages published via [Broadcast From the Database](https://supabase.com/docs/guides/realtime/broadcast#trigger-broadcast-messages-from-your-database) are available for replay.\n\nYou can configure replay with the following options:\n\n- **`since`** (Required): The epoch timestamp in milliseconds, specifying the earliest point from which messages should be retrieved.\n- **`limit`** (Optional): The number of messages to return. This must be a positive integer, with a maximum value of 25.\n\nExample:\n\n```typescript\nconst twelveHours = 12 * 60 * 60 * 1000\nconst twelveHoursAgo = Date.now() - twelveHours\n\nconst config = { private: true, broadcast: { replay: { since: twelveHoursAgo, limit: 10 } } }\n\nsupabase\n  .channel('main:room', { config })\n  .on('broadcast', { event: 'my_event' }, (payload) => {\n    if (payload?.meta?.replayed) {\n      console.log('This message was sent earlier:', payload)\n    } else {\n      console.log('This is a new message', payload)\n    }\n    // ...\n  })\n  .subscribe()\n```\n\n## Presence\n\nYour client can track and sync state that's stored in the channel.\n\n```js\n// Setup...\n\nconst channel = client.channel('presence-test', {\n  config: {\n    presence: {\n      key: '',\n    },\n  },\n})\n\nchannel.on('presence', { event: 'sync' }, () => {\n  console.log('Online users: ', channel.presenceState())\n})\n\nchannel.on('presence', { event: 'join' }, ({ newPresences }) => {\n  console.log('New users have joined: ', newPresences)\n})\n\nchannel.on('presence', { event: 'leave' }, ({ leftPresences }) => {\n  console.log('Users have left: ', leftPresences)\n})\n\nchannel.subscribe(async (status) => {\n  if (status === 'SUBSCRIBED') {\n    const status = await channel.track({ user_id: 1 })\n    console.log(status)\n  }\n})\n```\n\n> `config.presence.enabled` (set automatically if you add an `.on('presence', ...)` listener)\n> controls whether _this_ client receives presence state and updates from other clients —\n> without it, `presenceState()` stays empty for you. It does not affect whether other clients\n> see you: calling `track()` always makes you visible to subscribers that do have presence\n> enabled. On RLS-protected channels, receiving presence updates additionally requires the\n> `presence.read` policy to authorize this client.\n\n## Postgres CDC\n\nReceive database changes on the client.\n\n```js\n// Setup...\n\nconst channel = client.channel('db-changes')\n\nchannel.on('postgres_changes', { event: '*', schema: 'public' }, (payload) => {\n  console.log('All changes in public schema: ', payload)\n})\n\nchannel.on(\n  'postgres_changes',\n  { event: 'INSERT', schema: 'public', table: 'messages' },\n  (payload) => {\n    console.log('All inserts in messages table: ', payload)\n  }\n)\n\nchannel.on(\n  'postgres_changes',\n  { event: 'UPDATE', schema: 'public', table: 'users', filter: 'username=eq.Realtime' },\n  (payload) => {\n    console.log('All updates on users table when username is Realtime: ', payload)\n  }\n)\n\nchannel.subscribe(async (status) => {\n  if (status === 'SUBSCRIBED') {\n    console.log('Ready to receive database changes!')\n  }\n})\n```\n\n### Filters\n\nThe `filter` option accepts **either** a raw string **or** a\n`postgresChangesFilter()` builder — both produce the exact same wire format, so\nyou can mix and match and existing string filters keep working unchanged:\n\n```js\n// Raw string — always supported, fully backward compatible\n{ event: 'UPDATE', schema: 'public', table: 'users', filter: 'id=eq.1' }\n\n// Builder — type-checked, ergonomic; the SDK serializes it for you\n{ event: 'UPDATE', schema: 'public', table: 'users', filter: postgresChangesFilter().eq('id', 1) }\n```\n\nA filter is a `column=operator.value` expression evaluated server-side. The\nfollowing operators are supported:\n\n| Operator              | String form                  | Builder                                | Meaning                           |\n| --------------------- | ---------------------------- | -------------------------------------- | --------------------------------- |\n| `eq`                  | `id=eq.1`                    | `.eq('id', 1)`                         | equal                             |\n| `neq`                 | `id=neq.1`                   | `.neq('id', 1)`                        | not equal                         |\n| `lt` `lte` `gt` `gte` | `age=gte.18`                 | `.gte('age', 18)`                      | comparison                        |\n| `in`                  | `status=in.(active,pending)` | `.in('status', ['active', 'pending'])` | in list                           |\n| `like` `ilike`        | `title=like.%foo%`           | `.like('title', '%foo%')`              | pattern match (case in/sensitive) |\n| `is`                  | `deleted_at=is.null`         | `.is('deleted_at', null)`              | `IS null/true/false/unknown`      |\n| `match` `imatch`      | `title=match.^foo`           | `.match('title', '^foo')`              | POSIX regex match (`~` / `~*`)    |\n| `isdistinct`          | `value=isdistinct.1`         | `.isDistinct('value', 1)`              | NULL-safe inequality              |\n\n**Negation** — prefix any operator with `not.` (string) or use\n`.not(column, operator, value)` (builder):\n\n```js\n// String\n{ event: '*', schema: 'public', table: 'posts', filter: 'status=not.in.(draft,archived)' }\n\n// Builder\n{\n  event: '*',\n  schema: 'public',\n  table: 'posts',\n  filter: postgresChangesFilter().not('status', 'in', ['draft', 'archived']),\n}\n```\n\n**AND composition** — multiple conditions are combined with commas and applied\nas an `AND`. With the builder you just chain calls:\n\n```js\n// String\n{ event: 'UPDATE', schema: 'public', table: 'orders', filter: 'amount=gt.100,status=in.(open,pending)' }\n\n// Builder — equivalent, chained\n{\n  event: 'UPDATE',\n  schema: 'public',\n  table: 'orders',\n  filter: postgresChangesFilter().gt('amount', 100).in('status', ['open', 'pending']),\n}\n```\n\n#### Building filters with `postgresChangesFilter()`\n\nThe builder (modeled on the `postgrest-js` filter methods) is the recommended,\ntype-checked way to compose filters — but it is entirely optional; raw strings\nremain fully supported.\n\n```js\nimport { postgresChangesFilter } from '@supabase/realtime-js'\n\nchannel.on(\n  'postgres_changes',\n  {\n    event: 'UPDATE',\n    schema: 'public',\n    table: 'orders',\n    // → 'amount=gt.100,status=not.in.(draft,archived)'\n    filter: postgresChangesFilter().gt('amount', 100).not('status', 'in', ['draft', 'archived']),\n  },\n  (payload) => console.log(payload)\n)\n```\n\nThe builder exposes `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `in`, `like`,\n`ilike`, `match`, `imatch`, `is`, `isDistinct` and `not`. Call `.build()` if you\nneed the raw string yourself (e.g. to log it or store it).\n\n**Values are sent verbatim** — the server has no quoting/escaping, so spaces and\nquotes are preserved as-is. The server separates conditions by commas outside\nparentheses, so a literal comma in a scalar value can't be expressed (commas\ninside `in.(…)` are fine); the builder throws on such values rather than\nsilently producing a broken filter.\n\n> **Note for PostgREST users:** Realtime evaluates filters server-side over a\n> single table's WAL — there is no resource embedding (`!inner`, embedded\n> filters) and no `or()` grouping. Use `%` (not `*`) for `like`/`ilike`\n> wildcards, since filters travel in the WebSocket payload rather than a URL.\n\n### Selecting columns\n\nUse `select` to receive only a subset of columns instead of the full row. This\nreduces payload size (helpful for large `bytea`/`jsonb` columns). The selected\ncolumns must be selectable by the subscribing role:\n\n```js\nchannel.on(\n  'postgres_changes',\n  { event: '*', schema: 'public', table: 'users', select: ['id', 'first_name'] },\n  (payload) => {\n    // payload.new only contains { id, first_name }\n    console.log(payload)\n  }\n)\n```\n\n## Get All Channels\n\nYou can see all the channels that your client has instantiatied.\n\n```js\n// Setup...\n\nclient.getChannels()\n```\n\n## Cleanup\n\nIt is highly recommended that you clean up your channels after you're done with them.\n\n- Remove a single channel\n\n```js\n// Setup...\n\nconst channel = client.channel('some-channel-to-remove')\n\nchannel.unsubscribe()\nclient.removeChannel(channel)\n```\n\n- Remove all channels and close the connection\n\n```js\n// Setup...\n\nclient.removeAllChannels()\nclient.disconnect()\n```\n\n## Development\n\nThis package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:\n\n### Building\n\n```bash\n# Complete build (from monorepo root)\npnpm nx build realtime-js\n\n# Build with watch mode for development\npnpm nx build realtime-js --watch\n\n# Individual build targets\npnpm nx build:main realtime-js    # CommonJS build (dist/main/)\npnpm nx build:module realtime-js  # ES Modules build (dist/module/)\n\n# Other useful commands\npnpm nx clean realtime-js         # Clean build artifacts\npnpm nx lint realtime-js          # Run ESLint\npnpm nx typecheck realtime-js     # TypeScript type checking\n```\n\n#### Build Outputs\n\n- **CommonJS (`dist/main/`)** - For Node.js environments\n- **ES Modules (`dist/module/`)** - For modern bundlers (Webpack, Vite, Rollup)\n- **TypeScript definitions (`dist/module/index.d.ts`)** - Type definitions for TypeScript projects\n\nNote: Unlike some other packages, realtime-js doesn't include a UMD build since it's primarily used in Node.js or bundled applications.\n\n#### Validating Package Exports\n\n```bash\n# Check if package exports are correctly configured\npnpm nx check-exports realtime-js\n```\n\nThis command uses [\"Are the types wrong?\"](https://github.com/arethetypeswrong/arethetypeswrong.github.io) to verify that the package exports work correctly in different environments. Run this before publishing to ensure your package can be imported correctly by all consumers.\n\n### Testing\n\n**No Docker or Supabase instance required!** The realtime-js tests use mocked WebSocket connections, so they're completely self-contained.\n\n```bash\n# Run unit tests (from monorepo root)\npnpm nx test realtime-js\n\n# Run tests with coverage report\npnpm nx test:coverage realtime-js\n\n# Run tests in watch mode during development\npnpm nx test:watch realtime-js\n```\n\n#### Test Scripts Explained\n\n- **test** - Runs all unit tests once using Vitest\n- **test:coverage** - Runs tests and generates coverage report with terminal output\n- **test:watch** - Runs tests in interactive watch mode for development\n\nThe tests mock WebSocket connections using `mock-socket`, so you can run them anytime without any external dependencies.\n\n### Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.\n\nFor major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.\n\n## Credits\n\nThis repo draws heavily from [phoenix-js](https://github.com/phoenixframework/phoenix/tree/master/assets/js/phoenix).\n\n## License\n\nMIT.\n\n<!-- ... +7 more modular skills available via /api/skills/supabase/supabase-js?path={path} -->\n</yakaai_skills>"}