@rawsql-ts/ztd-cli 0.15.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.
- package/README.md +38 -25
- package/dist/commands/init.d.ts +13 -0
- package/dist/commands/init.js +372 -118
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/lint.d.ts +4 -4
- package/dist/commands/lint.js +60 -40
- package/dist/commands/lint.js.map +1 -1
- package/dist/commands/ztdConfig.d.ts +2 -2
- package/dist/commands/ztdConfig.js +26 -12
- package/dist/commands/ztdConfig.js.map +1 -1
- package/dist/utils/optionalDependencies.d.ts +35 -0
- package/dist/utils/optionalDependencies.js +96 -0
- package/dist/utils/optionalDependencies.js.map +1 -0
- package/package.json +18 -10
- package/templates/AGENTS.md +36 -296
- package/templates/README.md +12 -237
- package/templates/dist/drivers/pg-testkit/src/driver/PgTestkitClient.d.ts +38 -0
- package/templates/dist/drivers/pg-testkit/src/driver/PgTestkitClient.js +117 -0
- package/templates/dist/drivers/pg-testkit/src/driver/PgTestkitClient.js.map +1 -0
- package/templates/dist/drivers/pg-testkit/src/driver/createPgTestkitPool.d.ts +4 -0
- package/templates/dist/drivers/pg-testkit/src/driver/createPgTestkitPool.js +71 -0
- package/templates/dist/drivers/pg-testkit/src/driver/createPgTestkitPool.js.map +1 -0
- package/templates/dist/drivers/pg-testkit/src/index.d.ts +5 -0
- package/templates/dist/drivers/pg-testkit/src/index.js +11 -0
- package/templates/dist/drivers/pg-testkit/src/index.js.map +1 -0
- package/templates/dist/drivers/pg-testkit/src/proxy/wrapPgClient.d.ts +3 -0
- package/templates/dist/drivers/pg-testkit/src/proxy/wrapPgClient.js +79 -0
- package/templates/dist/drivers/pg-testkit/src/proxy/wrapPgClient.js.map +1 -0
- package/templates/dist/drivers/pg-testkit/src/types.d.ts +69 -0
- package/templates/dist/drivers/pg-testkit/src/types.js +3 -0
- package/templates/dist/drivers/pg-testkit/src/types.js.map +1 -0
- package/templates/dist/drivers/pg-testkit/src/utils/fixtureState.d.ts +15 -0
- package/templates/dist/drivers/pg-testkit/src/utils/fixtureState.js +34 -0
- package/templates/dist/drivers/pg-testkit/src/utils/fixtureState.js.map +1 -0
- package/templates/dist/drivers/pg-testkit/src/utils/fixtureValidation.d.ts +12 -0
- package/templates/dist/drivers/pg-testkit/src/utils/fixtureValidation.js +53 -0
- package/templates/dist/drivers/pg-testkit/src/utils/fixtureValidation.js.map +1 -0
- package/templates/dist/mapper-core/src/index.d.ts +160 -0
- package/templates/dist/mapper-core/src/index.js +637 -0
- package/templates/dist/mapper-core/src/index.js.map +1 -0
- package/templates/dist/testkit-core/src/errors/index.d.ts +49 -0
- package/templates/dist/testkit-core/src/errors/index.js +111 -0
- package/templates/dist/testkit-core/src/errors/index.js.map +1 -0
- package/templates/dist/testkit-core/src/fixtures/ColumnAffinity.d.ts +5 -0
- package/templates/dist/testkit-core/src/fixtures/ColumnAffinity.js +29 -0
- package/templates/dist/testkit-core/src/fixtures/ColumnAffinity.js.map +1 -0
- package/templates/dist/testkit-core/src/fixtures/DdlFixtureLoader.d.ts +37 -0
- package/templates/dist/testkit-core/src/fixtures/DdlFixtureLoader.js +182 -0
- package/templates/dist/testkit-core/src/fixtures/DdlFixtureLoader.js.map +1 -0
- package/templates/dist/testkit-core/src/fixtures/FixtureProvider.d.ts +20 -0
- package/templates/dist/testkit-core/src/fixtures/FixtureProvider.js +121 -0
- package/templates/dist/testkit-core/src/fixtures/FixtureProvider.js.map +1 -0
- package/templates/dist/testkit-core/src/fixtures/FixtureStore.d.ts +51 -0
- package/templates/dist/testkit-core/src/fixtures/FixtureStore.js +199 -0
- package/templates/dist/testkit-core/src/fixtures/FixtureStore.js.map +1 -0
- package/templates/dist/testkit-core/src/fixtures/TableDefinitionSchemaRegistry.d.ts +10 -0
- package/templates/dist/testkit-core/src/fixtures/TableDefinitionSchemaRegistry.js +28 -0
- package/templates/dist/testkit-core/src/fixtures/TableDefinitionSchemaRegistry.js.map +1 -0
- package/templates/dist/testkit-core/src/fixtures/TableNameResolver.d.ts +18 -0
- package/templates/dist/testkit-core/src/fixtures/TableNameResolver.js +80 -0
- package/templates/dist/testkit-core/src/fixtures/TableNameResolver.js.map +1 -0
- package/templates/dist/testkit-core/src/fixtures/ddlLint.d.ts +59 -0
- package/templates/dist/testkit-core/src/fixtures/ddlLint.js +489 -0
- package/templates/dist/testkit-core/src/fixtures/ddlLint.js.map +1 -0
- package/templates/dist/testkit-core/src/fixtures/naming.d.ts +1 -0
- package/templates/dist/testkit-core/src/fixtures/naming.js +6 -0
- package/templates/dist/testkit-core/src/fixtures/naming.js.map +1 -0
- package/templates/dist/testkit-core/src/index.d.ts +17 -0
- package/templates/dist/testkit-core/src/index.js +47 -0
- package/templates/dist/testkit-core/src/index.js.map +1 -0
- package/templates/dist/testkit-core/src/logger/NoopLogger.d.ts +8 -0
- package/templates/dist/testkit-core/src/logger/NoopLogger.js +16 -0
- package/templates/dist/testkit-core/src/logger/NoopLogger.js.map +1 -0
- package/templates/dist/testkit-core/src/provider/TestkitProvider.d.ts +57 -0
- package/templates/dist/testkit-core/src/provider/TestkitProvider.js +149 -0
- package/templates/dist/testkit-core/src/provider/TestkitProvider.js.map +1 -0
- package/templates/dist/testkit-core/src/rewriter/ResultSelectRewriter.d.ts +43 -0
- package/templates/dist/testkit-core/src/rewriter/ResultSelectRewriter.js +473 -0
- package/templates/dist/testkit-core/src/rewriter/ResultSelectRewriter.js.map +1 -0
- package/templates/dist/testkit-core/src/rewriter/SelectAnalyzer.d.ts +9 -0
- package/templates/dist/testkit-core/src/rewriter/SelectAnalyzer.js +38 -0
- package/templates/dist/testkit-core/src/rewriter/SelectAnalyzer.js.map +1 -0
- package/templates/dist/testkit-core/src/rewriter/SelectFixtureRewriter.d.ts +42 -0
- package/templates/dist/testkit-core/src/rewriter/SelectFixtureRewriter.js +298 -0
- package/templates/dist/testkit-core/src/rewriter/SelectFixtureRewriter.js.map +1 -0
- package/templates/dist/testkit-core/src/sql/SqliteValuesBuilder.d.ts +12 -0
- package/templates/dist/testkit-core/src/sql/SqliteValuesBuilder.js +63 -0
- package/templates/dist/testkit-core/src/sql/SqliteValuesBuilder.js.map +1 -0
- package/templates/dist/testkit-core/src/types/index.d.ts +69 -0
- package/templates/dist/testkit-core/src/types/index.js +3 -0
- package/templates/dist/testkit-core/src/types/index.js.map +1 -0
- package/templates/dist/testkit-core/src/utils/queryHelpers.d.ts +28 -0
- package/templates/dist/testkit-core/src/utils/queryHelpers.js +81 -0
- package/templates/dist/testkit-core/src/utils/queryHelpers.js.map +1 -0
- package/templates/dist/writer-core/src/index.d.ts +34 -0
- package/templates/dist/writer-core/src/index.js +115 -0
- package/templates/dist/writer-core/src/index.js.map +1 -0
- package/templates/dist/ztd-cli/templates/src/db/sql-client.d.ts +20 -0
- package/templates/dist/ztd-cli/templates/src/db/sql-client.js +3 -0
- package/templates/dist/ztd-cli/templates/src/db/sql-client.js.map +1 -0
- package/templates/dist/ztd-cli/templates/src/db/sql-client.ts +24 -0
- package/templates/dist/ztd-cli/templates/src/repositories/user-accounts.d.ts +36 -0
- package/templates/dist/ztd-cli/templates/src/repositories/user-accounts.js +85 -0
- package/templates/dist/ztd-cli/templates/src/repositories/user-accounts.js.map +1 -0
- package/templates/dist/ztd-cli/templates/tests/generated/ztd-row-map.generated.d.ts +20 -0
- package/templates/dist/ztd-cli/templates/tests/generated/ztd-row-map.generated.js +33 -0
- package/templates/dist/ztd-cli/templates/tests/generated/ztd-row-map.generated.js.map +1 -0
- package/templates/dist/ztd-cli/templates/tests/support/global-setup.d.ts +10 -0
- package/templates/dist/ztd-cli/templates/tests/support/global-setup.js +29 -0
- package/templates/dist/ztd-cli/templates/tests/support/global-setup.js.map +1 -0
- package/templates/dist/ztd-cli/templates/tests/support/testkit-client.d.ts +66 -0
- package/templates/dist/ztd-cli/templates/tests/support/testkit-client.js +552 -0
- package/templates/dist/ztd-cli/templates/tests/support/testkit-client.js.map +1 -0
- package/templates/dist/ztd-cli/templates/tests/user-profiles.test.d.ts +1 -0
- package/templates/dist/ztd-cli/templates/tests/user-profiles.test.js +82 -0
- package/templates/dist/ztd-cli/templates/tests/user-profiles.test.js.map +1 -0
- package/templates/dist/ztd-cli/templates/tests/writer-constraints.test.d.ts +1 -0
- package/templates/dist/ztd-cli/templates/tests/writer-constraints.test.js +29 -0
- package/templates/dist/ztd-cli/templates/tests/writer-constraints.test.js.map +1 -0
- package/templates/dist/ztd-cli/templates/tests/ztd-layout.generated.d.ts +7 -0
- package/templates/dist/ztd-cli/templates/tests/ztd-layout.generated.js +10 -0
- package/templates/dist/ztd-cli/templates/tests/ztd-layout.generated.js.map +1 -0
- package/templates/src/AGENTS.md +26 -0
- package/templates/src/catalog/AGENTS.md +37 -0
- package/templates/src/catalog/runtime/AGENTS.md +75 -0
- package/templates/src/catalog/runtime/_coercions.ts +1 -0
- package/templates/src/catalog/runtime/_smoke.runtime.ts +21 -0
- package/templates/src/catalog/specs/AGENTS.md +48 -0
- package/templates/src/catalog/specs/_smoke.spec.arktype.ts +21 -0
- package/templates/src/catalog/specs/_smoke.spec.zod.ts +20 -0
- package/templates/src/db/sql-client.ts +5 -5
- package/templates/src/jobs/AGENTS.md +26 -0
- package/templates/src/jobs/README.md +3 -0
- package/templates/src/repositories/AGENTS.md +118 -0
- package/templates/src/repositories/tables/AGENTS.md +94 -0
- package/templates/src/repositories/tables/README.md +3 -0
- package/templates/src/repositories/views/AGENTS.md +25 -0
- package/templates/src/repositories/views/README.md +3 -0
- package/templates/src/sql/AGENTS.md +77 -0
- package/templates/src/sql/README.md +6 -0
- package/templates/tests/AGENTS.md +43 -129
- package/templates/tests/generated/AGENTS.md +16 -0
- package/templates/tests/smoke.test.ts +5 -0
- package/templates/tests/smoke.validation.test.ts +34 -0
- package/templates/tests/support/AGENTS.md +26 -0
- package/templates/tests/support/global-setup.ts +8 -23
- package/templates/tests/support/testkit-client.ts +13 -741
- package/templates/tests/ztd-layout.generated.ts +0 -2
- package/templates/tsconfig.json +9 -3
- package/templates/ztd/AGENTS.md +11 -142
- package/templates/ztd/README.md +4 -82
- package/templates/ztd/ddl/AGENTS.md +34 -0
- package/templates/ztd/ddl/demo.sql +74 -0
package/dist/commands/init.js
CHANGED
|
@@ -5,6 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.createConsolePrompter = createConsolePrompter;
|
|
7
7
|
exports.runInitCommand = runInitCommand;
|
|
8
|
+
exports.normalizeSchemaName = normalizeSchemaName;
|
|
9
|
+
exports.sanitizeSchemaFileName = sanitizeSchemaFileName;
|
|
8
10
|
exports.registerInitCommand = registerInitCommand;
|
|
9
11
|
const node_child_process_1 = require("node:child_process");
|
|
10
12
|
const node_fs_1 = require("node:fs");
|
|
@@ -15,7 +17,6 @@ const agents_1 = require("../utils/agents");
|
|
|
15
17
|
const ztdProjectConfig_1 = require("../utils/ztdProjectConfig");
|
|
16
18
|
const ztdConfig_1 = require("./ztdConfig");
|
|
17
19
|
const pull_1 = require("./pull");
|
|
18
|
-
const options_1 = require("./options");
|
|
19
20
|
/**
|
|
20
21
|
* Create a readline-backed prompter that reads from stdin/stdout.
|
|
21
22
|
*/
|
|
@@ -28,6 +29,11 @@ function createConsolePrompter() {
|
|
|
28
29
|
async function requestLine(question) {
|
|
29
30
|
return (await rl.question(question)).trim();
|
|
30
31
|
}
|
|
32
|
+
async function requestLineWithDefault(question, defaultValue, example) {
|
|
33
|
+
const prompt = `${question}${example ? ` (${example})` : ''} [default: ${defaultValue}]: `;
|
|
34
|
+
const answer = await requestLine(prompt);
|
|
35
|
+
return answer.length > 0 ? answer : defaultValue;
|
|
36
|
+
}
|
|
31
37
|
return {
|
|
32
38
|
async selectChoice(question, choices) {
|
|
33
39
|
while (true) {
|
|
@@ -52,6 +58,9 @@ function createConsolePrompter() {
|
|
|
52
58
|
console.log('This value cannot be empty.');
|
|
53
59
|
}
|
|
54
60
|
},
|
|
61
|
+
async promptInputWithDefault(question, defaultValue, example) {
|
|
62
|
+
return requestLineWithDefault(question, defaultValue, example);
|
|
63
|
+
},
|
|
55
64
|
async confirm(question) {
|
|
56
65
|
while (true) {
|
|
57
66
|
const answer = (await requestLine(`${question} (y/N): `)).toLowerCase();
|
|
@@ -72,24 +81,64 @@ function createConsolePrompter() {
|
|
|
72
81
|
}
|
|
73
82
|
};
|
|
74
83
|
}
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
84
|
+
const MANDATORY_TESTKIT_DEPENDENCIES = {
|
|
85
|
+
'@rawsql-ts/adapter-node-pg': '^0.15.1',
|
|
86
|
+
'@rawsql-ts/testkit-postgres': '^0.15.1'
|
|
87
|
+
};
|
|
88
|
+
const SQL_CONTRACT_DEPENDENCY = {
|
|
89
|
+
'@rawsql-ts/sql-contract': '^0.1.0'
|
|
90
|
+
};
|
|
91
|
+
const ZOD_DEPENDENCY = {
|
|
92
|
+
zod: '^4.3.6'
|
|
93
|
+
};
|
|
94
|
+
const ARKTYPE_DEPENDENCY = {
|
|
95
|
+
arktype: '^2.1.29'
|
|
96
|
+
};
|
|
97
|
+
async function gatherOptionalFeatures(prompter, _dependencies) {
|
|
98
|
+
const validatorChoice = await prompter.selectChoice('Runtime DTO validation is required for ZTD tests. Which validator backend should we install?', ['Zod (zod, recommended)', 'ArkType (arktype)']);
|
|
99
|
+
const validator = validatorChoice === 0 ? 'zod' : 'arktype';
|
|
100
|
+
return { validator };
|
|
101
|
+
}
|
|
80
102
|
const README_TEMPLATE = 'README.md';
|
|
81
|
-
const TESTS_CONFIG_TEMPLATE = 'tests/ztd-layout.generated.ts';
|
|
82
103
|
const TESTS_AGENTS_TEMPLATE = 'tests/AGENTS.md';
|
|
104
|
+
const TESTS_SUPPORT_AGENTS_TEMPLATE = 'tests/support/AGENTS.md';
|
|
105
|
+
const TESTS_GENERATED_AGENTS_TEMPLATE = 'tests/generated/AGENTS.md';
|
|
106
|
+
const SMOKE_SPEC_ZOD_TEMPLATE = 'src/catalog/specs/_smoke.spec.zod.ts';
|
|
107
|
+
const SMOKE_SPEC_ARKTYPE_TEMPLATE = 'src/catalog/specs/_smoke.spec.arktype.ts';
|
|
108
|
+
const SMOKE_COERCIONS_TEMPLATE = 'src/catalog/runtime/_coercions.ts';
|
|
109
|
+
const SMOKE_RUNTIME_TEMPLATE = 'src/catalog/runtime/_smoke.runtime.ts';
|
|
110
|
+
const SMOKE_VALIDATION_TEST_TEMPLATE = 'tests/smoke.validation.test.ts';
|
|
111
|
+
const TESTS_SMOKE_TEMPLATE = 'tests/smoke.test.ts';
|
|
83
112
|
const TESTKIT_CLIENT_TEMPLATE = 'tests/support/testkit-client.ts';
|
|
84
113
|
const GLOBAL_SETUP_TEMPLATE = 'tests/support/global-setup.ts';
|
|
85
114
|
const VITEST_CONFIG_TEMPLATE = 'vitest.config.ts';
|
|
115
|
+
const TSCONFIG_TEMPLATE = 'tsconfig.json';
|
|
86
116
|
const SQL_CLIENT_TEMPLATE = 'src/db/sql-client.ts';
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
117
|
+
const SQL_README_TEMPLATE = 'src/sql/README.md';
|
|
118
|
+
const VIEWS_REPO_README_TEMPLATE = 'src/repositories/views/README.md';
|
|
119
|
+
const TABLES_REPO_README_TEMPLATE = 'src/repositories/tables/README.md';
|
|
120
|
+
const JOBS_README_TEMPLATE = 'src/jobs/README.md';
|
|
121
|
+
const SRC_AGENTS_TEMPLATE = 'src/AGENTS.md';
|
|
122
|
+
const SRC_CATALOG_AGENTS_TEMPLATE = 'src/catalog/AGENTS.md';
|
|
123
|
+
const SRC_CATALOG_RUNTIME_AGENTS_TEMPLATE = 'src/catalog/runtime/AGENTS.md';
|
|
124
|
+
const SRC_CATALOG_SPECS_AGENTS_TEMPLATE = 'src/catalog/specs/AGENTS.md';
|
|
125
|
+
const SRC_SQL_AGENTS_TEMPLATE = 'src/sql/AGENTS.md';
|
|
126
|
+
const SRC_REPOS_AGENTS_TEMPLATE = 'src/repositories/AGENTS.md';
|
|
127
|
+
const VIEWS_REPO_AGENTS_TEMPLATE = 'src/repositories/views/AGENTS.md';
|
|
128
|
+
const TABLES_REPO_AGENTS_TEMPLATE = 'src/repositories/tables/AGENTS.md';
|
|
129
|
+
const JOBS_AGENTS_TEMPLATE = 'src/jobs/AGENTS.md';
|
|
130
|
+
const ZTD_AGENTS_TEMPLATE = 'ztd/AGENTS.md';
|
|
131
|
+
const ZTD_README_TEMPLATE = 'ztd/README.md';
|
|
132
|
+
const ZTD_DDL_AGENTS_TEMPLATE = 'ztd/ddl/AGENTS.md';
|
|
133
|
+
const ZTD_DDL_DEMO_TEMPLATE = 'ztd/ddl/demo.sql';
|
|
134
|
+
const EMPTY_SCHEMA_COMMENT = (schemaName) => [
|
|
135
|
+
`-- DDL for schema "${schemaName}".`,
|
|
136
|
+
'-- Add CREATE TABLE statements here.',
|
|
137
|
+
''
|
|
138
|
+
].join('\n');
|
|
139
|
+
const DEMO_SCHEMA_TEMPLATE = (_schemaName) => {
|
|
140
|
+
return loadTemplate(ZTD_DDL_DEMO_TEMPLATE);
|
|
141
|
+
};
|
|
93
142
|
const AGENTS_FILE_CANDIDATES = ['AGENTS.md', 'AGENTS_ztd.md'];
|
|
94
143
|
const APP_INTERFACE_SECTION_MARKER = '## Application Interface Guidance';
|
|
95
144
|
const APP_INTERFACE_SECTION = `---
|
|
@@ -184,26 +233,67 @@ const DEFAULT_DEPENDENCIES = {
|
|
|
184
233
|
* Run the interactive `ztd init` workflow and return the resulting summary.
|
|
185
234
|
*/
|
|
186
235
|
async function runInitCommand(prompter, options) {
|
|
187
|
-
var _a, _b;
|
|
236
|
+
var _a, _b, _c, _d;
|
|
188
237
|
const rootDir = (_a = options === null || options === void 0 ? void 0 : options.rootDir) !== null && _a !== void 0 ? _a : process.cwd();
|
|
189
238
|
const dependencies = {
|
|
190
239
|
...DEFAULT_DEPENDENCIES,
|
|
191
240
|
...((_b = options === null || options === void 0 ? void 0 : options.dependencies) !== null && _b !== void 0 ? _b : {})
|
|
192
241
|
};
|
|
193
|
-
const
|
|
242
|
+
const overwritePolicy = {
|
|
243
|
+
force: (_c = options === null || options === void 0 ? void 0 : options.forceOverwrite) !== null && _c !== void 0 ? _c : false,
|
|
244
|
+
nonInteractive: (_d = options === null || options === void 0 ? void 0 : options.nonInteractive) !== null && _d !== void 0 ? _d : false
|
|
245
|
+
};
|
|
246
|
+
if (options === null || options === void 0 ? void 0 : options.withAppInterface) {
|
|
247
|
+
// Provide the documentation-only path before triggering any scaffolding work.
|
|
248
|
+
const summary = await appendAppInterfaceGuidance(rootDir, dependencies);
|
|
249
|
+
dependencies.log(`Appended application interface guidance to ${summary.relativePath}.`);
|
|
250
|
+
return {
|
|
251
|
+
summary: `App interface guidance appended to ${summary.relativePath}.`,
|
|
252
|
+
files: [summary]
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
// Ask how the user prefers to populate the initial schema.
|
|
256
|
+
const workflowChoice = await prompter.selectChoice('How do you want to start your database workflow?', [
|
|
257
|
+
'Pull schema from Postgres (pg_dump)',
|
|
258
|
+
'Create empty scaffold (I will write DDL)',
|
|
259
|
+
'Create scaffold with demo DDL (no app code)'
|
|
260
|
+
]);
|
|
261
|
+
const workflow = workflowChoice === 0 ? 'pg_dump' : workflowChoice === 1 ? 'empty' : 'demo';
|
|
262
|
+
const schemaName = normalizeSchemaName(ztdProjectConfig_1.DEFAULT_ZTD_CONFIG.ddl.defaultSchema);
|
|
263
|
+
const schemaFileName = `${sanitizeSchemaFileName(schemaName)}.sql`;
|
|
194
264
|
const absolutePaths = {
|
|
195
265
|
schema: node_path_1.default.join(rootDir, ztdProjectConfig_1.DEFAULT_ZTD_CONFIG.ddlDir, schemaFileName),
|
|
196
266
|
config: node_path_1.default.join(rootDir, 'ztd.config.json'),
|
|
197
|
-
|
|
198
|
-
|
|
267
|
+
smokeSpec: node_path_1.default.join(rootDir, 'src', 'catalog', 'specs', '_smoke.spec.ts'),
|
|
268
|
+
smokeCoercions: node_path_1.default.join(rootDir, 'src', 'catalog', 'runtime', '_coercions.ts'),
|
|
269
|
+
smokeRuntime: node_path_1.default.join(rootDir, 'src', 'catalog', 'runtime', '_smoke.runtime.ts'),
|
|
270
|
+
smokeValidationTest: node_path_1.default.join(rootDir, ztdProjectConfig_1.DEFAULT_ZTD_CONFIG.testsDir, 'smoke.validation.test.ts'),
|
|
199
271
|
testsAgents: node_path_1.default.join(rootDir, ztdProjectConfig_1.DEFAULT_ZTD_CONFIG.testsDir, 'AGENTS.md'),
|
|
272
|
+
testsSupportAgents: node_path_1.default.join(rootDir, ztdProjectConfig_1.DEFAULT_ZTD_CONFIG.testsDir, 'support', 'AGENTS.md'),
|
|
273
|
+
testsGeneratedAgents: node_path_1.default.join(rootDir, ztdProjectConfig_1.DEFAULT_ZTD_CONFIG.testsDir, 'generated', 'AGENTS.md'),
|
|
274
|
+
testsSmoke: node_path_1.default.join(rootDir, ztdProjectConfig_1.DEFAULT_ZTD_CONFIG.testsDir, 'smoke.test.ts'),
|
|
200
275
|
readme: node_path_1.default.join(rootDir, 'README.md'),
|
|
276
|
+
sqlReadme: node_path_1.default.join(rootDir, 'src', 'sql', 'README.md'),
|
|
277
|
+
viewsRepoReadme: node_path_1.default.join(rootDir, 'src', 'repositories', 'views', 'README.md'),
|
|
278
|
+
tablesRepoReadme: node_path_1.default.join(rootDir, 'src', 'repositories', 'tables', 'README.md'),
|
|
279
|
+
jobsReadme: node_path_1.default.join(rootDir, 'src', 'jobs', 'README.md'),
|
|
280
|
+
srcAgents: node_path_1.default.join(rootDir, 'src', 'AGENTS.md'),
|
|
281
|
+
srcCatalogAgents: node_path_1.default.join(rootDir, 'src', 'catalog', 'AGENTS.md'),
|
|
282
|
+
srcCatalogRuntimeAgents: node_path_1.default.join(rootDir, 'src', 'catalog', 'runtime', 'AGENTS.md'),
|
|
283
|
+
srcCatalogSpecsAgents: node_path_1.default.join(rootDir, 'src', 'catalog', 'specs', 'AGENTS.md'),
|
|
284
|
+
srcSqlAgents: node_path_1.default.join(rootDir, 'src', 'sql', 'AGENTS.md'),
|
|
285
|
+
srcReposAgents: node_path_1.default.join(rootDir, 'src', 'repositories', 'AGENTS.md'),
|
|
286
|
+
viewsRepoAgents: node_path_1.default.join(rootDir, 'src', 'repositories', 'views', 'AGENTS.md'),
|
|
287
|
+
tablesRepoAgents: node_path_1.default.join(rootDir, 'src', 'repositories', 'tables', 'AGENTS.md'),
|
|
288
|
+
jobsAgents: node_path_1.default.join(rootDir, 'src', 'jobs', 'AGENTS.md'),
|
|
201
289
|
sqlClient: node_path_1.default.join(rootDir, 'src', 'db', 'sql-client.ts'),
|
|
202
290
|
testkitClient: node_path_1.default.join(rootDir, ztdProjectConfig_1.DEFAULT_ZTD_CONFIG.testsDir, 'support', 'testkit-client.ts'),
|
|
203
291
|
globalSetup: node_path_1.default.join(rootDir, ztdProjectConfig_1.DEFAULT_ZTD_CONFIG.testsDir, 'support', 'global-setup.ts'),
|
|
204
292
|
vitestConfig: node_path_1.default.join(rootDir, 'vitest.config.ts'),
|
|
293
|
+
tsconfig: node_path_1.default.join(rootDir, 'tsconfig.json'),
|
|
205
294
|
ztdDocsAgent: node_path_1.default.join(rootDir, 'ztd', 'AGENTS.md'),
|
|
206
295
|
ztdDocsReadme: node_path_1.default.join(rootDir, 'ztd', 'README.md'),
|
|
296
|
+
ztdDdlAgents: node_path_1.default.join(rootDir, 'ztd', 'ddl', 'AGENTS.md'),
|
|
207
297
|
agents: node_path_1.default.join(rootDir, 'AGENTS.md'),
|
|
208
298
|
gitignore: node_path_1.default.join(rootDir, '.gitignore'),
|
|
209
299
|
editorconfig: node_path_1.default.join(rootDir, '.editorconfig'),
|
|
@@ -213,116 +303,171 @@ async function runInitCommand(prompter, options) {
|
|
|
213
303
|
};
|
|
214
304
|
const relativePath = (key) => node_path_1.default.relative(rootDir, absolutePaths[key]).replace(/\\/g, '/') || absolutePaths[key];
|
|
215
305
|
const summaries = {};
|
|
216
|
-
if (options === null || options === void 0 ? void 0 : options.withAppInterface) {
|
|
217
|
-
// Provide the documentation-only path before triggering any scaffolding work.
|
|
218
|
-
const summary = await appendAppInterfaceGuidance(rootDir, dependencies);
|
|
219
|
-
dependencies.log(`Appended application interface guidance to ${summary.relativePath}.`);
|
|
220
|
-
return {
|
|
221
|
-
summary: `App interface guidance appended to ${summary.relativePath}.`,
|
|
222
|
-
files: [summary]
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
306
|
// Ask how the user prefers to populate the initial schema.
|
|
226
|
-
|
|
227
|
-
if (workflow === 0) {
|
|
307
|
+
if (workflow === 'pg_dump') {
|
|
228
308
|
// Database-first path: pull the schema before writing any DDL files.
|
|
229
309
|
if (!dependencies.checkPgDump()) {
|
|
230
310
|
throw new Error('Unable to find pg_dump. Install Postgres or set PG_DUMP_PATH before running ztd init.');
|
|
231
311
|
}
|
|
232
312
|
const connectionString = await prompter.promptInput('Enter the Postgres connection string for your database', 'postgres://user:pass@host:5432/db');
|
|
233
|
-
const schemaSummary = await writeFileWithConsent(absolutePaths.schema, relativePath('schema'), dependencies, prompter, async () => {
|
|
313
|
+
const schemaSummary = await writeFileWithConsent(absolutePaths.schema, relativePath('schema'), dependencies, prompter, overwritePolicy, async () => {
|
|
234
314
|
dependencies.ensureDirectory(node_path_1.default.dirname(absolutePaths.schema));
|
|
235
315
|
await dependencies.runPullSchema({
|
|
236
316
|
url: connectionString,
|
|
237
|
-
out: node_path_1.default.dirname(absolutePaths.schema)
|
|
317
|
+
out: node_path_1.default.dirname(absolutePaths.schema),
|
|
318
|
+
schemas: [schemaName]
|
|
238
319
|
});
|
|
239
320
|
});
|
|
240
321
|
summaries.schema = schemaSummary;
|
|
241
322
|
}
|
|
242
|
-
else {
|
|
323
|
+
else if (workflow === 'empty') {
|
|
243
324
|
// Manual path: seed the DDL directory with a starter schema so ztd-config can run.
|
|
244
|
-
const schemaSummary = await writeFileWithConsent(absolutePaths.schema, relativePath('schema'), dependencies, prompter, async () => {
|
|
325
|
+
const schemaSummary = await writeFileWithConsent(absolutePaths.schema, relativePath('schema'), dependencies, prompter, overwritePolicy, async () => {
|
|
245
326
|
dependencies.ensureDirectory(node_path_1.default.dirname(absolutePaths.schema));
|
|
246
|
-
dependencies.writeFile(absolutePaths.schema,
|
|
327
|
+
dependencies.writeFile(absolutePaths.schema, EMPTY_SCHEMA_COMMENT(schemaName));
|
|
328
|
+
});
|
|
329
|
+
summaries.schema = schemaSummary;
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
const schemaSummary = await writeFileWithConsent(absolutePaths.schema, relativePath('schema'), dependencies, prompter, overwritePolicy, async () => {
|
|
333
|
+
dependencies.ensureDirectory(node_path_1.default.dirname(absolutePaths.schema));
|
|
334
|
+
dependencies.writeFile(absolutePaths.schema, DEMO_SCHEMA_TEMPLATE(schemaName));
|
|
247
335
|
});
|
|
248
336
|
summaries.schema = schemaSummary;
|
|
249
337
|
}
|
|
250
338
|
// Seed the ztd.config.json defaults so downstream tooling knows where ddl/tests live.
|
|
251
|
-
const configSummary = await writeFileWithConsent(absolutePaths.config, relativePath('config'), dependencies, prompter, () => {
|
|
252
|
-
(0, ztdProjectConfig_1.writeZtdProjectConfig)(rootDir
|
|
339
|
+
const configSummary = await writeFileWithConsent(absolutePaths.config, relativePath('config'), dependencies, prompter, overwritePolicy, () => {
|
|
340
|
+
(0, ztdProjectConfig_1.writeZtdProjectConfig)(rootDir, {
|
|
341
|
+
ddl: {
|
|
342
|
+
defaultSchema: schemaName,
|
|
343
|
+
searchPath: [schemaName]
|
|
344
|
+
}
|
|
345
|
+
});
|
|
253
346
|
});
|
|
254
347
|
summaries.config = configSummary;
|
|
255
|
-
const
|
|
256
|
-
const ztdConfigTarget = await confirmOverwriteIfExists(absolutePaths.ztdConfig, relativePath('ztdConfig'), dependencies, prompter);
|
|
257
|
-
if (ztdConfigTarget.write) {
|
|
258
|
-
// Regenerate tests/generated/ztd-row-map.generated.ts so TestRowMap reflects the DDL snapshot.
|
|
259
|
-
dependencies.ensureDirectory(node_path_1.default.dirname(absolutePaths.ztdConfig));
|
|
260
|
-
await dependencies.runGenerateZtdConfig({
|
|
261
|
-
directories: [node_path_1.default.resolve(node_path_1.default.dirname(absolutePaths.schema))],
|
|
262
|
-
extensions: options_1.DEFAULT_EXTENSIONS,
|
|
263
|
-
out: absolutePaths.ztdConfig,
|
|
264
|
-
defaultSchema: projectConfig.ddl.defaultSchema,
|
|
265
|
-
searchPath: projectConfig.ddl.searchPath,
|
|
266
|
-
ddlLint: projectConfig.ddlLint
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
else {
|
|
270
|
-
dependencies.log('Skipping ZTD config generation; existing tests/generated/ztd-row-map.generated.ts preserved.');
|
|
271
|
-
}
|
|
272
|
-
summaries.ztdConfig = {
|
|
273
|
-
relativePath: relativePath('ztdConfig'),
|
|
274
|
-
outcome: ztdConfigTarget.existed
|
|
275
|
-
? ztdConfigTarget.write
|
|
276
|
-
? 'overwritten'
|
|
277
|
-
: 'unchanged'
|
|
278
|
-
: 'created'
|
|
279
|
-
};
|
|
348
|
+
const optionalFeatures = await gatherOptionalFeatures(prompter, dependencies);
|
|
280
349
|
// Emit supporting documentation that describes the workflow for contributors.
|
|
281
|
-
const readmeSummary = await writeTemplateFile(rootDir, absolutePaths.readme, relativePath('readme'), README_TEMPLATE, dependencies, prompter, true);
|
|
350
|
+
const readmeSummary = await writeTemplateFile(rootDir, absolutePaths.readme, relativePath('readme'), README_TEMPLATE, dependencies, prompter, overwritePolicy, true);
|
|
282
351
|
if (readmeSummary) {
|
|
283
352
|
summaries.readme = readmeSummary;
|
|
284
353
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
354
|
+
const ztdDocsAgentSummary = await writeTemplateFile(rootDir, absolutePaths.ztdDocsAgent, relativePath('ztdDocsAgent'), ZTD_AGENTS_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
355
|
+
if (ztdDocsAgentSummary) {
|
|
356
|
+
summaries.ztdDocsAgent = ztdDocsAgentSummary;
|
|
357
|
+
}
|
|
358
|
+
const ztdDocsReadmeSummary = await writeTemplateFile(rootDir, absolutePaths.ztdDocsReadme, relativePath('ztdDocsReadme'), ZTD_README_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
359
|
+
if (ztdDocsReadmeSummary) {
|
|
360
|
+
summaries.ztdDocsReadme = ztdDocsReadmeSummary;
|
|
361
|
+
}
|
|
362
|
+
const ztdDdlAgentsSummary = await writeTemplateFile(rootDir, absolutePaths.ztdDdlAgents, relativePath('ztdDdlAgents'), ZTD_DDL_AGENTS_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
363
|
+
if (ztdDdlAgentsSummary) {
|
|
364
|
+
summaries.ztdDdlAgents = ztdDdlAgentsSummary;
|
|
365
|
+
}
|
|
366
|
+
const srcAgentsSummary = await writeTemplateFile(rootDir, absolutePaths.srcAgents, relativePath('srcAgents'), SRC_AGENTS_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
367
|
+
if (srcAgentsSummary) {
|
|
368
|
+
summaries.srcAgents = srcAgentsSummary;
|
|
369
|
+
}
|
|
370
|
+
const srcCatalogAgentsSummary = await writeTemplateFile(rootDir, absolutePaths.srcCatalogAgents, relativePath('srcCatalogAgents'), SRC_CATALOG_AGENTS_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
371
|
+
if (srcCatalogAgentsSummary) {
|
|
372
|
+
summaries.srcCatalogAgents = srcCatalogAgentsSummary;
|
|
373
|
+
}
|
|
374
|
+
const srcCatalogRuntimeAgentsSummary = await writeTemplateFile(rootDir, absolutePaths.srcCatalogRuntimeAgents, relativePath('srcCatalogRuntimeAgents'), SRC_CATALOG_RUNTIME_AGENTS_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
375
|
+
if (srcCatalogRuntimeAgentsSummary) {
|
|
376
|
+
summaries.srcCatalogRuntimeAgents = srcCatalogRuntimeAgentsSummary;
|
|
377
|
+
}
|
|
378
|
+
const srcCatalogSpecsAgentsSummary = await writeTemplateFile(rootDir, absolutePaths.srcCatalogSpecsAgents, relativePath('srcCatalogSpecsAgents'), SRC_CATALOG_SPECS_AGENTS_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
379
|
+
if (srcCatalogSpecsAgentsSummary) {
|
|
380
|
+
summaries.srcCatalogSpecsAgents = srcCatalogSpecsAgentsSummary;
|
|
381
|
+
}
|
|
382
|
+
const srcSqlAgentsSummary = await writeTemplateFile(rootDir, absolutePaths.srcSqlAgents, relativePath('srcSqlAgents'), SRC_SQL_AGENTS_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
383
|
+
if (srcSqlAgentsSummary) {
|
|
384
|
+
summaries.srcSqlAgents = srcSqlAgentsSummary;
|
|
385
|
+
}
|
|
386
|
+
const srcReposAgentsSummary = await writeTemplateFile(rootDir, absolutePaths.srcReposAgents, relativePath('srcReposAgents'), SRC_REPOS_AGENTS_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
387
|
+
if (srcReposAgentsSummary) {
|
|
388
|
+
summaries.srcReposAgents = srcReposAgentsSummary;
|
|
389
|
+
}
|
|
390
|
+
const viewsRepoAgentsSummary = await writeTemplateFile(rootDir, absolutePaths.viewsRepoAgents, relativePath('viewsRepoAgents'), VIEWS_REPO_AGENTS_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
391
|
+
if (viewsRepoAgentsSummary) {
|
|
392
|
+
summaries.viewsRepoAgents = viewsRepoAgentsSummary;
|
|
393
|
+
}
|
|
394
|
+
const tablesRepoAgentsSummary = await writeTemplateFile(rootDir, absolutePaths.tablesRepoAgents, relativePath('tablesRepoAgents'), TABLES_REPO_AGENTS_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
395
|
+
if (tablesRepoAgentsSummary) {
|
|
396
|
+
summaries.tablesRepoAgents = tablesRepoAgentsSummary;
|
|
397
|
+
}
|
|
398
|
+
const jobsAgentsSummary = await writeTemplateFile(rootDir, absolutePaths.jobsAgents, relativePath('jobsAgents'), JOBS_AGENTS_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
399
|
+
if (jobsAgentsSummary) {
|
|
400
|
+
summaries.jobsAgents = jobsAgentsSummary;
|
|
401
|
+
}
|
|
402
|
+
const sqlReadmeSummary = await writeTemplateFile(rootDir, absolutePaths.sqlReadme, relativePath('sqlReadme'), SQL_README_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
403
|
+
if (sqlReadmeSummary) {
|
|
404
|
+
summaries.sqlReadme = sqlReadmeSummary;
|
|
405
|
+
}
|
|
406
|
+
const viewsRepoReadmeSummary = await writeTemplateFile(rootDir, absolutePaths.viewsRepoReadme, relativePath('viewsRepoReadme'), VIEWS_REPO_README_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
407
|
+
if (viewsRepoReadmeSummary) {
|
|
408
|
+
summaries.viewsRepoReadme = viewsRepoReadmeSummary;
|
|
409
|
+
}
|
|
410
|
+
const tablesRepoReadmeSummary = await writeTemplateFile(rootDir, absolutePaths.tablesRepoReadme, relativePath('tablesRepoReadme'), TABLES_REPO_README_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
411
|
+
if (tablesRepoReadmeSummary) {
|
|
412
|
+
summaries.tablesRepoReadme = tablesRepoReadmeSummary;
|
|
413
|
+
}
|
|
414
|
+
const jobsReadmeSummary = await writeTemplateFile(rootDir, absolutePaths.jobsReadme, relativePath('jobsReadme'), JOBS_README_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
415
|
+
if (jobsReadmeSummary) {
|
|
416
|
+
summaries.jobsReadme = jobsReadmeSummary;
|
|
290
417
|
}
|
|
291
|
-
const
|
|
418
|
+
const smokeSpecTemplate = optionalFeatures.validator === 'zod' ? SMOKE_SPEC_ZOD_TEMPLATE : SMOKE_SPEC_ARKTYPE_TEMPLATE;
|
|
419
|
+
const smokeSpecSummary = await writeTemplateFile(rootDir, absolutePaths.smokeSpec, relativePath('smokeSpec'), smokeSpecTemplate, dependencies, prompter, overwritePolicy);
|
|
420
|
+
if (smokeSpecSummary) {
|
|
421
|
+
summaries.smokeSpec = smokeSpecSummary;
|
|
422
|
+
}
|
|
423
|
+
const smokeCoercionsSummary = await writeTemplateFile(rootDir, absolutePaths.smokeCoercions, relativePath('smokeCoercions'), SMOKE_COERCIONS_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
424
|
+
if (smokeCoercionsSummary) {
|
|
425
|
+
summaries.smokeCoercions = smokeCoercionsSummary;
|
|
426
|
+
}
|
|
427
|
+
const smokeRuntimeSummary = await writeTemplateFile(rootDir, absolutePaths.smokeRuntime, relativePath('smokeRuntime'), SMOKE_RUNTIME_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
428
|
+
if (smokeRuntimeSummary) {
|
|
429
|
+
summaries.smokeRuntime = smokeRuntimeSummary;
|
|
430
|
+
}
|
|
431
|
+
const smokeValidationTestSummary = await writeTemplateFile(rootDir, absolutePaths.smokeValidationTest, relativePath('smokeValidationTest'), SMOKE_VALIDATION_TEST_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
432
|
+
if (smokeValidationTestSummary) {
|
|
433
|
+
summaries.smokeValidationTest = smokeValidationTestSummary;
|
|
434
|
+
}
|
|
435
|
+
const sqlClientSummary = writeOptionalTemplateFile(absolutePaths.sqlClient, relativePath('sqlClient'), SQL_CLIENT_TEMPLATE, dependencies);
|
|
436
|
+
if (sqlClientSummary) {
|
|
437
|
+
summaries.sqlClient = sqlClientSummary;
|
|
438
|
+
}
|
|
439
|
+
const testsAgentsSummary = await writeTemplateFile(rootDir, absolutePaths.testsAgents, relativePath('testsAgents'), TESTS_AGENTS_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
440
|
+
if (testsAgentsSummary) {
|
|
441
|
+
summaries.testsAgents = testsAgentsSummary;
|
|
442
|
+
}
|
|
443
|
+
const testsSupportAgentsSummary = await writeTemplateFile(rootDir, absolutePaths.testsSupportAgents, relativePath('testsSupportAgents'), TESTS_SUPPORT_AGENTS_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
444
|
+
if (testsSupportAgentsSummary) {
|
|
445
|
+
summaries.testsSupportAgents = testsSupportAgentsSummary;
|
|
446
|
+
}
|
|
447
|
+
const testsGeneratedAgentsSummary = await writeTemplateFile(rootDir, absolutePaths.testsGeneratedAgents, relativePath('testsGeneratedAgents'), TESTS_GENERATED_AGENTS_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
448
|
+
if (testsGeneratedAgentsSummary) {
|
|
449
|
+
summaries.testsGeneratedAgents = testsGeneratedAgentsSummary;
|
|
450
|
+
}
|
|
451
|
+
const testsSmokeSummary = await writeTemplateFile(rootDir, absolutePaths.testsSmoke, relativePath('testsSmoke'), TESTS_SMOKE_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
452
|
+
if (testsSmokeSummary) {
|
|
453
|
+
summaries.testsSmoke = testsSmokeSummary;
|
|
454
|
+
}
|
|
455
|
+
const testkitSummary = await writeTemplateFile(rootDir, absolutePaths.testkitClient, relativePath('testkitClient'), TESTKIT_CLIENT_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
292
456
|
if (testkitSummary) {
|
|
293
457
|
summaries.testkitClient = testkitSummary;
|
|
294
458
|
}
|
|
295
|
-
const globalSetupSummary = await writeTemplateFile(rootDir, absolutePaths.globalSetup, relativePath('globalSetup'), GLOBAL_SETUP_TEMPLATE, dependencies, prompter);
|
|
459
|
+
const globalSetupSummary = await writeTemplateFile(rootDir, absolutePaths.globalSetup, relativePath('globalSetup'), GLOBAL_SETUP_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
296
460
|
if (globalSetupSummary) {
|
|
297
461
|
summaries.globalSetup = globalSetupSummary;
|
|
298
462
|
}
|
|
299
|
-
const vitestConfigSummary = await writeTemplateFile(rootDir, absolutePaths.vitestConfig, relativePath('vitestConfig'), VITEST_CONFIG_TEMPLATE, dependencies, prompter);
|
|
463
|
+
const vitestConfigSummary = await writeTemplateFile(rootDir, absolutePaths.vitestConfig, relativePath('vitestConfig'), VITEST_CONFIG_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
300
464
|
if (vitestConfigSummary) {
|
|
301
465
|
summaries.vitestConfig = vitestConfigSummary;
|
|
302
466
|
}
|
|
303
|
-
const
|
|
304
|
-
if (
|
|
305
|
-
summaries.
|
|
306
|
-
}
|
|
307
|
-
// Ensure the generated tests guidance lands beside the generated layout config.
|
|
308
|
-
const testsAgentsSummary = await writeTemplateFile(rootDir, absolutePaths.testsAgents, relativePath('testsAgents'), TESTS_AGENTS_TEMPLATE, dependencies, prompter);
|
|
309
|
-
if (testsAgentsSummary) {
|
|
310
|
-
summaries.testsAgents = testsAgentsSummary;
|
|
467
|
+
const tsconfigSummary = await writeTemplateFile(rootDir, absolutePaths.tsconfig, relativePath('tsconfig'), TSCONFIG_TEMPLATE, dependencies, prompter, overwritePolicy);
|
|
468
|
+
if (tsconfigSummary) {
|
|
469
|
+
summaries.tsconfig = tsconfigSummary;
|
|
311
470
|
}
|
|
312
|
-
// Seed the shared guidance that lives inside the ztd/ directory so contributors see the new instructions.
|
|
313
|
-
const ztdDocsAgentSummary = await writeTemplateFile(rootDir, absolutePaths.ztdDocsAgent, relativePath('ztdDocsAgent'), 'ztd/AGENTS.md', dependencies, prompter);
|
|
314
|
-
if (ztdDocsAgentSummary) {
|
|
315
|
-
summaries.ztdDocsAgent = ztdDocsAgentSummary;
|
|
316
|
-
}
|
|
317
|
-
// Provide the companion README inside ztd/ so maintainers understand the schema, spec, and enum intentions.
|
|
318
|
-
const ztdDocsReadmeSummary = await writeTemplateFile(rootDir, absolutePaths.ztdDocsReadme, relativePath('ztdDocsReadme'), 'ztd/README.md', dependencies, prompter);
|
|
319
|
-
if (ztdDocsReadmeSummary) {
|
|
320
|
-
summaries.ztdDocsReadme = ztdDocsReadmeSummary;
|
|
321
|
-
}
|
|
322
|
-
const ztdRootDir = node_path_1.default.join(rootDir, 'ztd');
|
|
323
|
-
// Ensure the domain-specs and enums anchors exist so contributors immediately see where those artifacts belong.
|
|
324
|
-
dependencies.ensureDirectory(node_path_1.default.join(ztdRootDir, 'domain-specs'));
|
|
325
|
-
dependencies.ensureDirectory(node_path_1.default.join(ztdRootDir, 'enums'));
|
|
326
471
|
const editorconfigSummary = copyTemplateFileIfMissing(rootDir, relativePath('editorconfig'), '.editorconfig', dependencies);
|
|
327
472
|
if (editorconfigSummary) {
|
|
328
473
|
summaries.editorconfig = editorconfigSummary;
|
|
@@ -339,7 +484,7 @@ async function runInitCommand(prompter, options) {
|
|
|
339
484
|
if (prettierignoreSummary) {
|
|
340
485
|
summaries.prettierignore = prettierignoreSummary;
|
|
341
486
|
}
|
|
342
|
-
const packageSummary = ensurePackageJsonFormatting(rootDir, relativePath('package'), dependencies);
|
|
487
|
+
const packageSummary = ensurePackageJsonFormatting(rootDir, relativePath('package'), dependencies, optionalFeatures);
|
|
343
488
|
if (packageSummary) {
|
|
344
489
|
summaries.package = packageSummary;
|
|
345
490
|
}
|
|
@@ -349,7 +494,8 @@ async function runInitCommand(prompter, options) {
|
|
|
349
494
|
summaries.agents = agentsRelative;
|
|
350
495
|
}
|
|
351
496
|
await ensureTemplateDependenciesInstalled(rootDir, absolutePaths, summaries, dependencies);
|
|
352
|
-
const
|
|
497
|
+
const nextSteps = buildNextSteps(normalizeRelative(rootDir, absolutePaths.schema), workflow);
|
|
498
|
+
const summaryLines = buildSummaryLines(summaries, optionalFeatures, nextSteps);
|
|
353
499
|
summaryLines.forEach(dependencies.log);
|
|
354
500
|
return {
|
|
355
501
|
summary: summaryLines.join('\n'),
|
|
@@ -525,7 +671,7 @@ function listDeclaredPackages(rootDir) {
|
|
|
525
671
|
return declared;
|
|
526
672
|
}
|
|
527
673
|
function listTemplateReferencedPackages(absolutePaths, summaries) {
|
|
528
|
-
const packages = new Set(
|
|
674
|
+
const packages = new Set();
|
|
529
675
|
const touchedKeys = Object.entries(summaries)
|
|
530
676
|
.filter((entry) => Boolean(entry[1]))
|
|
531
677
|
.filter(([, summary]) => summary.outcome === 'created' || summary.outcome === 'overwritten')
|
|
@@ -548,7 +694,7 @@ async function ensureTemplateDependenciesInstalled(rootDir, absolutePaths, summa
|
|
|
548
694
|
var _a;
|
|
549
695
|
const packageJsonPath = node_path_1.default.join(rootDir, 'package.json');
|
|
550
696
|
if (!dependencies.fileExists(packageJsonPath)) {
|
|
551
|
-
dependencies.log('Skipping dependency installation because package.json is missing.');
|
|
697
|
+
dependencies.log('Skipping dependency installation because package.json is missing. Next: run pnpm init (or npm init), install dependencies, then run npx ztd ztd-config.');
|
|
552
698
|
return;
|
|
553
699
|
}
|
|
554
700
|
const packageManager = detectPackageManager(rootDir);
|
|
@@ -603,18 +749,22 @@ function writeOptionalTemplateFile(absolutePath, relative, templateName, depende
|
|
|
603
749
|
dependencies.writeFile(absolutePath, (0, node_fs_1.readFileSync)(templatePath, 'utf8'));
|
|
604
750
|
return { relativePath: relative, outcome: 'created' };
|
|
605
751
|
}
|
|
606
|
-
function ensurePackageJsonFormatting(rootDir, relative, dependencies) {
|
|
752
|
+
function ensurePackageJsonFormatting(rootDir, relative, dependencies, optionalFeatures) {
|
|
607
753
|
var _a, _b;
|
|
608
754
|
const packagePath = node_path_1.default.join(rootDir, 'package.json');
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
755
|
+
const packageExists = dependencies.fileExists(packagePath);
|
|
756
|
+
const parsed = packageExists
|
|
757
|
+
? JSON.parse((0, node_fs_1.readFileSync)(packagePath, 'utf8'))
|
|
758
|
+
: {
|
|
759
|
+
name: inferPackageName(rootDir),
|
|
760
|
+
version: '0.0.0',
|
|
761
|
+
private: true
|
|
762
|
+
};
|
|
615
763
|
let changed = false;
|
|
616
764
|
const scripts = (_a = parsed.scripts) !== null && _a !== void 0 ? _a : {};
|
|
617
765
|
const requiredScripts = {
|
|
766
|
+
test: 'vitest run',
|
|
767
|
+
typecheck: 'tsc --noEmit',
|
|
618
768
|
format: 'prettier . --write',
|
|
619
769
|
lint: 'eslint .',
|
|
620
770
|
'lint:fix': 'eslint . --fix'
|
|
@@ -652,6 +802,11 @@ function ensurePackageJsonFormatting(rootDir, relative, dependencies) {
|
|
|
652
802
|
'prettier-plugin-sql': '^0.19.2',
|
|
653
803
|
'simple-git-hooks': '^2.13.1'
|
|
654
804
|
};
|
|
805
|
+
const testingDeps = {
|
|
806
|
+
vitest: '^4.0.7',
|
|
807
|
+
typescript: '^5.8.2',
|
|
808
|
+
'@types/node': '^22.13.10'
|
|
809
|
+
};
|
|
655
810
|
// Add the formatting toolchain dependencies that back the scripts and hooks.
|
|
656
811
|
for (const [dep, version] of Object.entries(formattingDeps)) {
|
|
657
812
|
if (dep in devDependencies) {
|
|
@@ -660,6 +815,31 @@ function ensurePackageJsonFormatting(rootDir, relative, dependencies) {
|
|
|
660
815
|
devDependencies[dep] = version;
|
|
661
816
|
changed = true;
|
|
662
817
|
}
|
|
818
|
+
const stackDependencies = {
|
|
819
|
+
...MANDATORY_TESTKIT_DEPENDENCIES,
|
|
820
|
+
...SQL_CONTRACT_DEPENDENCY
|
|
821
|
+
};
|
|
822
|
+
if (optionalFeatures.validator === 'zod') {
|
|
823
|
+
Object.assign(stackDependencies, ZOD_DEPENDENCY);
|
|
824
|
+
}
|
|
825
|
+
else {
|
|
826
|
+
Object.assign(stackDependencies, ARKTYPE_DEPENDENCY);
|
|
827
|
+
}
|
|
828
|
+
// Ensure test and typecheck toolchain dependencies are present for a runnable scaffold.
|
|
829
|
+
for (const [dep, version] of Object.entries(testingDeps)) {
|
|
830
|
+
if (dep in devDependencies) {
|
|
831
|
+
continue;
|
|
832
|
+
}
|
|
833
|
+
devDependencies[dep] = version;
|
|
834
|
+
changed = true;
|
|
835
|
+
}
|
|
836
|
+
for (const [dep, version] of Object.entries(stackDependencies)) {
|
|
837
|
+
if (dep in devDependencies) {
|
|
838
|
+
continue;
|
|
839
|
+
}
|
|
840
|
+
devDependencies[dep] = version;
|
|
841
|
+
changed = true;
|
|
842
|
+
}
|
|
663
843
|
if (!changed) {
|
|
664
844
|
return null;
|
|
665
845
|
}
|
|
@@ -667,42 +847,56 @@ function ensurePackageJsonFormatting(rootDir, relative, dependencies) {
|
|
|
667
847
|
dependencies.ensureDirectory(node_path_1.default.dirname(packagePath));
|
|
668
848
|
// Persist the updated manifest so the new scripts and tools are available immediately.
|
|
669
849
|
dependencies.writeFile(packagePath, `${JSON.stringify(parsed, null, 2)}\n`);
|
|
670
|
-
return { relativePath: relative, outcome: 'overwritten' };
|
|
850
|
+
return { relativePath: relative, outcome: packageExists ? 'overwritten' : 'created' };
|
|
851
|
+
}
|
|
852
|
+
function inferPackageName(rootDir) {
|
|
853
|
+
const baseName = node_path_1.default.basename(rootDir).toLowerCase();
|
|
854
|
+
const normalized = baseName.replace(/[^a-z0-9._-]+/g, '-').replace(/^-+|-+$/g, '');
|
|
855
|
+
if (normalized.length > 0) {
|
|
856
|
+
return normalized;
|
|
857
|
+
}
|
|
858
|
+
return 'ztd-project';
|
|
671
859
|
}
|
|
672
|
-
async function writeFileWithConsent(absolutePath, relative, dependencies, prompter, writer) {
|
|
673
|
-
const { existed, write } = await confirmOverwriteIfExists(absolutePath, relative, dependencies, prompter);
|
|
860
|
+
async function writeFileWithConsent(absolutePath, relative, dependencies, prompter, overwritePolicy, writer) {
|
|
861
|
+
const { existed, write } = await confirmOverwriteIfExists(absolutePath, relative, dependencies, prompter, overwritePolicy);
|
|
674
862
|
if (!write) {
|
|
675
863
|
return { relativePath: relative, outcome: 'unchanged' };
|
|
676
864
|
}
|
|
677
865
|
await writer();
|
|
678
866
|
return { relativePath: relative, outcome: existed ? 'overwritten' : 'created' };
|
|
679
867
|
}
|
|
680
|
-
async function confirmOverwriteIfExists(absolutePath, relative, dependencies, prompter) {
|
|
868
|
+
async function confirmOverwriteIfExists(absolutePath, relative, dependencies, prompter, overwritePolicy) {
|
|
681
869
|
const existed = dependencies.fileExists(absolutePath);
|
|
682
870
|
if (!existed) {
|
|
683
871
|
return { existed: false, write: true };
|
|
684
872
|
}
|
|
873
|
+
if (overwritePolicy.force) {
|
|
874
|
+
return { existed: true, write: true };
|
|
875
|
+
}
|
|
876
|
+
if (overwritePolicy.nonInteractive) {
|
|
877
|
+
throw new Error(`File ${relative} already exists. Re-run with --yes to overwrite or remove the file before running ztd init.`);
|
|
878
|
+
}
|
|
685
879
|
const overwrite = await prompter.confirm(`File ${relative} already exists. Overwrite?`);
|
|
686
880
|
if (!overwrite) {
|
|
687
881
|
return { existed: true, write: false };
|
|
688
882
|
}
|
|
689
883
|
return { existed: true, write: true };
|
|
690
884
|
}
|
|
691
|
-
async function writeDocFile(absolutePath, relative, contents, dependencies, prompter) {
|
|
692
|
-
const summary = await writeFileWithConsent(absolutePath, relative, dependencies, prompter, () => {
|
|
885
|
+
async function writeDocFile(absolutePath, relative, contents, dependencies, prompter, overwritePolicy) {
|
|
886
|
+
const summary = await writeFileWithConsent(absolutePath, relative, dependencies, prompter, overwritePolicy, () => {
|
|
693
887
|
dependencies.ensureDirectory(node_path_1.default.dirname(absolutePath));
|
|
694
888
|
dependencies.writeFile(absolutePath, contents);
|
|
695
889
|
});
|
|
696
890
|
return summary;
|
|
697
891
|
}
|
|
698
|
-
async function writeTemplateFile(rootDir, absolutePath, relative, templateName, dependencies, prompter, allowFallback) {
|
|
892
|
+
async function writeTemplateFile(rootDir, absolutePath, relative, templateName, dependencies, prompter, overwritePolicy, allowFallback) {
|
|
699
893
|
const templateTarget = resolveTemplateTarget(rootDir, absolutePath, relative, dependencies, allowFallback);
|
|
700
894
|
if (!templateTarget) {
|
|
701
895
|
return null;
|
|
702
896
|
}
|
|
703
897
|
// Load shared documentation templates so every new project gets the same guidance.
|
|
704
898
|
const contents = loadTemplate(templateName);
|
|
705
|
-
return writeDocFile(templateTarget.absolutePath, templateTarget.relativePath, contents, dependencies, prompter);
|
|
899
|
+
return writeDocFile(templateTarget.absolutePath, templateTarget.relativePath, contents, dependencies, prompter, overwritePolicy);
|
|
706
900
|
}
|
|
707
901
|
function resolveTemplateTarget(rootDir, absolutePath, relative, dependencies, allowFallback) {
|
|
708
902
|
if (!dependencies.fileExists(absolutePath)) {
|
|
@@ -729,6 +923,25 @@ function normalizeRelative(rootDir, absolutePath) {
|
|
|
729
923
|
const relative = node_path_1.default.relative(rootDir, absolutePath).replace(/\\/g, '/');
|
|
730
924
|
return relative || absolutePath;
|
|
731
925
|
}
|
|
926
|
+
/**
|
|
927
|
+
* Normalizes a schema identifier into the canonical lowercase form used by ztd-cli file naming.
|
|
928
|
+
* Empty input falls back to the configured default schema.
|
|
929
|
+
*/
|
|
930
|
+
function normalizeSchemaName(value) {
|
|
931
|
+
const trimmed = value.trim();
|
|
932
|
+
if (!trimmed) {
|
|
933
|
+
return ztdProjectConfig_1.DEFAULT_ZTD_CONFIG.ddl.defaultSchema;
|
|
934
|
+
}
|
|
935
|
+
return trimmed.replace(/^"|"$/g, '').toLowerCase();
|
|
936
|
+
}
|
|
937
|
+
/**
|
|
938
|
+
* Sanitizes a normalized schema identifier so it can be used as a filesystem-safe file stem.
|
|
939
|
+
* Returns `schema` when all characters are stripped by sanitization.
|
|
940
|
+
*/
|
|
941
|
+
function sanitizeSchemaFileName(schemaName) {
|
|
942
|
+
const sanitized = schemaName.replace(/[^a-z0-9_-]/g, '_').replace(/^_+|_+$/g, '');
|
|
943
|
+
return sanitized || 'schema';
|
|
944
|
+
}
|
|
732
945
|
function resolveOrCreateAgentsFile(rootDir, dependencies) {
|
|
733
946
|
// Prefer materializing the bundled template before looking for existing attention files.
|
|
734
947
|
const templateTarget = dependencies.copyAgentsTemplate(rootDir);
|
|
@@ -771,20 +984,51 @@ function loadTemplate(templateName) {
|
|
|
771
984
|
}
|
|
772
985
|
return (0, node_fs_1.readFileSync)(templatePath, 'utf8');
|
|
773
986
|
}
|
|
774
|
-
function
|
|
987
|
+
function buildNextSteps(schemaRelativePath, workflow) {
|
|
988
|
+
const stepOne = workflow === 'pg_dump'
|
|
989
|
+
? ` 1. Review the dumped DDL in ${schemaRelativePath}`
|
|
990
|
+
: ` 1. If the schema file is empty, edit ${schemaRelativePath}`;
|
|
991
|
+
return [
|
|
992
|
+
stepOne,
|
|
993
|
+
' 2. Run npx ztd ztd-config',
|
|
994
|
+
' 3. Provide a SqlClient implementation (adapter or mock)',
|
|
995
|
+
' 4. Run tests (pnpm test or npx vitest run)'
|
|
996
|
+
];
|
|
997
|
+
}
|
|
998
|
+
function buildSummaryLines(summaries, optionalFeatures, nextSteps) {
|
|
775
999
|
const orderedKeys = [
|
|
776
1000
|
'schema',
|
|
777
1001
|
'config',
|
|
778
|
-
'testsConfig',
|
|
779
|
-
'testsAgents',
|
|
780
|
-
'ztdConfig',
|
|
781
1002
|
'readme',
|
|
1003
|
+
'ztdDocsAgent',
|
|
1004
|
+
'ztdDocsReadme',
|
|
1005
|
+
'ztdDdlAgents',
|
|
1006
|
+
'srcAgents',
|
|
1007
|
+
'srcCatalogAgents',
|
|
1008
|
+
'srcCatalogRuntimeAgents',
|
|
1009
|
+
'srcCatalogSpecsAgents',
|
|
1010
|
+
'srcSqlAgents',
|
|
1011
|
+
'srcReposAgents',
|
|
1012
|
+
'viewsRepoAgents',
|
|
1013
|
+
'tablesRepoAgents',
|
|
1014
|
+
'jobsAgents',
|
|
1015
|
+
'sqlReadme',
|
|
1016
|
+
'viewsRepoReadme',
|
|
1017
|
+
'tablesRepoReadme',
|
|
1018
|
+
'jobsReadme',
|
|
1019
|
+
'smokeSpec',
|
|
1020
|
+
'smokeCoercions',
|
|
1021
|
+
'smokeRuntime',
|
|
1022
|
+
'smokeValidationTest',
|
|
1023
|
+
'testsAgents',
|
|
1024
|
+
'testsSupportAgents',
|
|
1025
|
+
'testsGeneratedAgents',
|
|
1026
|
+
'testsSmoke',
|
|
782
1027
|
'sqlClient',
|
|
783
1028
|
'testkitClient',
|
|
784
1029
|
'globalSetup',
|
|
785
1030
|
'vitestConfig',
|
|
786
|
-
'
|
|
787
|
-
'ztdDocsReadme',
|
|
1031
|
+
'tsconfig',
|
|
788
1032
|
'agents',
|
|
789
1033
|
'gitignore',
|
|
790
1034
|
'editorconfig',
|
|
@@ -804,7 +1048,13 @@ function buildSummaryLines(summaries) {
|
|
|
804
1048
|
lines.push(` - ${summary.relativePath}${note}`);
|
|
805
1049
|
}
|
|
806
1050
|
}
|
|
807
|
-
lines.push('', '
|
|
1051
|
+
lines.push('', 'Validation configuration:');
|
|
1052
|
+
lines.push(' - SQL catalog/mapping support via @rawsql-ts/sql-contract (see docs/recipes/sql-contract.md)');
|
|
1053
|
+
const validatorLabel = optionalFeatures.validator === 'zod'
|
|
1054
|
+
? 'Zod (zod, docs/recipes/validation-zod.md)'
|
|
1055
|
+
: 'ArkType (arktype, docs/recipes/validation-arktype.md)';
|
|
1056
|
+
lines.push(` - Validator backend: ${validatorLabel}`);
|
|
1057
|
+
lines.push('', 'Next steps:', ...nextSteps);
|
|
808
1058
|
return lines;
|
|
809
1059
|
}
|
|
810
1060
|
function registerInitCommand(program) {
|
|
@@ -813,12 +1063,16 @@ function registerInitCommand(program) {
|
|
|
813
1063
|
.description('Automate project setup for Zero Table Dependency workflows')
|
|
814
1064
|
.option('--with-sqlclient', 'Generate a minimal SqlClient interface for repositories')
|
|
815
1065
|
.option('--with-app-interface', 'Append application interface guidance to AGENTS.md only')
|
|
1066
|
+
.option('--yes', 'Overwrite existing scaffold files without prompting')
|
|
816
1067
|
.action(async (options) => {
|
|
1068
|
+
var _a;
|
|
817
1069
|
const prompter = createConsolePrompter();
|
|
818
1070
|
try {
|
|
819
1071
|
await runInitCommand(prompter, {
|
|
820
1072
|
withSqlClient: options.withSqlclient,
|
|
821
|
-
withAppInterface: options.withAppInterface
|
|
1073
|
+
withAppInterface: options.withAppInterface,
|
|
1074
|
+
forceOverwrite: (_a = options.yes) !== null && _a !== void 0 ? _a : false,
|
|
1075
|
+
nonInteractive: !process.stdin.isTTY
|
|
822
1076
|
});
|
|
823
1077
|
}
|
|
824
1078
|
finally {
|