@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-profiles.test.js","sourceRoot":"","sources":["../../../../tests/user-profiles.test.ts"],"names":[],"mappings":";;AAAA,mCAAgD;AAEhD,6EAI2C;AAC3C,6DAA+D;AAC/D,qEAAqE;AAErE,SAAS,iBAAiB;IACxB,OAAO;QACL;YACE,eAAe,EAAE,CAAC;YAClB,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,mBAAmB;YAC1B,YAAY,EAAE,cAAc;YAC5B,UAAU,EAAE,sBAAsB;YAClC,UAAU,EAAE,sBAAsB;SACnC;QACD;YACE,eAAe,EAAE,CAAC;YAClB,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,mBAAmB;YAC1B,YAAY,EAAE,eAAe;YAC7B,UAAU,EAAE,sBAAsB;YAClC,UAAU,EAAE,sBAAsB;SACnC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB;IACxB,OAAO;QACL;YACE,UAAU,EAAE,GAAG;YACf,eAAe,EAAE,CAAC;YAClB,GAAG,EAAE,oCAAoC;YACzC,OAAO,EAAE,qBAAqB;YAC9B,QAAQ,EAAE,IAAI;SACf;KACF,CAAC;AACJ,CAAC;AAED,SAAS,aAAa;IACpB,OAAO;QACL,IAAA,oCAAY,EACV,qBAAqB,EACrB,iBAAiB,EAAE,EACnB,oCAAY,CAAC,qBAAqB,CAAC,CACpC;QACD,IAAA,oCAAY,EACV,qBAAqB,EACrB,iBAAiB,EAAE,EACnB,oCAAY,CAAC,qBAAqB,CAAC,CACpC;KACF,CAAC;AACJ,CAAC;AAED,IAAA,iBAAQ,EAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,IAAA,aAAI,EAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,IAAA,oCAAmB,EAAC,QAAQ,CAAC,CAAC;QACnD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAA,gCAAgB,EAAC,MAAM,CAAC,CAAC;YAC9C,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,OAAO,CAAC;gBACrB;oBACE,aAAa,EAAE,CAAC;oBAChB,QAAQ,EAAE,OAAO;oBACjB,KAAK,EAAE,mBAAmB;oBAC1B,WAAW,EAAE,cAAc;oBAC3B,SAAS,EAAE,IAAI,IAAI,CAAC,sBAAsB,CAAC;oBAC3C,SAAS,EAAE,IAAI,IAAI,CAAC,sBAAsB,CAAC;oBAC3C,OAAO,EAAE;wBACP,SAAS,EAAE,GAAG;wBACd,aAAa,EAAE,CAAC;wBAChB,GAAG,EAAE,oCAAoC;wBACzC,OAAO,EAAE,qBAAqB;wBAC9B,QAAQ,EAAE,IAAI;qBACf;iBACF;gBACD;oBACE,aAAa,EAAE,CAAC;oBAChB,QAAQ,EAAE,OAAO;oBACjB,KAAK,EAAE,mBAAmB;oBAC1B,WAAW,EAAE,eAAe;oBAC5B,SAAS,EAAE,IAAI,IAAI,CAAC,sBAAsB,CAAC;oBAC3C,SAAS,EAAE,IAAI,IAAI,CAAC,sBAAsB,CAAC;oBAC3C,OAAO,EAAE,SAAS;iBACnB;aACF,CAAC,CAAC;QACL,CAAC;gBAAS,CAAC;YACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const ztd_row_map_generated_1 = require("./generated/ztd-row-map.generated");
|
|
5
|
+
const user_accounts_1 = require("../src/repositories/user-accounts");
|
|
6
|
+
const userColumns = new Set(Object.keys(ztd_row_map_generated_1.tableSchemas['public.user_account'].columns));
|
|
7
|
+
(0, vitest_1.describe)('user_account writer columns', () => {
|
|
8
|
+
(0, vitest_1.test)('insert columns must exist on the canonical table', () => {
|
|
9
|
+
const { insertColumns } = user_accounts_1.userAccountWriterColumnSets;
|
|
10
|
+
const missing = insertColumns.filter((column) => !userColumns.has(column));
|
|
11
|
+
(0, vitest_1.expect)(missing).toEqual([]);
|
|
12
|
+
(0, vitest_1.expect)(insertColumns).toEqual(vitest_1.expect.arrayContaining(['username', 'email', 'display_name']));
|
|
13
|
+
});
|
|
14
|
+
(0, vitest_1.test)('update columns stay within allowed set and avoid immutable columns', () => {
|
|
15
|
+
const { updateColumns, immutableColumns } = user_accounts_1.userAccountWriterColumnSets;
|
|
16
|
+
const missing = updateColumns.filter((column) => !userColumns.has(column));
|
|
17
|
+
(0, vitest_1.expect)(missing).toEqual([]);
|
|
18
|
+
(0, vitest_1.expect)(updateColumns).not.toEqual(vitest_1.expect.arrayContaining([...immutableColumns]));
|
|
19
|
+
});
|
|
20
|
+
(0, vitest_1.test)('immutable columns reflect the DDL and are not targetted by updates', () => {
|
|
21
|
+
const { immutableColumns, updateColumns } = user_accounts_1.userAccountWriterColumnSets;
|
|
22
|
+
const missing = immutableColumns.filter((column) => !userColumns.has(column));
|
|
23
|
+
(0, vitest_1.expect)(missing).toEqual([]);
|
|
24
|
+
immutableColumns.forEach((column) => {
|
|
25
|
+
(0, vitest_1.expect)(updateColumns).not.toContain(column);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
//# sourceMappingURL=writer-constraints.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writer-constraints.test.js","sourceRoot":"","sources":["../../../../tests/writer-constraints.test.ts"],"names":[],"mappings":";;AAAA,mCAAgD;AAChD,6EAAiE;AACjE,qEAAgF;AAEhF,MAAM,WAAW,GAAG,IAAI,GAAG,CACzB,MAAM,CAAC,IAAI,CAAC,oCAAY,CAAC,qBAAqB,CAAC,CAAC,OAAO,CAAC,CACzD,CAAC;AAEF,IAAA,iBAAQ,EAAC,6BAA6B,EAAE,GAAG,EAAE;IAC3C,IAAA,aAAI,EAAC,kDAAkD,EAAE,GAAG,EAAE;QAC5D,MAAM,EAAE,aAAa,EAAE,GAAG,2CAA2B,CAAC;QACtD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;QAC3E,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC5B,IAAA,eAAM,EAAC,aAAa,CAAC,CAAC,OAAO,CAC3B,eAAM,CAAC,eAAe,CAAC,CAAC,UAAU,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAC9D,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAA,aAAI,EAAC,oEAAoE,EAAE,GAAG,EAAE;QAC9E,MAAM,EAAE,aAAa,EAAE,gBAAgB,EAAE,GAAG,2CAA2B,CAAC;QACxE,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;QAC3E,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC5B,IAAA,eAAM,EAAC,aAAa,CAAC,CAAC,GAAG,CAAC,OAAO,CAC/B,eAAM,CAAC,eAAe,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAC9C,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAA,aAAI,EAAC,oEAAoE,EAAE,GAAG,EAAE;QAC9E,MAAM,EAAE,gBAAgB,EAAE,aAAa,EAAE,GAAG,2CAA2B,CAAC;QACxE,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9E,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC5B,gBAAgB,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;YAClC,IAAA,eAAM,EAAC,aAAa,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// GENERATED FILE. DO NOT EDIT.
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.default = {
|
|
5
|
+
ztdRootDir: 'ztd',
|
|
6
|
+
ddlDir: 'ztd/ddl',
|
|
7
|
+
enumsDir: 'ztd/enums',
|
|
8
|
+
domainSpecsDir: 'ztd/domain-specs',
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=ztd-layout.generated.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ztd-layout.generated.js","sourceRoot":"","sources":["../../../../tests/ztd-layout.generated.ts"],"names":[],"mappings":";AAAA,+BAA+B;;AAE/B,kBAAe;IACb,UAAU,EAAE,KAAK;IACjB,MAAM,EAAE,SAAS;IACjB,QAAQ,EAAE,WAAW;IACrB,cAAc,EAAE,kBAAkB;CACnC,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# src AGENTS
|
|
2
|
+
|
|
3
|
+
This directory is runtime application code.
|
|
4
|
+
|
|
5
|
+
## Boundaries
|
|
6
|
+
|
|
7
|
+
- Code under "src/" MUST NOT import from:
|
|
8
|
+
- "tests/"
|
|
9
|
+
- "tests/generated/"
|
|
10
|
+
- any test-only helpers
|
|
11
|
+
- Runtime code MUST NOT depend on ZTD internals.
|
|
12
|
+
- Generated artifacts are test-only signals, not runtime dependencies.
|
|
13
|
+
|
|
14
|
+
## Implementation principles
|
|
15
|
+
|
|
16
|
+
- Keep modules small and explicit.
|
|
17
|
+
- Prefer explicit contracts over inference.
|
|
18
|
+
- Favor deterministic behavior and clear error surfaces.
|
|
19
|
+
|
|
20
|
+
## Verification (required)
|
|
21
|
+
|
|
22
|
+
After changes:
|
|
23
|
+
- Run the project typecheck command (example: "pnpm typecheck").
|
|
24
|
+
- Run relevant tests (example: "pnpm test" or a filtered command).
|
|
25
|
+
|
|
26
|
+
If you touched SQL contracts or catalog specs, run tests that exercise them.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# src/catalog AGENTS
|
|
2
|
+
|
|
3
|
+
This directory is runtime code.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
Catalog defines named query entry points by binding:
|
|
8
|
+
- SQL assets ("src/sql/*.sql")
|
|
9
|
+
- input parameter contracts
|
|
10
|
+
- output DTO contracts
|
|
11
|
+
- validation and mapping behavior
|
|
12
|
+
- observability hooks (if supported)
|
|
13
|
+
|
|
14
|
+
## Directory roles (important)
|
|
15
|
+
|
|
16
|
+
- "src/catalog/specs": human-owned contracts (params + DTO + semantics)
|
|
17
|
+
- "src/catalog/runtime": AI-assisted runtime wiring (executors, helpers, sinks)
|
|
18
|
+
|
|
19
|
+
## Non-negotiable ownership
|
|
20
|
+
|
|
21
|
+
- Specs are contracts. Do not infer, guess, widen, or narrow them.
|
|
22
|
+
- Do not change params / DTO shapes in "specs" without explicit instruction.
|
|
23
|
+
|
|
24
|
+
## Boundaries
|
|
25
|
+
|
|
26
|
+
- Code under "src/catalog/" MUST NOT import from:
|
|
27
|
+
- "tests/"
|
|
28
|
+
- "tests/generated/"
|
|
29
|
+
- "ztd/"
|
|
30
|
+
- Do not depend on ZTD internals at runtime.
|
|
31
|
+
|
|
32
|
+
## Testing rule (required)
|
|
33
|
+
|
|
34
|
+
Every spec MUST have tests that verify:
|
|
35
|
+
- SQL executes under ZTD rewriting
|
|
36
|
+
- mapping/validation behavior is correct (success and failure)
|
|
37
|
+
- output DTO shape matches expectations
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# src/catalog/runtime AGENTS
|
|
2
|
+
|
|
3
|
+
This directory contains runtime wiring for catalog specs:
|
|
4
|
+
- parameter validation entrypoints
|
|
5
|
+
- row-to-DTO mapping
|
|
6
|
+
- output validation
|
|
7
|
+
|
|
8
|
+
## Runtime classification
|
|
9
|
+
|
|
10
|
+
- This is a runtime directory.
|
|
11
|
+
- Code here is executed/loaded by the application.
|
|
12
|
+
|
|
13
|
+
## Responsibilities (critical)
|
|
14
|
+
|
|
15
|
+
- Runtime MUST be the only place that:
|
|
16
|
+
- validates unknown inputs into typed params
|
|
17
|
+
- maps SQL rows (snake_case) into DTO objects
|
|
18
|
+
- validates DTO outputs before returning to repositories
|
|
19
|
+
- Runtime output validation MUST follow the output contract type (DTO or scalar).
|
|
20
|
+
- Command outputs MAY be scalar identifiers or `void`; DTO mapping is required only when the output contract is DTO.
|
|
21
|
+
|
|
22
|
+
Repositories MUST call runtime helpers (ensure*/map*) and MUST NOT bypass them.
|
|
23
|
+
|
|
24
|
+
## Validator requirement (required)
|
|
25
|
+
|
|
26
|
+
- A validator library (zod or arktype) is always available.
|
|
27
|
+
- Runtime MUST apply validators for:
|
|
28
|
+
- input params (unknown -> typed)
|
|
29
|
+
- outputs (mapped DTO -> validated DTO)
|
|
30
|
+
|
|
31
|
+
Do not rely on TypeScript types alone.
|
|
32
|
+
|
|
33
|
+
## SQL row normalization (important)
|
|
34
|
+
|
|
35
|
+
SQL drivers may return different runtime representations for the same column types.
|
|
36
|
+
Runtime MUST normalize driver-dependent values before validating DTOs.
|
|
37
|
+
|
|
38
|
+
Required normalization rules:
|
|
39
|
+
- Timestamp columns (e.g. timestamptz) may arrive as Date or string.
|
|
40
|
+
- Runtime MUST use `timestampFromDriver` from `@rawsql-ts/sql-contract`.
|
|
41
|
+
- Do NOT re-implement `normalizeTimestamp` locally.
|
|
42
|
+
- Do NOT call `new Date(...)` directly for driver-dependent timestamp normalization.
|
|
43
|
+
- Numeric columns may arrive as number, string, or bigint depending on driver.
|
|
44
|
+
- Normalization rules MUST be explicit per contract and MUST NOT be silent.
|
|
45
|
+
|
|
46
|
+
Never force SQL assets to encode driver-specific behavior.
|
|
47
|
+
|
|
48
|
+
## Mapping rules (required)
|
|
49
|
+
|
|
50
|
+
- Keep SQL assets snake_case and DTO-independent.
|
|
51
|
+
- Mapping occurs in runtime:
|
|
52
|
+
- snake_case row -> DTO-shaped object
|
|
53
|
+
- apply normalization
|
|
54
|
+
- validate via spec-owned validator
|
|
55
|
+
- DTO camelCase aliases in SQL are forbidden.
|
|
56
|
+
|
|
57
|
+
## Entry points (recommended)
|
|
58
|
+
|
|
59
|
+
Prefer these patterns:
|
|
60
|
+
- `ensureXxxParams(value: unknown): XxxParams` (validate inputs)
|
|
61
|
+
- `mapXxxRowToDto(row: XxxSqlRow): XxxDto` (normalize + validate outputs)
|
|
62
|
+
|
|
63
|
+
The `map*` functions MUST always validate before returning.
|
|
64
|
+
|
|
65
|
+
## Error behavior (required)
|
|
66
|
+
|
|
67
|
+
- Validation errors must fail fast with clear messages.
|
|
68
|
+
- Do not swallow validator errors.
|
|
69
|
+
- Do not silently coerce invalid values unless explicitly defined by the contract.
|
|
70
|
+
|
|
71
|
+
## Boundaries
|
|
72
|
+
|
|
73
|
+
- Do not perform database I/O here.
|
|
74
|
+
- Do not import from "tests/" or "tests/generated/".
|
|
75
|
+
- Do not define human-owned contracts here; they live in "src/catalog/specs".
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { timestampFromDriver as normalizeTimestamp } from '@rawsql-ts/sql-contract';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { parseSmokeOutput, type SmokeOutput } from '../specs/_smoke.spec';
|
|
2
|
+
import { normalizeTimestamp } from './_coercions';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Validate runtime output against the catalog smoke invariant.
|
|
6
|
+
*/
|
|
7
|
+
export function ensureSmokeOutput(value: unknown): SmokeOutput {
|
|
8
|
+
// Normalize driver-dependent timestamp representations before contract validation.
|
|
9
|
+
if (isRecord(value) && 'createdAt' in value) {
|
|
10
|
+
return parseSmokeOutput({
|
|
11
|
+
...value,
|
|
12
|
+
createdAt: normalizeTimestamp(value.createdAt, 'createdAt')
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return parseSmokeOutput(value);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
20
|
+
return typeof value === 'object' && value !== null;
|
|
21
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# src/catalog/specs AGENTS
|
|
2
|
+
|
|
3
|
+
This directory defines query and command specifications (contracts).
|
|
4
|
+
|
|
5
|
+
## Runtime classification
|
|
6
|
+
|
|
7
|
+
- This is a runtime directory.
|
|
8
|
+
- Contents are human-owned contracts, not implementation details.
|
|
9
|
+
|
|
10
|
+
## Ownership (critical)
|
|
11
|
+
|
|
12
|
+
- Specs are human-owned.
|
|
13
|
+
- Input parameters are part of the domain contract.
|
|
14
|
+
- Output DTO shapes are part of the domain contract.
|
|
15
|
+
- Cardinality and semantics are part of the domain contract.
|
|
16
|
+
|
|
17
|
+
AI MUST NOT:
|
|
18
|
+
- infer missing parameters
|
|
19
|
+
- widen or narrow DTO shapes
|
|
20
|
+
- change nullability or optionality
|
|
21
|
+
- change CUD return shape implicitly
|
|
22
|
+
|
|
23
|
+
Changes require explicit human instruction.
|
|
24
|
+
|
|
25
|
+
## Validator requirement (required)
|
|
26
|
+
|
|
27
|
+
- A validator library (zod or arktype) is always available.
|
|
28
|
+
- Every spec MUST define validators for its public inputs/outputs.
|
|
29
|
+
- Validators are part of the contract and are human-owned.
|
|
30
|
+
|
|
31
|
+
## Driver variability policy (important)
|
|
32
|
+
|
|
33
|
+
Specs MUST NOT require SQL assets to encode driver-specific workarounds.
|
|
34
|
+
|
|
35
|
+
- Specs may acknowledge that SQL rows can vary in representation by driver
|
|
36
|
+
(e.g. timestamps as Date or string).
|
|
37
|
+
- Normalization for driver-dependent values is implemented in catalog runtime,
|
|
38
|
+
then validated against the spec.
|
|
39
|
+
|
|
40
|
+
Contracts define the final DTO shape.
|
|
41
|
+
Runtime defines normalization steps to reach that shape.
|
|
42
|
+
|
|
43
|
+
## What does NOT belong here
|
|
44
|
+
|
|
45
|
+
- No executors
|
|
46
|
+
- No database connections
|
|
47
|
+
- No ZTD internals
|
|
48
|
+
- No SQL camelCase aliasing rules (SQL rules live under src/sql)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type } from 'arktype';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Validator invariant contract used to prove runtime validation wiring.
|
|
5
|
+
*
|
|
6
|
+
* This file is intentionally minimal and domain-agnostic.
|
|
7
|
+
*/
|
|
8
|
+
export const smokeOutputSchema = type({
|
|
9
|
+
id: 'number.integer',
|
|
10
|
+
createdAt: 'Date'
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export type SmokeOutput = ReturnType<typeof smokeOutputSchema>;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Parse and validate an unknown runtime payload.
|
|
17
|
+
*/
|
|
18
|
+
export function parseSmokeOutput(value: unknown): SmokeOutput {
|
|
19
|
+
smokeOutputSchema.assert(value);
|
|
20
|
+
return value as SmokeOutput;
|
|
21
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Validator invariant contract used to prove runtime validation wiring.
|
|
5
|
+
*
|
|
6
|
+
* This file is intentionally minimal and domain-agnostic.
|
|
7
|
+
*/
|
|
8
|
+
export const smokeOutputSchema = z.object({
|
|
9
|
+
id: z.number().int(),
|
|
10
|
+
createdAt: z.date()
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export type SmokeOutput = z.infer<typeof smokeOutputSchema>;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Parse and validate an unknown runtime payload.
|
|
17
|
+
*/
|
|
18
|
+
export function parseSmokeOutput(value: unknown): SmokeOutput {
|
|
19
|
+
return smokeOutputSchema.parse(value);
|
|
20
|
+
}
|
|
@@ -9,16 +9,16 @@ export type SqlQueryRows<T> = Promise<T[]>;
|
|
|
9
9
|
/**
|
|
10
10
|
* Minimal SQL client interface required by the repository layer.
|
|
11
11
|
*
|
|
12
|
-
* - Production: adapt
|
|
13
|
-
* - Tests:
|
|
12
|
+
* - Production: adapt this interface to your preferred driver (pg, mysql2, etc.) and normalize the results to `T[]`.
|
|
13
|
+
* - Tests: replace the implementation with a mock, a fixture helper, or an adapter that follows this contract.
|
|
14
14
|
*
|
|
15
15
|
* Connection strategy note:
|
|
16
|
-
* - Prefer a shared client per worker process for performance.
|
|
17
|
-
* - Do not share a live client across parallel workers.
|
|
16
|
+
* - Prefer a shared client per worker process for better performance.
|
|
17
|
+
* - Do not share a live client across parallel workers without proper synchronization.
|
|
18
18
|
*/
|
|
19
19
|
export type SqlClient = {
|
|
20
20
|
query<T extends Record<string, unknown> = Record<string, unknown>>(
|
|
21
21
|
text: string,
|
|
22
|
-
values?: readonly unknown[]
|
|
22
|
+
values?: readonly unknown[] | Record<string, unknown>
|
|
23
23
|
): SqlQueryRows<T>;
|
|
24
24
|
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# src/jobs AGENTS
|
|
2
|
+
|
|
3
|
+
This folder contains script-like operations (procedural SQL execution).
|
|
4
|
+
|
|
5
|
+
## Scope
|
|
6
|
+
|
|
7
|
+
- Maintenance jobs
|
|
8
|
+
- Data backfills
|
|
9
|
+
- Batch operations
|
|
10
|
+
- Temporary-table driven workflows
|
|
11
|
+
|
|
12
|
+
## Safety rules
|
|
13
|
+
|
|
14
|
+
- Be explicit about transaction boundaries.
|
|
15
|
+
- Prefer idempotent design (safe to rerun).
|
|
16
|
+
- Emit clear logs/events at start and end of the job.
|
|
17
|
+
|
|
18
|
+
## SQL usage
|
|
19
|
+
|
|
20
|
+
- It is acceptable to run multiple statements in a job (including temp tables).
|
|
21
|
+
- Avoid coupling job logic to tests-only helpers.
|
|
22
|
+
|
|
23
|
+
## Testing
|
|
24
|
+
|
|
25
|
+
- Prefer integration-style tests that verify observable outcomes.
|
|
26
|
+
- If the job is heavy, test smaller units or use fixtures to limit scope.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# src/repositories AGENTS
|
|
2
|
+
|
|
3
|
+
This directory contains repository implementations.
|
|
4
|
+
|
|
5
|
+
## Runtime classification
|
|
6
|
+
|
|
7
|
+
- This is a runtime directory.
|
|
8
|
+
- Code here is executed by the application.
|
|
9
|
+
|
|
10
|
+
## Responsibilities
|
|
11
|
+
|
|
12
|
+
Repositories orchestrate execution only.
|
|
13
|
+
|
|
14
|
+
They are responsible for:
|
|
15
|
+
- loading SQL assets from `src/sql`
|
|
16
|
+
- validating external inputs via catalog runtime
|
|
17
|
+
- binding parameters
|
|
18
|
+
- calling `SqlClient`
|
|
19
|
+
- mapping SQL rows to DTOs via catalog runtime
|
|
20
|
+
- returning application-facing results
|
|
21
|
+
|
|
22
|
+
Repositories MUST remain thin adapters over SQL.
|
|
23
|
+
|
|
24
|
+
Repositories MUST NOT:
|
|
25
|
+
- embed business rules
|
|
26
|
+
- infer schema or DTO structure
|
|
27
|
+
- compensate for driver limitations with extra queries
|
|
28
|
+
|
|
29
|
+
## Contract boundaries (important)
|
|
30
|
+
|
|
31
|
+
- Human-owned contracts live under "src/catalog/specs".
|
|
32
|
+
- Runtime normalization and validation live under "src/catalog/runtime".
|
|
33
|
+
- Repositories MUST NOT invent, infer, or modify contracts.
|
|
34
|
+
|
|
35
|
+
If a contract is insufficient, update the spec/runtime first.
|
|
36
|
+
|
|
37
|
+
## Mandatory runtime usage (required)
|
|
38
|
+
|
|
39
|
+
Repositories MUST use catalog runtime helpers:
|
|
40
|
+
- `ensure*Params` for all external inputs (`unknown -> typed`)
|
|
41
|
+
- `map*RowToDto` for row-to-DTO mapping and output validation
|
|
42
|
+
|
|
43
|
+
Repositories MUST NOT:
|
|
44
|
+
- call spec validators directly
|
|
45
|
+
- bypass runtime normalization
|
|
46
|
+
- return DTOs without runtime validation
|
|
47
|
+
- assume driver-specific runtime types (e.g. timestamps always `Date`)
|
|
48
|
+
|
|
49
|
+
## SQL rules
|
|
50
|
+
|
|
51
|
+
- SQL assets MUST remain DTO-independent.
|
|
52
|
+
- SQL files MUST use snake_case column names.
|
|
53
|
+
- Repositories MUST NOT push DTO aliasing into SQL.
|
|
54
|
+
- Inline SQL strings are forbidden.
|
|
55
|
+
- Repository SQL loading MUST be centralized in shared runtime/repository infrastructure.
|
|
56
|
+
- Repositories MUST reference SQL assets by stable logical key (example: `user/insert_user.sql`).
|
|
57
|
+
- Repository modules MUST NOT pass caller-relative paths (`./`, `../`) or absolute filesystem paths to SQL loaders.
|
|
58
|
+
- The shared loader MUST resolve logical keys against the `src/sql` root (or catalog SQL registry), never relative to the caller file location.
|
|
59
|
+
- Repository modules MUST NOT implement ad-hoc SQL file loading with `readFileSync`, `__dirname`, `import.meta.url`, or direct path resolution.
|
|
60
|
+
|
|
61
|
+
## CUD default policy (important)
|
|
62
|
+
|
|
63
|
+
Default policy for table-oriented CUD is:
|
|
64
|
+
- CREATE SQL MAY use `RETURNING` for identifier columns only.
|
|
65
|
+
- CREATE repository methods MUST return the generated identifier by default.
|
|
66
|
+
- CREATE repository methods MUST NOT perform a follow-up SELECT whose purpose is DTO return shaping.
|
|
67
|
+
- UPDATE/DELETE SQL MUST NOT use `RETURNING`.
|
|
68
|
+
- repositories do NOT perform follow-up SELECTs after UPDATE/DELETE.
|
|
69
|
+
- UPDATE/DELETE methods return `Promise<void>` by default.
|
|
70
|
+
|
|
71
|
+
If a CREATE method must return a DTO, that requirement MUST be explicitly declared in catalog specs by human instruction.
|
|
72
|
+
|
|
73
|
+
## CUD row count rules (non-negotiable)
|
|
74
|
+
|
|
75
|
+
- UPDATE and DELETE MUST rely on driver-reported affected row counts (`rowCount` or equivalent).
|
|
76
|
+
- Repositories MUST NOT use SQL `RETURNING` result presence/count as a substitute for affected row counts.
|
|
77
|
+
- Repositories MUST NOT emulate affected rows using:
|
|
78
|
+
- pre-check SELECT
|
|
79
|
+
- post-check SELECT
|
|
80
|
+
- retry loops
|
|
81
|
+
- shadow queries / CTE hacks
|
|
82
|
+
|
|
83
|
+
If `rowCount === 0`, repositories MUST throw an explicit error.
|
|
84
|
+
|
|
85
|
+
If the driver cannot report affected row counts:
|
|
86
|
+
- CUD verification is unsupported
|
|
87
|
+
- tests MUST fail fast
|
|
88
|
+
- do NOT add workaround logic in repositories
|
|
89
|
+
|
|
90
|
+
## Read (SELECT) rules
|
|
91
|
+
|
|
92
|
+
- SELECT methods may return:
|
|
93
|
+
- `T | null` for single-row queries
|
|
94
|
+
- `T[]` for multi-row queries
|
|
95
|
+
- Absence of rows is NOT an error unless specified by the contract.
|
|
96
|
+
|
|
97
|
+
## Error behavior
|
|
98
|
+
|
|
99
|
+
- Propagate validation errors as failures.
|
|
100
|
+
- Do not silently coerce invalid data.
|
|
101
|
+
- Error messages SHOULD include operation name and identifying parameters.
|
|
102
|
+
|
|
103
|
+
## Testing expectations
|
|
104
|
+
|
|
105
|
+
- Every public repository method MUST be covered by tests.
|
|
106
|
+
- Update/Delete tests MUST verify rowCount handling explicitly.
|
|
107
|
+
- Repository changes without tests are incomplete.
|
|
108
|
+
|
|
109
|
+
## Guiding principle
|
|
110
|
+
|
|
111
|
+
Repositories execute contracts.
|
|
112
|
+
They do not interpret intent.
|
|
113
|
+
|
|
114
|
+
If correctness depends on extra queries to "confirm" changes:
|
|
115
|
+
- the contract is wrong
|
|
116
|
+
- or the driver is unsupported
|
|
117
|
+
|
|
118
|
+
Fix the contract, not the repository.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# src/repositories/tables AGENTS
|
|
2
|
+
|
|
3
|
+
This directory contains simple CRUD-style repositories.
|
|
4
|
+
|
|
5
|
+
## Runtime classification
|
|
6
|
+
|
|
7
|
+
- This is a runtime directory.
|
|
8
|
+
- Code here executes SQL and returns application-facing results.
|
|
9
|
+
|
|
10
|
+
## Responsibilities
|
|
11
|
+
|
|
12
|
+
- Execute SQL assets using defined contracts.
|
|
13
|
+
- Perform explicit mapping from SQL rows to DTOs.
|
|
14
|
+
- Enforce CUD semantics at the application boundary (including "0 rows" handling).
|
|
15
|
+
|
|
16
|
+
## Contract ownership (important)
|
|
17
|
+
|
|
18
|
+
- Input parameter types and DTO shapes are defined in specs ("src/catalog/specs").
|
|
19
|
+
- Repositories MUST NOT invent or modify contracts.
|
|
20
|
+
- Repositories may adapt SQL results into DTOs, but must not redefine the contract.
|
|
21
|
+
|
|
22
|
+
## SQL usage rules (tables CRUD quality bar)
|
|
23
|
+
|
|
24
|
+
- Repositories in this folder MUST treat SQL assets as human-maintained, idiomatic SQL.
|
|
25
|
+
- Do not require SQL assets to implement driver-specific behaviors.
|
|
26
|
+
- If a driver does not provide affected-row counts for UPDATE/DELETE, fail fast as unsupported.
|
|
27
|
+
|
|
28
|
+
Examples:
|
|
29
|
+
- Prefer a plain UPDATE statement in SQL.
|
|
30
|
+
- Do not force SQL to return `affected_count` via CTE tricks.
|
|
31
|
+
|
|
32
|
+
## CUD behavior rules
|
|
33
|
+
|
|
34
|
+
### CREATE (INSERT)
|
|
35
|
+
|
|
36
|
+
Default:
|
|
37
|
+
- SQL MUST use `insert ... returning <primary_key>` when a generated key is needed.
|
|
38
|
+
- Repository CREATE MUST return identifier only (scalar) per contract.
|
|
39
|
+
- Repository CREATE MUST NOT perform a follow-up SELECT for DTO return shaping.
|
|
40
|
+
- SQL MUST NOT return full rows or DTO-shaped payloads.
|
|
41
|
+
|
|
42
|
+
Exception:
|
|
43
|
+
- If a CREATE endpoint must return DTO, the spec MUST explicitly require it by human instruction.
|
|
44
|
+
- Without that explicit contract, identifier-only return is mandatory.
|
|
45
|
+
|
|
46
|
+
### UPDATE
|
|
47
|
+
|
|
48
|
+
Default:
|
|
49
|
+
- SQL: plain UPDATE without RETURNING.
|
|
50
|
+
- Repository: determine success by affected row count when available.
|
|
51
|
+
|
|
52
|
+
Driver variability handling:
|
|
53
|
+
- If affected row count is unavailable:
|
|
54
|
+
- Treat UPDATE verification as unsupported for that driver/runtime.
|
|
55
|
+
- Throw an explicit error.
|
|
56
|
+
- Do not add fallback checks or workaround logic in repositories.
|
|
57
|
+
- Do not push this variability down into SQL assets.
|
|
58
|
+
|
|
59
|
+
0-row rule (important):
|
|
60
|
+
- Treat "0 rows updated" as a meaningful condition.
|
|
61
|
+
- Default behavior is to surface it clearly (often an error), per spec.
|
|
62
|
+
|
|
63
|
+
### DELETE
|
|
64
|
+
|
|
65
|
+
Default:
|
|
66
|
+
- SQL: plain DELETE without RETURNING.
|
|
67
|
+
- Repository: determine success by affected row count when available.
|
|
68
|
+
|
|
69
|
+
Driver variability handling:
|
|
70
|
+
- If affected row count is unavailable:
|
|
71
|
+
- Treat DELETE verification as unsupported for that driver/runtime.
|
|
72
|
+
- Throw an explicit error.
|
|
73
|
+
- Do not add fallback checks or workaround logic in repositories.
|
|
74
|
+
|
|
75
|
+
0-row rule (important):
|
|
76
|
+
- Treat "0 rows deleted" as a meaningful condition, per spec.
|
|
77
|
+
|
|
78
|
+
## Patch updates (important)
|
|
79
|
+
|
|
80
|
+
- Avoid ambiguous patterns such as `coalesce(param, column)` by default.
|
|
81
|
+
- Contracts should distinguish:
|
|
82
|
+
- "not provided"
|
|
83
|
+
- "explicitly set to null"
|
|
84
|
+
- If patch semantics are needed, implement them explicitly via:
|
|
85
|
+
- separate SQL variants, or
|
|
86
|
+
- explicit contract types that preserve intent.
|
|
87
|
+
|
|
88
|
+
## Testing rule (required)
|
|
89
|
+
|
|
90
|
+
- Every public repository method MUST be covered by tests.
|
|
91
|
+
- Tests should verify:
|
|
92
|
+
- correct mapping behavior
|
|
93
|
+
- correct "0 rows" behavior for UPDATE/DELETE
|
|
94
|
+
- correct error surfaces (do not silently succeed)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# src/repositories/views AGENTS
|
|
2
|
+
|
|
3
|
+
This folder is for complex read-only queries.
|
|
4
|
+
|
|
5
|
+
## Scope
|
|
6
|
+
|
|
7
|
+
- Complex SELECT queries (joins, aggregations, window functions).
|
|
8
|
+
- Read models that are not 1:1 with a single table.
|
|
9
|
+
|
|
10
|
+
## Allowed
|
|
11
|
+
|
|
12
|
+
- Multi-table joins and aggregations.
|
|
13
|
+
- Purpose-built DTOs for read models.
|
|
14
|
+
- Validation at the boundary (catalog validator or repository-level validator).
|
|
15
|
+
|
|
16
|
+
## Forbidden
|
|
17
|
+
|
|
18
|
+
- INSERT/UPDATE/DELETE in this folder by default.
|
|
19
|
+
- Hidden write side-effects.
|
|
20
|
+
|
|
21
|
+
## Guidance
|
|
22
|
+
|
|
23
|
+
- Keep query intent clear in naming.
|
|
24
|
+
- Document cardinality assumptions (one, many, optional).
|
|
25
|
+
- Prefer stable ordering if tests rely on order.
|