Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
7cc95d1
feat(e2e): add scenario JSON schema, fragments, and validator
jeffredodd May 14, 2026
b4e7b94
feat(e2e): scenario loader — $ref resolution, overrides, templates
jeffredodd May 14, 2026
e5fdb61
feat(e2e): scenario structural hash via canonical JSON + SHA-256
jeffredodd May 14, 2026
bf01fa8
feat(e2e): scenario infrastructure — cache, runner, decorations, fixt…
jeffredodd May 14, 2026
29a08fa
fix(e2e): stabilize scenario CI paths across msw and demo runs
jeffredodd May 15, 2026
74fe089
fix(e2e): normalize legacy onboarding status values in runner
jeffredodd May 15, 2026
92e97af
fix(e2e): avoid hard-failing on onboarding status API rejection
jeffredodd May 15, 2026
6c2e251
fix(e2e): make scenario payroll and URL overrides less brittle
jeffredodd May 15, 2026
54196c4
fix(e2e): tolerate payroll blockers during scenario seeding
jeffredodd May 15, 2026
8b9c185
fix(e2e): include start_date and end_date when creating off-cycle pay…
jeffredodd May 15, 2026
ca97c4b
ci(e2e): gate Playwright runs behind scenario validation
jeffredodd May 15, 2026
560021d
ci(e2e): drop MSW e2e job, keep e2e-demo as the only Playwright gate
jeffredodd May 19, 2026
2ce9214
ci(e2e): rename e2e-demo job to e2e (now the sole Playwright gate)
jeffredodd May 19, 2026
52fb9c2
chore: install @gusto/embedded-api-v-2025-11-15 and migrate shared im…
jeffredodd May 19, 2026
31aa516
chore: complete @gusto/embedded-api-v-2025-11-15 migration across com…
jeffredodd May 19, 2026
9469a51
feat(e2e): payroll domain — scenarios, spec rewrites, legacy cleanup
jeffredodd May 14, 2026
bc0f3f9
feat(e2e): expand payroll domain with multi-entity and weekly cadence…
jeffredodd May 15, 2026
b32749d
fix(e2e): assert real payroll panel content beyond just tab visibility
jeffredodd May 15, 2026
964c2df
feat(e2e): cover payroll blockers view-all terminal state
jeffredodd May 16, 2026
b957d2c
feat(e2e): cover payroll execution-entry + cancel dialog lifecycle
jeffredodd May 19, 2026
d081d6e
feat(e2e): cover payroll execution entry from an unprocessed row
jeffredodd May 19, 2026
2df31ff
feat(e2e): cover payroll execution breadcrumb-back lifecycle
jeffredodd May 19, 2026
0d613b8
feat(e2e): dismissal domain — scenario + spec rewrite
jeffredodd May 15, 2026
4fd3f35
fix(e2e): unblock dismissal CI checks
jeffredodd May 15, 2026
5d2b2a6
fix(e2e): harden dismissal tests for scenario and state variance
jeffredodd May 15, 2026
c95b73a
feat(e2e): expand dismissal domain with scenario-backed termination v…
jeffredodd May 15, 2026
7aba3da
fix(e2e): unskip legacy dismissal specs by deferring scenario fixture…
jeffredodd May 15, 2026
20861f3
fix(e2e): drive scenario-backed dismissal flow into payroll execution
jeffredodd May 15, 2026
38a0266
feat(e2e): cover termination flow create lifecycle
jeffredodd May 19, 2026
b00aa60
feat(e2e): cover termination summary cancel-dialog lifecycle
jeffredodd May 19, 2026
bb18927
feat(e2e): company domain — scenario + spec rewrite
jeffredodd May 15, 2026
c15eaa1
fix(e2e): harden company onboarding scenario for CI
jeffredodd May 15, 2026
2c59974
fix(e2e): accept company onboarding copy variations in demo runs
jeffredodd May 15, 2026
b5682e0
feat(e2e): expand company domain with multi-entity, filing/mailing sp…
jeffredodd May 15, 2026
2e7ff26
fix(e2e): walk into onboarding flow in company complex/split scenario…
jeffredodd May 15, 2026
1a18dbc
feat(e2e): walk company onboarding through step 5 (bank account)
jeffredodd May 16, 2026
f435dfc
feat(e2e): cover company onboarding bank account empty-state lifecycle
jeffredodd May 19, 2026
b0df94a
feat(e2e): employee domain — scenarios + spec rewrites
jeffredodd May 14, 2026
575c4c9
fix(e2e): stabilize employee scenario CI provisioning
jeffredodd May 15, 2026
849dfa5
feat(e2e): expand employee domain with focused entry and existing-emp…
jeffredodd May 15, 2026
57ba35c
fix(e2e): assert grid presence instead of seeded employee name
jeffredodd May 15, 2026
8d69df7
fix(e2e): make employee self-onboarding actually drive the flow
jeffredodd May 15, 2026
1898aff
feat(e2e): cover employee update re-entry from list lifecycle
jeffredodd May 19, 2026
b765279
feat(e2e): contractor domain — scenarios + spec rewrites
jeffredodd May 14, 2026
c3aad74
fix(e2e): stabilize contractor scenario provisioning in CI
jeffredodd May 15, 2026
205d3ea
feat(e2e): expand contractor domain with business and mixed roster sc…
jeffredodd May 15, 2026
49f56c2
fix(e2e): assert real terminal states in contractor lifecycle tests
jeffredodd May 15, 2026
37069a5
feat(e2e): cover contractor onboarding state-machine branches
jeffredodd May 16, 2026
89a9f46
feat(e2e): cover contractor payment submit validation terminal state
jeffredodd May 16, 2026
99cd4d3
feat(e2e): cover contractor payment create-to-summary full lifecycle
jeffredodd May 19, 2026
c767f6c
feat(e2e): cover contractor edit re-entry from list lifecycle
jeffredodd May 19, 2026
2c38f44
feat(e2e): time-off domain — scenario + spec rewrite
jeffredodd May 15, 2026
7cfc7f9
fix(e2e): use valid onboarding status in time-off scenario
jeffredodd May 15, 2026
44d7d2a
feat(e2e): expand time-off domain with scenario-driven policy coverage
jeffredodd May 15, 2026
1da818c
fix(e2e): assert visible Time off radio instead of named radiogroup
jeffredodd May 15, 2026
46505e9
feat(e2e): rewrite time-off specs as end-to-end CRUD lifecycle flows
jeffredodd May 15, 2026
d1edfef
feat(e2e): cover all time-off state-machine branches end-to-end
jeffredodd May 16, 2026
7991ace
feat(e2e): cover time-off policy details form UI validation lifecycle
jeffredodd May 19, 2026
009c2fb
chore: merge e2e/payroll-domain into api-upgrade-integration
jeffredodd May 19, 2026
ec2d1c6
chore: merge e2e/employee-domain into api-upgrade-integration
jeffredodd May 19, 2026
1a986c9
chore: merge e2e/contractor-domain into api-upgrade-integration
jeffredodd May 19, 2026
729035f
chore: merge e2e/timeoff-domain into api-upgrade-integration
jeffredodd May 19, 2026
70db485
chore: merge e2e/dismissal-domain into api-upgrade-integration
jeffredodd May 19, 2026
35d89f3
chore: merge e2e/company-domain into api-upgrade-integration
jeffredodd May 19, 2026
cd89023
feat(e2e): wire information-requests flow + add MSW-backed spec
jeffredodd May 19, 2026
d0f8500
ci(e2e): shard Playwright job by domain
jeffredodd May 19, 2026
364419e
ci(e2e): throttle matrix to max-parallel 2 to avoid demo backend time…
jeffredodd May 19, 2026
45d3ba0
ci(e2e): provision demo companies once via shared e2e-setup job
jeffredodd May 19, 2026
0da4ebd
ci(e2e): include hidden files when uploading e2e state artifact
jeffredodd May 19, 2026
db4cf2b
ci(e2e): drop information-requests domain shard and MSW-backed spec
jeffredodd May 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .claude/commands/create-hook.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ import { useMemo } from 'react'
import { useForm } from 'react-hook-form'
import type { UseFormProps } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import type { {Entity} } from '@gusto/embedded-api/models/components/{entity}'
import type { {Entity} } from '@gusto/embedded-api-v-2025-11-15/models/components/{entity}'
// React-query hooks for the GET / mutations this hook drives
import {
create{Domain}Schema,
Expand Down
12 changes: 6 additions & 6 deletions .claude/commands/starttechspec.md
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ git commit -m "docs: initialize {feature_name} tech spec"

### Step 5: Run Zod Validation Tests

Validate the `@gusto/embedded-api` Zod schemas against real API responses to catch bugs early.
Validate the `@gusto/embedded-api-v-2025-11-15` Zod schemas against real API responses to catch bugs early.

**Why this matters:**
The embedded-api SDK uses Zod schemas to validate API responses. If the schema doesn't match reality, the SDK throws `ResponseValidationError`. Finding these mismatches during spec phase prevents runtime failures later.
Expand Down Expand Up @@ -357,7 +357,7 @@ In the spec repo, create a quick test harness:
```bash
cd ~/workspace/{slug}-spec/zod-validation-test
npm init -y
npm install @gusto/embedded-api tsx typescript
npm install @gusto/embedded-api-v-2025-11-15 tsx typescript
```

**Step 5d: Test via the embedded-api React Query hooks**
Expand All @@ -373,9 +373,9 @@ The SDK provides React Query hooks that validate responses with Zod schemas. If

```tsx
import { ApiProvider } from './ApiProvider'
import { useEmployeesListSuspense } from '@gusto/embedded-api/react-query/employeesList'
import { usePayrollsListSuspense } from '@gusto/embedded-api/react-query/payrollsList'
import { usePayrollsCreateOffCycleMutation } from '@gusto/embedded-api/react-query/payrollsCreateOffCycle'
import { useEmployeesListSuspense } from '@gusto/embedded-api-v-2025-11-15/react-query/employeesList'
import { usePayrollsListSuspense } from '@gusto/embedded-api-v-2025-11-15/react-query/payrollsList'
import { usePayrollsCreateOffCycleMutation } from '@gusto/embedded-api-v-2025-11-15/react-query/payrollsCreateOffCycle'

function TestHarness({ companyId }: { companyId: string }) {
// Each hook call triggers Zod validation on the response
Expand All @@ -399,7 +399,7 @@ function TestHarness({ companyId }: { companyId: string }) {
**Test the hooks you'll use in this feature:**

- List through your API inventory
- Call each React Query hook from `@gusto/embedded-api/react-query/*`
- Call each React Query hook from `@gusto/embedded-api-v-2025-11-15/react-query/*`
- Record which hooks pass/fail Zod validation

**Step 5e: Document findings**
Expand Down
6 changes: 3 additions & 3 deletions .claude/hooks-implementation.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ export function JobTitleField(props: JobTitleFieldProps) {

### Data Fetching

- Use `@gusto/embedded-api/react-query/*` hooks for all API calls
- Use `@gusto/embedded-api-v-2025-11-15/react-query/*` hooks for all API calls
- Gate dependent queries with `enabled: !!dependency`
- Use `composeErrorHandler` to build the `errorHandling` bag (see Error Handling section below)

Expand Down Expand Up @@ -308,7 +308,7 @@ const errorHandling = composeErrorHandler(queries, { submitError, setSubmitError

You can pass **nested SDK hook results** (objects with `errorHandling`) plus extra React Query results in the first array — see `composeErrorHandler` in `src/partner-hook-utils/composeErrorHandler.ts`.

**Multi-form screens:** `composeSubmitHandler` coordinates validation + ordered submits **and** returns `{ handleSubmit, errorHandling }` aggregated across the forms it receives. Partners that want to combine in extra `@gusto/embedded-api` queries or screen-level submit state feed the result into **`composeErrorHandler([submitResult, ...extraQueries], optionalScreenSubmit)`**.
**Multi-form screens:** `composeSubmitHandler` coordinates validation + ordered submits **and** returns `{ handleSubmit, errorHandling }` aggregated across the forms it receives. Partners that want to combine in extra `@gusto/embedded-api-v-2025-11-15` queries or screen-level submit state feed the result into **`composeErrorHandler([submitResult, ...extraQueries], optionalScreenSubmit)`**.

`composeErrorHandler` returns `HookErrorHandling`:

Expand Down Expand Up @@ -407,7 +407,7 @@ Reference `gws-flows/app/frontend/react_sdk/CustomCompensationForm.tsx` as the r

Infrastructure utilities like `buildFormSchema`, `useDeriveFieldsMetadata`, `deriveFieldsMetadata`, `withOptions`, `FormFieldsMetadataProvider`, `composeErrorHandler`, `collectErrors`, generic `*HookField` components, and base types like `HookFormInternals`, `BaseFormHookReady` are used by the SDK to build hooks — not by partners. Only promote to the public barrel if a partner use case demands it.

Do NOT re-export `@gusto/embedded-api` entity types directly — partners derive them from field prop generics (e.g. `NonNullable<FlsaStatusFieldProps['getOptionLabel']>` infers the entity type).
Do NOT re-export `@gusto/embedded-api-v-2025-11-15` entity types directly — partners derive them from field prop generics (e.g. `NonNullable<FlsaStatusFieldProps['getOptionLabel']>` infers the entity type).

## 7. Validation Parity with Stable Components

Expand Down
121 changes: 101 additions & 20 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -207,13 +207,46 @@ jobs:
- name: Test with coverage
run: npm run test:ci

# E2E job: Run Playwright e2e tests (parallel with other checks)
e2e:
# Scenarios job: Validate scenario JSON against schema and run scenario unit tests.
# E2E jobs depend on this so a broken scenario fails fast (cheap) before Playwright runs (expensive).
scenarios:
needs: setup
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- uses: actions/setup-node@v6
with:
node-version-file: '.nvmrc'

- name: Restore node_modules cache
uses: actions/cache/restore@v5
with:
path: node_modules
key: ${{ needs.setup.outputs.cache-key }}

- name: Validate scenario JSON
run: npm run scenarios:validate

- name: Run scenario unit tests
run: npm run test:scenarios

# E2E setup: Provision demo companies once on flows.gusto-demo.com and
# publish the resulting state (flow token, primary company, dismissal
# company, terminated employee, etc.) as an artifact. Each e2e shard
# downloads this artifact and skips provisioning thanks to
# globalSetup's idempotency check.
#
# Without this job, every shard's globalSetup re-provisions ~2 demo
# companies; with 9 shards that meant ~18 concurrent demo creations on
# the demo backend, which caused 200s flow-token lookup timeouts and
# cascading shard failures. Provisioning once removes the bottleneck.
e2e-setup:
needs: [setup, scenarios]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- uses: actions/setup-node@v6
with:
node-version-file: '.nvmrc'
Expand Down Expand Up @@ -241,24 +274,58 @@ jobs:
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: npx playwright install-deps chromium

- name: Initialize MSW
run: npx msw init e2e/public --save=false

- name: Run e2e tests
run: npm run test:e2e
- name: Provision demo companies
env:
E2E_LOCAL: 'true'
run: npm run e2e:setup

- name: Upload test results
if: ${{ !cancelled() }}
- name: Upload e2e state
uses: actions/upload-artifact@v6
with:
name: playwright-report
path: playwright-report/
retention-days: 7

# E2E Demo job: Run Playwright e2e tests against the live demo environment
e2e-demo:
needs: setup
name: e2e-state
path: e2e/.e2e-state.json
# File starts with a dot (.e2e-state.json); upload-artifact@v6
# excludes hidden files by default, so opt in explicitly.
include-hidden-files: true
retention-days: 1
if-no-files-found: error

# E2E job: Run Playwright e2e tests against the live demo environment.
# This is the sole Playwright gate. A previous MSW-mode e2e job was removed
# because its mock fixtures could not keep pace with real demo backend
# behavior, and the duplicate run added CI minutes for shallow coverage
# already provided by Storybook + unit tests. This job exercises the
# actual API contract, scenario provisioning, and state machine terminal
# states. The local npm script is still named test:e2e:demo to reflect
# what it points at.
#
# Sharded by domain so each domain runs in parallel and one domain's
# failure doesn't block feedback on the others. The `domain` filter is a
# Playwright path-substring match, so it picks up both flat specs at
# `e2e/tests/<domain>*.spec.ts` and nested specs at
# `e2e/tests/<domain>/**/*.spec.ts`.
e2e:
needs: [setup, scenarios, e2e-setup]
runs-on: ubuntu-latest
strategy:
fail-fast: false
# Throttle concurrent shards to avoid overwhelming flows.gusto-demo.com
# with per-test scenario provisioning. globalSetup is now shared via
# the e2e-setup job's artifact, but scenario-backed specs still create
# additional demo companies on demand. 2 concurrent shards keeps that
# load manageable.
max-parallel: 2
matrix:
domain:
- company
- contractor
- dismissal
- employee
- payroll
- termination
- time-off
- legacy
name: e2e (${{ matrix.domain }})
steps:
- uses: actions/checkout@v6

Expand Down Expand Up @@ -289,13 +356,27 @@ jobs:
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: npx playwright install-deps chromium

- name: Run e2e tests against demo environment
run: npm run test:e2e:demo
- name: Download e2e state
uses: actions/download-artifact@v6
with:
name: e2e-state
path: e2e/

- name: Run e2e tests
run: npm run test:e2e:demo -- --pass-with-no-tests ${{ matrix.domain }}

- name: Upload demo test results
- name: Upload test results
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v6
with:
name: playwright-report-demo
name: playwright-report-${{ matrix.domain }}
path: playwright-report/
retention-days: 7

- name: Upload scenario reports
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v6
with:
name: e2e-scenario-report-${{ matrix.domain }}
path: e2e/reports/
retention-days: 7
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,11 @@ test-results/

# E2E local testing
e2e/.e2e-state.json
e2e/.scenario-cache.json
e2e/local.config.env
e2e/recordings/
e2e-recordings/
e2e/reports/

# Playwright MCP artifacts
.playwright-mcp/
Expand Down
14 changes: 7 additions & 7 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,16 @@ src/components/
└── Flow/ # Multi-step flow orchestration
```

### API Layer (`@gusto/embedded-api`)
### API Layer (`@gusto/embedded-api-v-2025-11-15`)

All API calls go through `@gusto/embedded-api` with React Query hooks and Zod schema validation.
All API calls go through `@gusto/embedded-api-v-2025-11-15` with React Query hooks and Zod schema validation.

Import paths:

- `@gusto/embedded-api/react-query/<operation>` — React Query hooks
- `@gusto/embedded-api/models/components/<name>` — Entity types
- `@gusto/embedded-api/models/operations/<name>` — Request/response types
- `@gusto/embedded-api/models/errors/<name>` — Error types
- `@gusto/embedded-api-v-2025-11-15/react-query/<operation>` — React Query hooks
- `@gusto/embedded-api-v-2025-11-15/models/components/<name>` — Entity types
- `@gusto/embedded-api-v-2025-11-15/models/operations/<name>` — Request/response types
- `@gusto/embedded-api-v-2025-11-15/models/errors/<name>` — Error types

Hook naming: `use<Resource><Action>Suspense` (queries), `use<Resource><Action>Mutation` (mutations)

Expand All @@ -101,7 +101,7 @@ All user-facing text uses i18next. Run `npm run i18n:generate` after changing tr

### Partner hooks (`composeErrorHandler` / `composeSubmitHandler`)

Exported headless hooks build `errorHandling` with **`composeErrorHandler`** (not a React hook). For multi-form screens, **`composeSubmitHandler`** coordinates validation + ordered submits and returns `{ handleSubmit, errorHandling }` aggregated across those forms. The result plugs back into `composeErrorHandler` when partners need extra `@gusto/embedded-api` queries or screen-level submit state in the same error surface — see [docs/hooks/hooks.md](docs/hooks/hooks.md).
Exported headless hooks build `errorHandling` with **`composeErrorHandler`** (not a React hook). For multi-form screens, **`composeSubmitHandler`** coordinates validation + ordered submits and returns `{ handleSubmit, errorHandling }` aggregated across those forms. The result plugs back into `composeErrorHandler` when partners need extra `@gusto/embedded-api-v-2025-11-15` queries or screen-level submit state in the same error surface — see [docs/hooks/hooks.md](docs/hooks/hooks.md).

## PR and Commit Conventions

Expand Down
14 changes: 7 additions & 7 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,16 @@ src/components/
└── Flow/ # Multi-step flow orchestration
```

### API Layer (`@gusto/embedded-api`)
### API Layer (`@gusto/embedded-api-v-2025-11-15`)

All API calls go through `@gusto/embedded-api` with React Query hooks and Zod schema validation.
All API calls go through `@gusto/embedded-api-v-2025-11-15` with React Query hooks and Zod schema validation.

Import paths:

- `@gusto/embedded-api/react-query/<operation>` — React Query hooks
- `@gusto/embedded-api/models/components/<name>` — Entity types
- `@gusto/embedded-api/models/operations/<name>` — Request/response types
- `@gusto/embedded-api/models/errors/<name>` — Error types
- `@gusto/embedded-api-v-2025-11-15/react-query/<operation>` — React Query hooks
- `@gusto/embedded-api-v-2025-11-15/models/components/<name>` — Entity types
- `@gusto/embedded-api-v-2025-11-15/models/operations/<name>` — Request/response types
- `@gusto/embedded-api-v-2025-11-15/models/errors/<name>` — Error types

Hook naming: `use<Resource><Action>Suspense` (queries), `use<Resource><Action>Mutation` (mutations)

Expand All @@ -101,7 +101,7 @@ All user-facing text uses i18next. Run `npm run i18n:generate` after changing tr

### Partner hooks (`composeErrorHandler` / `composeSubmitHandler`)

Exported headless hooks build `errorHandling` with **`composeErrorHandler`** (not a React hook). For multi-form screens, **`composeSubmitHandler`** coordinates validation + ordered submits and returns `{ handleSubmit, errorHandling }` aggregated across those forms. The result plugs back into `composeErrorHandler` when partners need extra `@gusto/embedded-api` queries or screen-level submit state in the same error surface — see [docs/hooks/hooks.md](docs/hooks/hooks.md).
Exported headless hooks build `errorHandling` with **`composeErrorHandler`** (not a React hook). For multi-form screens, **`composeSubmitHandler`** coordinates validation + ordered submits and returns `{ handleSubmit, errorHandling }` aggregated across those forms. The result plugs back into `composeErrorHandler` when partners need extra `@gusto/embedded-api-v-2025-11-15` queries or screen-level submit state in the same error surface — see [docs/hooks/hooks.md](docs/hooks/hooks.md).

## PR and Commit Conventions

Expand Down
21 changes: 12 additions & 9 deletions build/deriveEndpointInventory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)

const ROOT = join(__dirname, '..')
const FUNCS_DIR = join(ROOT, 'node_modules/@gusto/embedded-api/src/funcs')
const OPS_DIR = join(ROOT, 'node_modules/@gusto/embedded-api/src/models/operations')
const FUNCS_DIR = join(ROOT, 'node_modules/@gusto/embedded-api-v-2025-11-15/src/funcs')
const OPS_DIR = join(ROOT, 'node_modules/@gusto/embedded-api-v-2025-11-15/src/models/operations')
const COMPONENTS_DIR = join(ROOT, 'src/components')
const JSON_OUTPUT_PATH = join(ROOT, 'docs/reference/endpoint-inventory.json')
const MD_OUTPUT_PATH = join(ROOT, 'docs/reference/endpoint-reference.md')
Expand All @@ -33,7 +33,7 @@ interface FlowEntry {
variables: string[]
}

// --- AST-based extraction from @gusto/embedded-api ---
// --- AST-based extraction from @gusto/embedded-api-v-2025-11-15 ---

function createApiProject(): Project {
return new Project({
Expand Down Expand Up @@ -175,13 +175,14 @@ function walkDir(dir: string): string[] {
return results
}

// --- Extract @gusto/embedded-api imports from component files ---
// --- Extract @gusto/embedded-api-v-2025-11-15 imports from component files ---

function extractApiImports(filePaths: string[]): Set<string> {
const funcNames = new Set<string>()

const hookImportPattern = /from\s+['"]@gusto\/embedded-api\/react-query\/([^'"]+)['"]/g
const funcImportPattern = /from\s+['"]@gusto\/embedded-api\/funcs\/([^'"]+)['"]/g
const hookImportPattern =
/from\s+['"]@gusto\/embedded-api-v-2025-11-15\/react-query\/([^'"]+)['"]/g
const funcImportPattern = /from\s+['"]@gusto\/embedded-api-v-2025-11-15\/funcs\/([^'"]+)['"]/g

for (const filePath of filePaths) {
const content = readFileSync(filePath, 'utf-8')
Expand Down Expand Up @@ -626,7 +627,7 @@ function generateMarkdown(inventory: Inventory): string {
return lines.join('\n')
}

// --- Validate all inventory endpoints exist in @gusto/embedded-api ---
// --- Validate all inventory endpoints exist in @gusto/embedded-api-v-2025-11-15 ---

function validateEndpoints(
inventory: { blocks: Record<string, BlockEntry> },
Expand All @@ -648,7 +649,9 @@ function validateEndpoints(
}

if (invalid.length > 0) {
console.error('WARNING: Some inventory endpoints were not found in @gusto/embedded-api:')
console.error(
'WARNING: Some inventory endpoints were not found in @gusto/embedded-api-v-2025-11-15:',
)
for (const ep of invalid) console.error(` ${ep}`)
console.error('')
}
Expand Down Expand Up @@ -708,7 +711,7 @@ function verify() {
console.error('This can happen when:')
console.error(' - A component added or removed an API hook/function import')
console.error(' - A flow added or removed a block component')
console.error(' - The @gusto/embedded-api package was updated')
console.error(' - The @gusto/embedded-api-v-2025-11-15 package was updated')
console.error(' - The pre-commit hook was bypassed (--no-verify)')
console.error('')
console.error('Fix: run "npm run endpoints:derive" and commit the updated files.')
Expand Down
Loading
Loading