@rawsql-ts/ztd-cli 0.16.0 → 0.19.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 (242) hide show
  1. package/README.md +532 -353
  2. package/package.json +35 -17
  3. package/templates/.editorconfig +16 -16
  4. package/templates/.prettierignore +2 -2
  5. package/templates/.prettierrc +24 -24
  6. package/templates/AGENTS.md +30 -325
  7. package/templates/CONTEXT.md +11 -0
  8. package/templates/CONTEXT.webapi.md +11 -0
  9. package/templates/DESIGN.md +17 -0
  10. package/templates/DEV_NOTES.md +14 -0
  11. package/templates/PROMPT_DOGFOOD.webapi.md +49 -0
  12. package/templates/README.md +46 -217
  13. package/templates/README.webapi.md +38 -0
  14. package/templates/scripts/local-source-guard.mjs +189 -0
  15. package/templates/src/AGENTS.md +26 -0
  16. package/templates/src/application/AGENTS.md +15 -0
  17. package/templates/src/application/README.md +6 -0
  18. package/templates/src/catalog/AGENTS.md +28 -0
  19. package/templates/src/catalog/runtime/AGENTS.md +28 -0
  20. package/templates/src/catalog/runtime/_coercions.local-source.ts +30 -0
  21. package/templates/src/catalog/runtime/_coercions.ts +30 -0
  22. package/templates/src/catalog/runtime/_smoke.runtime.ts +21 -0
  23. package/templates/src/catalog/specs/AGENTS.md +41 -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-adapters.ts +32 -0
  27. package/templates/src/db/sql-client.ts +24 -24
  28. package/templates/src/domain/AGENTS.md +15 -0
  29. package/templates/src/domain/README.md +6 -0
  30. package/templates/src/infrastructure/AGENTS.md +14 -0
  31. package/templates/src/infrastructure/README.md +6 -0
  32. package/templates/src/infrastructure/db/AGENTS.md +14 -0
  33. package/templates/src/infrastructure/db/sql-client-adapters.ts +34 -0
  34. package/templates/src/infrastructure/db/sql-client.ts +24 -0
  35. package/templates/src/infrastructure/persistence/AGENTS.md +18 -0
  36. package/templates/src/infrastructure/persistence/README.md +8 -0
  37. package/templates/src/infrastructure/persistence/repositories/AGENTS.md +17 -0
  38. package/templates/src/infrastructure/persistence/repositories/tables/AGENTS.md +20 -0
  39. package/templates/src/infrastructure/persistence/repositories/tables/README.md +5 -0
  40. package/templates/src/infrastructure/persistence/repositories/views/AGENTS.md +16 -0
  41. package/templates/src/infrastructure/persistence/repositories/views/README.md +5 -0
  42. package/templates/src/infrastructure/telemetry/AGENTS.md +14 -0
  43. package/templates/src/infrastructure/telemetry/consoleRepositoryTelemetry.ts +66 -0
  44. package/templates/src/infrastructure/telemetry/repositoryTelemetry.ts +26 -0
  45. package/templates/src/infrastructure/telemetry/types.ts +48 -0
  46. package/templates/src/jobs/AGENTS.md +25 -0
  47. package/templates/src/jobs/README.md +3 -0
  48. package/templates/src/local/sql-contract.ts +1 -0
  49. package/templates/src/presentation/AGENTS.md +15 -0
  50. package/templates/src/presentation/http/AGENTS.md +15 -0
  51. package/templates/src/presentation/http/README.md +6 -0
  52. package/templates/src/repositories/AGENTS.md +30 -0
  53. package/templates/src/repositories/tables/AGENTS.md +29 -0
  54. package/templates/src/repositories/tables/README.md +5 -0
  55. package/templates/src/repositories/views/AGENTS.md +25 -0
  56. package/templates/src/repositories/views/README.md +5 -0
  57. package/templates/src/sql/AGENTS.md +30 -0
  58. package/templates/src/sql/README.md +6 -0
  59. package/templates/tests/AGENTS.md +29 -169
  60. package/templates/tests/generated/AGENTS.md +23 -0
  61. package/templates/tests/smoke.test.ts +25 -0
  62. package/templates/tests/smoke.validation.test.ts +34 -0
  63. package/templates/tests/support/AGENTS.md +24 -0
  64. package/templates/tests/support/global-setup.ts +15 -30
  65. package/templates/tests/support/testkit-client.ts +14 -742
  66. package/templates/tests/support/testkit-client.webapi.ts +14 -0
  67. package/templates/tests/ztd-layout.generated.ts +6 -6
  68. package/templates/tsconfig.json +15 -8
  69. package/templates/vitest.config.ts +13 -13
  70. package/templates/ztd/AGENTS.md +23 -74
  71. package/templates/ztd/README.md +6 -15
  72. package/templates/ztd/ddl/AGENTS.md +26 -0
  73. package/templates/ztd/ddl/demo.sql +74 -0
  74. package/LICENSE +0 -21
  75. package/dist/commands/ddl.d.ts +0 -7
  76. package/dist/commands/ddl.js +0 -118
  77. package/dist/commands/ddl.js.map +0 -1
  78. package/dist/commands/diff.d.ts +0 -10
  79. package/dist/commands/diff.js +0 -38
  80. package/dist/commands/diff.js.map +0 -1
  81. package/dist/commands/genEntities.d.ts +0 -6
  82. package/dist/commands/genEntities.js +0 -50
  83. package/dist/commands/genEntities.js.map +0 -1
  84. package/dist/commands/init.d.ts +0 -66
  85. package/dist/commands/init.js +0 -838
  86. package/dist/commands/init.js.map +0 -1
  87. package/dist/commands/lint.d.ts +0 -59
  88. package/dist/commands/lint.js +0 -338
  89. package/dist/commands/lint.js.map +0 -1
  90. package/dist/commands/options.d.ts +0 -9
  91. package/dist/commands/options.js +0 -48
  92. package/dist/commands/options.js.map +0 -1
  93. package/dist/commands/pull.d.ts +0 -10
  94. package/dist/commands/pull.js +0 -105
  95. package/dist/commands/pull.js.map +0 -1
  96. package/dist/commands/ztdConfig.d.ts +0 -23
  97. package/dist/commands/ztdConfig.js +0 -202
  98. package/dist/commands/ztdConfig.js.map +0 -1
  99. package/dist/commands/ztdConfigCommand.d.ts +0 -5
  100. package/dist/commands/ztdConfigCommand.js +0 -157
  101. package/dist/commands/ztdConfigCommand.js.map +0 -1
  102. package/dist/index.d.ts +0 -2
  103. package/dist/index.js +0 -22
  104. package/dist/index.js.map +0 -1
  105. package/dist/utils/agents.d.ts +0 -1
  106. package/dist/utils/agents.js +0 -48
  107. package/dist/utils/agents.js.map +0 -1
  108. package/dist/utils/collectSqlFiles.d.ts +0 -9
  109. package/dist/utils/collectSqlFiles.js +0 -58
  110. package/dist/utils/collectSqlFiles.js.map +0 -1
  111. package/dist/utils/connectionSummary.d.ts +0 -3
  112. package/dist/utils/connectionSummary.js +0 -29
  113. package/dist/utils/connectionSummary.js.map +0 -1
  114. package/dist/utils/dbConnection.d.ts +0 -29
  115. package/dist/utils/dbConnection.js +0 -210
  116. package/dist/utils/dbConnection.js.map +0 -1
  117. package/dist/utils/fs.d.ts +0 -1
  118. package/dist/utils/fs.js +0 -12
  119. package/dist/utils/fs.js.map +0 -1
  120. package/dist/utils/normalizePulledSchema.d.ts +0 -12
  121. package/dist/utils/normalizePulledSchema.js +0 -213
  122. package/dist/utils/normalizePulledSchema.js.map +0 -1
  123. package/dist/utils/pgDump.d.ts +0 -11
  124. package/dist/utils/pgDump.js +0 -55
  125. package/dist/utils/pgDump.js.map +0 -1
  126. package/dist/utils/sqlLintHelpers.d.ts +0 -18
  127. package/dist/utils/sqlLintHelpers.js +0 -270
  128. package/dist/utils/sqlLintHelpers.js.map +0 -1
  129. package/dist/utils/typeMapper.d.ts +0 -4
  130. package/dist/utils/typeMapper.js +0 -76
  131. package/dist/utils/typeMapper.js.map +0 -1
  132. package/dist/utils/ztdProjectConfig.d.ts +0 -40
  133. package/dist/utils/ztdProjectConfig.js +0 -167
  134. package/dist/utils/ztdProjectConfig.js.map +0 -1
  135. package/templates/dist/drivers/pg-testkit/src/driver/PgTestkitClient.d.ts +0 -38
  136. package/templates/dist/drivers/pg-testkit/src/driver/PgTestkitClient.js +0 -117
  137. package/templates/dist/drivers/pg-testkit/src/driver/PgTestkitClient.js.map +0 -1
  138. package/templates/dist/drivers/pg-testkit/src/driver/createPgTestkitPool.d.ts +0 -4
  139. package/templates/dist/drivers/pg-testkit/src/driver/createPgTestkitPool.js +0 -71
  140. package/templates/dist/drivers/pg-testkit/src/driver/createPgTestkitPool.js.map +0 -1
  141. package/templates/dist/drivers/pg-testkit/src/index.d.ts +0 -5
  142. package/templates/dist/drivers/pg-testkit/src/index.js +0 -11
  143. package/templates/dist/drivers/pg-testkit/src/index.js.map +0 -1
  144. package/templates/dist/drivers/pg-testkit/src/proxy/wrapPgClient.d.ts +0 -3
  145. package/templates/dist/drivers/pg-testkit/src/proxy/wrapPgClient.js +0 -79
  146. package/templates/dist/drivers/pg-testkit/src/proxy/wrapPgClient.js.map +0 -1
  147. package/templates/dist/drivers/pg-testkit/src/types.d.ts +0 -69
  148. package/templates/dist/drivers/pg-testkit/src/types.js +0 -3
  149. package/templates/dist/drivers/pg-testkit/src/types.js.map +0 -1
  150. package/templates/dist/drivers/pg-testkit/src/utils/fixtureState.d.ts +0 -15
  151. package/templates/dist/drivers/pg-testkit/src/utils/fixtureState.js +0 -34
  152. package/templates/dist/drivers/pg-testkit/src/utils/fixtureState.js.map +0 -1
  153. package/templates/dist/drivers/pg-testkit/src/utils/fixtureValidation.d.ts +0 -12
  154. package/templates/dist/drivers/pg-testkit/src/utils/fixtureValidation.js +0 -53
  155. package/templates/dist/drivers/pg-testkit/src/utils/fixtureValidation.js.map +0 -1
  156. package/templates/dist/mapper-core/src/index.d.ts +0 -160
  157. package/templates/dist/mapper-core/src/index.js +0 -637
  158. package/templates/dist/mapper-core/src/index.js.map +0 -1
  159. package/templates/dist/testkit-core/src/errors/index.d.ts +0 -49
  160. package/templates/dist/testkit-core/src/errors/index.js +0 -111
  161. package/templates/dist/testkit-core/src/errors/index.js.map +0 -1
  162. package/templates/dist/testkit-core/src/fixtures/ColumnAffinity.d.ts +0 -5
  163. package/templates/dist/testkit-core/src/fixtures/ColumnAffinity.js +0 -29
  164. package/templates/dist/testkit-core/src/fixtures/ColumnAffinity.js.map +0 -1
  165. package/templates/dist/testkit-core/src/fixtures/DdlFixtureLoader.d.ts +0 -37
  166. package/templates/dist/testkit-core/src/fixtures/DdlFixtureLoader.js +0 -182
  167. package/templates/dist/testkit-core/src/fixtures/DdlFixtureLoader.js.map +0 -1
  168. package/templates/dist/testkit-core/src/fixtures/FixtureProvider.d.ts +0 -20
  169. package/templates/dist/testkit-core/src/fixtures/FixtureProvider.js +0 -121
  170. package/templates/dist/testkit-core/src/fixtures/FixtureProvider.js.map +0 -1
  171. package/templates/dist/testkit-core/src/fixtures/FixtureStore.d.ts +0 -51
  172. package/templates/dist/testkit-core/src/fixtures/FixtureStore.js +0 -199
  173. package/templates/dist/testkit-core/src/fixtures/FixtureStore.js.map +0 -1
  174. package/templates/dist/testkit-core/src/fixtures/TableDefinitionSchemaRegistry.d.ts +0 -10
  175. package/templates/dist/testkit-core/src/fixtures/TableDefinitionSchemaRegistry.js +0 -28
  176. package/templates/dist/testkit-core/src/fixtures/TableDefinitionSchemaRegistry.js.map +0 -1
  177. package/templates/dist/testkit-core/src/fixtures/TableNameResolver.d.ts +0 -18
  178. package/templates/dist/testkit-core/src/fixtures/TableNameResolver.js +0 -80
  179. package/templates/dist/testkit-core/src/fixtures/TableNameResolver.js.map +0 -1
  180. package/templates/dist/testkit-core/src/fixtures/ddlLint.d.ts +0 -59
  181. package/templates/dist/testkit-core/src/fixtures/ddlLint.js +0 -489
  182. package/templates/dist/testkit-core/src/fixtures/ddlLint.js.map +0 -1
  183. package/templates/dist/testkit-core/src/fixtures/naming.d.ts +0 -1
  184. package/templates/dist/testkit-core/src/fixtures/naming.js +0 -6
  185. package/templates/dist/testkit-core/src/fixtures/naming.js.map +0 -1
  186. package/templates/dist/testkit-core/src/index.d.ts +0 -17
  187. package/templates/dist/testkit-core/src/index.js +0 -47
  188. package/templates/dist/testkit-core/src/index.js.map +0 -1
  189. package/templates/dist/testkit-core/src/logger/NoopLogger.d.ts +0 -8
  190. package/templates/dist/testkit-core/src/logger/NoopLogger.js +0 -16
  191. package/templates/dist/testkit-core/src/logger/NoopLogger.js.map +0 -1
  192. package/templates/dist/testkit-core/src/provider/TestkitProvider.d.ts +0 -57
  193. package/templates/dist/testkit-core/src/provider/TestkitProvider.js +0 -149
  194. package/templates/dist/testkit-core/src/provider/TestkitProvider.js.map +0 -1
  195. package/templates/dist/testkit-core/src/rewriter/ResultSelectRewriter.d.ts +0 -43
  196. package/templates/dist/testkit-core/src/rewriter/ResultSelectRewriter.js +0 -473
  197. package/templates/dist/testkit-core/src/rewriter/ResultSelectRewriter.js.map +0 -1
  198. package/templates/dist/testkit-core/src/rewriter/SelectAnalyzer.d.ts +0 -9
  199. package/templates/dist/testkit-core/src/rewriter/SelectAnalyzer.js +0 -38
  200. package/templates/dist/testkit-core/src/rewriter/SelectAnalyzer.js.map +0 -1
  201. package/templates/dist/testkit-core/src/rewriter/SelectFixtureRewriter.d.ts +0 -42
  202. package/templates/dist/testkit-core/src/rewriter/SelectFixtureRewriter.js +0 -298
  203. package/templates/dist/testkit-core/src/rewriter/SelectFixtureRewriter.js.map +0 -1
  204. package/templates/dist/testkit-core/src/sql/SqliteValuesBuilder.d.ts +0 -12
  205. package/templates/dist/testkit-core/src/sql/SqliteValuesBuilder.js +0 -63
  206. package/templates/dist/testkit-core/src/sql/SqliteValuesBuilder.js.map +0 -1
  207. package/templates/dist/testkit-core/src/types/index.d.ts +0 -69
  208. package/templates/dist/testkit-core/src/types/index.js +0 -3
  209. package/templates/dist/testkit-core/src/types/index.js.map +0 -1
  210. package/templates/dist/testkit-core/src/utils/queryHelpers.d.ts +0 -28
  211. package/templates/dist/testkit-core/src/utils/queryHelpers.js +0 -81
  212. package/templates/dist/testkit-core/src/utils/queryHelpers.js.map +0 -1
  213. package/templates/dist/writer-core/src/index.d.ts +0 -34
  214. package/templates/dist/writer-core/src/index.js +0 -115
  215. package/templates/dist/writer-core/src/index.js.map +0 -1
  216. package/templates/dist/ztd-cli/templates/src/db/sql-client.d.ts +0 -20
  217. package/templates/dist/ztd-cli/templates/src/db/sql-client.js +0 -3
  218. package/templates/dist/ztd-cli/templates/src/db/sql-client.js.map +0 -1
  219. package/templates/dist/ztd-cli/templates/src/repositories/user-accounts.d.ts +0 -36
  220. package/templates/dist/ztd-cli/templates/src/repositories/user-accounts.js +0 -85
  221. package/templates/dist/ztd-cli/templates/src/repositories/user-accounts.js.map +0 -1
  222. package/templates/dist/ztd-cli/templates/tests/generated/ztd-row-map.generated.d.ts +0 -20
  223. package/templates/dist/ztd-cli/templates/tests/generated/ztd-row-map.generated.js +0 -33
  224. package/templates/dist/ztd-cli/templates/tests/generated/ztd-row-map.generated.js.map +0 -1
  225. package/templates/dist/ztd-cli/templates/tests/support/global-setup.d.ts +0 -10
  226. package/templates/dist/ztd-cli/templates/tests/support/global-setup.js +0 -29
  227. package/templates/dist/ztd-cli/templates/tests/support/global-setup.js.map +0 -1
  228. package/templates/dist/ztd-cli/templates/tests/support/testkit-client.d.ts +0 -66
  229. package/templates/dist/ztd-cli/templates/tests/support/testkit-client.js +0 -552
  230. package/templates/dist/ztd-cli/templates/tests/support/testkit-client.js.map +0 -1
  231. package/templates/dist/ztd-cli/templates/tests/user-profiles.test.d.ts +0 -1
  232. package/templates/dist/ztd-cli/templates/tests/user-profiles.test.js +0 -82
  233. package/templates/dist/ztd-cli/templates/tests/user-profiles.test.js.map +0 -1
  234. package/templates/dist/ztd-cli/templates/tests/writer-constraints.test.d.ts +0 -1
  235. package/templates/dist/ztd-cli/templates/tests/writer-constraints.test.js +0 -29
  236. package/templates/dist/ztd-cli/templates/tests/writer-constraints.test.js.map +0 -1
  237. package/templates/dist/ztd-cli/templates/tests/ztd-layout.generated.d.ts +0 -7
  238. package/templates/dist/ztd-cli/templates/tests/ztd-layout.generated.js +0 -10
  239. package/templates/dist/ztd-cli/templates/tests/ztd-layout.generated.js.map +0 -1
  240. package/templates/src/repositories/user-accounts.ts +0 -179
  241. package/templates/tests/user-profiles.test.ts +0 -161
  242. package/templates/tests/writer-constraints.test.ts +0 -32
package/README.md CHANGED
@@ -1,353 +1,532 @@
1
- # @rawsql-ts/ztd-cli
2
-
3
- Scaffold **Zero Table Dependency (ZTD)** projects and keep DDL-derived test types in sync.
4
-
5
- `@rawsql-ts/ztd-cli` does **not** execute SQL. To run queries in tests, install the Postgres driver stack `@rawsql-ts/testkit-postgres` plus the Node adapter `@rawsql-ts/adapter-node-pg`.
6
-
7
- ## Install
8
-
9
- ```bash
10
- pnpm add -D @rawsql-ts/ztd-cli
11
- ```
12
-
13
- For actual test execution, install the Postgres fixtures and adapter:
14
-
15
- ```bash
16
- pnpm add -D @rawsql-ts/testkit-postgres @rawsql-ts/adapter-node-pg
17
- ```
18
-
19
- If you run `npx ztd init`, the CLI will automatically add and install the devDependencies referenced by the generated templates (Postgres defaults to `@rawsql-ts/testkit-postgres` plus `@rawsql-ts/adapter-node-pg`).
20
-
21
- Then use the CLI through `npx ztd` or the installed `ztd` bin.
22
-
23
- ## Getting Started (Fast Path)
24
-
25
- 1. Initialize a ZTD layout:
26
-
27
- ```bash
28
- npx ztd init
29
- ```
30
-
31
- For tutorials and greenfield projects, we recommend the optional SQL client seam:
32
-
33
- ```bash
34
- npx ztd init --with-sqlclient
35
- ```
36
-
37
- Use `--with-sqlclient` when you want a minimal `SqlClient` boundary for repositories. Skip it if your project
38
- already has a database abstraction (Prisma, Drizzle, Kysely, custom adapters) to avoid duplicating layers.
39
-
40
- ```bash
41
- npx ztd init --with-app-interface
42
- ```
43
-
44
- Use `--with-app-interface` to append the application interface guidance block to `AGENTS.md` without generating the ZTD layout or touching other files.
45
-
46
- 2. Put your schema into `ztd/ddl/`:
47
-
48
- - Edit the starter file (default): `ztd/ddl/public.sql`, or
49
- - Pull from a live Postgres database: `npx ztd ddl pull` (Postgres only; uses `pg_dump`)
50
-
51
- 3. Generate test types (`TestRowMap`) from DDL:
52
-
53
- ```bash
54
- npx ztd ztd-config
55
- # or keep it updated while you edit SQL:
56
- npx ztd ztd-config --watch
57
- ```
58
-
59
- This step writes files under `tests/generated/`. Treat everything in that directory as generated output: never edit it and never commit it. If you clone the repo into a clean environment and TypeScript reports missing modules under `tests/generated/`, rerun `npx ztd ztd-config`.
60
-
61
- 4. Write tests using the generated test types + the driver wiring:
62
-
63
- - `tests/generated/ztd-row-map.generated.ts` (generated test types; authoritative `TestRowMap`)
64
- - `tests/support/testkit-client.ts` (driver wiring helper)
65
-
66
- If you already have a database, the most common loop is:
67
- `ztd ddl pull` -> edit `ztd/ddl/*.sql` -> `ztd ztd-config --watch` -> write tests.
68
-
69
- At this point, you can write deterministic DB tests without creating tables or running migrations.
70
-
71
- You can introduce ZTD incrementally; existing tests and ORMs can remain untouched.
72
-
73
- ## What `ztd init` Generates
74
-
75
- - `ztd/ddl/<schema>.sql` (starter schema files you can edit or replace; the default schema is `public.sql`)
76
- - `tests/generated/ztd-row-map.generated.ts` (auto-generated `TestRowMap`, the canonical test type contract; do not commit)
77
- - `tests/support/testkit-client.ts` (auto-generated helper that boots a database client, wires a driver, and shares fixtures across the suite)
78
- - `ztd.config.json` (CLI defaults and resolver hints: `dialect`, `ddlDir`, `testsDir`, `ddlLint`, plus `ddl.defaultSchema`/`ddl.searchPath` for resolving unqualified tables)
79
- - `tests/generated/ztd-layout.generated.ts` (generated layout snapshot; do not commit)
80
- - `tests/support/global-setup.ts` (shared test setup used by the generated testkit client)
81
- - `README.md` describing the workflow and commands
82
- - `AGENTS.md` (copied from the package template unless the project already has one; `--with-app-interface` adds the application interface guidance block at the end)
83
- - `ztd/AGENTS.md` and `ztd/README.md` (folder-specific instructions that describe the new schema/domain layout)
84
- - `src/db/sql-client.ts` (optional; generated only with `--with-sqlclient`)
85
- - Optional guide stubs under `src/` and `tests/` if requested
86
-
87
- The resulting project follows the "DDL -> ztd-config -> tests" flow so you can regenerate everything from SQL-first artifacts.
88
-
89
- ## Commands
90
-
91
- ### `ztd init`
92
-
93
- Creates a ZTD-ready project layout (DDL folder, config, generated layout, and test support stubs). It does not connect to your database.
94
-
95
- Use `--with-sqlclient` to scaffold a minimal repository-facing SQL client for tutorials and new projects. It is opt-in
96
- to avoid colliding with existing database layers. If you use `pg`, adapt `client.query(...)` so it returns a plain row
97
- array (`T[]`) that satisfies the generated `SqlClient` interface.
98
-
99
- Use `--with-app-interface` to append the application interface guidance block to `AGENTS.md`. This documentation-only option leaves every other file untouched, making it easy to apply the guidance to existing repositories without rerunning the full layout generator.
100
-
101
- ### `ztd ztd-config`
102
-
103
- Reads every `.sql` file under the configured DDL directory and produces the generated artifacts under `tests/generated/`:
104
- - `tests/generated/ztd-row-map.generated.ts`
105
- - `tests/generated/ztd-layout.generated.ts`
106
-
107
- - The row map exports `TestRowMap` plus table-specific test-row interfaces.
108
- - `--watch` overwrites only the `tests/generated/` outputs (no other folders are touched during the watch cycle).
109
- - Pass `--default-schema` or `--search-path` to update the `ddl.defaultSchema`/`ddl.searchPath` block in `ztd.config.json` so the CLI and drivers resolve unqualified tables the same way.
110
- - Never edit `tests/generated/` by hand. Rerun `npx ztd ztd-config` whenever schema/layout inputs change.
111
-
112
- ### `ztd ddl ...`
113
-
114
- Every `ztd ddl` subcommand targets the shared DDL directory defined in `ztd.config.json` (default `ztd/ddl/`).
115
-
116
- ### `ztd ddl pull`
117
-
118
- Fetches the schema via `pg_dump`, normalizes the DDL, and writes one file per schema under `ztd/ddl/<schema>.sql` (no `schemas/` subdirectory so each namespace lives at the DDL root).
119
-
120
- - Output is deterministic: it drops headers/`SET` statements, sorts objects, and ensures each schema file ends with a clean newline so diffs stay stable.
121
- - You can scope the pull with `--schema <name>` (repeatable) or `--table <schema.table>` (repeatable).
122
-
123
- Connection resolution (in order):
124
-
125
- 1. `DATABASE_URL`
126
- 2. CLI overrides (`--url` / `--db-*` flags)
127
- 3. A `connection` block in `ztd.config.json`
128
-
129
- A sample `connection` block looks like:
130
-
131
- ```json
132
- {
133
- "connection": {
134
- "host": "db.example",
135
- "port": 5432,
136
- "user": "app",
137
- "password": "secret",
138
- "database": "app_db"
139
- }
140
- }
141
- ```
142
-
143
- Unqualified table references are treated as belonging to the `public` schema by default, so `users` is interpreted as `public.users`. If your project relies on a different namespace, update the `ddl.defaultSchema`/`ddl.searchPath` block in `ztd.config.json` so the CLI and downstream tests agree on how unqualified names are resolved.
144
-
145
- > **Note:** `ztd ddl` commands that contact your database depend on the `pg_dump` executable. Ensure `pg_dump` is installed and reachable via your `PATH` (Windows users can add `C:\Program Files\PostgreSQL\<version>\bin` or open a shell that already exposes `pg_dump`), or pass `--pg-dump-path <path>` / set `PG_DUMP_PATH` to the absolute path before running the command. When authentication fails the CLI echoes the target host/port/database/user so you know what credential set to double-check.
146
-
147
- On Windows, register the executable for future PowerShell sessions:
148
-
149
- ```powershell
150
- setx PG_DUMP_PATH "C:\Program Files\PostgreSQL\18\bin\pg_dump.exe"
151
- ```
152
-
153
- Open a new PowerShell window after running this command so the updated environment variable is available to `ztd` commands.
154
-
155
- ### `ztd ddl gen-entities`
156
-
157
- Reads the DDL directory and generates `entities.ts` (optional reference for helpers). Use it when you want TypeScript helpers for ad-hoc schema inspection without replacing `TestRowMap` as the source of truth.
158
-
159
- ### `ztd ddl diff`
160
-
161
- Diffs the local DDL snapshot against a live Postgres database. It uses the shared DDL directory, respects configured extensions, and outputs a human-readable plan with `pg_dump`.
162
-
163
- ### `ztd lint`
164
-
165
- Lint SQL files before writing ZTD tests so syntax and analysis issues surface immediately.
166
-
167
- ```bash
168
- npx ztd lint path/to/query.sql
169
- ```
170
-
171
- - Accepts a single `.sql` file, glob pattern, or directory (directories expand to `**/*.sql`).
172
- - Spins up a temporary PostgreSQL container through `@testcontainers/postgresql` (Docker must be available) and rewrites every statement via `@rawsql-ts/adapter-node-pg`/`@rawsql-ts/testkit-postgres` so no physical tables or migrations are required.
173
- - Executes each rewritten query using `PREPARE ... AS ...` (falling back to `EXPLAIN`) so Postgres performs the same parsing/type resolution used in tests.
174
- - Reports the file path, line/column (when provided), the error code/message/detail/hint, and a caret-marked excerpt to make fixes actionable before running tests.
175
- - Override the database image with `ZTD_LINT_DB_IMAGE` (default `postgres:16-alpine`) when a different Postgres version or variant is desired.
176
-
177
- ## ZTD Testing
178
-
179
- Driver responsibilities live in companion packages such as `@rawsql-ts/testkit-postgres` and `@rawsql-ts/adapter-node-pg` for Postgres.
180
-
181
- The driver sits downstream of `testkit-core` and applies the rewrite + fixture pipeline before running any database interaction. Install the driver, configure it in your tests, and point it at the row map from `tests/generated/ztd-row-map.generated.ts`.
182
-
183
- ### SQL rewrite logging (generated `testkit-client.ts`)
184
-
185
- The `tests/support/testkit-client.ts` helper generated by `ztd init` can emit structured logs that show the SQL before and after the adapter rewrites it via `@rawsql-ts/testkit-postgres`.
186
-
187
- Enable it via environment variables:
188
-
189
- - `ZTD_SQL_LOG=1` (or `true`/`yes`): log original + rewritten SQL
190
- - `ZTD_SQL_LOG_PARAMS=1` (or `true`/`yes`): include parameters in the logs
191
-
192
- You can also enable/disable logging per call by passing `ZtdSqlLogOptions` as the second argument to `createTestkitClient`.
193
-
194
- ## Benchmark summary
195
-
196
- ### Purpose
197
-
198
- This benchmark executes the same repository implementation with two different supporting stacks: the Traditional schema/migration workflow (schema setup + seed + query + cleanup) and the ZTD fixture-backed workflow (repository query → rewrite → fixture materialization). The comparison highlights:
199
-
200
- - End-to-end wall-clock time including runner startup.
201
- - DB execution time and SQL count so Traditional’s higher SQL volume is explicit.
202
- - ZTD rewrite and fixture breakdowns so the internal costs of the testkit-postgres pipeline are visible.
203
- - Parallelism effects, runner startup costs, and where the break-even point lies as suite size grows.
204
-
205
- ### Assumptions and environment
206
-
207
- This benchmark compares ZTD-style repository tests against a traditional migration-based workflow while exercising the same repository methods. All numbers are measured with the test runner included unless stated otherwise.
208
-
209
- #### Environment (measured run)
210
-
211
- - Node.js: v22.14.0
212
- - OS: Windows 10 (build 26100)
213
- - CPU: AMD Ryzen 7 7800X3D (16 logical cores)
214
- - Database: PostgreSQL 18.1 (containerized; `testcontainers`)
215
- - Parallel workers: 4
216
- - Report date: 2025-12-20
217
-
218
- #### Benchmark shape
219
-
220
- - Repository test cases: 3 (`customer_summary`, `product_ranking`, `sales_summary`)
221
- - Each test performs: 1 repository call (1 SQL execution per test case)
222
- - The Traditional workflow wraps every repository execution with migration, seeding, and cleanup SQL, whereas the ZTD workflow captures the same query, feeds it to the testkit-postgres adapter, and replays the rewritten/select-only statements backed by fixtures.
223
- - Suite sizes shown in the report:
224
- - 3 tests (baseline)
225
- - 30 tests (the same 3 cases repeated to approximate a larger suite)
226
-
227
- The 30-test suite exists to show how runner overhead amortizes as the number of executed tests grows, while keeping the tested SQL and data constant.
228
-
229
- #### What is included / excluded
230
-
231
- - **Runner-included runs (main comparison):** wall-clock time including `pnpm` + `vitest` startup and test execution.
232
- - **Steady-state section:** measures incremental cost per iteration after the runner is warm (first iteration excluded), to approximate watch/CI-like “many tests per single runner invocation.”
233
- - **Container startup:** excluded (the Postgres container is shared across runs).
234
-
235
- #### Fairness / bias notes (important)
236
-
237
- This benchmark intentionally measures the **Traditional** workflow under favorable assumptions:
238
-
239
- - **Traditional SQL construction cost is treated as zero**: queries are hard-coded raw SQL strings (no ORM/query-builder generation time).
240
- - **Traditional migration/DDL generation cost is treated as zero**: schema/migration SQL is also written directly (no ORM schema DSL or migration generation time).
241
-
242
- In contrast, the **ZTD** benchmark includes the repository layer’s normal SQL usage:
243
-
244
- - **ZTD includes SQL construction time as exercised by the repository layer** (i.e., whatever the test code does to produce the SQL text), in addition to rewrite/fixture overhead.
245
-
246
- Because real-world ORM workflows usually add both query generation and migration generation overhead on top of what is measured here, this setup should be interpreted as a **lower bound for Traditional** and a relatively conservative comparison against ZTD.
247
-
248
- ### Results (runner included)
249
-
250
- #### End-to-end runtime
251
-
252
- | Suite size | Scenario | Workers | Avg Total (ms) | Avg Startup (ms) | Avg Execution (ms) | Startup % | Avg ms/test | Avg SQL Count | Avg DB (ms) |
253
- | ---: | --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
254
- | 3 | Traditional | 1 | 1951.08 | 1013.22 | 937.86 | 51.8% | 650.36 | 36 | 123.06 |
255
- | 3 | Traditional | 4 | 1301.56 | 967.02 | 334.54 | 74.3% | 433.85 | 36 | 39.06 |
256
- | 3 | ZTD | 1 | 2283.66 | 979.91 | 1303.74 | 42.9% | 761.22 | 3 | 11.34 |
257
- | 3 | ZTD | 4 | 1430.64 | 957.75 | 472.89 | 66.9% | 476.88 | 3 | 3.81 |
258
- | 30 | Traditional | 1 | 3085.48 | 1018.71 | 2066.77 | 33.0% | 102.85 | 360 | 1009.85 |
259
- | 30 | Traditional | 4 | 1788.35 | 996.66 | 791.68 | 55.8% | 59.61 | 360 | 392.83 |
260
- | 30 | ZTD | 1 | 2480.84 | 957.91 | 1522.94 | 38.6% | 82.69 | 30 | 44.82 |
261
- | 30 | ZTD | 4 | 1507.46 | 944.57 | 562.88 | 62.7% | 50.25 | 30 | 17.69 |
262
-
263
- ### What this shows
264
- - **Small suites (3 tests) are dominated by runner startup.** At this scale, Traditional is faster (both serial and 4-worker), because fixed startup overhead and per-test harness work overwhelm ZTD’s per-test savings.
265
- - **As suite size grows (30 tests), ZTD becomes faster end-to-end.**
266
- - Serial: ZTD 2480.84 ms vs Traditional 3085.48 ms
267
- - 4 workers: ZTD 1507.46 ms vs Traditional 1788.35 ms
268
- - **Parallel execution helps both approaches**, but the improvement is constrained by startup overhead:
269
- - With 4 workers, the startup share rises (more of the total becomes fixed runner cost), so scaling is not linear.
270
-
271
- ### Break-even intuition (where ZTD starts to win)
272
-
273
- From these results, the practical break-even is **between 3 and 30 tests** under the current environment and runner-included setup.
274
-
275
- Why:
276
- - Traditional has high per-test DB work (many SQL statements + significant DB time).
277
- - ZTD has low per-test DB work (few SQL statements), but adds rewrite + fixture overhead.
278
- - Once the suite is large enough that **execution dominates startup**, ZTD’s reduced DB work overtakes its rewrite/fixture costs.
279
-
280
- ### ZTD cost structure (what is expensive)
281
-
282
- ZTD’s incremental work per test is primarily:
283
- - **SQL-to-ZTD rewrite time**
284
- - **Fixture materialization time**
285
- - **DB query time** (typically small compared to Traditional)
286
-
287
- A concrete view is easiest in the steady-state section below, where the runner is warm.
288
-
289
- ### Steady-state (runner warm) incremental cost
290
-
291
- This approximates watch/CI iterations where the runner has already started (first repetition excluded as warmup).
292
-
293
- | Suite | Workers | Avg incremental time per iteration (ms) | Avg SQL Count | Avg DB time (ms) | Avg rewrite (ms) | Avg fixture (ms) |
294
- | --- | ---: | ---: | ---: | ---: | ---: | ---: |
295
- | Traditional (30 tests) | 1 | 1260.20 | 360 | 1039.98 | - | - |
296
- | ZTD (30 tests) | 1 | 93.73 | 30 | 30.08 | 32.00 | 20.42 |
297
- | ZTD (30 tests) | 4 | 91.14 | 30 | 29.95 | 30.75 | 19.40 |
298
-
299
- ### What this shows
300
- - Traditional steady-state is dominated by DB time (~1040 ms out of ~1260 ms).
301
- - ZTD steady-state is dominated by **rewrite (~31 ms) + fixture (~20 ms)**; DB time is ~30 ms.
302
- - Parallelism has limited impact in ZTD steady-state here because the per-iteration work is already small and may be bounded by coordination / shared overheads.
303
-
304
- ### Conclusion
305
-
306
- - **Runner included (realistic)**:
307
- - For very small suites, startup dominates and Traditional can be faster.
308
- - For larger suites, ZTD wins end-to-end due to dramatically lower DB work and SQL count.
309
- - **Parallel execution matters**, but it mainly reduces the execution portion; runner startup becomes the limiting floor.
310
- - **ZTD’s main costs are rewrite and fixture preparation**, not DB time. This is good news: optimizing rewrite/fixture logic is the highest-leverage path for further speedups.
311
-
312
- To regenerate the report, run:
313
-
314
- ```bash
315
- pnpm ztd:bench
316
- ```
317
-
318
- The report is written to `tmp/bench/report.md`.
319
-
320
- ## Concepts (Why ZTD?)
321
-
322
- ### What is ZTD?
323
-
324
- Zero Table Dependency (ZTD) keeps your tests aligned with a real database engine without ever creating or mutating physical tables during the test run.
325
-
326
- - Application CRUD statements are rewritten into fixture-backed `SELECT` queries.
327
- - Schema changes are expressed via SQL files (DDL) and their generated row map.
328
- - Tests consume fixtures + types, not a live mutable schema, which keeps the suite deterministic and safe for automated code generation.
329
-
330
- ### Schema resolution (`defaultSchema` / `searchPath`)
331
-
332
- Application SQL can omit schema qualifiers (for example, `SELECT ... FROM users`). Drivers resolve those references using the `ddl.defaultSchema` and `ddl.searchPath` settings in `ztd.config.json` before matching fixtures / DDL metadata.
333
-
334
- ## Glossary
335
-
336
- - **DDL**: SQL files that define schema objects (tables, enums, indexes, etc.).
337
- - **Row map (`TestRowMap`)**: Generated TypeScript types describing test rows for each table from DDL.
338
- - **Fixture**: Static rows used by the driver to answer queries deterministically.
339
- - **Driver**: The package that connects to your database engine and runs the rewrite + fixture pipeline (for example, `@rawsql-ts/testkit-postgres` plus `@rawsql-ts/adapter-node-pg`).
340
-
341
- ## AI Coding Workflow (Optional)
342
-
343
- 1. Update the relevant `ztd/ddl/<schema>.sql` file (for example, `ztd/ddl/public.sql`) with the desired schema.
344
- 2. Run `npx ztd ztd-config` (or `--watch`) to regenerate the generated outputs under `tests/generated/`.
345
- 3. Use the row map + fixtures to write repositories, tests, and fixtures.
346
- 4. Run tests through the testkit-postgres stack (`@rawsql-ts/testkit-postgres` + `@rawsql-ts/adapter-node-pg`) (or another driver) since `ztd-cli` itself never executes SQL.
347
- 5. When generating code with an AI tool, feed it `tests/generated/ztd-row-map.generated.ts`, `tests/generated/ztd-layout.generated.ts`, `ztd.config.json`, and any AGENTS guidance so it can respect the ZTD contract.
348
-
349
- ## AGENTS.md
350
-
351
- `ztd init` copies the AGENTS template from this package into the project root, preferring `AGENTS.md` unless a file already exists (then it falls back to `AGENTS_ztd.md`). The template explains the conventions for AI agents, including which testkit to use, how to treat `tests/generated/ztd-row-map.generated.ts`, and how to avoid mutating schema files. Keep the generated AGENTS file in version control so every future AI assistant receives the same guidance.
352
-
353
- `ztd init` also creates `ztd/AGENTS.md` and `ztd/README.md` so contributors always see the canonical DDL, enum, and domain-spec guidance inside the new layout.
1
+ # @rawsql-ts/ztd-cli
2
+
3
+ ![npm version](https://img.shields.io/npm/v/@rawsql-ts/ztd-cli)
4
+ ![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)
5
+
6
+ SQL-first CLI for **Zero Table Dependency (ZTD)** workflows, schema inspection, and migration SQL artifact generation.
7
+
8
+ `ztd-cli` helps scaffold ZTD projects, keep DDL-derived test types in sync, inspect explicit database targets when needed, and generate reviewable SQL artifacts without silently owning runtime or deployment databases. ZTD keeps tests aligned with a real database engine without creating or mutating physical application tables during the test run.
9
+
10
+ `ztd-cli` does **not** execute SQL by itself. To run ZTD tests, plug in a database adapter and a DBMS-specific testkit such as `@rawsql-ts/adapter-node-pg` + `@rawsql-ts/testkit-postgres` for Postgres.
11
+
12
+ ## Database Ownership Model
13
+
14
+ `ztd-cli` owns only the ZTD test database, not the application or deployment database.
15
+
16
+ | Setting / action | Owned by `ztd-cli` | Typical use |
17
+ |---|---|---|
18
+ | `ZTD_TEST_DATABASE_URL` | Yes (implicit) | ZTD tests, internal verification, perf workflows |
19
+ | `DATABASE_URL` | No | Application runtime, CI/CD, deployment tooling |
20
+ | `--url` / complete `--db-*` | No (explicit only) | Non-ZTD target inspection such as `ddl pull`, `ddl diff` |
21
+
22
+ - `ztd-cli` does not read `DATABASE_URL` automatically — it is not a `ztd-cli` default target.
23
+ - Any non-ZTD database target must be passed explicitly via `--url` or `--db-*`.
24
+ - `ztd-cli` may generate migration SQL artifacts, but it does not apply them.
25
+
26
+ ## Features
27
+
28
+ - Project scaffolding with `ztd init` (DDL folder, config, test stubs)
29
+ - DDL-to-TypeScript type generation (`TestRowMap`)
30
+ - QuerySpec scaffold generation from SQL assets (`ztd model-gen`) via ZTD-owned inspection or explicit-target inspection
31
+ - Schema pull from an explicit target Postgres database via `pg_dump`
32
+ - DDL diff against an explicit target database for inspection
33
+ - SQL linting with fixture-backed validation
34
+ - Deterministic test specification evidence export (JSON / Markdown)
35
+ - Human-readable test documentation export for ZTD test assets
36
+ - Watch mode for continuous regeneration
37
+ - Validator selection (Zod or ArkType) during init
38
+ - Global machine-readable mode via `--output json`
39
+ - Runtime command introspection via `ztd describe`
40
+ - Dry-run support for write-capable commands such as `init`, `ztd-config`, `model-gen`, and `ddl *`
41
+ - Optional raw JSON request payloads for automation on selected commands
42
+ - `query uses` powered by the reusable `@rawsql-ts/sql-grep-core` engine
43
+
44
+ ## Installation
45
+
46
+ ```bash
47
+ npm install -D @rawsql-ts/ztd-cli
48
+ ```
49
+
50
+ ## Getting Started with AI
51
+
52
+ If you are using an AI coding agent, start with a short prompt that sets only the minimum project shape and domain language. You do **not** need to explain package-manager setup in that prompt — the agent handles `npm install` or `pnpm install` automatically.
53
+
54
+ Example prompt:
55
+
56
+ ```text
57
+ I want to build a WebAPI application with @rawsql-ts/ztd-cli.
58
+ Use Docker and Postgres.
59
+ Start from the webapi scaffold.
60
+ Model three tables: sales, sale_lines, and products.
61
+ Keep domain, application, presentation, and persistence concerns separated.
62
+ Prepare the initial DDL, scaffold the ZTD project, and explain what was created.
63
+ Do not apply migrations automatically.
64
+ ```
65
+
66
+ What a prompt at this level should usually guarantee:
67
+
68
+ * a `webapi`-shaped project layout
69
+ * starter DDL under `ztd/ddl/`
70
+ * initial smoke tests and generated-type workflow via `ztd-config`
71
+ * separation between app-facing layers and ZTD-owned persistence assets
72
+ * README / CONTEXT / AGENTS guidance that tells the next actor where to keep working
73
+
74
+ What it does **not** guarantee by itself:
75
+
76
+ * production-ready DDL review
77
+ * finalized API boundaries, DTOs, or SQL contracts
78
+ * migration application or deployment execution
79
+ * non-ZTD target inspection unless the caller explicitly passes `--url` or `--db-*`
80
+
81
+ For a typical `webapi` scaffold, the generated directory shape looks like this:
82
+
83
+ ```text
84
+ src/
85
+ domain/
86
+ application/
87
+ presentation/
88
+ http/
89
+ infrastructure/
90
+ db/
91
+ telemetry/
92
+ persistence/
93
+ repositories/
94
+ views/
95
+ tables/
96
+ sql/
97
+ catalog/
98
+ specs/
99
+ runtime/
100
+ ztd/
101
+ ddl/
102
+ tests/
103
+ support/
104
+ generated/
105
+ .ztd/
106
+ agents/
107
+ ```
108
+
109
+ How to read that layout:
110
+
111
+ * `src/domain`, `src/application`, and `src/presentation/http` are where generic WebAPI work should begin.
112
+ * `src/infrastructure/persistence`, `src/sql`, `src/catalog`, and `ztd/ddl` are the ZTD-owned persistence side.
113
+ * `tests/generated` is generated output. Recreate it with `ztd ztd-config` instead of editing it manually.
114
+ * `.ztd/agents` contains managed AI guidance so a later prompt such as "WebAPI化して" does not accidentally jump straight into persistence-specific rules.
115
+
116
+ ## Choose The Right Happy Path
117
+
118
+ `ztd-cli` has two valid happy paths, and they answer different questions:
119
+
120
+ * `Published package mode` validates what a normal npm consumer sees in a standalone project.
121
+ * `Local-source developer mode` validates unreleased changes from a local `rawsql-ts` checkout without publishing first.
122
+
123
+ Use `Published package mode` when you want to check the real package-consumer experience. Use `Local-source developer mode` when you want to dogfood unpublished changes. A published-package failure does not automatically mean the local-source developer path is broken, and a local-source-only workaround should not be presented as the default npm user flow.
124
+
125
+ For pre-release work inside this monorepo, use the repository-root verification command `pnpm verify:published-package-mode` to pack artifacts and smoke-test the standalone `ztd-cli` flow before publishing. See [Published-Package Verification Before Release](../../docs/guide/published-package-verification.md).
126
+
127
+ ## Happy Path Quickstart (Published Package Mode)
128
+
129
+ A complete copy-paste sequence to reach a green test run. Choose the **demo** workflow during `ztd init` to get a working example immediately.
130
+
131
+ ### Prerequisites
132
+
133
+ * Node.js 20+
134
+ * npm, pnpm, or yarn
135
+
136
+ ### Steps
137
+
138
+ ```bash
139
+ # 1. Create a new project (skip if you already have one)
140
+ mkdir my-ztd-project && cd my-ztd-project
141
+ npm init -y
142
+
143
+ # 2. Install ztd-cli and the test runner
144
+ npm install -D @rawsql-ts/ztd-cli vitest typescript
145
+
146
+ # 3. Scaffold a ZTD project
147
+ # Select: workflow "demo", validator "Zod (recommended)"
148
+ npx ztd init
149
+ ```
150
+
151
+ After `ztd init` you should see:
152
+
153
+ | Path | Purpose |
154
+ | --------------------------------- | --------------------------------------------------------------- |
155
+ | `ztd/ddl/public.sql` | Sample or starter DDL for the default schema |
156
+ | `ztd.config.json` | CLI defaults for DDL and test layout metadata |
157
+ | `tests/smoke.test.ts` | Minimal smoke test |
158
+ | `tests/smoke.validation.test.ts` | Validator integration smoke test |
159
+ | `tests/support/testkit-client.ts` | Driver wiring placeholder |
160
+ | `src/catalog/specs/` | Spec and runtime files for the smoke contract |
161
+ | `CONTEXT.md` | Agent-focused project invariants and recommended command usage |
162
+ | `.ztd/agents/manifest.json` | Managed AI guidance index with security notices and entrypoints |
163
+
164
+ ```bash
165
+ # 4. Generate test types from the demo DDL
166
+ npx ztd ztd-config
167
+ ```
168
+
169
+ After `ztd-config` you should see:
170
+
171
+ | Path | Purpose |
172
+ | ------------------------------------------ | ---------------------------------------- |
173
+ | `tests/generated/ztd-row-map.generated.ts` | Authoritative `TestRowMap` (do not edit) |
174
+ | `tests/generated/ztd-layout.generated.ts` | Layout metadata for the test harness |
175
+
176
+ ```bash
177
+ # 5. Run the smoke tests
178
+ npx vitest run
179
+ ```
180
+
181
+ All smoke tests should pass. You now have a working ZTD project.
182
+
183
+ ### Next steps
184
+
185
+ * Replace the demo DDL with your own schema, or inspect an explicit target with `npx ztd ddl pull --url <target>`
186
+ * Re-run `npx ztd ztd-config` whenever DDL changes (or use `--watch`)
187
+ * Install visible AGENTS files only if you want them in the repo: `npx ztd agents install`
188
+ * Wire a real driver in `tests/support/testkit-client.ts` (see [adapter-node-pg](../adapters/adapter-node-pg) for Postgres)
189
+ * Write domain tests against generated `TestRowMap` types
190
+
191
+ > **Tip:** For a non-interactive setup (CI, scripts), use `npx ztd init --yes` with explicit flags. See [Commands](#commands) for details.
192
+
193
+ ## Happy Path Quickstart (Local-Source Developer Mode)
194
+
195
+ Use this mode when you need to dogfood unreleased `rawsql-ts` changes from a local checkout. This is the supported path for validating new CLI behavior before package publication.
196
+
197
+ ### Prerequisites
198
+
199
+ * A local `rawsql-ts` checkout
200
+ * Node.js 20+
201
+ * `pnpm`
202
+ * A throwaway project outside any `pnpm` workspace
203
+
204
+ ### Steps
205
+
206
+ ```bash
207
+ # 1. Build the CLI from the local checkout
208
+ pnpm -C "<LOCAL_SOURCE_ROOT>" --filter @rawsql-ts/ztd-cli build
209
+
210
+ # 2. Create a standalone throwaway app outside the monorepo
211
+ mkdir /tmp/my-ztd-dogfood && cd /tmp/my-ztd-dogfood
212
+
213
+ # 3. Scaffold from local source
214
+ node "<LOCAL_SOURCE_ROOT>/packages/ztd-cli/dist/index.js" init \
215
+ --workflow empty \
216
+ --validator zod \
217
+ --local-source-root "<LOCAL_SOURCE_ROOT>"
218
+
219
+ # 4. Install the scaffolded dependencies
220
+ pnpm install --ignore-workspace
221
+
222
+ # 5. Generate test types from the DDL
223
+ npx ztd ztd-config
224
+
225
+ # 6. Continue the normal loop
226
+ pnpm typecheck
227
+ pnpm test
228
+ ```
229
+
230
+ Use this path for pre-release dogfooding and unpublished dependency combinations. Use the published-package quickstart above when validating the end-user npm experience.
231
+
232
+ ## Quick Reference
233
+
234
+ ```bash
235
+ # Common workflow loop
236
+ ZTD_TEST_DATABASE_URL=postgres://... npx ztd ztd-config # Regenerate types from DDL
237
+ ZTD_TEST_DATABASE_URL=postgres://... npx vitest run # Run tests
238
+ npx ztd ddl pull --url postgres://... # Inspect an explicit target (optional)
239
+ npx ztd ztd-config --watch # Keep types updated while editing DDL
240
+ ```
241
+
242
+ ## Agent-Friendly Automation
243
+
244
+ `ztd-cli` keeps the human-oriented CLI, but also exposes a machine-readable path for agents and scripts.
245
+
246
+ Reference docs:
247
+
248
+ * [ztd-cli Agent Interface](../../docs/guide/ztd-cli-agent-interface.md)
249
+ * [ztd-cli Describe Schema](../../docs/guide/ztd-cli-describe-schema.md)
250
+
251
+ ### Global JSON mode
252
+
253
+ ```bash
254
+ npx ztd --output json describe
255
+ npx ztd --output json describe command model-gen
256
+ npx ztd --output json query uses column public.users.email --format json
257
+ ```
258
+
259
+ Use global `--output json` when you want command envelopes on stdout and structured diagnostics on stderr.
260
+
261
+ ### Dry-run safety rails
262
+
263
+ Use `--dry-run` before commands that would write files:
264
+
265
+ ```bash
266
+ npx ztd init --dry-run --workflow demo --validator zod
267
+ npx ztd ztd-config --dry-run
268
+ npx ztd model-gen src/sql/users/list.sql --sql-root src/sql --out src/catalog/specs/list.spec.ts --dry-run
269
+ npx ztd ddl pull --url postgres://... --out ztd/ddl --dry-run
270
+ npx ztd ddl diff --url postgres://... --out artifacts/schema.diff --dry-run
271
+ npx ztd ddl gen-entities --out src/entities.ts --dry-run
272
+ ```
273
+
274
+ ### JSON request payloads
275
+
276
+ Selected commands accept `--json <payload>` to reduce flag-by-flag construction in automation. Prefix the value with `@` to load JSON from a file.
277
+
278
+ ```bash
279
+ npx ztd init --dry-run --json '{"workflow":"demo","validator":"zod","withSqlclient":true}'
280
+ npx ztd ztd-config --output json --json '{"ddlDir":"ztd/ddl","extensions":".sql,.ddl","dryRun":true}'
281
+ npx ztd ddl pull --output json --json '{"url":"postgres://example:example@127.0.0.1:5432/app_db","out":"ztd/ddl","schema":["public"],"dryRun":true}'
282
+ npx ztd model-gen src/sql/users/list.sql --json '{"sqlRoot":"src/sql","probeMode":"ztd","dryRun":true}'
283
+ npx ztd check contract --json '{"format":"json","strict":true}'
284
+ npx ztd query uses column --json '{"target":"public.users.email","format":"json","summaryOnly":true}'
285
+ npx ztd lint --json '{"path":"src/sql/**/*.sql"}'
286
+ ```
287
+
288
+ ## Recommended Backend Happy Path
289
+
290
+ For backend work, split the loop into **ZTD-owned** work and **explicit-target inspection** work instead of mixing them from the start.
291
+
292
+ | Step | Primary actor | Phase | Why |
293
+ | -------------------------------------------------------------------------------------------------- | ------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
294
+ | Choose the PostgreSQL version and test DB bootstrap | AI / Human | ZTD-owned | Fix the ZTD-owned test database first so generated files, tests, and docs all refer to the same environment. |
295
+ | Draft the DDL in `ztd/ddl/*.sql` | AI / Human | ZTD-owned | Treat DDL as the source of truth. Prefer application-owned identifiers/timestamps in the initial loop so tests do not depend on sequences or DB defaults. |
296
+ | Run `ztd init --workflow empty` | CLI | ZTD-owned | Scaffold folders, config, and test placeholders mechanically. |
297
+ | Run `ztd ztd-config` | CLI | ZTD-owned | Regenerate `TestRowMap` directly from DDL without applying migrations. |
298
+ | Write SQL assets under `src/sql` using named params | AI / Human | ZTD-owned | Keep the handwritten SQL authoritative while matching the default `model-gen` policy. |
299
+ | Implement QuerySpecs, repositories, and ZTD tests | AI / Human | ZTD-owned | Contract semantics, DTO shape, and query boundaries still require judgment. |
300
+ | Run `vitest` against an empty Postgres instance | CLI | ZTD-owned | ZTD should stay green before any physical app tables exist. |
301
+ | Run `ztd model-gen --probe-mode ztd` against your local DDL snapshot | CLI | ZTD-owned | This keeps QuerySpec scaffolding inside the zero-migration inner loop as long as the referenced schema is represented in `ztd/ddl/*.sql`. |
302
+ | Inspect a non-ZTD database target only when you need deployed metadata | Human / CLI | Explicit-target inspection | This is where `ddl pull`, `ddl diff`, explicit-target inspection, E2E setup, and migration artifact preparation begin. |
303
+ | Run `ztd model-gen --probe-mode live` only when local DDL is intentionally not the source of truth | CLI | Explicit-target inspection | Use explicit-target inspection for objects missing from local DDL or when you explicitly want deployed metadata. |
304
+
305
+ Use this split to classify repetition:
306
+
307
+ * Repeated CLI retries caused by missing flags, missing paths, or boilerplate setup usually belong in docs or CLI automation.
308
+ * Repeated AI retries caused by contract shape, nullability, naming, or domain semantics usually indicate design choices that should stay reviewable.
309
+ * Prefer the ZTD-owned loop by default. If a task is impossible there because the required metadata is not represented in local DDL, treat it as an explicit-target inspection concern instead of forcing migrations into the inner loop.
310
+
311
+ ## Commands
312
+
313
+ Most write-capable commands support `--dry-run` and `--json <payload>` for automation. Run `npx ztd describe command <name>` for per-command details.
314
+
315
+ | Command | Description |
316
+ |---------|-------------|
317
+ | `ztd init` | Create a ZTD-ready project layout (DDL folder, config, test stubs). Flags: `--yes`, `--workflow <pg_dump\|empty\|demo>`, `--validator <zod\|arktype>`, `--with-sqlclient`, `--with-app-interface`, `--local-source-root <path>` |
318
+ | `ztd agents install` | Materialize visible `AGENTS.md` files from the managed templates |
319
+ | `ztd agents status` | Report internal/visible AGENTS state and drift signals |
320
+ | `ztd ztd-config` | Generate `TestRowMap` and layout from DDL files. Flags: `--watch`, `--quiet` |
321
+ | `ztd model-gen <sql-file>` | Generate QuerySpec DTO types and rowMapping by inspecting DDL or an explicit target. Flags: `--probe-mode <ztd\|live>`, `--import-style <package\|relative>`, `--import-from`, `--describe-output`, `--debug-probe` |
322
+ | `ztd ddl pull` | Inspect schema state from an explicit target Postgres database via `pg_dump`. Flag: `--pg-dump-shell` |
323
+ | `ztd ddl diff` | Compare local DDL snapshot against an explicit target database. Flag: `--pg-dump-shell` |
324
+ | `ztd ddl gen-entities` | Generate `entities.ts` for ad-hoc schema inspection |
325
+ | `ztd lint <path>` | Lint SQL files with fixture-backed validation |
326
+ | `ztd evidence --mode specification` | Export executable specification evidence from SQL catalogs and test files |
327
+ | `ztd check contract` | Validate contract consistency |
328
+ | `ztd describe` | List command descriptions and machine-readable capability metadata |
329
+ | `ztd describe command <name>` | Describe one command in detail, including dry-run and JSON support |
330
+ | `ztd --output json <command>` | Emit a versioned JSON envelope for supported commands |
331
+ | `ztd query uses table <schema.table>` | Find catalog SQL statements that use a table target |
332
+ | `ztd query uses column <schema.table>.<col>` | Find catalog SQL statements that use a column target. Flags: `--sql-root`, `--exclude-generated`, `--any-schema`, `--any-table`, `--view <impact\|detail>` |
333
+
334
+ ### Introspection examples
335
+
336
+ ```bash
337
+ npx ztd describe
338
+ npx ztd describe command init
339
+ npx ztd --output json describe command model-gen
340
+ ```
341
+
342
+ ## Impact Investigation
343
+
344
+ Use `ztd query uses` before renaming or deleting catalog-facing SQL assets. The command is strict by default and never broadens matching unless you opt in with relaxed flags.
345
+
346
+ * `impact` (default) aggregated "used or not, and by which queries?" view
347
+ * `--view detail` edit-ready locations and snippets for refactoring
348
+ * `--exclude-generated` — omit `src/catalog/specs/generated` when those scaffolds add noise
349
+ * `--any-schema` / `--any-table` — relaxed matching (drops confidence to `low`)
350
+
351
+ ```bash
352
+ # Strict
353
+ npx ztd query uses table public.users
354
+ npx ztd query uses column public.users.email --view detail
355
+ npx ztd query uses table public.sale_lines --exclude-generated
356
+
357
+ # Relaxed
358
+ npx ztd query uses column users.email --any-schema --format json
359
+ ```
360
+
361
+ Output includes `confidence`, `notes` (why confidence dropped), `source` (AST vs fallback), and `statement_fingerprint` (stable across whitespace changes). Static column analysis does not guarantee semantic identity.
362
+
363
+ For the full JSON schema and output field reference, see `npx ztd query uses column public.users.email --format json`.
364
+
365
+ ## What is ZTD?
366
+
367
+ Zero Table Dependency rewrites application CRUD statements into fixture-backed SELECT queries, so tests consume fixtures and generated types instead of a live mutable schema.
368
+
369
+ * Schema changes are expressed via SQL files (DDL)
370
+ * `ztd-config` generates TypeScript types from those DDL files
371
+ * Tests run deterministically without creating or mutating physical tables
372
+
373
+ The typical loop: edit `ztd/ddl/*.sql` -> `ZTD_TEST_DATABASE_URL=... ztd ztd-config --watch` -> write tests. Use `ddl pull` only when you intentionally inspect an explicit target.
374
+
375
+ ## After DDL/Schema Changes
376
+
377
+ When your database schema evolves, regenerate test types and re-run tests. Here is the standard workflow and common patterns.
378
+
379
+ ### Standard workflow
380
+
381
+ ```bash
382
+ # 1. Update DDL files in ztd/ddl/
383
+ # Edit manually, or inspect an explicit target:
384
+ npx ztd ddl pull --url postgres://...
385
+
386
+ # 2. Regenerate test types
387
+ npx ztd ztd-config
388
+
389
+ # 3. Fix compile errors (if any) in tests and specs
390
+ # Generated TestRowMap shapes may have changed
391
+
392
+ # 4. Re-run tests
393
+ npx vitest run
394
+
395
+ # 5. (Optional) Lint SQL files against the new schema
396
+ npx ztd lint src/sql/
397
+ ```
398
+
399
+ ### Common patterns
400
+
401
+ #### Add a column
402
+
403
+ 1. Add the column to your DDL file (`ztd/ddl/*.sql`)
404
+ 2. Run `npx ztd ztd-config` — the new column appears in `TestRowMap`
405
+ 3. Update fixtures in tests to include the new column (if required by NOT NULL)
406
+ 4. Run `npx vitest run`
407
+
408
+ #### Rename a column
409
+
410
+ 1. Rename the column in the DDL file
411
+ 2. Run `npx ztd ztd-config` — old name disappears, new name appears in `TestRowMap`
412
+ 3. Update all references: SQL files, `rowMapping` column maps, fixtures, and specs
413
+ 4. Run `npx vitest run` to catch any remaining references via compile errors
414
+
415
+ #### Add a new table
416
+
417
+ 1. Add the CREATE TABLE to a DDL file (new file or existing)
418
+ 2. Run `npx ztd ztd-config` — new table type appears in `TestRowMap`
419
+ 3. Write SQL queries and tests for the new table
420
+ 4. Run `npx vitest run`
421
+
422
+ #### Drop a column or table
423
+
424
+ 1. Remove from DDL
425
+ 2. Run `npx ztd ztd-config` — the removed type/column disappears
426
+ 3. Compile errors guide you to all affected code
427
+ 4. Remove or update references, then run `npx vitest run`
428
+
429
+ ### Troubleshooting
430
+
431
+ | Symptom | Cause | Fix |
432
+ | ----------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------------------- |
433
+ | `TestRowMap` not updated | Forgot to run `ztd-config` | Run `npx ztd ztd-config` |
434
+ | Compile errors after `ztd-config` | Schema shape changed | Update fixtures, specs, and column maps to match new shape |
435
+ | `ztd-config` fails to parse DDL | Unsupported SQL syntax | Simplify the DDL or check for dialect-specific constructs |
436
+ | Tests pass but SQL fails at runtime | DDL and an explicit target are out of sync | Run `npx ztd ddl diff --url <target>` to compare, then `npx ztd ddl pull --url <target>` to inspect again |
437
+
438
+ > **Tip:** Use `npx ztd ztd-config --watch` during development to regenerate types automatically when DDL files change.
439
+
440
+ ## QuerySpec Workflow
441
+
442
+ `ztd model-gen` is designed for SQL asset files under `src/sql/` and assumes **named parameters** (`:name`).
443
+
444
+ Important context:
445
+
446
+ * `:name` is an intentional project-level SQL asset convention, not native PostgreSQL syntax.
447
+ * Before inspection, `model-gen` binds named parameters to PostgreSQL placeholders such as `$1`, `$2` and runs a metadata-only wrapper query.
448
+ * `--probe-mode ztd` uses `ZTD_TEST_DATABASE_URL` for the ZTD-owned inspection path.
449
+ * `--probe-mode live` is the explicit-target inspection path. Pass `--url` or a complete `--db-*` flag set.
450
+ * `ztd-cli` does not read `DATABASE_URL` automatically for either path.
451
+ * `--probe-mode ztd` still rewrites the inspection through your DDL snapshot so physical app tables are not required. It uses `ztd.config.json` (`ddlDir`, `ddl.defaultSchema`, `ddl.searchPath`) unless you override the directory with `--ddl-dir`.
452
+
453
+ ```text
454
+ 1. Write SQL in src/sql/ using named parameters such as :customerId
455
+ 2. Prefer the ZTD-first command during the inner loop:
456
+ - `ztd model-gen src/sql/my_query.sql --probe-mode ztd --out src/catalog/specs/my-query.spec.ts`
457
+ - Or validate only: `ztd model-gen src/sql/my_query.sql --probe-mode ztd --out src/catalog/specs/my-query.spec.ts --dry-run`
458
+ 3. Use explicit-target inspection only when local DDL is not the source of truth:
459
+ - `ztd model-gen src/sql/my_query.sql --probe-mode live --out src/catalog/specs/my-query.spec.ts`
460
+ 4. Review the generated types, rowMapping key, nullability, and normalization
461
+ 5. Run ZTD tests to confirm the contract
462
+ ```
463
+
464
+ Example SQL asset:
465
+
466
+ ```sql
467
+ select
468
+ p.id as product_id,
469
+ p.name as product_name,
470
+ p.price as list_price
471
+ from public.products p
472
+ where p.id = :product_id
473
+ ```
474
+
475
+ Example generated scaffold excerpt:
476
+
477
+ ```ts
478
+ export const getProductSpec: QuerySpec<{ product_id: unknown }, GetProductRow> = {
479
+ id: 'product.getProduct',
480
+ sqlFile: 'product/get_product.sql',
481
+ params: { shape: 'named', example: { product_id: null } },
482
+ output: {
483
+ mapping: getProductMapping,
484
+ example: {
485
+ productId: 0,
486
+ productName: '',
487
+ listPrice: '',
488
+ },
489
+ },
490
+ };
491
+ ```
492
+
493
+ Notes:
494
+
495
+ * SQL asset files should use named parameters (`:name`). `model-gen` rewrites them to `$1`, `$2` before inspection. Positional placeholders are rejected by default (`--allow-positional` for legacy SQL).
496
+ * `--probe-mode ztd` (recommended) uses `ZTD_TEST_DATABASE_URL` and your DDL snapshot — no physical app tables needed. Unqualified names resolve via `ddl.defaultSchema` / `ddl.searchPath` in `ztd.config.json`.
497
+ * `--probe-mode live` (default for backward compatibility) is for schema objects not yet in local DDL, or when you want metadata from an explicit target.
498
+ * The generated file is a starting point. Review nullability, rowMapping key, and example values before committing.
499
+ * Run `--describe-output` to inspect the artifact contract without connecting to PostgreSQL. Use `--dry-run` to validate without writing files.
500
+
501
+ ### Optional-condition SQL
502
+
503
+ For optional filters, prefer keeping the condition in the SQL file itself (`where (:param is null or col = :param)`) before reaching for string-built query assembly. See [ztd-cli SSSQL Authoring](../../docs/guide/ztd-cli-sssql-authoring.md) and [What Is SSSQL?](../../docs/guide/sssql-overview.md) for the full pattern.
504
+
505
+ ## Telemetry Philosophy
506
+
507
+ `ztd-cli` telemetry is opt-in investigation tooling for dogfooding, debugging, and optimization. It is intentionally outside the default happy path, it must not become mandatory for published-package usage, and production embedding/export stays optional and off by default.
508
+
509
+ Read the full guidance in [ztd-cli Telemetry Philosophy](../../docs/guide/ztd-cli-telemetry-philosophy.md), [ztd-cli Telemetry Policy](../../docs/guide/ztd-cli-telemetry-policy.md), [ztd-cli Telemetry Export Modes](../../docs/guide/ztd-cli-telemetry-export-modes.md), [Telemetry Dogfooding Scenarios](../../docs/dogfooding/telemetry-dogfooding.md), [SQL Debug Recovery Dogfooding](../../docs/dogfooding/sql-debug-recovery.md), and [Test Documentation Dogfooding](../../docs/dogfooding/test-documentation.md).
510
+
511
+ ## Further Reading
512
+
513
+ * [Feature Index](../../docs/guide/feature-index.md) — at-a-glance list of easy-to-miss capabilities
514
+ * [SQL Tool Happy Paths](../../docs/guide/sql-tool-happy-paths.md) — choose between query plan, perf, query uses, and telemetry based on the problem shape
515
+ * [ztd-cli SSSQL Authoring](../../docs/guide/ztd-cli-sssql-authoring.md) — keep optional-condition requests on the SQL-first path
516
+ * [Local-Source Dogfooding](../../docs/guide/ztd-local-source-dogfooding.md) — local-source quick start, workspace drift, and import mismatches
517
+ * [Postgres Pitfalls](../../docs/guide/postgres-pitfalls.md) — common Postgres-specific surprises
518
+ * [Spec-Change Scenarios](../../docs/guide/spec-change-scenarios.md) — condensed digest of common schema changes
519
+ * [Mapping vs Validation Pipeline](../../docs/recipes/mapping-vs-validation.md) — avoid coerce/validator conflicts
520
+
521
+ ## Glossary
522
+
523
+ | Term | Description |
524
+ | -------------- | ------------------------------------------------------------------------------- |
525
+ | **DDL** | SQL files defining schema objects (tables, enums, indexes) |
526
+ | **TestRowMap** | Generated TypeScript types describing test rows for each table |
527
+ | **Fixture** | Static rows used by the driver to answer queries deterministically |
528
+ | **Driver** | Package connecting to your DB engine and running the rewrite + fixture pipeline |
529
+
530
+ ## License
531
+
532
+ MIT