@rawsql-ts/ztd-cli 0.14.4 → 0.16.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 +25 -11
- package/dist/commands/init.js +27 -10
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/lint.d.ts +59 -0
- package/dist/commands/lint.js +338 -0
- package/dist/commands/lint.js.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/sqlLintHelpers.d.ts +18 -0
- package/dist/utils/sqlLintHelpers.js +270 -0
- package/dist/utils/sqlLintHelpers.js.map +1 -0
- package/package.json +11 -4
- package/templates/AGENTS.md +95 -53
- package/templates/README.md +45 -67
- 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/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/db/sql-client.ts +1 -1
- package/templates/src/repositories/user-accounts.ts +179 -0
- package/templates/tests/AGENTS.md +59 -6
- package/templates/tests/support/global-setup.ts +1 -1
- package/templates/tests/support/testkit-client.ts +4 -4
- package/templates/tests/user-profiles.test.ts +161 -0
- package/templates/tests/writer-constraints.test.ts +32 -0
- package/templates/tests/ztd-layout.generated.ts +0 -2
- package/templates/tsconfig.json +1 -2
- package/templates/ztd/AGENTS.md +10 -85
- package/templates/ztd/README.md +10 -79
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runSqlLint = runSqlLint;
|
|
7
|
+
exports.registerLintCommand = registerLintCommand;
|
|
8
|
+
exports.buildParserFailure = buildParserFailure;
|
|
9
|
+
const node_fs_1 = require("node:fs");
|
|
10
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
11
|
+
const pg_1 = require("pg");
|
|
12
|
+
const rawsql_ts_1 = require("rawsql-ts");
|
|
13
|
+
const testkit_core_1 = require("@rawsql-ts/testkit-core");
|
|
14
|
+
const adapter_node_pg_1 = require("@rawsql-ts/adapter-node-pg");
|
|
15
|
+
const postgresql_1 = require("@testcontainers/postgresql");
|
|
16
|
+
const ztdProjectConfig_1 = require("../utils/ztdProjectConfig");
|
|
17
|
+
const sqlLintHelpers_1 = require("../utils/sqlLintHelpers");
|
|
18
|
+
/**
|
|
19
|
+
* Validate every SQL file against the configured DDL fixtures by replaying each
|
|
20
|
+
* statement through `@rawsql-ts/adapter-node-pg`'s `PgTestkitClient`.
|
|
21
|
+
* @param options Configuration values that describe which files and schemas to lint.
|
|
22
|
+
* @returns A summary of the failures observed and how many files were processed.
|
|
23
|
+
*/
|
|
24
|
+
async function runSqlLint(options) {
|
|
25
|
+
const { sqlFiles, ddlDirectories, defaultSchema, searchPath, ddlLint, client } = options;
|
|
26
|
+
let tableDefinitions;
|
|
27
|
+
try {
|
|
28
|
+
const resolver = new testkit_core_1.TableNameResolver({ defaultSchema, searchPath });
|
|
29
|
+
const loader = new testkit_core_1.DdlFixtureLoader({
|
|
30
|
+
directories: ddlDirectories,
|
|
31
|
+
tableNameResolver: resolver,
|
|
32
|
+
ddlLint
|
|
33
|
+
});
|
|
34
|
+
const fixtures = loader.getFixtures();
|
|
35
|
+
tableDefinitions = fixtures.map((fixture) => fixture.tableDefinition);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
return {
|
|
39
|
+
failures: [buildTransformFailureFromLoaderError(error, ddlDirectories)],
|
|
40
|
+
filesChecked: sqlFiles.length
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const enumLabels = (0, sqlLintHelpers_1.extractEnumLabels)(ddlDirectories);
|
|
44
|
+
const tableRows = tableDefinitions.map((definition) => ({
|
|
45
|
+
tableName: definition.name,
|
|
46
|
+
rows: [(0, sqlLintHelpers_1.buildLintFixtureRow)(definition, enumLabels)]
|
|
47
|
+
}));
|
|
48
|
+
// Build fixture data so that required columns pass the Postgres checks.
|
|
49
|
+
let rewrittenStatement = null;
|
|
50
|
+
const testkit = (0, adapter_node_pg_1.createPgTestkitClient)({
|
|
51
|
+
connectionFactory: async () => client,
|
|
52
|
+
tableDefinitions,
|
|
53
|
+
tableRows,
|
|
54
|
+
defaultSchema,
|
|
55
|
+
searchPath,
|
|
56
|
+
// Track the rewritten SQL so we can show it when a validation failure occurs.
|
|
57
|
+
onExecute: (sql) => {
|
|
58
|
+
rewrittenStatement = sql;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
const failures = [];
|
|
62
|
+
try {
|
|
63
|
+
for (const filePath of sqlFiles) {
|
|
64
|
+
const contents = readFileSafe(filePath);
|
|
65
|
+
await lintFile(filePath, contents, testkit, failures, () => {
|
|
66
|
+
rewrittenStatement = null;
|
|
67
|
+
}, () => rewrittenStatement);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
await testkit.close();
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
failures,
|
|
75
|
+
filesChecked: sqlFiles.length
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Register the `ztd lint` CLI command that validates raw SQL with a temporary Postgres instance.
|
|
80
|
+
* @param program CLI root command that receives the lint subcommand.
|
|
81
|
+
*/
|
|
82
|
+
function registerLintCommand(program) {
|
|
83
|
+
program
|
|
84
|
+
.command('lint <path>')
|
|
85
|
+
.description('Lint SQL files for syntax and analysis correctness via ZTD')
|
|
86
|
+
.action(async (pattern) => {
|
|
87
|
+
await runLintCommand(pattern);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
async function runLintCommand(pattern) {
|
|
91
|
+
var _a;
|
|
92
|
+
const config = (0, ztdProjectConfig_1.loadZtdProjectConfig)();
|
|
93
|
+
const projectRoot = process.cwd();
|
|
94
|
+
const ddlRoot = node_path_1.default.resolve(projectRoot, config.ddlDir);
|
|
95
|
+
const sqlFiles = (0, sqlLintHelpers_1.resolveSqlFiles)(pattern);
|
|
96
|
+
const containerImage = (_a = process.env.ZTD_LINT_DB_IMAGE) !== null && _a !== void 0 ? _a : 'postgres:16-alpine';
|
|
97
|
+
const container = await new postgresql_1.PostgreSqlContainer(containerImage)
|
|
98
|
+
.withDatabase('ztdlint')
|
|
99
|
+
.withUsername('ztd')
|
|
100
|
+
.withPassword('ztd')
|
|
101
|
+
.start();
|
|
102
|
+
const client = new pg_1.Client({ connectionString: container.getConnectionUri() });
|
|
103
|
+
await client.connect();
|
|
104
|
+
try {
|
|
105
|
+
const result = await runSqlLint({
|
|
106
|
+
sqlFiles,
|
|
107
|
+
ddlDirectories: [ddlRoot],
|
|
108
|
+
defaultSchema: config.ddl.defaultSchema,
|
|
109
|
+
searchPath: config.ddl.searchPath,
|
|
110
|
+
ddlLint: config.ddlLint,
|
|
111
|
+
client
|
|
112
|
+
});
|
|
113
|
+
if (result.failures.length > 0) {
|
|
114
|
+
reportFailures(result.failures);
|
|
115
|
+
process.exitCode = 1;
|
|
116
|
+
throw new Error('ztd lint failed');
|
|
117
|
+
}
|
|
118
|
+
// Success is implied by the absence of failures, so the command stays silent.
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
await client.end().catch(() => undefined);
|
|
122
|
+
await container.stop();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function readFileSafe(filePath) {
|
|
126
|
+
return (0, node_fs_1.readFileSync)(filePath, 'utf8');
|
|
127
|
+
}
|
|
128
|
+
async function lintFile(filePath, contents, testkit, failures, resetRewritten, getRewritten) {
|
|
129
|
+
let split;
|
|
130
|
+
try {
|
|
131
|
+
split = rawsql_ts_1.MultiQuerySplitter.split(contents);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
failures.push(buildParserFailure(filePath, contents, error));
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
// Validate every statement that survives the splitter to catch syntax and semantic issues.
|
|
138
|
+
for (const chunk of split.queries) {
|
|
139
|
+
if (chunk.isEmpty) {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
const statement = chunk.sql.trim();
|
|
143
|
+
if (!statement) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
try {
|
|
147
|
+
rawsql_ts_1.SqlParser.parse(statement);
|
|
148
|
+
}
|
|
149
|
+
catch (parseError) {
|
|
150
|
+
failures.push(buildParserFailure(filePath, statement, parseError));
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
resetRewritten();
|
|
155
|
+
await executeValidationStatement(testkit, statement);
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
failures.push(buildStatementFailure(filePath, statement, contents, error, getRewritten()));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
async function executeValidationStatement(testkit, statement) {
|
|
163
|
+
// Execute the rewritten statement so fixtures are applied before Postgres validation.
|
|
164
|
+
await testkit.query(statement);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Build a parser failure record that surfaces rawsql-ts errors from runSqlLint.
|
|
168
|
+
* @param filePath The SQL file that triggered the parser issue.
|
|
169
|
+
* @param contents Statement contents to display alongside the error.
|
|
170
|
+
* @param error The parser error produced by rawsql-ts.
|
|
171
|
+
* @returns A failure record that keeps the command output consistent.
|
|
172
|
+
*/
|
|
173
|
+
function buildParserFailure(filePath, contents, error) {
|
|
174
|
+
const message = `RawSQL parser: ${error instanceof Error ? error.message : 'Unknown parser error'}`;
|
|
175
|
+
return buildLintFailure({
|
|
176
|
+
kind: 'parser',
|
|
177
|
+
filePath,
|
|
178
|
+
statement: contents,
|
|
179
|
+
message,
|
|
180
|
+
location: null
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
function buildStatementFailure(filePath, statement, contents, error, rewritten) {
|
|
184
|
+
if (isTransformError(error)) {
|
|
185
|
+
return buildTransformFailureFromStatement(filePath, statement, error, rewritten);
|
|
186
|
+
}
|
|
187
|
+
return buildDbFailure(filePath, statement, contents, error, rewritten);
|
|
188
|
+
}
|
|
189
|
+
function buildDbFailure(filePath, statement, contents, error, rewritten) {
|
|
190
|
+
var _a;
|
|
191
|
+
const pgError = error;
|
|
192
|
+
const position = typeof pgError.position === 'string'
|
|
193
|
+
? Number(pgError.position) - 1
|
|
194
|
+
: typeof pgError.position === 'number'
|
|
195
|
+
? pgError.position
|
|
196
|
+
: undefined;
|
|
197
|
+
const location = position !== undefined ? findLineColumn(contents, position) : null;
|
|
198
|
+
const details = {};
|
|
199
|
+
if (typeof pgError.code === 'string') {
|
|
200
|
+
details.code = pgError.code;
|
|
201
|
+
}
|
|
202
|
+
if (typeof pgError.position === 'string' && !Number.isNaN(Number(pgError.position))) {
|
|
203
|
+
details.position = Number(pgError.position);
|
|
204
|
+
}
|
|
205
|
+
else if (typeof pgError.position === 'number') {
|
|
206
|
+
details.position = pgError.position;
|
|
207
|
+
}
|
|
208
|
+
if (typeof pgError.detail === 'string') {
|
|
209
|
+
details.detail = pgError.detail;
|
|
210
|
+
}
|
|
211
|
+
if (typeof pgError.hint === 'string') {
|
|
212
|
+
details.hint = pgError.hint;
|
|
213
|
+
}
|
|
214
|
+
return buildLintFailure({
|
|
215
|
+
kind: 'db',
|
|
216
|
+
filePath,
|
|
217
|
+
statement,
|
|
218
|
+
message: (_a = pgError.message) !== null && _a !== void 0 ? _a : 'Unknown error',
|
|
219
|
+
location,
|
|
220
|
+
rewritten,
|
|
221
|
+
details: Object.keys(details).length > 0 ? details : undefined
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
function buildTransformFailureFromStatement(filePath, statement, error, rewritten) {
|
|
225
|
+
const message = `ZTD transform: ${error.message}`;
|
|
226
|
+
const details = getTransformDetails(error);
|
|
227
|
+
return buildLintFailure({
|
|
228
|
+
kind: 'transform',
|
|
229
|
+
filePath,
|
|
230
|
+
statement,
|
|
231
|
+
message,
|
|
232
|
+
location: null,
|
|
233
|
+
rewritten,
|
|
234
|
+
details
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
function buildTransformFailureFromLoaderError(error, ddlDirectories) {
|
|
238
|
+
if (error instanceof testkit_core_1.DdlLintError && error.diagnostics.length > 0) {
|
|
239
|
+
const diag = error.diagnostics[0];
|
|
240
|
+
const filePath = resolveDdlFailurePath(diag.source, ddlDirectories);
|
|
241
|
+
return buildLintFailure({
|
|
242
|
+
kind: 'transform',
|
|
243
|
+
filePath,
|
|
244
|
+
message: `ZTD transform: ${diag.message}`,
|
|
245
|
+
location: null,
|
|
246
|
+
details: { code: diag.code }
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
const filePath = resolveDdlFailurePath(undefined, ddlDirectories);
|
|
250
|
+
return buildLintFailure({
|
|
251
|
+
kind: 'transform',
|
|
252
|
+
filePath,
|
|
253
|
+
message: `ZTD transform: ${error instanceof Error ? error.message : 'Unknown transform error'}`,
|
|
254
|
+
location: null
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
function resolveDdlFailurePath(source, directories) {
|
|
258
|
+
if (source) {
|
|
259
|
+
return node_path_1.default.resolve(process.cwd(), source);
|
|
260
|
+
}
|
|
261
|
+
if (directories.length) {
|
|
262
|
+
return node_path_1.default.resolve(directories[0]);
|
|
263
|
+
}
|
|
264
|
+
return process.cwd();
|
|
265
|
+
}
|
|
266
|
+
function getTransformDetails(error) {
|
|
267
|
+
if (error instanceof testkit_core_1.MissingFixtureError) {
|
|
268
|
+
return { code: 'missing-fixture' };
|
|
269
|
+
}
|
|
270
|
+
if (error instanceof testkit_core_1.SchemaValidationError) {
|
|
271
|
+
return { code: 'schema-validation' };
|
|
272
|
+
}
|
|
273
|
+
if (error instanceof testkit_core_1.QueryRewriteError) {
|
|
274
|
+
return { code: 'query-rewrite' };
|
|
275
|
+
}
|
|
276
|
+
return undefined;
|
|
277
|
+
}
|
|
278
|
+
function isTransformError(error) {
|
|
279
|
+
return (error instanceof testkit_core_1.MissingFixtureError ||
|
|
280
|
+
error instanceof testkit_core_1.SchemaValidationError ||
|
|
281
|
+
error instanceof testkit_core_1.QueryRewriteError);
|
|
282
|
+
}
|
|
283
|
+
function buildLintFailure(params) {
|
|
284
|
+
var _a, _b;
|
|
285
|
+
return {
|
|
286
|
+
kind: params.kind,
|
|
287
|
+
filePath: params.filePath,
|
|
288
|
+
statement: params.statement,
|
|
289
|
+
message: params.message,
|
|
290
|
+
location: (_a = params.location) !== null && _a !== void 0 ? _a : null,
|
|
291
|
+
rewritten: (_b = params.rewritten) !== null && _b !== void 0 ? _b : null,
|
|
292
|
+
details: params.details
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
function findLineColumn(contents, position) {
|
|
296
|
+
const lines = contents.split(/\r?\n/);
|
|
297
|
+
let offset = 0;
|
|
298
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
299
|
+
const lineLength = lines[i].length + 1;
|
|
300
|
+
if (position < offset + lineLength) {
|
|
301
|
+
return {
|
|
302
|
+
line: i + 1,
|
|
303
|
+
column: position - offset + 1
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
offset += lineLength;
|
|
307
|
+
}
|
|
308
|
+
return {
|
|
309
|
+
line: lines.length,
|
|
310
|
+
column: lines[lines.length - 1].length + 1
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
function reportFailures(failures) {
|
|
314
|
+
var _a, _b, _c, _d;
|
|
315
|
+
for (const failure of failures) {
|
|
316
|
+
console.error(`\n[${failure.filePath}] (${failure.kind}) ${failure.message}`);
|
|
317
|
+
if (failure.location) {
|
|
318
|
+
console.error(`at line ${failure.location.line} column ${failure.location.column}`);
|
|
319
|
+
}
|
|
320
|
+
if (((_a = failure.details) === null || _a === void 0 ? void 0 : _a.position) !== undefined) {
|
|
321
|
+
console.error(`position: ${failure.details.position}`);
|
|
322
|
+
}
|
|
323
|
+
if ((_b = failure.details) === null || _b === void 0 ? void 0 : _b.code) {
|
|
324
|
+
console.error(`code: ${failure.details.code}`);
|
|
325
|
+
}
|
|
326
|
+
if ((_c = failure.details) === null || _c === void 0 ? void 0 : _c.detail) {
|
|
327
|
+
console.error(`detail: ${failure.details.detail}`);
|
|
328
|
+
}
|
|
329
|
+
if ((_d = failure.details) === null || _d === void 0 ? void 0 : _d.hint) {
|
|
330
|
+
console.error(`hint: ${failure.details.hint}`);
|
|
331
|
+
}
|
|
332
|
+
if (failure.rewritten) {
|
|
333
|
+
console.error('rewritten SQL:');
|
|
334
|
+
console.error(failure.rewritten);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
//# sourceMappingURL=lint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lint.js","sourceRoot":"","sources":["../../src/commands/lint.ts"],"names":[],"mappings":";;;;;AAqEA,gCA8DC;AAMD,kDAOC;AAqGD,gDAcC;AAnQD,qCAAuC;AACvC,0DAA6B;AAE7B,2BAA4B;AAC5B,yCAA0D;AAE1D,0DASiC;AACjC,gEAAmE;AACnE,2DAAiE;AACjE,gEAAiE;AACjE,4DAIiC;AAwCjC;;;;;GAKG;AACI,KAAK,UAAU,UAAU,CAAC,OAA0B;IACzD,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IACzF,IAAI,gBAAwC,CAAC;IAC7C,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,gCAAiB,CAAC,EAAE,aAAa,EAAE,UAAU,EAAE,CAAC,CAAC;QACtE,MAAM,MAAM,GAAG,IAAI,+BAAgB,CAAC;YAClC,WAAW,EAAE,cAAc;YAC3B,iBAAiB,EAAE,QAAQ;YAC3B,OAAO;SACR,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;QACtC,gBAAgB,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IACxE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,QAAQ,EAAE,CAAC,oCAAoC,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;YACvE,YAAY,EAAE,QAAQ,CAAC,MAAM;SAC9B,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,IAAA,kCAAiB,EAAC,cAAc,CAAC,CAAC;IACrD,MAAM,SAAS,GAAuB,gBAAgB,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAC1E,SAAS,EAAE,UAAU,CAAC,IAAI;QAC1B,IAAI,EAAE,CAAC,IAAA,oCAAmB,EAAC,UAAU,EAAE,UAAU,CAAC,CAAC;KACpD,CAAC,CAAC,CAAC;IAEJ,wEAAwE;IACxE,IAAI,kBAAkB,GAAkB,IAAI,CAAC;IAC7C,MAAM,OAAO,GAAG,IAAA,uCAAqB,EAAC;QACpC,iBAAiB,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM;QACrC,gBAAgB;QAChB,SAAS;QACT,aAAa;QACb,UAAU;QACV,8EAA8E;QAC9E,SAAS,EAAE,CAAC,GAAW,EAAE,EAAE;YACzB,kBAAkB,GAAG,GAAG,CAAC;QAC3B,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAkB,EAAE,CAAC;IACnC,IAAI,CAAC;QACH,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;YAChC,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;YACxC,MAAM,QAAQ,CACZ,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,GAAG,EAAE;gBACH,kBAAkB,GAAG,IAAI,CAAC;YAC5B,CAAC,EACD,GAAG,EAAE,CAAC,kBAAkB,CACzB,CAAC;QACJ,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;IAED,OAAO;QACL,QAAQ;QACR,YAAY,EAAE,QAAQ,CAAC,MAAM;KAC9B,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAgB,mBAAmB,CAAC,OAAgB;IAClD,OAAO;SACJ,OAAO,CAAC,aAAa,CAAC;SACtB,WAAW,CAAC,4DAA4D,CAAC;SACzE,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,EAAE;QAChC,MAAM,cAAc,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACP,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,OAAe;;IAC3C,MAAM,MAAM,GAAG,IAAA,uCAAoB,GAAE,CAAC;IACtC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAClC,MAAM,OAAO,GAAG,mBAAI,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACzD,MAAM,QAAQ,GAAG,IAAA,gCAAe,EAAC,OAAO,CAAC,CAAC;IAE1C,MAAM,cAAc,GAAG,MAAA,OAAO,CAAC,GAAG,CAAC,iBAAiB,mCAAI,oBAAoB,CAAC;IAC7E,MAAM,SAAS,GAAG,MAAM,IAAI,gCAAmB,CAAC,cAAc,CAAC;SAC5D,YAAY,CAAC,SAAS,CAAC;SACvB,YAAY,CAAC,KAAK,CAAC;SACnB,YAAY,CAAC,KAAK,CAAC;SACnB,KAAK,EAAE,CAAC;IACX,MAAM,MAAM,GAAG,IAAI,WAAM,CAAC,EAAE,gBAAgB,EAAE,SAAS,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;IAC9E,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;IAEvB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;YAC9B,QAAQ;YACR,cAAc,EAAE,CAAC,OAAO,CAAC;YACzB,aAAa,EAAE,MAAM,CAAC,GAAG,CAAC,aAAa;YACvC,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,UAAU;YACjC,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,MAAM;SACP,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/B,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAChC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACrC,CAAC;QAED,8EAA8E;IAChF,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC1C,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,QAAgB;IACpC,OAAO,IAAA,sBAAY,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AACxC,CAAC;AAED,KAAK,UAAU,QAAQ,CACrB,QAAgB,EAChB,QAAgB,EAChB,OAAiD,EACjD,QAAuB,EACvB,cAA0B,EAC1B,YAAiC;IAEjC,IAAI,KAAK,CAAC;IACV,IAAI,CAAC;QACH,KAAK,GAAG,8BAAkB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,QAAQ,CAAC,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;QAC7D,OAAO;IACT,CAAC;IAED,2FAA2F;IAC3F,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClC,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,SAAS;QACX,CAAC;QACD,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,SAAS;QACX,CAAC;QACD,IAAI,CAAC;YACH,qBAAS,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,UAAU,EAAE,CAAC;YACpB,QAAQ,CAAC,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;YACnE,SAAS;QACX,CAAC;QACD,IAAI,CAAC;YACH,cAAc,EAAE,CAAC;YACjB,MAAM,0BAA0B,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,QAAQ,CAAC,IAAI,CACX,qBAAqB,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAC5E,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,0BAA0B,CACvC,OAAiD,EACjD,SAAiB;IAEjB,sFAAsF;IACtF,MAAM,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;AACjC,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,kBAAkB,CAChC,QAAgB,EAChB,QAAgB,EAChB,KAAc;IAEd,MAAM,OAAO,GACX,kBAAkB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,sBAAsB,EAAE,CAAC;IACtF,OAAO,gBAAgB,CAAC;QACtB,IAAI,EAAE,QAAQ;QACd,QAAQ;QACR,SAAS,EAAE,QAAQ;QACnB,OAAO;QACP,QAAQ,EAAE,IAAI;KACf,CAAC,CAAC;AACL,CAAC;AAED,SAAS,qBAAqB,CAC5B,QAAgB,EAChB,SAAiB,EACjB,QAAgB,EAChB,KAAc,EACd,SAAwB;IAExB,IAAI,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,kCAAkC,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IACnF,CAAC;IACD,OAAO,cAAc,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;AACzE,CAAC;AAED,SAAS,cAAc,CACrB,QAAgB,EAChB,SAAiB,EACjB,QAAgB,EAChB,KAAc,EACd,SAAwB;;IAExB,MAAM,OAAO,GAAG,KAAgC,CAAC;IACjD,MAAM,QAAQ,GACZ,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ;QAClC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;QAC9B,CAAC,CAAC,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ;YACpC,CAAC,CAAC,OAAO,CAAC,QAAQ;YAClB,CAAC,CAAC,SAAS,CAAC;IAClB,MAAM,QAAQ,GACZ,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACrE,MAAM,OAAO,GAAuB,EAAE,CAAC;IACvC,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACrC,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC9B,CAAC;IACD,IAAI,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;QACpF,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;SAAM,IAAI,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IACtC,CAAC;IACD,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACvC,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAClC,CAAC;IACD,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACrC,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC9B,CAAC;IACD,OAAO,gBAAgB,CAAC;QACtB,IAAI,EAAE,IAAI;QACV,QAAQ;QACR,SAAS;QACT,OAAO,EAAE,MAAC,OAAO,CAAC,OAAkB,mCAAI,eAAe;QACvD,QAAQ;QACR,SAAS;QACT,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;KAC/D,CAAC,CAAC;AACL,CAAC;AAED,SAAS,kCAAkC,CACzC,QAAgB,EAChB,SAAiB,EACjB,KAAsE,EACtE,SAAwB;IAExB,MAAM,OAAO,GAAG,kBAAkB,KAAK,CAAC,OAAO,EAAE,CAAC;IAClD,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAC3C,OAAO,gBAAgB,CAAC;QACtB,IAAI,EAAE,WAAW;QACjB,QAAQ;QACR,SAAS;QACT,OAAO;QACP,QAAQ,EAAE,IAAI;QACd,SAAS;QACT,OAAO;KACR,CAAC,CAAC;AACL,CAAC;AAED,SAAS,oCAAoC,CAC3C,KAAc,EACd,cAAwB;IAExB,IAAI,KAAK,YAAY,2BAAY,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClE,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,QAAQ,GAAG,qBAAqB,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;QACpE,OAAO,gBAAgB,CAAC;YACtB,IAAI,EAAE,WAAW;YACjB,QAAQ;YACR,OAAO,EAAE,kBAAkB,IAAI,CAAC,OAAO,EAAE;YACzC,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;SAC7B,CAAC,CAAC;IACL,CAAC;IACD,MAAM,QAAQ,GAAG,qBAAqB,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IAClE,OAAO,gBAAgB,CAAC;QACtB,IAAI,EAAE,WAAW;QACjB,QAAQ;QACR,OAAO,EAAE,kBAAkB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,yBAAyB,EAAE;QAC/F,QAAQ,EAAE,IAAI;KACf,CAAC,CAAC;AACL,CAAC;AAED,SAAS,qBAAqB,CAC5B,MAA0B,EAC1B,WAAqB;IAErB,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,mBAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC;QACvB,OAAO,mBAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC;AACvB,CAAC;AAED,SAAS,mBAAmB,CAC1B,KAAsE;IAEtE,IAAI,KAAK,YAAY,kCAAmB,EAAE,CAAC;QACzC,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC;IACrC,CAAC;IACD,IAAI,KAAK,YAAY,oCAAqB,EAAE,CAAC;QAC3C,OAAO,EAAE,IAAI,EAAE,mBAAmB,EAAE,CAAC;IACvC,CAAC;IACD,IAAI,KAAK,YAAY,gCAAiB,EAAE,CAAC;QACvC,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;IACnC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,gBAAgB,CACvB,KAAc;IAEd,OAAO,CACL,KAAK,YAAY,kCAAmB;QACpC,KAAK,YAAY,oCAAqB;QACtC,KAAK,YAAY,gCAAiB,CACnC,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,MAQzB;;IACC,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,QAAQ,EAAE,MAAA,MAAM,CAAC,QAAQ,mCAAI,IAAI;QACjC,SAAS,EAAE,MAAA,MAAM,CAAC,SAAS,mCAAI,IAAI;QACnC,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CACrB,QAAgB,EAChB,QAAgB;IAEhB,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;QACvC,IAAI,QAAQ,GAAG,MAAM,GAAG,UAAU,EAAE,CAAC;YACnC,OAAO;gBACL,IAAI,EAAE,CAAC,GAAG,CAAC;gBACX,MAAM,EAAE,QAAQ,GAAG,MAAM,GAAG,CAAC;aAC9B,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,UAAU,CAAC;IACvB,CAAC;IACD,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,MAAM;QAClB,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC;KAC3C,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,QAAuB;;IAC7C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,MAAM,OAAO,CAAC,QAAQ,MAAM,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QAC9E,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACrB,OAAO,CAAC,KAAK,CACX,WAAW,OAAO,CAAC,QAAQ,CAAC,IAAI,WAAW,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,CACrE,CAAC;QACJ,CAAC;QACD,IAAI,CAAA,MAAA,OAAO,CAAC,OAAO,0CAAE,QAAQ,MAAK,SAAS,EAAE,CAAC;YAC5C,OAAO,CAAC,KAAK,CAAC,aAAa,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;QACzD,CAAC;QACD,IAAI,MAAA,OAAO,CAAC,OAAO,0CAAE,IAAI,EAAE,CAAC;YAC1B,OAAO,CAAC,KAAK,CAAC,SAAS,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QACjD,CAAC;QACD,IAAI,MAAA,OAAO,CAAC,OAAO,0CAAE,MAAM,EAAE,CAAC;YAC5B,OAAO,CAAC,KAAK,CAAC,WAAW,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACrD,CAAC;QACD,IAAI,MAAA,OAAO,CAAC,OAAO,0CAAE,IAAI,EAAE,CAAC;YAC1B,OAAO,CAAC,KAAK,CAAC,SAAS,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QACjD,CAAC;QACD,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;YAChC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,11 +4,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
const commander_1 = require("commander");
|
|
5
5
|
const ddl_1 = require("./commands/ddl");
|
|
6
6
|
const init_1 = require("./commands/init");
|
|
7
|
+
const lint_1 = require("./commands/lint");
|
|
7
8
|
const ztdConfigCommand_1 = require("./commands/ztdConfigCommand");
|
|
8
9
|
async function main() {
|
|
9
10
|
const program = new commander_1.Command();
|
|
10
11
|
program.name('ztd').description('Zero Table Dependency scaffolding and DDL helpers');
|
|
11
12
|
(0, init_1.registerInitCommand)(program);
|
|
13
|
+
(0, lint_1.registerLintCommand)(program);
|
|
12
14
|
(0, ztdConfigCommand_1.registerZtdConfigCommand)(program);
|
|
13
15
|
(0, ddl_1.registerDdlCommands)(program);
|
|
14
16
|
await program.parseAsync(process.argv);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,wCAAqD;AACrD,0CAAsD;AACtD,kEAAuE;AAEvE,KAAK,UAAU,IAAI;IACjB,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;IAC9B,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,mDAAmD,CAAC,CAAC;IAErF,IAAA,0BAAmB,EAAC,OAAO,CAAC,CAAC;IAC7B,IAAA,2CAAwB,EAAC,OAAO,CAAC,CAAC;IAClC,IAAA,yBAAmB,EAAC,OAAO,CAAC,CAAC;IAE7B,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,wCAAqD;AACrD,0CAAsD;AACtD,0CAAsD;AACtD,kEAAuE;AAEvE,KAAK,UAAU,IAAI;IACjB,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;IAC9B,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,mDAAmD,CAAC,CAAC;IAErF,IAAA,0BAAmB,EAAC,OAAO,CAAC,CAAC;IAC7B,IAAA,0BAAmB,EAAC,OAAO,CAAC,CAAC;IAC7B,IAAA,2CAAwB,EAAC,OAAO,CAAC,CAAC;IAClC,IAAA,yBAAmB,EAAC,OAAO,CAAC,CAAC;IAE7B,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { TableDefinitionModel } from 'rawsql-ts';
|
|
2
|
+
import type { FixtureRow } from '@rawsql-ts/testkit-core';
|
|
3
|
+
/**
|
|
4
|
+
* Resolve a CLI argument into an absolute list of `.sql` files.
|
|
5
|
+
*/
|
|
6
|
+
export declare function resolveSqlFiles(pattern: string): string[];
|
|
7
|
+
/**
|
|
8
|
+
* Scan the configured DDL directories for CREATE TYPE ... AS ENUM definitions.
|
|
9
|
+
*/
|
|
10
|
+
export declare function extractEnumLabels(directories: string[], extensions?: string[]): Map<string, string[]>;
|
|
11
|
+
/**
|
|
12
|
+
* Build a fixture row for linting using minimal values derived from the column types.
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildLintFixtureRow(definition: TableDefinitionModel, enumLabels: Map<string, string[]>): FixtureRow;
|
|
15
|
+
/**
|
|
16
|
+
* Infer a default value for a required column to keep Postgres happy.
|
|
17
|
+
*/
|
|
18
|
+
export declare function inferDefaultValue(typeName: string | undefined, enumLabels: Map<string, string[]>): unknown;
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.resolveSqlFiles = resolveSqlFiles;
|
|
7
|
+
exports.extractEnumLabels = extractEnumLabels;
|
|
8
|
+
exports.buildLintFixtureRow = buildLintFixtureRow;
|
|
9
|
+
exports.inferDefaultValue = inferDefaultValue;
|
|
10
|
+
const node_fs_1 = require("node:fs");
|
|
11
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
12
|
+
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
13
|
+
const options_1 = require("../commands/options");
|
|
14
|
+
const collectSqlFiles_1 = require("./collectSqlFiles");
|
|
15
|
+
/**
|
|
16
|
+
* Resolve a CLI argument into an absolute list of `.sql` files.
|
|
17
|
+
*/
|
|
18
|
+
function resolveSqlFiles(pattern) {
|
|
19
|
+
const absolutePattern = node_path_1.default.resolve(pattern);
|
|
20
|
+
if ((0, node_fs_1.existsSync)(absolutePattern)) {
|
|
21
|
+
const stats = (0, node_fs_1.lstatSync)(absolutePattern);
|
|
22
|
+
if (stats.isFile()) {
|
|
23
|
+
return [toPosixPattern(absolutePattern)];
|
|
24
|
+
}
|
|
25
|
+
if (stats.isDirectory()) {
|
|
26
|
+
const matches = fast_glob_1.default.sync(toPosixPattern(node_path_1.default.join(absolutePattern, '**', '*.sql')), {
|
|
27
|
+
absolute: true,
|
|
28
|
+
onlyFiles: true
|
|
29
|
+
});
|
|
30
|
+
if (matches.length === 0) {
|
|
31
|
+
throw new Error(`No SQL files were found under ${absolutePattern}`);
|
|
32
|
+
}
|
|
33
|
+
return matches.map(toPosixPattern).sort();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const globMatches = fast_glob_1.default.sync(toPosixPattern(pattern), {
|
|
37
|
+
absolute: true,
|
|
38
|
+
onlyFiles: true
|
|
39
|
+
});
|
|
40
|
+
if (globMatches.length === 0) {
|
|
41
|
+
throw new Error(`No SQL files matched ${pattern}`);
|
|
42
|
+
}
|
|
43
|
+
return globMatches.map(toPosixPattern).sort();
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Scan the configured DDL directories for CREATE TYPE ... AS ENUM definitions.
|
|
47
|
+
*/
|
|
48
|
+
function extractEnumLabels(directories, extensions = options_1.DEFAULT_EXTENSIONS) {
|
|
49
|
+
const enums = new Map();
|
|
50
|
+
for (const directory of directories) {
|
|
51
|
+
if (!(0, node_fs_1.existsSync)(directory)) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const files = (0, collectSqlFiles_1.collectSqlFiles)([directory], extensions);
|
|
55
|
+
for (const { sql } of files) {
|
|
56
|
+
for (const { name, labels } of parseEnumDefinitions(sql)) {
|
|
57
|
+
if (!labels.length) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
const normalized = normalizeQualifiedName(name);
|
|
61
|
+
if (!normalized) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (!enums.has(normalized)) {
|
|
65
|
+
enums.set(normalized, labels);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return enums;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Build a fixture row for linting using minimal values derived from the column types.
|
|
74
|
+
*/
|
|
75
|
+
function buildLintFixtureRow(definition, enumLabels) {
|
|
76
|
+
const row = {};
|
|
77
|
+
for (const column of definition.columns) {
|
|
78
|
+
row[column.name] = column.required
|
|
79
|
+
? inferDefaultValue(column.typeName, enumLabels)
|
|
80
|
+
: null;
|
|
81
|
+
}
|
|
82
|
+
return row;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Infer a default value for a required column to keep Postgres happy.
|
|
86
|
+
*/
|
|
87
|
+
function inferDefaultValue(typeName, enumLabels) {
|
|
88
|
+
if (!typeName) {
|
|
89
|
+
return '';
|
|
90
|
+
}
|
|
91
|
+
const normalized = normalizeTypeName(typeName);
|
|
92
|
+
const enumMatch = enumLabels.get(normalized.key);
|
|
93
|
+
if (enumMatch && enumMatch.length > 0) {
|
|
94
|
+
return enumMatch[0];
|
|
95
|
+
}
|
|
96
|
+
if (normalized.isArray) {
|
|
97
|
+
return '{}';
|
|
98
|
+
}
|
|
99
|
+
if (normalized.base.startsWith('int') ||
|
|
100
|
+
normalized.base.includes('serial') ||
|
|
101
|
+
normalized.base === 'numeric' ||
|
|
102
|
+
normalized.base === 'decimal' ||
|
|
103
|
+
normalized.base === 'real' ||
|
|
104
|
+
normalized.base === 'double precision') {
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
107
|
+
if (normalized.base === 'boolean' || normalized.base === 'bool') {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
if (normalized.base === 'uuid') {
|
|
111
|
+
return '00000000-0000-0000-0000-000000000000';
|
|
112
|
+
}
|
|
113
|
+
if (normalized.base.startsWith('character') ||
|
|
114
|
+
normalized.base.startsWith('varchar') ||
|
|
115
|
+
normalized.base === 'text' ||
|
|
116
|
+
normalized.base === 'citext' ||
|
|
117
|
+
normalized.base === 'name') {
|
|
118
|
+
return '';
|
|
119
|
+
}
|
|
120
|
+
if (normalized.base === 'date') {
|
|
121
|
+
return '1970-01-01';
|
|
122
|
+
}
|
|
123
|
+
if (normalized.base.startsWith('timestamp')) {
|
|
124
|
+
return '1970-01-01 00:00:00';
|
|
125
|
+
}
|
|
126
|
+
if (normalized.base.startsWith('time')) {
|
|
127
|
+
return '00:00:00';
|
|
128
|
+
}
|
|
129
|
+
if (normalized.base === 'json' || normalized.base === 'jsonb') {
|
|
130
|
+
return '{}';
|
|
131
|
+
}
|
|
132
|
+
return '';
|
|
133
|
+
}
|
|
134
|
+
function normalizeTypeName(typeName) {
|
|
135
|
+
const segments = splitQualifiedName(typeName);
|
|
136
|
+
if (segments.length === 0) {
|
|
137
|
+
return { base: '', key: '', isArray: false };
|
|
138
|
+
}
|
|
139
|
+
const cleaned = segments.map((token) => compactIdentifier(token).toLowerCase());
|
|
140
|
+
let isArray = false;
|
|
141
|
+
let lastSegment = cleaned[cleaned.length - 1];
|
|
142
|
+
if (lastSegment.endsWith('[]')) {
|
|
143
|
+
isArray = true;
|
|
144
|
+
lastSegment = lastSegment.slice(0, -2).trim();
|
|
145
|
+
}
|
|
146
|
+
const base = lastSegment.replace(/\(.*\)$/, '').trim();
|
|
147
|
+
cleaned[cleaned.length - 1] = base;
|
|
148
|
+
return {
|
|
149
|
+
base,
|
|
150
|
+
key: cleaned.join('.'),
|
|
151
|
+
isArray
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
function normalizeQualifiedName(value) {
|
|
155
|
+
const segments = splitQualifiedName(value);
|
|
156
|
+
if (segments.length === 0) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
const cleaned = segments.map((segment) => compactIdentifier(segment).toLowerCase());
|
|
160
|
+
return cleaned.join('.');
|
|
161
|
+
}
|
|
162
|
+
function splitQualifiedName(value) {
|
|
163
|
+
const parts = [];
|
|
164
|
+
let buffer = '';
|
|
165
|
+
let inQuotes = false;
|
|
166
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
167
|
+
const char = value[i];
|
|
168
|
+
if (char === '"') {
|
|
169
|
+
buffer += char;
|
|
170
|
+
if (inQuotes && value[i + 1] === '"') {
|
|
171
|
+
buffer += '"';
|
|
172
|
+
i += 1;
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
inQuotes = !inQuotes;
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
if (char === '.' && !inQuotes) {
|
|
179
|
+
if (buffer.length > 0) {
|
|
180
|
+
parts.push(buffer);
|
|
181
|
+
}
|
|
182
|
+
buffer = '';
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
buffer += char;
|
|
186
|
+
}
|
|
187
|
+
if (buffer.length > 0) {
|
|
188
|
+
parts.push(buffer);
|
|
189
|
+
}
|
|
190
|
+
return parts
|
|
191
|
+
.map((segment) => segment.trim())
|
|
192
|
+
.filter(Boolean);
|
|
193
|
+
}
|
|
194
|
+
function compactIdentifier(value) {
|
|
195
|
+
const trimmed = value.trim();
|
|
196
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
|
|
197
|
+
return trimmed
|
|
198
|
+
.slice(1, -1)
|
|
199
|
+
.replace(/""/g, '"');
|
|
200
|
+
}
|
|
201
|
+
return trimmed.replace(/\s+/g, ' ');
|
|
202
|
+
}
|
|
203
|
+
function parseEnumDefinitions(sql) {
|
|
204
|
+
const results = [];
|
|
205
|
+
const regex = /create\s+type\s+(.+?)\s+as\s+enum\s*\(/gsi;
|
|
206
|
+
let match;
|
|
207
|
+
while ((match = regex.exec(sql))) {
|
|
208
|
+
const rawName = match[1].trim();
|
|
209
|
+
const openParenIndex = regex.lastIndex - 1;
|
|
210
|
+
if (openParenIndex < 0 || sql[openParenIndex] !== '(') {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
const { labels, end } = parseEnumLabelList(sql, openParenIndex);
|
|
214
|
+
results.push({ name: rawName, labels });
|
|
215
|
+
regex.lastIndex = end;
|
|
216
|
+
}
|
|
217
|
+
return results;
|
|
218
|
+
}
|
|
219
|
+
function parseEnumLabelList(sql, startIndex) {
|
|
220
|
+
const labels = [];
|
|
221
|
+
let idx = startIndex + 1;
|
|
222
|
+
while (idx < sql.length) {
|
|
223
|
+
idx = skipWhitespace(sql, idx);
|
|
224
|
+
if (sql[idx] === ')') {
|
|
225
|
+
idx += 1;
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
if (sql[idx] === ',') {
|
|
229
|
+
idx += 1;
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
if (sql[idx] !== "'") {
|
|
233
|
+
idx += 1;
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
const { value, newIndex } = parseStringLiteral(sql, idx);
|
|
237
|
+
labels.push(value);
|
|
238
|
+
idx = newIndex;
|
|
239
|
+
}
|
|
240
|
+
return { labels, end: idx };
|
|
241
|
+
}
|
|
242
|
+
function parseStringLiteral(sql, index) {
|
|
243
|
+
let idx = index + 1;
|
|
244
|
+
let value = '';
|
|
245
|
+
while (idx < sql.length) {
|
|
246
|
+
const char = sql[idx];
|
|
247
|
+
if (char === "'") {
|
|
248
|
+
if (sql[idx + 1] === "'") {
|
|
249
|
+
value += "'";
|
|
250
|
+
idx += 2;
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
idx += 1;
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
value += char;
|
|
257
|
+
idx += 1;
|
|
258
|
+
}
|
|
259
|
+
return { value, newIndex: idx };
|
|
260
|
+
}
|
|
261
|
+
function skipWhitespace(sql, index) {
|
|
262
|
+
while (index < sql.length && /\s/.test(sql[index])) {
|
|
263
|
+
index += 1;
|
|
264
|
+
}
|
|
265
|
+
return index;
|
|
266
|
+
}
|
|
267
|
+
function toPosixPattern(value) {
|
|
268
|
+
return value.replace(/\\/g, '/');
|
|
269
|
+
}
|
|
270
|
+
//# sourceMappingURL=sqlLintHelpers.js.map
|