@deterministic-code/datasources-cli 0.1.12 → 0.1.14
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/dist/detect.js +21 -7
- package/dist/generate/CSharpRepositories.js +18 -14
- package/dist/generate/DeterministicProvider.js +23 -7
- package/dist/generate/RepositoryModel.js +10 -4
- package/dist/generate/RepositoryPlan.js +12 -5
- package/dist/generate/RustRepositories.js +42 -31
- package/dist/generate/TypeScriptRepositories.js +22 -18
- package/dist/generate/applyGenerate.js +9 -2
- package/dist/generate/applyMigrations.js +5 -13
- package/dist/generate/casing.js +28 -0
- package/dist/generate/migrateUp.js +2 -8
- package/dist/generate/sqlFlags.js +27 -0
- package/dist/migrateInit.js +4 -3
- package/dist/parse.js +102 -25
- package/dist/run.js +42 -67
- package/dist/setup.js +7 -9
- package/dist/version/applyVersion.js +11 -14
- package/dist/version/delta.js +0 -50
- package/dist/version/render.js +1 -11
- package/dist/wireRegister.js +29 -11
- package/dist/wireRustProviders.js +42 -0
- package/node_modules/@deterministic-code/csharp-generators/dist/import-generator.js +16 -12
- package/node_modules/@deterministic-code/csharp-generators/src/import-generator.test.ts +22 -11
- package/node_modules/@deterministic-code/csharp-generators/src/import-generator.ts +21 -13
- package/node_modules/@deterministic-code/datasources-code-generators/dist/nestedSelectTypes.js +2 -6
- package/node_modules/@deterministic-code/datasources-code-generators/dist/sql/common/infer-reference-types.d.ts +2 -0
- package/node_modules/@deterministic-code/datasources-code-generators/dist/sql/common/infer-reference-types.js +37 -0
- package/node_modules/@deterministic-code/datasources-code-generators/dist/sql/common/reference-target.d.ts +2 -0
- package/node_modules/@deterministic-code/datasources-code-generators/dist/sql/common/reference-target.js +6 -0
- package/node_modules/@deterministic-code/datasources-code-generators/dist/sql/common/sql-schema.d.ts +1 -1
- package/node_modules/@deterministic-code/datasources-code-generators/dist/sql/common/sql-schema.js +3 -6
- package/node_modules/@deterministic-code/datasources-code-generators/dist/sql/common/version-apply.d.ts +1 -0
- package/node_modules/@deterministic-code/datasources-code-generators/dist/sql/common/version-apply.js +38 -1
- package/node_modules/@deterministic-code/datasources-code-generators/dist/sql/common/version-migrations.js +25 -14
- package/node_modules/@deterministic-code/datasources-code-generators/package.json +4 -2
- package/node_modules/@deterministic-code/deterministic-generators-common/README.md +61 -1
- package/node_modules/@deterministic-code/deterministic-generators-common/typescript/parser/dist/specification-parser.js +128 -1
- package/node_modules/@deterministic-code/deterministic-generators-common/typescript/parser/specification-parser.ts +1 -0
- package/node_modules/@deterministic-code/deterministic-generators-common/typescript/parser/version-snapshot.ts +154 -0
- package/node_modules/@deterministic-code/deterministic-generators-common/typescript/parser/yaml-node.ts +2 -2
- package/node_modules/@deterministic-code/rust-generators/dist/import-generator.js +25 -15
- package/node_modules/@deterministic-code/rust-generators/src/import-generator.test.ts +11 -0
- package/node_modules/@deterministic-code/rust-generators/src/import-generator.ts +36 -18
- package/node_modules/@deterministic-code/typescript-generators/dist/generate-frontend-types.js +6 -1
- package/node_modules/@deterministic-code/typescript-generators/dist/generate-frontend-validators.js +6 -1
- package/node_modules/@deterministic-code/typescript-generators/dist/generate-routes.js +1 -1
- package/node_modules/@deterministic-code/typescript-generators/dist/generate-services.js +1 -1
- package/node_modules/@deterministic-code/typescript-generators/dist/import-generator.js +29 -21
- package/node_modules/@deterministic-code/typescript-generators/src/emit.ts +2 -5
- package/node_modules/@deterministic-code/typescript-generators/src/generate-frontend-types.ts +7 -1
- package/node_modules/@deterministic-code/typescript-generators/src/generate-frontend-validators.ts +7 -1
- package/node_modules/@deterministic-code/typescript-generators/src/generate-routes.ts +1 -1
- package/node_modules/@deterministic-code/typescript-generators/src/generate-services.ts +1 -1
- package/node_modules/@deterministic-code/typescript-generators/src/import-generator.test.ts +16 -0
- package/node_modules/@deterministic-code/typescript-generators/src/import-generator.ts +37 -22
- package/package.json +2 -2
|
@@ -45,7 +45,7 @@ const applyMigrateUp = async (command, flags, deps, env = process.env) => {
|
|
|
45
45
|
const connection = values.DATASOURCE_URL ?? "";
|
|
46
46
|
const provider = canonical(values.PROVIDER || scheme(connection) || "");
|
|
47
47
|
if (!provider || !connection) {
|
|
48
|
-
deps.log("migrate-up skipped: set PROVIDER and DATASOURCE_URL, or pass --no-migrate");
|
|
48
|
+
deps.log("migrate-up skipped: set PROVIDER and DATASOURCE_URL, or pass --no-auto-migrate-up");
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
51
|
if (inMemory(connection)) {
|
|
@@ -61,9 +61,6 @@ const applyMigrateUp = async (command, flags, deps, env = process.env) => {
|
|
|
61
61
|
`migrate-up: provider ${provider} is not in backend.datasources (${dialects.join(", ") || "none"})`
|
|
62
62
|
);
|
|
63
63
|
const npx = (verb, extra = []) => [
|
|
64
|
-
"--yes",
|
|
65
|
-
"--package",
|
|
66
|
-
"@deterministic-code/migraters",
|
|
67
64
|
verb,
|
|
68
65
|
"--provider",
|
|
69
66
|
provider,
|
|
@@ -72,10 +69,7 @@ const applyMigrateUp = async (command, flags, deps, env = process.env) => {
|
|
|
72
69
|
...extra
|
|
73
70
|
];
|
|
74
71
|
const setup = npx("migrate-setup");
|
|
75
|
-
const up = npx(
|
|
76
|
-
"migrate-up",
|
|
77
|
-
command.migrationsPath ? ["--migrations-path", command.migrationsPath] : ["--migrations-root", command.migrationsRoot]
|
|
78
|
-
);
|
|
72
|
+
const up = npx("migrate-up", ["--migrations-root", command.migrationsRoot]);
|
|
79
73
|
deps.log(`$ npx ${setup.join(" ")}`);
|
|
80
74
|
if (!flags.dryRun) await deps.run("npx", setup, flags.cwd);
|
|
81
75
|
deps.log(`$ npx ${up.join(" ")}`);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const letterCases = ["Upper", "Lower", "Auto"];
|
|
2
|
+
const parseLetterCaseFlag = (raw, name) => {
|
|
3
|
+
const parsed = letterCases.find((format) => format.toLowerCase() === raw.toLowerCase());
|
|
4
|
+
if (parsed === void 0) throw new Error(`${name} must be one of [${letterCases.join(", ")}] (got "${raw}").`);
|
|
5
|
+
return parsed;
|
|
6
|
+
};
|
|
7
|
+
const overlaySqlFlags = (settings, flags) => ({
|
|
8
|
+
...settings,
|
|
9
|
+
...flags.pluralizeTableNames === void 0 ? {} : { "datasource.pluralize_datatable_names": flags.pluralizeTableNames ? "true" : "false" },
|
|
10
|
+
...flags.tableNames === void 0 ? {} : { "datasource.casing.types": flags.tableNames },
|
|
11
|
+
...flags.columnNames === void 0 ? {} : { "datasource.casing.fields": flags.columnNames },
|
|
12
|
+
...flags.objectNames === void 0 ? {} : { "datasource.casing.objects": flags.objectNames },
|
|
13
|
+
...flags.sqlKeywords === void 0 ? {} : { "datasource.casing.keywords": flags.sqlKeywords }
|
|
14
|
+
});
|
|
15
|
+
const sqlFlagsOf = (flags) => ({
|
|
16
|
+
pluralizeTableNames: flags.pluralizeTableNames,
|
|
17
|
+
tableNames: flags.tableNames,
|
|
18
|
+
columnNames: flags.columnNames,
|
|
19
|
+
objectNames: flags.objectNames,
|
|
20
|
+
sqlKeywords: flags.sqlKeywords
|
|
21
|
+
});
|
|
22
|
+
export {
|
|
23
|
+
letterCases,
|
|
24
|
+
overlaySqlFlags,
|
|
25
|
+
parseLetterCaseFlag,
|
|
26
|
+
sqlFlagsOf
|
|
27
|
+
};
|
package/dist/migrateInit.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
const migrateProviders = ["sqlite", "postgres", "mysql", "sqlserver", "oracle"];
|
|
2
2
|
const migrateLanguage = (ecosystem) => ecosystem === "ts" ? "typescript" : ecosystem;
|
|
3
3
|
const sqlMigrateProviders = (names) => migrateProviders.filter((name) => names.includes(name));
|
|
4
|
-
const
|
|
5
|
-
|
|
4
|
+
const migratersPackage = (env = process.env) => env.MIGRATERS_PACKAGE || "@deterministic-code/migraters";
|
|
5
|
+
const migrateInitCommands = (dialects, language, env = process.env) => dialects.length === 0 ? [] : [
|
|
6
|
+
{ command: "npm", args: ["install", migratersPackage(env)] },
|
|
6
7
|
{
|
|
7
8
|
command: "npx",
|
|
8
9
|
args: [
|
|
9
10
|
"--yes",
|
|
10
11
|
"--package",
|
|
11
|
-
|
|
12
|
+
migratersPackage(env),
|
|
12
13
|
"migrate-init",
|
|
13
14
|
"--language",
|
|
14
15
|
language,
|
package/dist/parse.js
CHANGED
|
@@ -1,42 +1,62 @@
|
|
|
1
1
|
import { isEcosystem } from "./detect.js";
|
|
2
|
+
import { parseCaseFlag } from "./generate/casing.js";
|
|
3
|
+
import { parseLetterCaseFlag } from "./generate/sqlFlags.js";
|
|
2
4
|
import { isDialect } from "./generate/GenerateRequest.js";
|
|
3
5
|
const generateTargets = ["all", "types", "repositories", "datasource"];
|
|
4
6
|
const help = `Usage: datasources <command> [options]
|
|
5
7
|
|
|
6
|
-
setup [
|
|
8
|
+
setup [name...] Interactive .env, datasource install, and optional deterministic/
|
|
7
9
|
--cwd <dir> Consumer project directory (default: .)
|
|
8
|
-
--
|
|
10
|
+
--languages ts|rust|csharp Project languages (default: every type found)
|
|
11
|
+
--datasources <name...> Datasources to install (default: existing .env)
|
|
9
12
|
--dry-run Print package-manager commands without running them
|
|
10
13
|
--yes Setup without prompts (defaults / existing .env)
|
|
11
14
|
|
|
12
|
-
add
|
|
15
|
+
add [name...] Add datasource packages
|
|
13
16
|
--cwd <dir> Consumer project directory (default: .)
|
|
14
|
-
--
|
|
17
|
+
--languages ts|rust|csharp Project languages (default: every type found)
|
|
18
|
+
--datasources <name...> Datasources to add
|
|
15
19
|
--dry-run Print package-manager commands without running them
|
|
16
20
|
|
|
17
|
-
remove
|
|
21
|
+
remove [name...] Remove datasource packages
|
|
18
22
|
--cwd <dir> Consumer project directory (default: .)
|
|
19
|
-
--
|
|
23
|
+
--languages ts|rust|csharp Project languages (default: every type found)
|
|
24
|
+
--datasources <name...> Datasources to remove
|
|
20
25
|
--dry-run Print package-manager commands without running them
|
|
21
26
|
|
|
22
27
|
generate <all|types|repositories|datasource>
|
|
23
28
|
Types, repository classes, and SQL
|
|
29
|
+
https://deterministic-code.github.io/datasources/cli.html#generate
|
|
24
30
|
--dialect csharp|typescript|rust
|
|
25
31
|
--provider <name> Spec provider (default: deterministic)
|
|
26
32
|
--input <dir> Deterministic project (default: ./deterministic)
|
|
27
33
|
--output <dir> Generated files (default: ./generated)
|
|
28
34
|
--no-migrations Skip SQL migrations (generate all writes them)
|
|
29
|
-
--no-migrate
|
|
35
|
+
--no-auto-migrate-up Skip migrate-up (generate all applies them)
|
|
30
36
|
--migrations-root <dir> Root prefix for generate all (default: sql)
|
|
31
|
-
--migrations-path <dir> One migrations directory (single SQL dialect)
|
|
32
37
|
--stored-procedures Emit stored-procedure migrations when the dialect can
|
|
38
|
+
--pluralize-table-names Plural table names in SQL and runtime queries (default)
|
|
39
|
+
--no-pluralize-table-names Singular table names (procedure names stay plural)
|
|
40
|
+
--table-names Pascal|Camel|Snake|Kebab|Auto
|
|
41
|
+
--column-names Pascal|Camel|Snake|Kebab|Auto
|
|
42
|
+
--object-names Upper|Lower|Auto
|
|
43
|
+
--sql-keywords Upper|Lower|Auto
|
|
44
|
+
--file-names Pascal|Camel|Snake|Kebab|Auto
|
|
45
|
+
--type-names|--types Pascal|Camel|Snake|Kebab|Auto
|
|
46
|
+
--field-names|--fields Pascal|Camel|Snake|Kebab|Auto
|
|
47
|
+
--folder-names|--directories Pascal|Camel|Snake|Kebab|Auto
|
|
33
48
|
|
|
34
49
|
migrations create SQL migrations from the spec (migraters layout)
|
|
35
50
|
--provider <name> Spec provider (default: deterministic)
|
|
36
51
|
--input <dir> Deterministic project (default: ./deterministic)
|
|
37
52
|
--migrations-root <dir> Root prefix (default: sql)
|
|
38
|
-
--migrations-path <dir> One migrations directory (single SQL dialect)
|
|
39
53
|
--stored-procedures Emit stored-procedure migrations when the dialect can
|
|
54
|
+
--pluralize-table-names Plural table names in SQL (default)
|
|
55
|
+
--no-pluralize-table-names Singular table names (procedure names stay plural)
|
|
56
|
+
--table-names Pascal|Camel|Snake|Kebab|Auto
|
|
57
|
+
--column-names Pascal|Camel|Snake|Kebab|Auto
|
|
58
|
+
--object-names Upper|Lower|Auto
|
|
59
|
+
--sql-keywords Upper|Lower|Auto
|
|
40
60
|
|
|
41
61
|
version Snapshot top-level YAML as the next version-*/diff.yaml
|
|
42
62
|
--cwd <dir> Consumer project directory (default: .)
|
|
@@ -48,7 +68,7 @@ const take = (argv, index, name) => argv[index] ?? (() => {
|
|
|
48
68
|
throw new Error(`Missing value for ${name}`);
|
|
49
69
|
})();
|
|
50
70
|
const parseArgs = (argv, cwd = ".") => {
|
|
51
|
-
const flags = { cwd, dryRun: false, yes: false };
|
|
71
|
+
const flags = { cwd, languages: [], datasources: [], dryRun: false, yes: false };
|
|
52
72
|
const generate = {
|
|
53
73
|
dialect: "",
|
|
54
74
|
provider: "deterministic",
|
|
@@ -58,15 +78,29 @@ const parseArgs = (argv, cwd = ".") => {
|
|
|
58
78
|
migrate: true,
|
|
59
79
|
storedProcedures: false,
|
|
60
80
|
migrationsRoot: "sql",
|
|
61
|
-
|
|
81
|
+
fileNames: void 0,
|
|
82
|
+
types: void 0,
|
|
83
|
+
fields: void 0,
|
|
84
|
+
directories: void 0,
|
|
85
|
+
pluralizeTableNames: void 0,
|
|
86
|
+
tableNames: void 0,
|
|
87
|
+
columnNames: void 0,
|
|
88
|
+
objectNames: void 0,
|
|
89
|
+
sqlKeywords: void 0
|
|
62
90
|
};
|
|
63
91
|
const rest = [];
|
|
64
92
|
for (let i = 0; i < argv.length; i++) {
|
|
65
93
|
const arg = argv[i];
|
|
66
94
|
if (arg === "--cwd") flags.cwd = argv[++i] ?? flags.cwd;
|
|
67
95
|
else if (arg.startsWith("--cwd=")) flags.cwd = arg.slice("--cwd=".length);
|
|
68
|
-
else if (arg === "--
|
|
69
|
-
|
|
96
|
+
else if (arg === "--languages") {
|
|
97
|
+
i = takeList(argv, ++i, "--languages", (value) => flags.languages.push(language(value)));
|
|
98
|
+
} else if (arg.startsWith("--languages="))
|
|
99
|
+
splitList(arg.slice("--languages=".length), "--languages").forEach((value) => flags.languages.push(language(value)));
|
|
100
|
+
else if (arg === "--datasources") {
|
|
101
|
+
i = takeList(argv, ++i, "--datasources", (value) => flags.datasources.push(value));
|
|
102
|
+
} else if (arg.startsWith("--datasources="))
|
|
103
|
+
flags.datasources.push(...splitList(arg.slice("--datasources=".length), "--datasources"));
|
|
70
104
|
else if (arg === "--dry-run") flags.dryRun = true;
|
|
71
105
|
else if (arg === "--yes" || arg === "-y") flags.yes = true;
|
|
72
106
|
else if (arg === "--dialect") generate.dialect = take(argv, ++i, "--dialect");
|
|
@@ -78,23 +112,41 @@ const parseArgs = (argv, cwd = ".") => {
|
|
|
78
112
|
else if (arg === "--output") generate.output = take(argv, ++i, "--output");
|
|
79
113
|
else if (arg.startsWith("--output=")) generate.output = arg.slice("--output=".length);
|
|
80
114
|
else if (arg === "--no-migrations") generate.migrations = false;
|
|
81
|
-
else if (arg === "--no-migrate") generate.migrate = false;
|
|
115
|
+
else if (arg === "--no-auto-migrate-up") generate.migrate = false;
|
|
82
116
|
else if (arg === "--stored-procedures") generate.storedProcedures = true;
|
|
117
|
+
else if (arg === "--pluralize-table-names") generate.pluralizeTableNames = true;
|
|
118
|
+
else if (arg === "--no-pluralize-table-names") generate.pluralizeTableNames = false;
|
|
119
|
+
else if (arg === "--table-names") generate.tableNames = parseCaseFlag(take(argv, ++i, arg), arg);
|
|
120
|
+
else if (arg.startsWith("--table-names=")) generate.tableNames = parseCaseFlag(arg.slice("--table-names=".length), "--table-names");
|
|
121
|
+
else if (arg === "--column-names") generate.columnNames = parseCaseFlag(take(argv, ++i, arg), arg);
|
|
122
|
+
else if (arg.startsWith("--column-names=")) generate.columnNames = parseCaseFlag(arg.slice("--column-names=".length), "--column-names");
|
|
123
|
+
else if (arg === "--object-names") generate.objectNames = parseLetterCaseFlag(take(argv, ++i, arg), arg);
|
|
124
|
+
else if (arg.startsWith("--object-names=")) generate.objectNames = parseLetterCaseFlag(arg.slice("--object-names=".length), "--object-names");
|
|
125
|
+
else if (arg === "--sql-keywords") generate.sqlKeywords = parseLetterCaseFlag(take(argv, ++i, arg), arg);
|
|
126
|
+
else if (arg.startsWith("--sql-keywords=")) generate.sqlKeywords = parseLetterCaseFlag(arg.slice("--sql-keywords=".length), "--sql-keywords");
|
|
83
127
|
else if (arg === "--migrations-root") generate.migrationsRoot = take(argv, ++i, "--migrations-root");
|
|
84
128
|
else if (arg.startsWith("--migrations-root=")) generate.migrationsRoot = arg.slice("--migrations-root=".length);
|
|
85
|
-
else if (arg === "--
|
|
86
|
-
|
|
129
|
+
else if (arg === "--file-names" || arg === "--type-names" || arg === "--types" || arg === "--field-names" || arg === "--fields" || arg === "--folder-names" || arg === "--directories") {
|
|
130
|
+
const key = arg === "--file-names" ? "fileNames" : arg === "--type-names" || arg === "--types" ? "types" : arg === "--field-names" || arg === "--fields" ? "fields" : "directories";
|
|
131
|
+
generate[key] = parseCaseFlag(take(argv, ++i, arg), arg);
|
|
132
|
+
} else if (arg.startsWith("--file-names=")) generate.fileNames = parseCaseFlag(arg.slice("--file-names=".length), "--file-names");
|
|
133
|
+
else if (arg.startsWith("--type-names=")) generate.types = parseCaseFlag(arg.slice("--type-names=".length), "--type-names");
|
|
134
|
+
else if (arg.startsWith("--types=")) generate.types = parseCaseFlag(arg.slice("--types=".length), "--types");
|
|
135
|
+
else if (arg.startsWith("--field-names=")) generate.fields = parseCaseFlag(arg.slice("--field-names=".length), "--field-names");
|
|
136
|
+
else if (arg.startsWith("--fields=")) generate.fields = parseCaseFlag(arg.slice("--fields=".length), "--fields");
|
|
137
|
+
else if (arg.startsWith("--folder-names=")) generate.directories = parseCaseFlag(arg.slice("--folder-names=".length), "--folder-names");
|
|
138
|
+
else if (arg.startsWith("--directories=")) generate.directories = parseCaseFlag(arg.slice("--directories=".length), "--directories");
|
|
87
139
|
else if (arg === "--help" || arg === "-h") return { command: { kind: "help" }, flags };
|
|
88
140
|
else rest.push(arg);
|
|
89
141
|
}
|
|
90
142
|
const [verb, ...names] = rest;
|
|
91
|
-
return { command: commandOf(verb, names, generate), flags };
|
|
143
|
+
return { command: commandOf(verb, names, flags.datasources, generate), flags };
|
|
92
144
|
};
|
|
93
|
-
const commandOf = (verb, names, generate) => {
|
|
145
|
+
const commandOf = (verb, names, datasources, generate) => {
|
|
94
146
|
if (verb === void 0 || verb === "help") return { kind: "help" };
|
|
95
|
-
if (verb === "setup") return { kind: "setup", providers: names };
|
|
96
|
-
if (verb === "add") return { kind: "add", providers: names };
|
|
97
|
-
if (verb === "remove") return { kind: "remove", providers: names };
|
|
147
|
+
if (verb === "setup") return { kind: "setup", providers: unique([...datasources, ...names]) };
|
|
148
|
+
if (verb === "add") return { kind: "add", providers: unique([...datasources, ...names]) };
|
|
149
|
+
if (verb === "remove") return { kind: "remove", providers: unique([...datasources, ...names]) };
|
|
98
150
|
if (verb === "generate") return generateCommand(names, generate);
|
|
99
151
|
if (verb === "migrations") return migrationsCommand(names, generate);
|
|
100
152
|
if (verb === "version") return versionCommand(names, generate.input);
|
|
@@ -111,7 +163,11 @@ ${help}`);
|
|
|
111
163
|
input: generate.input,
|
|
112
164
|
storedProcedures: generate.storedProcedures,
|
|
113
165
|
migrationsRoot: generate.migrationsRoot,
|
|
114
|
-
|
|
166
|
+
pluralizeTableNames: generate.pluralizeTableNames,
|
|
167
|
+
tableNames: generate.tableNames,
|
|
168
|
+
columnNames: generate.columnNames,
|
|
169
|
+
objectNames: generate.objectNames,
|
|
170
|
+
sqlKeywords: generate.sqlKeywords
|
|
115
171
|
};
|
|
116
172
|
};
|
|
117
173
|
const versionCommand = (names, input) => {
|
|
@@ -137,12 +193,33 @@ ${help}`);
|
|
|
137
193
|
migrate: generate.migrate,
|
|
138
194
|
storedProcedures: generate.storedProcedures,
|
|
139
195
|
migrationsRoot: generate.migrationsRoot,
|
|
140
|
-
|
|
196
|
+
fileNames: generate.fileNames,
|
|
197
|
+
types: generate.types,
|
|
198
|
+
fields: generate.fields,
|
|
199
|
+
directories: generate.directories,
|
|
200
|
+
pluralizeTableNames: generate.pluralizeTableNames,
|
|
201
|
+
tableNames: generate.tableNames,
|
|
202
|
+
columnNames: generate.columnNames,
|
|
203
|
+
objectNames: generate.objectNames,
|
|
204
|
+
sqlKeywords: generate.sqlKeywords
|
|
141
205
|
};
|
|
142
206
|
};
|
|
143
|
-
const
|
|
144
|
-
throw new Error(`Unknown --
|
|
207
|
+
const language = (value) => value === "typescript" ? "ts" : isEcosystem(value) ? value : (() => {
|
|
208
|
+
throw new Error(`Unknown --languages ${value}. Use ts|rust|csharp`);
|
|
145
209
|
})();
|
|
210
|
+
const unique = (names) => [...new Set(names)];
|
|
211
|
+
const splitList = (value, name) => {
|
|
212
|
+
const names = value.split(",").map((part) => part.trim()).filter(Boolean);
|
|
213
|
+
return names.length ? names : (() => {
|
|
214
|
+
throw new Error(`Missing value for ${name}`);
|
|
215
|
+
})();
|
|
216
|
+
};
|
|
217
|
+
const takeList = (argv, index, name, push) => {
|
|
218
|
+
if (index >= argv.length || argv[index].startsWith("-")) throw new Error(`Missing value for ${name}`);
|
|
219
|
+
let i = index;
|
|
220
|
+
while (i < argv.length && !argv[i].startsWith("-")) push(argv[i++]);
|
|
221
|
+
return i - 1;
|
|
222
|
+
};
|
|
146
223
|
export {
|
|
147
224
|
generateTargets,
|
|
148
225
|
help,
|
package/dist/run.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { access, copyFile, mkdir } from "node:fs/promises";
|
|
2
1
|
import { join } from "node:path";
|
|
3
|
-
import {
|
|
2
|
+
import { requireProviders } from "./catalog.js";
|
|
4
3
|
import { addCommands, removeCommands } from "./commands.js";
|
|
5
|
-
import { csharpTarget, detect,
|
|
4
|
+
import { csharpTarget, detect, requireProjects, resolveLanguages } from "./detect.js";
|
|
6
5
|
import { parseEnv, serializeEnv, updateEnvProviders } from "./env.js";
|
|
7
6
|
import { defaultDatasourceYaml } from "./generate/loadSpec.js";
|
|
8
7
|
import {
|
|
@@ -15,9 +14,11 @@ import { applyMigrations } from "./generate/applyMigrations.js";
|
|
|
15
14
|
import { applyMigrateUp } from "./generate/migrateUp.js";
|
|
16
15
|
import { migrateInitCommands, migrateLanguage, sqlMigrateProviders } from "./migrateInit.js";
|
|
17
16
|
import { help, parseArgs } from "./parse.js";
|
|
17
|
+
import { sqlFlagsOf } from "./generate/sqlFlags.js";
|
|
18
18
|
import { applyVersion } from "./version/applyVersion.js";
|
|
19
19
|
import { answersForSetup, envFromAnswers, promptSetup, starterTypesYaml } from "./setup.js";
|
|
20
20
|
import { wireRegister } from "./wireRegister.js";
|
|
21
|
+
import { wireRustProviders } from "./wireRustProviders.js";
|
|
21
22
|
const run = async (argv, deps, cwd = ".") => {
|
|
22
23
|
try {
|
|
23
24
|
const parsed = parseArgs(argv, cwd);
|
|
@@ -45,7 +46,7 @@ const dispatch = async (command, flags, deps) => {
|
|
|
45
46
|
input: command.input,
|
|
46
47
|
storedProcedures: command.storedProcedures,
|
|
47
48
|
migrationsRoot: command.migrationsRoot,
|
|
48
|
-
...command
|
|
49
|
+
...sqlFlagsOf(command)
|
|
49
50
|
},
|
|
50
51
|
flags,
|
|
51
52
|
deps
|
|
@@ -53,33 +54,41 @@ const dispatch = async (command, flags, deps) => {
|
|
|
53
54
|
if (command.migrate) await applyMigrateUp(command, flags, deps);
|
|
54
55
|
};
|
|
55
56
|
const needNames = (names, verb) => names.length ? names : (() => {
|
|
56
|
-
throw new Error(`Usage: datasources ${verb} <
|
|
57
|
+
throw new Error(`Usage: datasources ${verb} --datasources <name...>`);
|
|
57
58
|
})();
|
|
58
59
|
const applySetup = async (flags, deps, requested) => {
|
|
59
60
|
const entries = await deps.fs.readdir(flags.cwd);
|
|
60
61
|
const found = detect(entries);
|
|
61
|
-
const existing =
|
|
62
|
+
const existing = {
|
|
63
|
+
...await readEnv(deps.fs, flags.cwd),
|
|
64
|
+
...process.env.INSTALLED_PROVIDERS ? { INSTALLED_PROVIDERS: process.env.INSTALLED_PROVIDERS } : {},
|
|
65
|
+
...process.env.PROVIDER ? { PROVIDER: process.env.PROVIDER } : {},
|
|
66
|
+
...process.env.DATASOURCE_URL ? { DATASOURCE_URL: process.env.DATASOURCE_URL } : {}
|
|
67
|
+
};
|
|
62
68
|
const specDir = join(flags.cwd, "deterministic");
|
|
63
69
|
const typesPath = join(specDir, "types.yaml");
|
|
64
70
|
const datasourcePath = join(specDir, "datasource.yaml");
|
|
65
71
|
const missingSpec = await optional(deps.fs, typesPath) === void 0;
|
|
66
|
-
const answers = flags.yes ? { ...answersForSetup(existing, requested),
|
|
67
|
-
const
|
|
72
|
+
const answers = flags.yes ? { ...answersForSetup(existing, requested), languages: flags.languages, scaffold: false } : await promptSetup(deps.prompt, existing, found, flags.languages, missingSpec, requested);
|
|
73
|
+
const languages = resolveLanguages(found, answers.languages ?? flags.languages);
|
|
74
|
+
requireProjects(languages, entries);
|
|
68
75
|
const selected = requireProviders(answers.providers);
|
|
69
|
-
const installed = await readInstalled(deps.fs, flags.cwd, ecosystem, entries);
|
|
70
76
|
if (!flags.dryRun) await writeEnv(deps.fs, flags.cwd, { ...existing, ...envFromAnswers(answers) });
|
|
71
|
-
|
|
72
|
-
flags,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
77
|
+
for (const language of languages) {
|
|
78
|
+
const installed = await readInstalled(deps.fs, flags.cwd, language, entries);
|
|
79
|
+
await applyPackages(
|
|
80
|
+
flags,
|
|
81
|
+
deps,
|
|
82
|
+
language,
|
|
83
|
+
entries,
|
|
84
|
+
selected.filter((name) => !installed.includes(name)),
|
|
85
|
+
installed.filter((name) => !selected.includes(name)),
|
|
86
|
+
selected
|
|
87
|
+
);
|
|
88
|
+
await applyMigrateInit(flags, deps, language, selected);
|
|
89
|
+
const dialect = migrateLanguage(language);
|
|
90
|
+
await wireRegister(flags.cwd, "generated", dialect, flags.dryRun, deps);
|
|
91
|
+
}
|
|
83
92
|
if (!answers.scaffold) return;
|
|
84
93
|
if (flags.dryRun) {
|
|
85
94
|
deps.log(typesPath);
|
|
@@ -93,16 +102,19 @@ const applySetup = async (flags, deps, requested) => {
|
|
|
93
102
|
const applyAddRemove = async (flags, deps, add, remove) => {
|
|
94
103
|
const entries = await deps.fs.readdir(flags.cwd);
|
|
95
104
|
const found = detect(entries);
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
const remaining = [
|
|
99
|
-
...installed.filter((name) => !remove.includes(name)),
|
|
100
|
-
...add.filter((name) => !installed.includes(name))
|
|
101
|
-
];
|
|
105
|
+
const languages = resolveLanguages(found, flags.languages);
|
|
106
|
+
requireProjects(languages, entries);
|
|
102
107
|
const env = await readEnvFile(deps.fs, join(flags.cwd, ".env"));
|
|
103
108
|
if (env && !flags.dryRun) await writeEnv(deps.fs, flags.cwd, updateEnvProviders(env, add, remove));
|
|
104
|
-
|
|
105
|
-
|
|
109
|
+
for (const language of languages) {
|
|
110
|
+
const installed = await readInstalled(deps.fs, flags.cwd, language, entries);
|
|
111
|
+
const remaining = [
|
|
112
|
+
...installed.filter((name) => !remove.includes(name)),
|
|
113
|
+
...add.filter((name) => !installed.includes(name))
|
|
114
|
+
];
|
|
115
|
+
await applyPackages(flags, deps, language, entries, add, remove, remaining);
|
|
116
|
+
await applyMigrateInit(flags, deps, language, remaining);
|
|
117
|
+
}
|
|
106
118
|
};
|
|
107
119
|
const applyPackages = async (flags, deps, ecosystem, entries, add, remove, remaining) => {
|
|
108
120
|
const procs = [
|
|
@@ -113,17 +125,7 @@ const applyPackages = async (flags, deps, ecosystem, entries, add, remove, remai
|
|
|
113
125
|
deps.log(`$ ${proc.command} ${proc.args.join(" ")}`);
|
|
114
126
|
if (!flags.dryRun) await deps.run(proc.command, proc.args, flags.cwd);
|
|
115
127
|
}
|
|
116
|
-
if (ecosystem === "rust")
|
|
117
|
-
for (const name of add) {
|
|
118
|
-
const proc = { command: "cargo", args: ["build", "-p", catalog[name].cargo] };
|
|
119
|
-
deps.log(`$ ${proc.command} ${proc.args.join(" ")}`);
|
|
120
|
-
if (!flags.dryRun) {
|
|
121
|
-
await deps.run(proc.command, proc.args, flags.cwd);
|
|
122
|
-
const copied = await copyPlugin(flags.cwd, catalog[name].cargo);
|
|
123
|
-
if (copied) deps.log(`copy ${copied}`);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
128
|
+
if (ecosystem === "rust") await wireRustProviders(flags.cwd, remaining, flags.dryRun, deps);
|
|
127
129
|
};
|
|
128
130
|
const applyMigrateInit = async (flags, deps, ecosystem, remaining) => {
|
|
129
131
|
for (const proc of migrateInitCommands(sqlMigrateProviders(remaining), migrateLanguage(ecosystem))) {
|
|
@@ -161,33 +163,6 @@ const optional = async (fs, path) => {
|
|
|
161
163
|
return void 0;
|
|
162
164
|
}
|
|
163
165
|
};
|
|
164
|
-
const pluginFileName = (cargoName, platform = process.platform) => {
|
|
165
|
-
const stem = cargoName.replaceAll("-", "_");
|
|
166
|
-
return platform === "win32" ? `${stem}.dll` : platform === "darwin" ? `lib${stem}.dylib` : `lib${stem}.so`;
|
|
167
|
-
};
|
|
168
|
-
const copyPlugin = async (cwd, cargoName) => {
|
|
169
|
-
const file = pluginFileName(cargoName);
|
|
170
|
-
const source = await firstFile(
|
|
171
|
-
[0, 1, 2].map((up) => join(cwd, ...Array.from({ length: up }, () => ".."), "target", "debug", file))
|
|
172
|
-
);
|
|
173
|
-
if (!source) return void 0;
|
|
174
|
-
const dest = join(cwd, "plugins", file);
|
|
175
|
-
await mkdir(join(cwd, "plugins"), { recursive: true });
|
|
176
|
-
await copyFile(source, dest);
|
|
177
|
-
return dest;
|
|
178
|
-
};
|
|
179
|
-
const firstFile = async (paths) => {
|
|
180
|
-
for (const path of paths) {
|
|
181
|
-
try {
|
|
182
|
-
await access(path);
|
|
183
|
-
return path;
|
|
184
|
-
} catch {
|
|
185
|
-
continue;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
return void 0;
|
|
189
|
-
};
|
|
190
166
|
export {
|
|
191
|
-
pluginFileName,
|
|
192
167
|
run
|
|
193
168
|
};
|
package/dist/setup.js
CHANGED
|
@@ -15,16 +15,15 @@ types:
|
|
|
15
15
|
size: 128
|
|
16
16
|
`;
|
|
17
17
|
const answersForSetup = (env, requested = []) => requested.length ? answersFromEnv({ ...env, INSTALLED_PROVIDERS: requested.join(",") }) : answersFromEnv(env);
|
|
18
|
-
const promptSetup = async (prompt, env, found, explicit, askScaffold = false, requested = []) => {
|
|
18
|
+
const promptSetup = async (prompt, env, found, explicit = [], askScaffold = false, requested = []) => {
|
|
19
19
|
const defaults = answersForSetup(env, requested);
|
|
20
|
-
const
|
|
21
|
-
message: "
|
|
22
|
-
choices: found.map((value) => ({ name: value, value }))
|
|
23
|
-
|
|
24
|
-
})));
|
|
20
|
+
const picked = explicit.length ? explicit : found.length === 1 ? found : found.length === 0 ? [] : (await prompt.checkbox({
|
|
21
|
+
message: "Languages",
|
|
22
|
+
choices: found.map((value) => ({ name: value, value, checked: true }))
|
|
23
|
+
})).filter(isEcosystem);
|
|
25
24
|
const fromUrl = scheme(defaults.url);
|
|
26
25
|
const selected = await prompt.checkbox({
|
|
27
|
-
message: "
|
|
26
|
+
message: "Datasources",
|
|
28
27
|
choices: providers.map((value) => ({
|
|
29
28
|
name: value,
|
|
30
29
|
value,
|
|
@@ -37,9 +36,8 @@ const promptSetup = async (prompt, env, found, explicit, askScaffold = false, re
|
|
|
37
36
|
});
|
|
38
37
|
const schema = await prompt.input({ message: "schema", default: defaults.schema });
|
|
39
38
|
const scaffold = askScaffold ? await prompt.confirm({ message: "Create deterministic directory", default: true }) : false;
|
|
40
|
-
return {
|
|
39
|
+
return { languages: picked.length ? picked : void 0, providers: selected, url, schema, scaffold };
|
|
41
40
|
};
|
|
42
|
-
const ecosystemOr = (value) => isEcosystem(value) ? value : void 0;
|
|
43
41
|
const envFromAnswers = (answers) => {
|
|
44
42
|
const provider = scheme(answers.url) ?? answers.providers[0] ?? "sqlite";
|
|
45
43
|
return {
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import { isAbsolute, join } from "node:path";
|
|
2
|
-
import {
|
|
2
|
+
import { VersionSnapshot } from "@deterministic-code/deterministic-generators-common/parser";
|
|
3
|
+
import { parseYaml, render } from "./render.js";
|
|
3
4
|
const versionDir = /^version-\d{8}T\d{6}Z-(\d{3})$/;
|
|
4
5
|
const at = (root, path) => isAbsolute(path) ? path : join(root, path);
|
|
5
6
|
const applyVersion = async (command, flags, deps, now = () => /* @__PURE__ */ new Date()) => {
|
|
6
7
|
const root = at(flags.cwd, command.input);
|
|
7
8
|
const names = await deps.fs.readdir(root);
|
|
8
9
|
const versions = names.filter((name) => versionDir.test(name)).sort();
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
const diffs = (await Promise.all(
|
|
11
|
+
versions.map(async (dir) => {
|
|
12
|
+
const listed = await deps.fs.readdir(join(root, dir));
|
|
13
|
+
if (!listed.includes("diff.yaml")) return void 0;
|
|
14
|
+
const text = await deps.fs.readFile(join(root, dir, "diff.yaml"));
|
|
15
|
+
return text === "" ? void 0 : parseYaml(text);
|
|
16
|
+
})
|
|
17
|
+
)).filter((diff) => diff !== void 0);
|
|
18
|
+
const before = VersionSnapshot.combine(diffs).documents;
|
|
15
19
|
const current = names.filter((name) => name.endsWith(".yaml")).sort();
|
|
16
20
|
const paths = [.../* @__PURE__ */ new Set([...Object.keys(before), ...current])];
|
|
17
21
|
const yaml = render(
|
|
@@ -39,13 +43,6 @@ const nextSeq = (versions) => {
|
|
|
39
43
|
};
|
|
40
44
|
const pad = (n) => String(n).padStart(3, "0");
|
|
41
45
|
const stamp = (date) => date.toISOString().replace(/[-:]/g, "").replace(/\.\d{3}/, "");
|
|
42
|
-
const optional = async (fs, path) => {
|
|
43
|
-
try {
|
|
44
|
-
return await fs.readFile(path);
|
|
45
|
-
} catch {
|
|
46
|
-
return void 0;
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
46
|
export {
|
|
50
47
|
applyVersion
|
|
51
48
|
};
|
package/dist/version/delta.js
CHANGED
|
@@ -4,20 +4,6 @@ const delta = (before, after) => {
|
|
|
4
4
|
const value = build(before, after);
|
|
5
5
|
return value === unchanged ? void 0 : value;
|
|
6
6
|
};
|
|
7
|
-
const apply = (before, next) => {
|
|
8
|
-
if (next == null) return before;
|
|
9
|
-
if (isKeyedCollection(before) && isKeyedSplit(next)) return applyKeyed(before, next);
|
|
10
|
-
if (isObject(before) && isObject(next)) return applyObject(before, next);
|
|
11
|
-
return next;
|
|
12
|
-
};
|
|
13
|
-
const applyFile = (before, envelope) => {
|
|
14
|
-
if (envelope == null) return before;
|
|
15
|
-
if (isObject(envelope)) {
|
|
16
|
-
if (envelope.removed === true && Object.keys(envelope).length === 1) return void 0;
|
|
17
|
-
if (envelope.added === true) return envelope.content;
|
|
18
|
-
}
|
|
19
|
-
return apply(before ?? null, envelope);
|
|
20
|
-
};
|
|
21
7
|
const build = (before, after) => {
|
|
22
8
|
if (isDeepStrictEqual(before, after)) return unchanged;
|
|
23
9
|
if (isKeyedCollection(before) && isKeyedCollection(after)) return keyedSplit(before, after);
|
|
@@ -60,40 +46,6 @@ const objectDelta = (beforeObj, afterObj) => {
|
|
|
60
46
|
if (removed.length) result.removed = removed;
|
|
61
47
|
return Object.keys(result).length === 0 ? unchanged : result;
|
|
62
48
|
};
|
|
63
|
-
const applyKeyed = (beforeVal, split) => {
|
|
64
|
-
const removed = new Set(split.removed ?? []);
|
|
65
|
-
const changed = /* @__PURE__ */ new Map();
|
|
66
|
-
for (const entry of split.changed ?? []) {
|
|
67
|
-
const key = Object.keys(entry)[0];
|
|
68
|
-
changed.set(key, entry[key]);
|
|
69
|
-
}
|
|
70
|
-
return [
|
|
71
|
-
...beforeVal.flatMap((entry) => {
|
|
72
|
-
const key = Object.keys(entry)[0];
|
|
73
|
-
if (removed.has(key)) return [];
|
|
74
|
-
return changed.has(key) ? [{ [key]: apply(entry[key], changed.get(key)) }] : [entry];
|
|
75
|
-
}),
|
|
76
|
-
...split.added ?? []
|
|
77
|
-
];
|
|
78
|
-
};
|
|
79
|
-
const applyObject = (beforeVal, next) => {
|
|
80
|
-
const removed = new Set(Array.isArray(next.removed) ? next.removed : []);
|
|
81
|
-
const out = {};
|
|
82
|
-
for (const key of Object.keys(beforeVal)) {
|
|
83
|
-
if (removed.has(key)) continue;
|
|
84
|
-
out[key] = key in next ? apply(beforeVal[key], next[key]) : beforeVal[key];
|
|
85
|
-
}
|
|
86
|
-
for (const key of Object.keys(next)) {
|
|
87
|
-
if (key === "removed" && Array.isArray(next.removed)) continue;
|
|
88
|
-
if (!(key in beforeVal)) out[key] = next[key];
|
|
89
|
-
}
|
|
90
|
-
return out;
|
|
91
|
-
};
|
|
92
|
-
const isKeyedSplit = (value) => {
|
|
93
|
-
if (!isObject(value)) return false;
|
|
94
|
-
const allowed = /* @__PURE__ */ new Set(["added", "changed", "removed"]);
|
|
95
|
-
return Object.keys(value).every((key) => allowed.has(key));
|
|
96
|
-
};
|
|
97
49
|
const isObject = (value) => value !== null && value !== void 0 && typeof value === "object" && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
|
|
98
50
|
const isKeyedCollection = (value) => Array.isArray(value) && value.length > 0 && value.every(
|
|
99
51
|
(item) => item !== null && typeof item === "object" && !Array.isArray(item) && Object.keys(item).length === 1
|
|
@@ -107,8 +59,6 @@ const keyedMap = (arr) => {
|
|
|
107
59
|
return map;
|
|
108
60
|
};
|
|
109
61
|
export {
|
|
110
|
-
apply,
|
|
111
|
-
applyFile,
|
|
112
62
|
delta,
|
|
113
63
|
isObject
|
|
114
64
|
};
|
package/dist/version/render.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parse, stringify } from "yaml";
|
|
2
|
-
import {
|
|
2
|
+
import { delta, isObject } from "./delta.js";
|
|
3
3
|
const render = (files) => {
|
|
4
4
|
const out = {};
|
|
5
5
|
for (const { path, before, after } of files) {
|
|
@@ -18,20 +18,10 @@ const render = (files) => {
|
|
|
18
18
|
return Object.keys(out).length === 0 ? "" : stringify(out);
|
|
19
19
|
};
|
|
20
20
|
const parseYaml = (text) => parse(text);
|
|
21
|
-
const applyDocument = (before, doc) => {
|
|
22
|
-
const out = { ...before };
|
|
23
|
-
for (const [path, envelope] of Object.entries(doc)) {
|
|
24
|
-
const next = applyFile(out[path], envelope);
|
|
25
|
-
if (next === void 0) delete out[path];
|
|
26
|
-
else out[path] = next;
|
|
27
|
-
}
|
|
28
|
-
return out;
|
|
29
|
-
};
|
|
30
21
|
const asDocument = (value, source) => isObject(value) ? value : (() => {
|
|
31
22
|
throw new Error(`${source}: expected a mapping`);
|
|
32
23
|
})();
|
|
33
24
|
export {
|
|
34
|
-
applyDocument,
|
|
35
25
|
asDocument,
|
|
36
26
|
parseYaml,
|
|
37
27
|
render
|