@rawsql-ts/ztd-cli 0.16.0 → 0.17.0

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 (50) hide show
  1. package/README.md +33 -20
  2. package/dist/commands/init.d.ts +13 -0
  3. package/dist/commands/init.js +372 -127
  4. package/dist/commands/init.js.map +1 -1
  5. package/dist/commands/lint.d.ts +4 -4
  6. package/dist/commands/lint.js +60 -40
  7. package/dist/commands/lint.js.map +1 -1
  8. package/dist/commands/ztdConfig.d.ts +2 -2
  9. package/dist/commands/ztdConfig.js +26 -12
  10. package/dist/commands/ztdConfig.js.map +1 -1
  11. package/dist/utils/optionalDependencies.d.ts +35 -0
  12. package/dist/utils/optionalDependencies.js +96 -0
  13. package/dist/utils/optionalDependencies.js.map +1 -0
  14. package/package.json +16 -9
  15. package/templates/AGENTS.md +36 -309
  16. package/templates/README.md +12 -215
  17. package/templates/dist/ztd-cli/templates/src/db/sql-client.ts +24 -0
  18. package/templates/src/AGENTS.md +26 -0
  19. package/templates/src/catalog/AGENTS.md +37 -0
  20. package/templates/src/catalog/runtime/AGENTS.md +75 -0
  21. package/templates/src/catalog/runtime/_coercions.ts +1 -0
  22. package/templates/src/catalog/runtime/_smoke.runtime.ts +21 -0
  23. package/templates/src/catalog/specs/AGENTS.md +48 -0
  24. package/templates/src/catalog/specs/_smoke.spec.arktype.ts +21 -0
  25. package/templates/src/catalog/specs/_smoke.spec.zod.ts +20 -0
  26. package/templates/src/db/sql-client.ts +5 -5
  27. package/templates/src/jobs/AGENTS.md +26 -0
  28. package/templates/src/jobs/README.md +3 -0
  29. package/templates/src/repositories/AGENTS.md +118 -0
  30. package/templates/src/repositories/tables/AGENTS.md +94 -0
  31. package/templates/src/repositories/tables/README.md +3 -0
  32. package/templates/src/repositories/views/AGENTS.md +25 -0
  33. package/templates/src/repositories/views/README.md +3 -0
  34. package/templates/src/sql/AGENTS.md +77 -0
  35. package/templates/src/sql/README.md +6 -0
  36. package/templates/tests/AGENTS.md +43 -150
  37. package/templates/tests/generated/AGENTS.md +16 -0
  38. package/templates/tests/smoke.test.ts +5 -0
  39. package/templates/tests/smoke.validation.test.ts +34 -0
  40. package/templates/tests/support/AGENTS.md +26 -0
  41. package/templates/tests/support/global-setup.ts +8 -23
  42. package/templates/tests/support/testkit-client.ts +13 -741
  43. package/templates/tsconfig.json +8 -1
  44. package/templates/ztd/AGENTS.md +11 -67
  45. package/templates/ztd/README.md +4 -13
  46. package/templates/ztd/ddl/AGENTS.md +34 -0
  47. package/templates/ztd/ddl/demo.sql +74 -0
  48. package/templates/src/repositories/user-accounts.ts +0 -179
  49. package/templates/tests/user-profiles.test.ts +0 -161
  50. package/templates/tests/writer-constraints.test.ts +0 -32
@@ -1,217 +1,14 @@
1
1
  # Zero Table Dependency Project
2
2
 
3
- This project organizes all SQL‑related artifacts under the `ztd/` directory, separating concerns so both humans and AI can collaborate effectively without interfering with each other's responsibilities.
4
-
5
- ```
6
- /ztd
7
- /ddl
8
- *.sql <- schema definitions (required)
9
- README.md <- documentation for the layout
10
- AGENTS.md <- combined guidance for DDL
11
-
12
- /src <- application & repository code
13
- /tests <- ZTD tests, fixtures, generated maps
14
- ```
15
-
16
- Only `ztd/ddl` is part of the template contract. Do not create or assume other `ztd` subdirectories unless the project explicitly adds them.
17
-
18
- ## Generated files (important)
19
-
20
- `tests/generated/` is auto-generated and must never be committed to git.
21
- After cloning the repository (or in a clean environment), run (strongly recommended):
22
-
23
- ```bash
24
- npx ztd ztd-config
25
- ```
26
-
27
- If TypeScript reports missing modules or type errors because `tests/generated/` is missing, rerun `npx ztd ztd-config`.
28
-
29
- `tests/generated/ztd-layout.generated.ts` declares the directories above so the CLI and your tests always point at the intended files. The authoritative directory remains `ztd/ddl/`; do not read or assume additional `ztd` subdirectories.
30
-
31
- ---
32
-
33
- # Optional SqlClient seam
34
-
35
- If this project was initialized with `npx ztd init --with-sqlclient`, you'll also have `src/db/sql-client.ts`.
36
- It defines a minimal `SqlClient` interface that repositories can depend on:
37
-
38
- - Use it for tutorials and greenfield projects to keep repository SQL decoupled from drivers.
39
- - Skip it when you already have a database abstraction (Prisma, Drizzle, Kysely, custom adapters).
40
- - For `pg`, adapt `client.query(...)` so it returns a plain `T[]` row array that matches the interface.
41
- - Prefer a shared client per worker process so tests and scripts do not reconnect on every query.
42
- - Do not share a live connection across parallel workers; each worker should own its own shared client.
43
-
44
- Example (driver-agnostic):
45
-
46
- ```ts
47
- let sharedClient: SqlClient | undefined;
48
-
49
- export function getSqlClient(): SqlClient {
50
- if (!sharedClient) {
51
- // Create the client once using your chosen driver (pg, mysql, etc.).
52
- sharedClient = createSqlClientOnce();
53
- }
54
- return sharedClient;
55
- }
56
- ```
57
-
58
- ---
59
-
60
- # Mapper + writer sample
61
-
62
- - This scaffold already exposes `src/repositories/user-accounts.ts`, which maps `public.user_account` rows together with optional `public.user_profile` data through `@rawsql-ts/sql-contract/mapper` and emits insert/update/remove helpers via `@rawsql-ts/sql-contract/writer`.
63
- - The SQL used here is defined in `src/repositories/user-accounts.ts`; the template tests exercise that implementation and `ztd/ddl` is the authoritative source for every column and constraint.
64
- - Two template tests demonstrate how to run the stitch:
65
- - `tests/user-profiles.test.ts` seeds fixtures, executes the query through the mapper, and verifies the DTO shape.
66
- - `tests/writer-constraints.test.ts` reads `userAccountWriterColumnSets` plus `tests/generated/ztd-row-map.generated.ts` so writer callers stay within the approved column set when referencing `public.user_account`.
67
- - Regenerate `tests/generated/ztd-row-map.generated.ts` (`npx ztd ztd-config`) before running the example tests so the row map reflects any schema changes.
68
- - The example tests require a real PostgreSQL connection via `DATABASE_URL`; they automatically skip when the variable is missing so local tooling stays fast.
69
-
70
- # Principles
71
-
72
- ### 1. Humans own the *definitions*
73
- - DDL (physical schema)
74
- Only `ztd/ddl` is part of the template contract; other subdirectories should not be assumed.
75
-
76
- ### 2. AI owns the *implementation*
77
- - Repository SQL generation
78
- - Test fixture updates
79
- - Intermediate TypeScript structures
80
- - SQL rewriting, parameter binding, shape resolution
81
-
82
- ### 3. ZTD ensures these stay in sync
83
- ZTD acts as the consistency layer ensuring:
84
- - DDL → SQL shape consistency
85
- - Do not rely on other directories unless the project explicitly adds them.
86
-
87
- If any part diverges, ZTD tests fail deterministically.
88
-
89
- ---
90
-
91
- # Workflow Overview
92
-
93
- Different tasks start from different entry points. Choose the workflow that matches what you want to change.
94
-
95
- ---
96
-
97
- # Workflow A — Starting From *DDL Changes*
98
- (Adding tables/columns, changing constraints)
99
-
100
- 1. Edit files under `ztd/ddl/`.
101
- 2. Run:
102
-
103
- ```bash
104
- npx ztd ztd-config
105
- ```
106
-
107
- This regenerates `tests/generated/ztd-row-map.generated.ts` from the new schema.
108
-
109
- 3. Update repository SQL so it matches the new schema.
110
- 4. Update fixtures if shapes changed.
111
- 5. Run tests. Any schema mismatch will fail fast.
112
-
113
- **Flow:**
114
- **DDL -> repository SQL -> fixtures/tests -> application**
115
-
116
- ---
117
-
118
- # Workflow B — Starting From *Repository Interface Changes*
119
- (Adding a method, changing return types, etc.)
120
-
121
- 1. Modify the repository interface or class in `/src`.
122
- 2. Allow AI to generate the SQL needed to satisfy the interface.
123
- 3. If the query contradicts DDL, reconcile the authoritative definition before continuing.
124
- 4. Run ZTD tests to confirm logic is consistent.
125
- 5. Regenerate ZTD config if result shapes changed.
126
-
127
- **Flow:**
128
- **repository interface -> SQL -> tests**
129
-
130
- ---
131
-
132
- # Workflow C — Starting From Repository SQL Logic Changes
133
- (Fixing a bug, optimizing logic, rewriting a query)
134
-
135
- 1. Edit SQL inside the repository.
136
- 2. Run ZTD tests.
137
- 3. If the intended behavior changes, update the DDL before adjusting dependent logic and keep documentation aligned with the confirmed schema.
138
- 4. Update fixtures as necessary.
139
- 5. If SQL result shape changed, run:
140
-
141
- ```bash
142
- npx ztd ztd-config
143
- ```
144
-
145
- **Flow:**
146
- **SQL -> fixtures/tests**
147
-
148
- ---
149
-
150
- # Combined Real‑World Flow Examples
151
-
152
- - **Add a new contract status**
153
- DDL -> SQL -> config -> tests
154
-
155
- - **Add a new table**
156
- DDL -> config -> SQL -> fixtures -> tests
157
-
158
- - **Fix business logic**
159
- SQL -> tests
160
-
161
- ZTD ensures all changes converge into a consistent, validated workflow.
162
- ---
163
-
164
- # Human Responsibilities
165
-
166
- - Humans maintain:
167
- - Physical schema (`ddl`)
168
- - High‑level repository interfaces
169
- - Acceptance of AI-generated changes
170
-
171
- Humans decide “what is correct.”
172
-
173
- ---
174
-
175
- # AI Responsibilities
176
-
177
- AI must:
178
-
179
- - Use DDL as the **physical shape constraint** and primary source of truth.
180
- - Do not assume any additional `ztd` directories exist unless a human explicitly creates them.
181
- - Generate repository SQL consistent with DDL and the documented behavior.
182
- - Regenerate fixtures and tests as instructed.
183
- - Never modify `ztd/AGENTS.md` or `ztd/README.md` unless explicitly asked.
184
-
185
- AI decides “how to implement” within those constraints.
186
-
187
- ---
188
-
189
- # ZTD CLI Responsibilities
190
-
191
- ZTD CLI:
192
-
193
- - Parses DDL files to build accurate table/column shapes
194
- - Rewrites SQL with fixture-based CTE shadowing (via testkit adapters)
195
- - Generates `ztd-row-map.generated.ts`
196
- - Produces deterministic, parallelizable tests
197
-
198
- ZTD is the verification engine guaranteeing correctness.
199
-
200
- ## Traditional execution mode
201
-
202
- - Set `ZTD_EXECUTION_MODE=traditional` or pass `{ mode: 'traditional', traditional: { isolation: 'schema', cleanup: 'drop_schema' } }` when you need to run the tests against a real Postgres schema (locking, isolation, constraints). The helper still applies the DDL inside `ztd/ddl/`, loads the fixture rows into the schema, optionally executes `setupSql`, and carries out the chosen cleanup strategy (`drop_schema`, `custom_sql`, or `none`).
203
- - Use `isolation: 'none'` if you need to target a schema that is already defined or if your SQL embeds schema qualifiers explicitly.
204
-
205
- ---
206
-
207
- # Summary
208
-
209
- ZTD enables a workflow where **humans define meaning**, **AI writes implementation**, and **tests guarantee correctness**.
210
-
211
- The project layout and workflows above ensure long-term maintainability, clarity, and full reproducibility of SQL logic independent of physical database state.
212
-
213
- ## Recommended local verification
214
-
215
- - `npx ztd ztd-config` (Recommended)
216
- - `pnpm -C packages/ztd-cli test` (Recommended)
217
- - `templates/tests/user-profiles.test.ts` runs only when `DATABASE_URL` is configured; otherwise it skips automatically.
3
+ This project uses Zero Table Dependency (ZTD) to keep SQL, DDL, and tests aligned.
4
+
5
+ Key folders:
6
+ - ztd/ddl: schema files (source of truth)
7
+ - src: application SQL and repositories
8
+ - tests: ZTD tests and support
9
+
10
+ Next steps:
11
+ 1. Update `ztd/ddl/<schema>.sql` if needed.
12
+ 2. Run `npx ztd ztd-config`.
13
+ 3. Provide a SqlClient implementation.
14
+ 4. Run tests (`pnpm test` or `npx vitest run`).
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Promise that resolves to the array of rows produced by an SQL query.
3
+ * @template T Shape of each row yielded by the SQL client.
4
+ * @example
5
+ * const rows: SqlQueryRows<{ id: number; name: string }> = client.query('SELECT id, name FROM users');
6
+ */
7
+ export type SqlQueryRows<T> = Promise<T[]>;
8
+
9
+ /**
10
+ * Minimal SQL client interface required by the repository layer.
11
+ *
12
+ * - Production: adapt this interface to your preferred driver (pg, mysql2, etc.) and normalize the results to `T[]`.
13
+ * - Tests: replace the implementation with a mock, a fixture helper, or an adapter that follows this contract.
14
+ *
15
+ * Connection strategy note:
16
+ * - Prefer a shared client per worker process for better performance.
17
+ * - Do not share a live client across parallel workers without proper synchronization.
18
+ */
19
+ export type SqlClient = {
20
+ query<T extends Record<string, unknown> = Record<string, unknown>>(
21
+ text: string,
22
+ values?: readonly unknown[]
23
+ ): SqlQueryRows<T>;
24
+ };
@@ -0,0 +1,26 @@
1
+ # src AGENTS
2
+
3
+ This directory is runtime application code.
4
+
5
+ ## Boundaries
6
+
7
+ - Code under "src/" MUST NOT import from:
8
+ - "tests/"
9
+ - "tests/generated/"
10
+ - any test-only helpers
11
+ - Runtime code MUST NOT depend on ZTD internals.
12
+ - Generated artifacts are test-only signals, not runtime dependencies.
13
+
14
+ ## Implementation principles
15
+
16
+ - Keep modules small and explicit.
17
+ - Prefer explicit contracts over inference.
18
+ - Favor deterministic behavior and clear error surfaces.
19
+
20
+ ## Verification (required)
21
+
22
+ After changes:
23
+ - Run the project typecheck command (example: "pnpm typecheck").
24
+ - Run relevant tests (example: "pnpm test" or a filtered command).
25
+
26
+ If you touched SQL contracts or catalog specs, run tests that exercise them.
@@ -0,0 +1,37 @@
1
+ # src/catalog AGENTS
2
+
3
+ This directory is runtime code.
4
+
5
+ ## Purpose
6
+
7
+ Catalog defines named query entry points by binding:
8
+ - SQL assets ("src/sql/*.sql")
9
+ - input parameter contracts
10
+ - output DTO contracts
11
+ - validation and mapping behavior
12
+ - observability hooks (if supported)
13
+
14
+ ## Directory roles (important)
15
+
16
+ - "src/catalog/specs": human-owned contracts (params + DTO + semantics)
17
+ - "src/catalog/runtime": AI-assisted runtime wiring (executors, helpers, sinks)
18
+
19
+ ## Non-negotiable ownership
20
+
21
+ - Specs are contracts. Do not infer, guess, widen, or narrow them.
22
+ - Do not change params / DTO shapes in "specs" without explicit instruction.
23
+
24
+ ## Boundaries
25
+
26
+ - Code under "src/catalog/" MUST NOT import from:
27
+ - "tests/"
28
+ - "tests/generated/"
29
+ - "ztd/"
30
+ - Do not depend on ZTD internals at runtime.
31
+
32
+ ## Testing rule (required)
33
+
34
+ Every spec MUST have tests that verify:
35
+ - SQL executes under ZTD rewriting
36
+ - mapping/validation behavior is correct (success and failure)
37
+ - output DTO shape matches expectations
@@ -0,0 +1,75 @@
1
+ # src/catalog/runtime AGENTS
2
+
3
+ This directory contains runtime wiring for catalog specs:
4
+ - parameter validation entrypoints
5
+ - row-to-DTO mapping
6
+ - output validation
7
+
8
+ ## Runtime classification
9
+
10
+ - This is a runtime directory.
11
+ - Code here is executed/loaded by the application.
12
+
13
+ ## Responsibilities (critical)
14
+
15
+ - Runtime MUST be the only place that:
16
+ - validates unknown inputs into typed params
17
+ - maps SQL rows (snake_case) into DTO objects
18
+ - validates DTO outputs before returning to repositories
19
+ - Runtime output validation MUST follow the output contract type (DTO or scalar).
20
+ - Command outputs MAY be scalar identifiers or `void`; DTO mapping is required only when the output contract is DTO.
21
+
22
+ Repositories MUST call runtime helpers (ensure*/map*) and MUST NOT bypass them.
23
+
24
+ ## Validator requirement (required)
25
+
26
+ - A validator library (zod or arktype) is always available.
27
+ - Runtime MUST apply validators for:
28
+ - input params (unknown -> typed)
29
+ - outputs (mapped DTO -> validated DTO)
30
+
31
+ Do not rely on TypeScript types alone.
32
+
33
+ ## SQL row normalization (important)
34
+
35
+ SQL drivers may return different runtime representations for the same column types.
36
+ Runtime MUST normalize driver-dependent values before validating DTOs.
37
+
38
+ Required normalization rules:
39
+ - Timestamp columns (e.g. timestamptz) may arrive as Date or string.
40
+ - Runtime MUST use `timestampFromDriver` from `@rawsql-ts/sql-contract`.
41
+ - Do NOT re-implement `normalizeTimestamp` locally.
42
+ - Do NOT call `new Date(...)` directly for driver-dependent timestamp normalization.
43
+ - Numeric columns may arrive as number, string, or bigint depending on driver.
44
+ - Normalization rules MUST be explicit per contract and MUST NOT be silent.
45
+
46
+ Never force SQL assets to encode driver-specific behavior.
47
+
48
+ ## Mapping rules (required)
49
+
50
+ - Keep SQL assets snake_case and DTO-independent.
51
+ - Mapping occurs in runtime:
52
+ - snake_case row -> DTO-shaped object
53
+ - apply normalization
54
+ - validate via spec-owned validator
55
+ - DTO camelCase aliases in SQL are forbidden.
56
+
57
+ ## Entry points (recommended)
58
+
59
+ Prefer these patterns:
60
+ - `ensureXxxParams(value: unknown): XxxParams` (validate inputs)
61
+ - `mapXxxRowToDto(row: XxxSqlRow): XxxDto` (normalize + validate outputs)
62
+
63
+ The `map*` functions MUST always validate before returning.
64
+
65
+ ## Error behavior (required)
66
+
67
+ - Validation errors must fail fast with clear messages.
68
+ - Do not swallow validator errors.
69
+ - Do not silently coerce invalid values unless explicitly defined by the contract.
70
+
71
+ ## Boundaries
72
+
73
+ - Do not perform database I/O here.
74
+ - Do not import from "tests/" or "tests/generated/".
75
+ - Do not define human-owned contracts here; they live in "src/catalog/specs".
@@ -0,0 +1 @@
1
+ export { timestampFromDriver as normalizeTimestamp } from '@rawsql-ts/sql-contract';
@@ -0,0 +1,21 @@
1
+ import { parseSmokeOutput, type SmokeOutput } from '../specs/_smoke.spec';
2
+ import { normalizeTimestamp } from './_coercions';
3
+
4
+ /**
5
+ * Validate runtime output against the catalog smoke invariant.
6
+ */
7
+ export function ensureSmokeOutput(value: unknown): SmokeOutput {
8
+ // Normalize driver-dependent timestamp representations before contract validation.
9
+ if (isRecord(value) && 'createdAt' in value) {
10
+ return parseSmokeOutput({
11
+ ...value,
12
+ createdAt: normalizeTimestamp(value.createdAt, 'createdAt')
13
+ });
14
+ }
15
+
16
+ return parseSmokeOutput(value);
17
+ }
18
+
19
+ function isRecord(value: unknown): value is Record<string, unknown> {
20
+ return typeof value === 'object' && value !== null;
21
+ }
@@ -0,0 +1,48 @@
1
+ # src/catalog/specs AGENTS
2
+
3
+ This directory defines query and command specifications (contracts).
4
+
5
+ ## Runtime classification
6
+
7
+ - This is a runtime directory.
8
+ - Contents are human-owned contracts, not implementation details.
9
+
10
+ ## Ownership (critical)
11
+
12
+ - Specs are human-owned.
13
+ - Input parameters are part of the domain contract.
14
+ - Output DTO shapes are part of the domain contract.
15
+ - Cardinality and semantics are part of the domain contract.
16
+
17
+ AI MUST NOT:
18
+ - infer missing parameters
19
+ - widen or narrow DTO shapes
20
+ - change nullability or optionality
21
+ - change CUD return shape implicitly
22
+
23
+ Changes require explicit human instruction.
24
+
25
+ ## Validator requirement (required)
26
+
27
+ - A validator library (zod or arktype) is always available.
28
+ - Every spec MUST define validators for its public inputs/outputs.
29
+ - Validators are part of the contract and are human-owned.
30
+
31
+ ## Driver variability policy (important)
32
+
33
+ Specs MUST NOT require SQL assets to encode driver-specific workarounds.
34
+
35
+ - Specs may acknowledge that SQL rows can vary in representation by driver
36
+ (e.g. timestamps as Date or string).
37
+ - Normalization for driver-dependent values is implemented in catalog runtime,
38
+ then validated against the spec.
39
+
40
+ Contracts define the final DTO shape.
41
+ Runtime defines normalization steps to reach that shape.
42
+
43
+ ## What does NOT belong here
44
+
45
+ - No executors
46
+ - No database connections
47
+ - No ZTD internals
48
+ - No SQL camelCase aliasing rules (SQL rules live under src/sql)
@@ -0,0 +1,21 @@
1
+ import { type } from 'arktype';
2
+
3
+ /**
4
+ * Validator invariant contract used to prove runtime validation wiring.
5
+ *
6
+ * This file is intentionally minimal and domain-agnostic.
7
+ */
8
+ export const smokeOutputSchema = type({
9
+ id: 'number.integer',
10
+ createdAt: 'Date'
11
+ });
12
+
13
+ export type SmokeOutput = ReturnType<typeof smokeOutputSchema>;
14
+
15
+ /**
16
+ * Parse and validate an unknown runtime payload.
17
+ */
18
+ export function parseSmokeOutput(value: unknown): SmokeOutput {
19
+ smokeOutputSchema.assert(value);
20
+ return value as SmokeOutput;
21
+ }
@@ -0,0 +1,20 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * Validator invariant contract used to prove runtime validation wiring.
5
+ *
6
+ * This file is intentionally minimal and domain-agnostic.
7
+ */
8
+ export const smokeOutputSchema = z.object({
9
+ id: z.number().int(),
10
+ createdAt: z.date()
11
+ });
12
+
13
+ export type SmokeOutput = z.infer<typeof smokeOutputSchema>;
14
+
15
+ /**
16
+ * Parse and validate an unknown runtime payload.
17
+ */
18
+ export function parseSmokeOutput(value: unknown): SmokeOutput {
19
+ return smokeOutputSchema.parse(value);
20
+ }
@@ -9,16 +9,16 @@ export type SqlQueryRows<T> = Promise<T[]>;
9
9
  /**
10
10
  * Minimal SQL client interface required by the repository layer.
11
11
  *
12
- * - Production: adapt `pg` (or other drivers) to normalize results into `T[]`
13
- * - Tests: compatible with the `testkit-postgres` pipeline exposed by `@rawsql-ts/adapter-node-pg` clients returned by `createTestkitClient()`
12
+ * - Production: adapt this interface to your preferred driver (pg, mysql2, etc.) and normalize the results to `T[]`.
13
+ * - Tests: replace the implementation with a mock, a fixture helper, or an adapter that follows this contract.
14
14
  *
15
15
  * Connection strategy note:
16
- * - Prefer a shared client per worker process for performance.
17
- * - Do not share a live client across parallel workers.
16
+ * - Prefer a shared client per worker process for better performance.
17
+ * - Do not share a live client across parallel workers without proper synchronization.
18
18
  */
19
19
  export type SqlClient = {
20
20
  query<T extends Record<string, unknown> = Record<string, unknown>>(
21
21
  text: string,
22
- values?: readonly unknown[]
22
+ values?: readonly unknown[] | Record<string, unknown>
23
23
  ): SqlQueryRows<T>;
24
24
  };
@@ -0,0 +1,26 @@
1
+ # src/jobs AGENTS
2
+
3
+ This folder contains script-like operations (procedural SQL execution).
4
+
5
+ ## Scope
6
+
7
+ - Maintenance jobs
8
+ - Data backfills
9
+ - Batch operations
10
+ - Temporary-table driven workflows
11
+
12
+ ## Safety rules
13
+
14
+ - Be explicit about transaction boundaries.
15
+ - Prefer idempotent design (safe to rerun).
16
+ - Emit clear logs/events at start and end of the job.
17
+
18
+ ## SQL usage
19
+
20
+ - It is acceptable to run multiple statements in a job (including temp tables).
21
+ - Avoid coupling job logic to tests-only helpers.
22
+
23
+ ## Testing
24
+
25
+ - Prefer integration-style tests that verify observable outcomes.
26
+ - If the job is heavy, test smaller units or use fixtures to limit scope.
@@ -0,0 +1,3 @@
1
+ # Jobs
2
+
3
+ Job runners that orchestrate repository or SQL workflows.
@@ -0,0 +1,118 @@
1
+ # src/repositories AGENTS
2
+
3
+ This directory contains repository implementations.
4
+
5
+ ## Runtime classification
6
+
7
+ - This is a runtime directory.
8
+ - Code here is executed by the application.
9
+
10
+ ## Responsibilities
11
+
12
+ Repositories orchestrate execution only.
13
+
14
+ They are responsible for:
15
+ - loading SQL assets from `src/sql`
16
+ - validating external inputs via catalog runtime
17
+ - binding parameters
18
+ - calling `SqlClient`
19
+ - mapping SQL rows to DTOs via catalog runtime
20
+ - returning application-facing results
21
+
22
+ Repositories MUST remain thin adapters over SQL.
23
+
24
+ Repositories MUST NOT:
25
+ - embed business rules
26
+ - infer schema or DTO structure
27
+ - compensate for driver limitations with extra queries
28
+
29
+ ## Contract boundaries (important)
30
+
31
+ - Human-owned contracts live under "src/catalog/specs".
32
+ - Runtime normalization and validation live under "src/catalog/runtime".
33
+ - Repositories MUST NOT invent, infer, or modify contracts.
34
+
35
+ If a contract is insufficient, update the spec/runtime first.
36
+
37
+ ## Mandatory runtime usage (required)
38
+
39
+ Repositories MUST use catalog runtime helpers:
40
+ - `ensure*Params` for all external inputs (`unknown -> typed`)
41
+ - `map*RowToDto` for row-to-DTO mapping and output validation
42
+
43
+ Repositories MUST NOT:
44
+ - call spec validators directly
45
+ - bypass runtime normalization
46
+ - return DTOs without runtime validation
47
+ - assume driver-specific runtime types (e.g. timestamps always `Date`)
48
+
49
+ ## SQL rules
50
+
51
+ - SQL assets MUST remain DTO-independent.
52
+ - SQL files MUST use snake_case column names.
53
+ - Repositories MUST NOT push DTO aliasing into SQL.
54
+ - Inline SQL strings are forbidden.
55
+ - Repository SQL loading MUST be centralized in shared runtime/repository infrastructure.
56
+ - Repositories MUST reference SQL assets by stable logical key (example: `user/insert_user.sql`).
57
+ - Repository modules MUST NOT pass caller-relative paths (`./`, `../`) or absolute filesystem paths to SQL loaders.
58
+ - The shared loader MUST resolve logical keys against the `src/sql` root (or catalog SQL registry), never relative to the caller file location.
59
+ - Repository modules MUST NOT implement ad-hoc SQL file loading with `readFileSync`, `__dirname`, `import.meta.url`, or direct path resolution.
60
+
61
+ ## CUD default policy (important)
62
+
63
+ Default policy for table-oriented CUD is:
64
+ - CREATE SQL MAY use `RETURNING` for identifier columns only.
65
+ - CREATE repository methods MUST return the generated identifier by default.
66
+ - CREATE repository methods MUST NOT perform a follow-up SELECT whose purpose is DTO return shaping.
67
+ - UPDATE/DELETE SQL MUST NOT use `RETURNING`.
68
+ - repositories do NOT perform follow-up SELECTs after UPDATE/DELETE.
69
+ - UPDATE/DELETE methods return `Promise<void>` by default.
70
+
71
+ If a CREATE method must return a DTO, that requirement MUST be explicitly declared in catalog specs by human instruction.
72
+
73
+ ## CUD row count rules (non-negotiable)
74
+
75
+ - UPDATE and DELETE MUST rely on driver-reported affected row counts (`rowCount` or equivalent).
76
+ - Repositories MUST NOT use SQL `RETURNING` result presence/count as a substitute for affected row counts.
77
+ - Repositories MUST NOT emulate affected rows using:
78
+ - pre-check SELECT
79
+ - post-check SELECT
80
+ - retry loops
81
+ - shadow queries / CTE hacks
82
+
83
+ If `rowCount === 0`, repositories MUST throw an explicit error.
84
+
85
+ If the driver cannot report affected row counts:
86
+ - CUD verification is unsupported
87
+ - tests MUST fail fast
88
+ - do NOT add workaround logic in repositories
89
+
90
+ ## Read (SELECT) rules
91
+
92
+ - SELECT methods may return:
93
+ - `T | null` for single-row queries
94
+ - `T[]` for multi-row queries
95
+ - Absence of rows is NOT an error unless specified by the contract.
96
+
97
+ ## Error behavior
98
+
99
+ - Propagate validation errors as failures.
100
+ - Do not silently coerce invalid data.
101
+ - Error messages SHOULD include operation name and identifying parameters.
102
+
103
+ ## Testing expectations
104
+
105
+ - Every public repository method MUST be covered by tests.
106
+ - Update/Delete tests MUST verify rowCount handling explicitly.
107
+ - Repository changes without tests are incomplete.
108
+
109
+ ## Guiding principle
110
+
111
+ Repositories execute contracts.
112
+ They do not interpret intent.
113
+
114
+ If correctness depends on extra queries to "confirm" changes:
115
+ - the contract is wrong
116
+ - or the driver is unsupported
117
+
118
+ Fix the contract, not the repository.