@deterministic-code/datasources-cli 0.1.8 → 0.1.10

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.
@@ -6,15 +6,17 @@ import { providerByName } from "./providers.js";
6
6
  import { writeEntries } from "./writeEntries.js";
7
7
  const at = (root, path) => isAbsolute(path) ? path : join(root, path);
8
8
  const afterMigrations = (filename) => filename.replace(/^[^/]+\/migrations\//, "");
9
- const dialectsOf = (entries) => [
10
- ...new Set(entries.map((entry) => entry.filename.split("/")[0]))
11
- ];
12
9
  const applyMigrations = async (command, flags, deps) => {
13
10
  providerByName(command.provider);
14
11
  const loaded = await loadSpec(deps.fs, at(flags.cwd, command.input));
15
- const entries = await generateSql({ reader: memoryReader(loaded.files), settings: loaded.settings });
16
- if (command.migrationsPath !== void 0 && dialectsOf(entries).length > 1)
12
+ const listed = [
13
+ ...new Set(
14
+ loaded.settings["backend.datasources"].split(",").map((name) => name.trim()).filter((name) => name !== "")
15
+ )
16
+ ];
17
+ if (command.migrationsPath !== void 0 && listed.length > 1)
17
18
  throw new Error("--migrations-path requires a single SQL dialect in backend.datasources");
19
+ const entries = await generateSql({ reader: memoryReader(loaded.files), settings: loaded.settings });
18
20
  const remapped = command.migrationsPath === void 0 ? entries : entries.map((entry) => ({ ...entry, filename: afterMigrations(entry.filename) }));
19
21
  const root = at(flags.cwd, command.migrationsPath ?? command.migrationsRoot);
20
22
  if (flags.dryRun) {
@@ -60,19 +60,26 @@ const applyMigrateUp = async (command, flags, deps, env = process.env) => {
60
60
  throw new Error(
61
61
  `migrate-up: provider ${provider} is not in backend.datasources (${dialects.join(", ") || "none"})`
62
62
  );
63
- const args = [
63
+ const npx = (verb, extra = []) => [
64
64
  "--yes",
65
65
  "--package",
66
66
  "@deterministic-code/migraters",
67
- "migrate-up",
67
+ verb,
68
68
  "--provider",
69
69
  provider,
70
70
  "--connection",
71
71
  connection,
72
- ...command.migrationsPath ? ["--migrations-path", command.migrationsPath] : ["--migrations-root", command.migrationsRoot]
72
+ ...extra
73
73
  ];
74
- deps.log(`$ npx ${args.join(" ")}`);
75
- if (!flags.dryRun) await deps.run("npx", args, flags.cwd);
74
+ const setup = npx("migrate-setup");
75
+ const up = npx(
76
+ "migrate-up",
77
+ command.migrationsPath ? ["--migrations-path", command.migrationsPath] : ["--migrations-root", command.migrationsRoot]
78
+ );
79
+ deps.log(`$ npx ${setup.join(" ")}`);
80
+ if (!flags.dryRun) await deps.run("npx", setup, flags.cwd);
81
+ deps.log(`$ npx ${up.join(" ")}`);
82
+ if (!flags.dryRun) await deps.run("npx", up, flags.cwd);
76
83
  };
77
84
  export {
78
85
  applyMigrateUp
@@ -1,6 +1,7 @@
1
1
  const migrateProviders = ["sqlite", "postgres", "mysql", "sqlserver", "oracle"];
2
+ const migrateLanguage = (ecosystem) => ecosystem === "ts" ? "typescript" : ecosystem;
2
3
  const sqlMigrateProviders = (names) => migrateProviders.filter((name) => names.includes(name));
3
- const migrateInitCommands = (dialects) => dialects.length === 0 ? [] : [
4
+ const migrateInitCommands = (dialects, language) => dialects.length === 0 ? [] : [
4
5
  { command: "npm", args: ["install", "@deterministic-code/migraters"] },
5
6
  {
6
7
  command: "npx",
@@ -9,12 +10,15 @@ const migrateInitCommands = (dialects) => dialects.length === 0 ? [] : [
9
10
  "--package",
10
11
  "@deterministic-code/migraters",
11
12
  "migrate-init",
13
+ "--language",
14
+ language,
12
15
  ...dialects.flatMap((name) => ["--dialect", name])
13
16
  ]
14
17
  }
15
18
  ];
16
19
  export {
17
20
  migrateInitCommands,
21
+ migrateLanguage,
18
22
  migrateProviders,
19
23
  sqlMigrateProviders
20
24
  };
package/dist/run.js CHANGED
@@ -18,7 +18,7 @@ import {
18
18
  import { applyGenerate } from "./generate/applyGenerate.js";
19
19
  import { applyMigrations } from "./generate/applyMigrations.js";
20
20
  import { applyMigrateUp } from "./generate/migrateUp.js";
21
- import { migrateInitCommands, sqlMigrateProviders } from "./migrateInit.js";
21
+ import { migrateInitCommands, migrateLanguage, sqlMigrateProviders } from "./migrateInit.js";
22
22
  import { help, parseArgs } from "./parse.js";
23
23
  import { applyVersion } from "./version/applyVersion.js";
24
24
  import { envFromAnswers, promptSetup, starterTypesYaml } from "./setup.js";
@@ -82,7 +82,7 @@ const applySetup = async (flags, deps) => {
82
82
  selected
83
83
  );
84
84
  await applyMigrateInit(flags, deps, ecosystem, selected);
85
- const dialect = ecosystem === "ts" ? "typescript" : ecosystem;
85
+ const dialect = migrateLanguage(ecosystem);
86
86
  await wireRegister(flags.cwd, "generated", dialect, flags.dryRun, deps);
87
87
  if (!answers.scaffold) return;
88
88
  if (flags.dryRun) {
@@ -130,8 +130,7 @@ const applyPackages = async (flags, deps, ecosystem, entries, add, remove, remai
130
130
  }
131
131
  };
132
132
  const applyMigrateInit = async (flags, deps, ecosystem, remaining) => {
133
- if (ecosystem !== "ts") return;
134
- for (const proc of migrateInitCommands(sqlMigrateProviders(remaining))) {
133
+ for (const proc of migrateInitCommands(sqlMigrateProviders(remaining), migrateLanguage(ecosystem))) {
135
134
  deps.log(`$ ${proc.command} ${proc.args.join(" ")}`);
136
135
  if (!flags.dryRun) await deps.run(proc.command, proc.args, flags.cwd);
137
136
  }
@@ -166,9 +165,9 @@ const optional = async (fs, path) => {
166
165
  return void 0;
167
166
  }
168
167
  };
169
- const pluginFileName = (cargoName) => {
168
+ const pluginFileName = (cargoName, platform = process.platform) => {
170
169
  const stem = cargoName.replaceAll("-", "_");
171
- return process.platform === "win32" ? `${stem}.dll` : process.platform === "darwin" ? `lib${stem}.dylib` : `lib${stem}.so`;
170
+ return platform === "win32" ? `${stem}.dll` : platform === "darwin" ? `lib${stem}.dylib` : `lib${stem}.so`;
172
171
  };
173
172
  const copyPlugin = async (cwd, cargoName) => {
174
173
  const file = pluginFileName(cargoName);
@@ -193,5 +192,6 @@ const firstFile = async (paths) => {
193
192
  return void 0;
194
193
  };
195
194
  export {
195
+ pluginFileName,
196
196
  run
197
197
  };
@@ -4,7 +4,8 @@ import { sqlStringLiteral } from "@deterministic-code/datasources";
4
4
  import { identityInsertStatementOf, seedInsertStatementOf } from "../statements.js";
5
5
  import { renderSql, sqlDefault } from "./sql-dialect.js";
6
6
  import { dialectConverter } from "./sql-dialect.js";
7
- import { isGeneratedIdentity, overlayOf, tableIdentity, } from "./sql-schema.js";
7
+ import { converterFieldOf } from "./converter-field.js";
8
+ import { isGeneratedIdentity, overlayOf, tableIdentity, usesGeneratedIdColumn, } from "./sql-schema.js";
8
9
  const SEED_UUID_NAMESPACE = "9b3a8e6c-2f1d-4a5b-8c9d-1e2f3a4b5c6d";
9
10
  const pkType = (table) => table.fields.find((f) => isPkField(f, table, overlayOf(table)))?.type ??
10
11
  "integer";
@@ -63,8 +64,10 @@ export const seedSections = (dialect, tables, seeds, mapping) => {
63
64
  if (rows.length === 0)
64
65
  continue;
65
66
  const generated = isGeneratedIdentity(table) ? tableIdentity(table) : [];
66
- const t = pkType(table);
67
- const identity = isGeneratedIdentity(table) && t !== "uuid" && t !== "string";
67
+ const pk = table.fields.find((field) => field.name === tableIdentity(table)[0]);
68
+ const identity = pk != null &&
69
+ usesGeneratedIdColumn(table, pk) &&
70
+ sqlDefault(dialect, converterFieldOf(pk)) == null;
68
71
  const inserts = rows.map((seed) => {
69
72
  const cols = colsForRow(table, seed.row);
70
73
  const values = cols.map((c) => {
@@ -7,6 +7,7 @@ export type SqlGenerateDriver = IDriver & {
7
7
  defaultValueConverter: DefaultValueConverter;
8
8
  statementRenderer: StatementTextRenderer;
9
9
  };
10
+ export declare const register: (dialect: string, driver: IDriver) => void;
10
11
  export declare const dialectDriver: (dialect: string) => SqlGenerateDriver;
11
12
  export declare const renderSql: (dialect: string, statement: IStatement) => string;
12
13
  export declare const dialectConverter: (dialect: string) => {
@@ -1,16 +1,28 @@
1
- import { createRequire } from "node:module";
2
1
  import { DriverLoader, ProviderCatalog, } from "@deterministic-code/datasources";
3
- const require = createRequire(import.meta.url);
4
- export const dialectDriver = (dialect) => {
5
- const catalog = ProviderCatalog.default[dialect];
6
- if (catalog === undefined)
2
+ const loaded = new Map();
3
+ const named = (dialect) => ProviderCatalog.default[dialect] === undefined
4
+ ? (() => {
7
5
  throw new Error(`Unknown SQL dialect "${dialect}".`);
8
- const driver = DriverLoader.load(new ProviderCatalog(catalog.name, require.resolve(catalog.location), catalog.module));
9
- if (driver.typeConverter == null ||
10
- driver.defaultValueConverter == null ||
11
- driver.statementRenderer == null) {
6
+ })()
7
+ : dialect;
8
+ const asGenerate = (dialect, driver) => driver.typeConverter == null ||
9
+ driver.defaultValueConverter == null ||
10
+ driver.statementRenderer == null
11
+ ? (() => {
12
12
  throw new Error(`"${dialect}" is not a SQL dialect.`);
13
- }
13
+ })()
14
+ : driver;
15
+ export const register = (dialect, driver) => {
16
+ loaded.set(named(dialect), asGenerate(dialect, driver));
17
+ };
18
+ export const dialectDriver = (dialect) => {
19
+ const key = named(dialect);
20
+ const hit = loaded.get(key);
21
+ if (hit !== undefined)
22
+ return hit;
23
+ const catalog = ProviderCatalog.default[key];
24
+ const driver = asGenerate(key, DriverLoader.load(catalog));
25
+ loaded.set(key, driver);
14
26
  return driver;
15
27
  };
16
28
  export const renderSql = (dialect, statement) => {
@@ -11,12 +11,15 @@ export const overlayOf = (table) => ({
11
11
  ...(table.mapping !== undefined ? { mapping: table.mapping } : {}),
12
12
  });
13
13
  export const fieldOverlay = (table, fieldName) => table.overlays.find((overlay) => overlay.name === fieldName);
14
- const GENERATED_ID_TYPES = new Set([
15
- "integer",
16
- "biginteger",
17
- "uuid",
18
- "string",
19
- ]);
14
+ const requireIdIsId = (spec) => {
15
+ for (const type of spec.types) {
16
+ for (const field of type.fields) {
17
+ if (field.name === "id" && field.isId !== true) {
18
+ throw new Error(`${type.name}.id must have is_id: true`);
19
+ }
20
+ }
21
+ }
22
+ };
20
23
  export const tableIdentity = (table) => {
21
24
  const keys = identityColumns(table, overlayOf(table));
22
25
  if (keys.length > 1) {
@@ -38,10 +41,9 @@ export const isGeneratedIdentity = (table) => {
38
41
  return false;
39
42
  return fieldOverlay(table, keys[0])?.isFixedId !== true;
40
43
  };
41
- export const usesGeneratedIdColumn = (table, field) => isGeneratedIdentity(table) &&
42
- field.name === tableIdentity(table)[0] &&
43
- GENERATED_ID_TYPES.has(field.type);
44
+ export const usesGeneratedIdColumn = (table, field) => field.isId === true && isGeneratedIdentity(table);
44
45
  export const sqlTablesFrom = (spec) => {
46
+ requireIdIsId(spec);
45
47
  const overlays = tableByName(spec);
46
48
  const byName = new Map(spec.expandedTypes.map((t) => [t.name, t]));
47
49
  return datasourceTypesOf(spec).map((type) => {
@@ -7,19 +7,14 @@ export const columnOf = (dialect, mapping, table, field) => {
7
7
  const overlay = fieldOverlay(table, field.name);
8
8
  const converterField = converterFieldOf(field);
9
9
  const generated = usesGeneratedIdColumn(table, field);
10
- const identity = generated && field.type !== "uuid" && field.type !== "string";
11
10
  const named = mapping.constraintName(table, mapping.fieldStem(table, field.name), "default_constraint");
12
- const utcNow = dialectDriver(dialect).defaultValueConverter.convert("datetime", "UtcNow");
13
- const newId = dialectDriver(dialect).defaultValueConverter.convert("uuid", "NewId");
14
11
  const fromSpec = sqlDefault(dialect, converterField);
15
- const defaultExpr = fromSpec ??
16
- (field.name === "created" || field.name === "updated" ? utcNow : null) ??
17
- (field.name === "uuid" || (generated && field.type === "uuid") ? newId : null);
12
+ const identity = generated && fromSpec == null;
18
13
  const keys = tableIdentity(table);
19
14
  return {
20
15
  name: q(dialect, mapping.columnName(table, field.name)),
21
16
  type: mapColumnType(dialect, converterField),
22
- ...(defaultExpr ? { default: new ColumnDefault(defaultExpr, q(dialect, named)) } : {}),
17
+ ...(fromSpec ? { default: new ColumnDefault(fromSpec, q(dialect, named)) } : {}),
23
18
  ...(!field.isNullable || keys.includes(field.name) ? { notNull: new NotNull() } : {}),
24
19
  ...(identity ? { identity: true } : {}),
25
20
  };
@@ -1,21 +1,22 @@
1
1
  {
2
2
  "name": "@deterministic-code/datasources-code-generators",
3
- "version": "0.1.2",
3
+ "version": "0.1.10",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dist/generateSql.js",
7
7
  "./generate-sql": "./dist/generate-sql.js",
8
+ "./sql/generate-sql": "./dist/sql/generate-sql.js",
8
9
  "./generate-stored-procedures": "./dist/generate-stored-procedures.js",
9
- "./common/sql-dialect": "./dist/sql/common/sql-dialect.js",
10
- "./sql/dialect-converters": "./dist/sql/dialect-converters.js"
10
+ "./sql/generate-stored-procedures": "./dist/sql/generate-stored-procedures.js",
11
+ "./common/sql-dialect": "./dist/sql/common/sql-dialect.js"
11
12
  },
12
13
  "dependencies": {
13
- "@deterministic-code/datasources": "^0.1.6",
14
- "@deterministic-code/datasources-mysql": "^0.1.6",
15
- "@deterministic-code/datasources-oracle": "^0.1.6",
16
- "@deterministic-code/datasources-postgres": "^0.1.6",
17
- "@deterministic-code/datasources-sqlite": "^0.1.6",
18
- "@deterministic-code/datasources-sqlserver": "^0.1.6",
14
+ "@deterministic-code/datasources": "^0.1.10",
15
+ "@deterministic-code/datasources-mysql": "^0.1.10",
16
+ "@deterministic-code/datasources-oracle": "^0.1.10",
17
+ "@deterministic-code/datasources-postgres": "^0.1.10",
18
+ "@deterministic-code/datasources-sqlite": "^0.1.10",
19
+ "@deterministic-code/datasources-sqlserver": "^0.1.10",
19
20
  "@deterministic-code/deterministic-generators-common": "0.1.0",
20
21
  "@deterministic-code/generators-common": "0.0.1",
21
22
  "pluralize": "^8.0.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deterministic-code/datasources-cli",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "datasources": "./bin/datasources.mjs"
@@ -13,7 +13,7 @@
13
13
  "access": "public"
14
14
  },
15
15
  "dependencies": {
16
- "@deterministic-code/datasources-code-generators": "0.1.2",
16
+ "@deterministic-code/datasources-code-generators": "0.1.10",
17
17
  "@deterministic-code/generators-common": "0.0.1",
18
18
  "@deterministic-code/deterministic-generators-common": "0.1.0",
19
19
  "@deterministic-code/typescript-generators": "0.0.1",
@@ -21,12 +21,12 @@
21
21
  "@deterministic-code/rust-generators": "0.0.1",
22
22
  "@deterministic-code/generators-openapi": "0.0.1",
23
23
  "@deterministic-code/patch-merger": "0.1.0",
24
- "@deterministic-code/datasources": "^0.1.6",
25
- "@deterministic-code/datasources-sqlite": "^0.1.6",
26
- "@deterministic-code/datasources-mysql": "^0.1.6",
27
- "@deterministic-code/datasources-postgres": "^0.1.6",
28
- "@deterministic-code/datasources-sqlserver": "^0.1.6",
29
- "@deterministic-code/datasources-oracle": "^0.1.6",
24
+ "@deterministic-code/datasources": "^0.1.10",
25
+ "@deterministic-code/datasources-sqlite": "^0.1.10",
26
+ "@deterministic-code/datasources-mysql": "^0.1.10",
27
+ "@deterministic-code/datasources-postgres": "^0.1.10",
28
+ "@deterministic-code/datasources-sqlserver": "^0.1.10",
29
+ "@deterministic-code/datasources-oracle": "^0.1.10",
30
30
  "@inquirer/prompts": "^7.8.0",
31
31
  "yaml": "^2.6.0",
32
32
  "mustache": "^4.2.0",