@tailor-platform/erp-kit 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +2 -3
  3. package/package.json +1 -1
  4. package/schemas/app-compose/business-flow.yml +3 -0
  5. package/schemas/app-compose/story.yml +1 -1
  6. package/skills/erp-kit-app-1-requirements/SKILL.md +6 -12
  7. package/skills/erp-kit-app-2-breakdown/SKILL.md +3 -10
  8. package/skills/erp-kit-app-3-doc-review/SKILL.md +1 -5
  9. package/skills/{erp-kit-app-6-impl-spec → erp-kit-app-4-impl-spec}/SKILL.md +10 -21
  10. package/skills/erp-kit-app-5-implementation/SKILL.md +149 -0
  11. package/skills/erp-kit-app-5-implementation/references/backend.md +232 -0
  12. package/skills/erp-kit-app-5-implementation/references/frontend.md +242 -0
  13. package/src/module.ts +38 -0
  14. package/skills/erp-kit-app-1-requirements/references/structure.md +0 -27
  15. package/skills/erp-kit-app-2-breakdown/references/screen-detailview.md +0 -106
  16. package/skills/erp-kit-app-2-breakdown/references/screen-form.md +0 -139
  17. package/skills/erp-kit-app-2-breakdown/references/screen-listview.md +0 -153
  18. package/skills/erp-kit-app-2-breakdown/references/structure.md +0 -27
  19. package/skills/erp-kit-app-3-doc-review/references/structure.md +0 -27
  20. package/skills/erp-kit-app-4-design/SKILL.md +0 -256
  21. package/skills/erp-kit-app-4-design/references/component.md +0 -50
  22. package/skills/erp-kit-app-4-design/references/screen-detailview.md +0 -106
  23. package/skills/erp-kit-app-4-design/references/screen-form.md +0 -139
  24. package/skills/erp-kit-app-4-design/references/screen-listview.md +0 -153
  25. package/skills/erp-kit-app-4-design/references/structure.md +0 -27
  26. package/skills/erp-kit-app-5-design-review/SKILL.md +0 -290
  27. package/skills/erp-kit-app-5-design-review/references/component.md +0 -50
  28. package/skills/erp-kit-app-5-design-review/references/screen-detailview.md +0 -106
  29. package/skills/erp-kit-app-5-design-review/references/screen-form.md +0 -139
  30. package/skills/erp-kit-app-5-design-review/references/screen-listview.md +0 -153
  31. package/skills/erp-kit-app-6-impl-spec/references/auth.md +0 -72
  32. package/skills/erp-kit-app-6-impl-spec/references/structure.md +0 -27
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @tailor-platform/erp-kit
2
2
 
3
+ ## 0.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 4c94ba6: Add erp-kit-app-5-implementation skill, remove app-4-design and app-5-design-review skills
8
+
3
9
  ## 0.2.0
4
10
 
5
11
  ### Minor Changes
package/README.md CHANGED
@@ -274,9 +274,8 @@ App-compose workflow:
274
274
  1. `erp-kit-app-1-requirements` — Tier 1-2: requirements, actors, business flows
275
275
  2. `erp-kit-app-2-breakdown` — Tier 3: stories and screens
276
276
  3. `erp-kit-app-3-doc-review` — Review doc parity
277
- 4. `erp-kit-app-4-design` — Create UI mockups from screen specs
278
- 5. `erp-kit-app-5-design-review` — Review mockups against specs
279
- 6. `erp-kit-app-6-impl-spec` — Tier 4: resolver specs
277
+ 4. `erp-kit-app-4-impl-spec` — Tier 4: resolver specs
278
+ 5. `erp-kit-app-5-implementation` — Implement backend and frontend
280
279
 
281
280
  Mock workflow:
282
281
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tailor-platform/erp-kit",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Opinionated ERP toolkit for building business applications on Tailor Platform",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -24,6 +24,9 @@ structure:
24
24
 
25
25
  # Diagram representing this flow - REQUIRED
26
26
  - heading: "## Flow Diagram"
27
+ description: |
28
+ Mermaid sequence diagram showing actor interactions across the flow.
29
+ Use actors from "Actors Involved" as participants.
27
30
  code_blocks:
28
31
  - min: 1
29
32
  lang: mermaid
@@ -24,7 +24,7 @@ structure:
24
24
  # Diagram representing this story - REQUIRED
25
25
  - heading: "## Story Diagram"
26
26
  description: |
27
- Mermaid sequence diagram showing user interactions with screens.
27
+ Mermaid flowchart showing user interactions with screens.
28
28
  Focus on actors, UI screens, and business outcomes.
29
29
  Avoid technical details (APIs, databases, endpoints).
30
30
  code_blocks:
@@ -44,13 +44,13 @@ Generate documentation using `erp-kit` CLI:
44
44
 
45
45
  ```bash
46
46
  # Tier 1: Requirements
47
- erp-kit scaffold --app-root examples requirements <app-name>
47
+ erp-kit app scaffold requirements <app-name> --root examples
48
48
 
49
49
  # Tier 2: Actors
50
- erp-kit scaffold --app-root examples actors <app-name> <actor-name>
50
+ erp-kit app scaffold actors <app-name> <actor-name> --root examples
51
51
 
52
52
  # Tier 2: Business Flows
53
- erp-kit scaffold --app-root examples business-flow <app-name> <flow-name>
53
+ erp-kit app scaffold business-flow <app-name> <flow-name> --root examples
54
54
  ```
55
55
 
56
56
  **Naming conventions:**
@@ -58,13 +58,11 @@ erp-kit scaffold --app-root examples business-flow <app-name> <flow-name>
58
58
  - Files: kebab-case (e.g., `sales-representative.md`)
59
59
  - H1 heading slug must match filename slug
60
60
 
61
- **Authorized Business Flows format (in actor docs):**
61
+ **Business flow diagram:** Use `sequenceDiagram` with actors from "Actors Involved" as participants. Show who initiates each step and the system responses.
62
62
 
63
- ```markdown
64
- - [Flow Name](../business-flow/<flow>/README.md) — role
65
- ```
63
+ **Business flow `## Stories` section:**
66
64
 
67
- Roles: `initiator`, `approver`, `viewer`
65
+ At Tier 2, story files do not exist yet. Use `- TBD` as a placeholder to avoid broken link violations. Replace with actual story links in `/erp-kit-app-2-breakdown`.
68
66
 
69
67
  ### Phase 4: Validate
70
68
 
@@ -83,7 +81,3 @@ pnpm run app:doc:check
83
81
  ## Next Step
84
82
 
85
83
  After completing Tier 1-2, use `/erp-kit-app-2-breakdown` to create Tier 3 documentation.
86
-
87
- ## References
88
-
89
- - [Application structure](references/structure.md)
@@ -46,10 +46,10 @@ Generate documentation using `erp-kit` CLI:
46
46
 
47
47
  ```bash
48
48
  # Tier 3: Stories
49
- erp-kit scaffold --app-root examples story <app> <flow>/<actor>--<story>
49
+ erp-kit app scaffold story <app> <flow>/<actor>--<story> --root examples
50
50
 
51
51
  # Tier 3: Screens
52
- erp-kit scaffold --app-root examples screen <app> <screen-name>
52
+ erp-kit app scaffold screen <app> <screen-name> --root examples
53
53
  ```
54
54
 
55
55
  **Naming conventions:**
@@ -58,7 +58,7 @@ erp-kit scaffold --app-root examples screen <app> <screen-name>
58
58
  - Story heading: Title Case of story name (after `--`)
59
59
  - Screen filename: kebab-case, noun-focused (e.g., `supplier-list.md`)
60
60
 
61
- **After creating stories**, update `## Stories` section in business flow README:
61
+ **After creating stories**, replace `- TBD` placeholders in the `## Stories` section of each business flow README with actual links:
62
62
 
63
63
  ```markdown
64
64
  - [Story Title](./story/<actor>--<story-name>.md)
@@ -86,10 +86,3 @@ pnpm run app:doc:check
86
86
  ## Next Step
87
87
 
88
88
  After completing Tier 3, use `/erp-kit-app-3-doc-review` to validate documentation parity.
89
-
90
- ## References
91
-
92
- - [Application structure](references/structure.md)
93
- - [ListView screen](references/screen-listview.md)
94
- - [Form screen](references/screen-form.md)
95
- - [DetailView screen](references/screen-detailview.md)
@@ -109,8 +109,4 @@ examples/<app-name>/docs/actors/*.md # Actors
109
109
 
110
110
  ## Next Step
111
111
 
112
- After fixing all issues, use `/erp-kit-app-4-design` to create visual UI mockups from screen specifications.
113
-
114
- ## References
115
-
116
- - [Application structure](references/structure.md)
112
+ After fixing all issues, use `/erp-kit-app-4-impl-spec` to create implementation specifications from screen and story documentation.
@@ -1,6 +1,6 @@
1
1
  ---
2
- name: erp-kit-app-6-impl-spec
3
- description: Create Tier 4 documentation (resolvers) for GraphQL operations. Use after completing design review with erp-kit-app-5-design-review.
2
+ name: erp-kit-app-4-impl-spec
3
+ description: Create Tier 4 documentation (resolvers) for GraphQL operations. Use after completing documentation review with erp-kit-app-3-doc-review.
4
4
  ---
5
5
 
6
6
  # Implementation Spec Workflow
@@ -9,14 +9,13 @@ Create Tier 4 documentation: GraphQL Resolvers (mutations and queries).
9
9
 
10
10
  ## Prerequisites
11
11
 
12
- Tier 1-3 documentation and design mockups must exist:
12
+ Tier 1-3 documentation must exist:
13
13
 
14
14
  - `README.md` (requirements)
15
15
  - `docs/actors/*.md` (actors)
16
16
  - `docs/business-flow/*/README.md` (flows)
17
17
  - `docs/business-flow/*/story/*.md` (stories)
18
18
  - `docs/screen/*.md` (screens)
19
- - `docs/design.pen` (UI mockups)
20
19
 
21
20
  ## Workflow Phases
22
21
 
@@ -42,7 +41,7 @@ Map stories to resolvers:
42
41
  | View/List/Search | Query |
43
42
  | Real-time updates | Subscription |
44
43
 
45
- **Naming:** Use action-verb names: `create-`, `update-`, `delete-`, `submit-`, `approve-`
44
+ **Naming:** Use camelCase action-verb names: `create`, `update`, `delete`, `submit`, `approve`
46
45
 
47
46
  ### Phase 3: Check Module Dependencies
48
47
 
@@ -51,13 +50,13 @@ Resolvers reference module commands. Before creating resolver docs, verify requi
51
50
  **Check existing modules:**
52
51
 
53
52
  ```bash
54
- ls modules/
53
+ ls packages/erp-kit/src/modules/
55
54
  ```
56
55
 
57
56
  **Check module commands:**
58
57
 
59
58
  ```bash
60
- ls modules/<module-name>/docs/commands/
59
+ ls packages/erp-kit/src/modules/<module-name>/docs/commands/
61
60
  ```
62
61
 
63
62
  **Map resolvers to modules:**
@@ -91,8 +90,8 @@ erp-kit scaffold --app-root examples resolver <app> <resolver-name>
91
90
 
92
91
  **Naming conventions:**
93
92
 
94
- - Filename must match H1 heading exactly (kebab-case)
95
- - Action-focused names: `create-supplier-invitation.md`
93
+ - Filename must match H1 heading exactly (camelCase)
94
+ - Action-focused names: `createSupplierInvitation.md`
96
95
 
97
96
  ### Phase 5: Validate
98
97
 
@@ -112,16 +111,6 @@ pnpm run app:doc:check
112
111
  - Group related operations logically
113
112
  - Document all error scenarios
114
113
 
115
- ## Completion
114
+ ## Next Step
116
115
 
117
- After Tier 4, the application specification is complete:
118
-
119
- - **Tier 1**: Application overview
120
- - **Tier 2**: Actors and business workflows
121
- - **Tier 3**: User stories and screens
122
- - **Tier 4**: Implementation specifications
123
-
124
- ## References
125
-
126
- - [Application structure](references/structure.md)
127
- - [Backend auth](references/auth.md)
116
+ After completing Tier 4, use `/erp-kit-app-5-implementation` to implement backend resolvers and frontend pages.
@@ -0,0 +1,149 @@
1
+ ---
2
+ name: erp-kit-app-5-implementation
3
+ description: Implement backend and frontend code for app-compose applications using erp-kit modules. Use after completing Tier 4 documentation (resolver specs) with erp-kit-app-4-impl-spec. Triggers when implementing resolvers, wiring modules, creating frontend pages, or building a full-stack application from documentation specs. Also use when the user mentions implementing an app, writing backend resolvers, creating frontend pages, or connecting erp-kit modules to an application.
4
+ ---
5
+
6
+ # App-Compose Implementation
7
+
8
+ Implement backend resolvers and frontend pages for an app-compose application, driven by Tier 1-4 documentation (actors, business flows, stories, screens, resolver specs).
9
+
10
+ ## When to Use
11
+
12
+ - Implementing backend resolvers from resolver spec docs
13
+ - Creating frontend pages from screen spec docs
14
+ - Wiring erp-kit modules into an application
15
+ - Building full-stack code for an app-compose application
16
+
17
+ ## Prerequisites
18
+
19
+ All four tiers of documentation must exist:
20
+
21
+ - `README.md` — Application overview
22
+ - `docs/actors/*.md` — Actor definitions
23
+ - `docs/business-flow/*/README.md` + `story/*.md` — Business flows and user stories
24
+ - `docs/screen/*.md` — Screen specifications (ListView, Form, DetailView)
25
+ - `docs/resolver/*.md` — Resolver specifications (mutations, queries)
26
+
27
+ ## Workflow
28
+
29
+ ```
30
+ ANALYZE DOCS → BACKEND SCAFFOLD → MODULE WIRING → CONFIG → RESOLVERS → GENERATED FILES → DEPLOY → FRONTEND SCAFFOLD → PAGES → VERIFY
31
+ ```
32
+
33
+ ### Phase 1: Analyze Documentation
34
+
35
+ Read all resolver and screen specs to build a complete picture:
36
+
37
+ 1. **Resolver docs** (`docs/resolver/*.md`) — Identify which module commands each resolver calls, what inputs/outputs it needs, and what errors it handles
38
+ 2. **Screen docs** (`docs/screen/*.md`) — Identify screen types (ListView, Form, DetailView) and their fields/columns/actions
39
+ 3. **Command source types** — For each module command the resolver calls, read the input type at `node_modules/@tailor-platform/erp-kit/src/modules/<module>/command/<commandName>.ts`. Do not invent fields that don't exist in the command, and preserve the required/optional distinction.
40
+
41
+ Classify resolvers into two categories:
42
+
43
+ | Category | Description | Implementation |
44
+ | -------------------- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
45
+ | **Custom resolvers** | Mutations that call module commands (create, update, activate, deactivate, assign) | Write `createResolver()` files |
46
+ | **Built-in queries** | List and get operations for reading data | Handled automatically by `gqlOperations: "query"` in config — no code needed |
47
+
48
+ Prefer built-in queries over custom resolvers for list/get operations where possible.
49
+
50
+ ### Phase 2: Backend Scaffold
51
+
52
+ Set up the backend project structure and config files.
53
+
54
+ **Read [backend reference](references/backend.md) § "Backend Scaffold" for the directory structure and boilerplate.**
55
+
56
+ Key files: `package.json` (dependencies, scripts), `tsconfig.json` (path alias, types), `eslint.config.js`.
57
+
58
+ ### Phase 3: Wire Modules (`src/modules.ts`)
59
+
60
+ Create the module wiring file that composes all required erp-kit modules.
61
+
62
+ **Read [backend reference](references/backend.md) § "Module Wiring" for the composition pattern.**
63
+
64
+ Key points:
65
+
66
+ - Use `defineXxxModule()` functions from `@tailor-platform/erp-kit/module`
67
+ - Pass inter-module dependencies explicitly (e.g., item-management needs primitives' unit type and query)
68
+ - Export `db`, `commands`, and `executors` for use in resolvers
69
+
70
+ ### Phase 4: Configure Application (`tailor.config.ts`)
71
+
72
+ **Read [backend reference](references/backend.md) § "Application Config" for the config pattern.**
73
+
74
+ Key points:
75
+
76
+ - Single DB namespace (`"main-db"`) with `gqlOperations: "query"` for automatic list/get queries
77
+ - Resolver/executor discovery via glob patterns
78
+ - Auth with OAuth2, DPoP, and user profile mapping
79
+ - Generators for Kysely types and seed data
80
+
81
+ ### Phase 5: Implement Backend Resolvers and Executors
82
+
83
+ Write one file per resolver under `src/modules/<module-name>/resolvers/`, one per executor under `executors/`.
84
+
85
+ **Read [backend reference](references/backend.md) § "Resolver Patterns" and "Executor Patterns".**
86
+
87
+ Do not directly mutate module-owned tables via Kysely — always use module commands.
88
+
89
+ ### Phase 6: Generated Files
90
+
91
+ - **Kysely types** (`src/generated/kysely-tailordb.ts`) — Auto-generated by `pnpm generate` after deployment. Before deployment, create a minimal placeholder so the codebase typechecks.
92
+ - **Seed data** (`seed/`) — `exec.mjs` runner + `data/*.jsonl` (records) and `data/*.schema.ts` (validation). Create seed records for initial data (permissions, roles, test users, etc.). Seeded users must have concrete permission keys required by the wired modules.
93
+
94
+ ### Phase 7: Deploy Backend
95
+
96
+ Frontend implementation requires a deployed backend (for GraphQL schema generation). Prompt the user to:
97
+
98
+ 1. Create a workspace and configure `.env` (including `TAILOR_PLATFORM_WORKSPACE_ID`)
99
+ 2. Run `pnpm deploy` and `pnpm generate`
100
+ 3. Run `pnpm seed` if seed data was created
101
+ 4. Retrieve OAuth2 client ID via `tailor-sdk oauth2client get default --json` for frontend `.env`
102
+
103
+ Wait for the user to confirm deployment is complete before proceeding.
104
+
105
+ ### Phase 8: Frontend Scaffold
106
+
107
+ Set up the frontend project structure, config files, and generate GraphQL schema.
108
+
109
+ **Read [frontend reference](references/frontend.md) § "Frontend Scaffold" for the directory structure, boilerplate, and schema generation.**
110
+
111
+ Key files: `package.json`, `tsconfig.json`, `vite.config.ts`, `eslint.config.js`, UI components, `scripts/generate-graphql.mjs`. After scaffolding, run `pnpm generate` to fetch the GraphQL schema from the deployed backend.
112
+
113
+ ### Phase 9: Implement Frontend Pages
114
+
115
+ Create pages driven by screen spec docs. Each screen type has a standard implementation pattern.
116
+
117
+ **Read [frontend reference](references/frontend.md) § "Frontend Pages" for the full pattern catalog.**
118
+
119
+ Page types and their file structure:
120
+
121
+ | Screen Type | Files |
122
+ | ------------- | ------------------------------------------------------------------------------------------------ |
123
+ | ListView | `page.tsx` + `components/<entity>-table.tsx` |
124
+ | Form (create) | `create/page.tsx` + `create/components/create-<entity>-form.tsx` |
125
+ | Form (edit) | `[id]/edit/page.tsx` + `[id]/edit/components/edit-<entity>-form.tsx` |
126
+ | DetailView | `[id]/page.tsx` + `[id]/components/<entity>-detail.tsx` + `[id]/components/<entity>-actions.tsx` |
127
+
128
+ Key frontend patterns:
129
+
130
+ - **GraphQL fragments** — Each table/form/detail component exports its own fragment; page-level queries compose fragments
131
+ - **gql.tada** — Type-safe GraphQL via `graphql()` from `@/graphql`
132
+ - **React Hook Form + Zod** — Form validation with `zodResolver`
133
+ - **urql** — `useQuery` for reads, `useMutation` for writes
134
+ - **app-shell routing** — `Layout`, `Link`, `useParams`, `useNavigate` from `@tailor-platform/app-shell`
135
+
136
+ ### Phase 10: Verify
137
+
138
+ ```bash
139
+ # Backend
140
+ cd <app-root>/backend
141
+ pnpm lint
142
+ pnpm typecheck
143
+
144
+ # Frontend
145
+ cd <app-root>/frontend
146
+ pnpm lint
147
+ pnpm typecheck
148
+ pnpm build
149
+ ```
@@ -0,0 +1,232 @@
1
+ # Backend Implementation Patterns
2
+
3
+ ## Table of Contents
4
+
5
+ - [Backend Scaffold](#backend-scaffold)
6
+ - [Module Wiring](#module-wiring)
7
+ - [Application Config](#application-config)
8
+ - [Resolver Patterns](#resolver-patterns)
9
+ - [Executor Patterns](#executor-pattern)
10
+
11
+ ---
12
+
13
+ ## Backend Scaffold
14
+
15
+ ```
16
+ backend/
17
+ ├── src/
18
+ │ ├── modules.ts # Module wiring
19
+ │ ├── generated/kysely-tailordb.ts # Auto-generated (placeholder until deploy)
20
+ │ └── modules/<module-name>/
21
+ │ ├── resolvers/<name>.ts
22
+ │ └── executors/<name>.ts
23
+ ├── seed/ # Seed data scripts
24
+ ├── package.json
25
+ ├── tsconfig.json
26
+ ├── eslint.config.js
27
+ └── tailor.config.ts
28
+ ```
29
+
30
+ `package.json` key dependencies and scripts:
31
+
32
+ ```json
33
+ {
34
+ "type": "module",
35
+ "scripts": {
36
+ "generate": "tailor-sdk generate",
37
+ "deploy": "tailor-sdk apply --env-file-if-exists .env",
38
+ "lint": "eslint --cache .",
39
+ "typecheck": "tsc --noEmit",
40
+ "seed": "node --env-file-if-exists=.env seed/exec.mjs"
41
+ },
42
+ "dependencies": {
43
+ "@tailor-platform/erp-kit": "...",
44
+ "@tailor-platform/function-kysely-tailordb": "...",
45
+ "kysely": "..."
46
+ },
47
+ "devDependencies": {
48
+ "@tailor-platform/sdk": "...",
49
+ "@tailor-platform/function-types": "...",
50
+ "typescript": "..."
51
+ }
52
+ }
53
+ ```
54
+
55
+ `tsconfig.json` — requires `@/*` path alias and `@tailor-platform/function-types` in types:
56
+
57
+ ```json
58
+ {
59
+ "compilerOptions": {
60
+ "target": "ES2022",
61
+ "module": "ESNext",
62
+ "moduleResolution": "bundler",
63
+ "strict": true,
64
+ "noEmit": true,
65
+ "skipLibCheck": true,
66
+ "types": ["node", "@tailor-platform/function-types"],
67
+ "paths": { "@/*": ["./src/*"] }
68
+ },
69
+ "include": ["**/*.ts"]
70
+ }
71
+ ```
72
+
73
+ ---
74
+
75
+ ## Module Wiring
76
+
77
+ `src/modules.ts` composes erp-kit modules and exports their parts for resolver use.
78
+
79
+ ```ts
80
+ import { db as field } from "@tailor-platform/sdk";
81
+ import {
82
+ definePrimitivesModule,
83
+ defineUserManagementModule,
84
+ defineItemManagementModule,
85
+ } from "@tailor-platform/erp-kit/module";
86
+
87
+ const primitivesModules = definePrimitivesModule({});
88
+
89
+ const umModules = defineUserManagementModule({
90
+ dbNamespace: "main-db",
91
+ user: {
92
+ fields: {
93
+ /* custom fields */
94
+ },
95
+ additionalStatuses: ["SUSPENDED"],
96
+ },
97
+ });
98
+
99
+ // Pass inter-module dependencies explicitly
100
+ const imModules = defineItemManagementModule({
101
+ primitives: {
102
+ db: { unit: primitivesModules.db.unit },
103
+ queries: { getUnit: primitivesModules.queries.getUnit },
104
+ },
105
+ });
106
+
107
+ // Destructure db into individual table exports (required for DB scanner)
108
+ export const { db: primitivesDb, commands: primitivesCommands } = primitivesModules;
109
+ export const { uomCategory, unit, currency, exchangeRate } = primitivesDb;
110
+
111
+ export const { db: umDb, executors: umExecutors, commands: umCommands } = umModules;
112
+ export const { user, permission, role, userRole, rolePermission, auditEvent } = umDb;
113
+
114
+ export const { db: imDb, commands: imCommands } = imModules;
115
+ export const { item, taxonomyNode, itemTaxonomyAssignment } = imDb;
116
+ ```
117
+
118
+ Key conventions:
119
+
120
+ - Prefix exports to avoid collisions (`umCommands`, `imCommands`, `primitivesCommands`)
121
+ - Every module's `db` must be destructured into individual table exports — the DB scanner only picks up named exports
122
+ - Extract individual executors for re-export in executor files
123
+
124
+ ---
125
+
126
+ ## Application Config
127
+
128
+ `tailor.config.ts` defines the Tailor application configuration. Key structure:
129
+
130
+ ```ts
131
+ export default defineConfig({
132
+ name: "<app-name>",
133
+ cors: ["http://localhost:5173", website.url],
134
+ db: {
135
+ "main-db": {
136
+ files: [`./src/modules.ts`],
137
+ gqlOperations: "query",
138
+ },
139
+ },
140
+ resolver: {
141
+ "main-resolver": { files: [`./src/modules/**/resolvers/**/*.ts`] },
142
+ },
143
+ executor: { files: [`./src/modules/**/executors/**/*.ts`] },
144
+ auth: auth,
145
+ idp: [idp],
146
+ staticWebsites: [website],
147
+ });
148
+ ```
149
+
150
+ Key points:
151
+
152
+ - `gqlOperations: "query"` — Auto-generates list/get GraphQL queries for all DB types
153
+ - Glob patterns for resolver/executor discovery
154
+ - See [SDK configuration docs](https://raw.githubusercontent.com/tailor-platform/sdk/refs/heads/main/packages/sdk/docs/configuration.md) for full config options
155
+
156
+ ### Auth configuration
157
+
158
+ - Define IdP (`defineIdp`), Auth (`defineAuth`), and static website (`defineStaticWebSite`) using Tailor SDK
159
+ - Prefer stable default naming: auth `default`, IdP `default`, OAuth2 client `default`
160
+ - `userProfile.type` must reference the `user` DB type from `modules.ts`
161
+ - `userProfile.usernameField`: stable unique field (e.g., `email`)
162
+ - Include static website URL and localhost in CORS: `cors: ["http://localhost:5173", website.url]`
163
+ - Frontend `VITE_TAILOR_CLIENT_ID` must come from `tailor-sdk oauth2client get default --json` — do not hardcode
164
+
165
+ ---
166
+
167
+ ## Resolver Patterns
168
+
169
+ All resolvers export a default `createResolver()` from `@tailor-platform/sdk`.
170
+
171
+ ### Verify command input types
172
+
173
+ Before implementing a resolver, read the command's type definition:
174
+
175
+ ```
176
+ node_modules/@tailor-platform/erp-kit/src/modules/<module>/command/<commandName>.ts
177
+ ```
178
+
179
+ The command source is the ground truth. Do not invent fields that don't exist, and preserve the required/optional distinction.
180
+
181
+ ### SDK type system
182
+
183
+ See [Resolver docs](https://raw.githubusercontent.com/tailor-platform/sdk/refs/heads/main/packages/sdk/docs/services/resolver.md) for the `t` namespace.
184
+
185
+ `t.array()` and `t.boolean()` do **not exist**. Never attempt to use them.
186
+
187
+ ### Command-based mutation
188
+
189
+ The most common pattern. Key points:
190
+
191
+ ```ts
192
+ import { createContext } from "@tailor-platform/erp-kit/app";
193
+
194
+ body: async (context) => {
195
+ const db = getDB("main-db");
196
+ const result = await imCommands.createItem(db, { ...context.input }, createContext(context));
197
+ if (!result.ok) throw result.error;
198
+ return { id: result.value.item.id, ... };
199
+ },
200
+ ```
201
+
202
+ - `context.input.optionalField ?? undefined` — Convert null to undefined for command inputs
203
+ - `result.value.entity.nullableField ?? ""` — Handle nullable return values
204
+ - `createContext(context)` wraps the resolver context for erp-kit commands
205
+ - `getDB("main-db")` — Namespace must match `tailor.config.ts`
206
+
207
+ ### Error handling
208
+
209
+ When the resolver spec documents specific error codes, use `result.error.code` to switch:
210
+
211
+ ```ts
212
+ if (!result.ok) {
213
+ switch (result.error.code) {
214
+ case "USER_NOT_FOUND":
215
+ throw new Error(`User ${context.input.userId} not found`);
216
+ // ...
217
+ }
218
+ }
219
+ ```
220
+
221
+ Do not directly mutate module-owned tables via Kysely — always use module commands.
222
+
223
+ ---
224
+
225
+ ## Executor Patterns
226
+
227
+ Executors re-export module-provided event handlers. One file per executor, no custom logic:
228
+
229
+ ```ts
230
+ import { rolePermissionCreated } from "@/modules";
231
+ export default rolePermissionCreated;
232
+ ```