@schemic/cli 0.1.0-alpha.3 → 0.1.0-alpha.4
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/lib/cli.js +45 -13
- package/package.json +4 -4
- package/src/cli/resolve.ts +65 -14
package/lib/cli.js
CHANGED
|
@@ -7,11 +7,11 @@ import {
|
|
|
7
7
|
mkdirSync as mkdirSync3,
|
|
8
8
|
writeFileSync as writeFileSync3
|
|
9
9
|
} from "fs";
|
|
10
|
-
import { dirname as
|
|
10
|
+
import { dirname as dirname3, join as join3, relative as relative2 } from "path";
|
|
11
11
|
import { createInterface } from "readline/promises";
|
|
12
12
|
|
|
13
13
|
// package.json
|
|
14
|
-
var version = "0.1.0-alpha.
|
|
14
|
+
var version = "0.1.0-alpha.4";
|
|
15
15
|
|
|
16
16
|
// src/cli/index.ts
|
|
17
17
|
import {
|
|
@@ -428,8 +428,9 @@ async function closeQuietly(conn) {
|
|
|
428
428
|
}
|
|
429
429
|
|
|
430
430
|
// src/cli/resolve.ts
|
|
431
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
431
432
|
import { createRequire } from "module";
|
|
432
|
-
import { join as join2 } from "path";
|
|
433
|
+
import { dirname as dirname2, join as join2 } from "path";
|
|
433
434
|
import { pathToFileURL } from "url";
|
|
434
435
|
import {
|
|
435
436
|
driverNames,
|
|
@@ -438,23 +439,54 @@ import {
|
|
|
438
439
|
loadProject,
|
|
439
440
|
resolveConnectionConfig
|
|
440
441
|
} from "@schemic/core";
|
|
442
|
+
function pickCompiled(node) {
|
|
443
|
+
if (typeof node === "string") return node;
|
|
444
|
+
if (node && typeof node === "object") {
|
|
445
|
+
const o = node;
|
|
446
|
+
return pickCompiled(o.import) ?? pickCompiled(o.default) ?? pickCompiled(o.require);
|
|
447
|
+
}
|
|
448
|
+
return void 0;
|
|
449
|
+
}
|
|
450
|
+
function compiledEntry(pkg, base) {
|
|
451
|
+
try {
|
|
452
|
+
const manifestPath = createRequire(base).resolve(`${pkg}/package.json`);
|
|
453
|
+
const m = JSON.parse(readFileSync2(manifestPath, "utf8"));
|
|
454
|
+
const rel = pickCompiled(m.exports?.["."]) ?? m.module ?? m.main ?? "index.js";
|
|
455
|
+
return join2(dirname2(manifestPath), rel);
|
|
456
|
+
} catch {
|
|
457
|
+
return null;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
441
460
|
async function ensureDriver(name) {
|
|
442
461
|
if (driverNames().includes(name)) return;
|
|
443
462
|
const pkg = `@schemic/${name}`;
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
463
|
+
let lastErr;
|
|
464
|
+
let loaded = false;
|
|
465
|
+
for (const base of [join2(process.cwd(), "noop.js"), import.meta.url]) {
|
|
466
|
+
const entry = compiledEntry(pkg, base);
|
|
467
|
+
if (!entry) continue;
|
|
468
|
+
try {
|
|
469
|
+
await import(pathToFileURL(entry).href);
|
|
470
|
+
loaded = true;
|
|
471
|
+
break;
|
|
472
|
+
} catch (e) {
|
|
473
|
+
lastErr = e;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
if (!loaded) {
|
|
448
477
|
try {
|
|
449
478
|
await import(pkg);
|
|
479
|
+
loaded = true;
|
|
450
480
|
} catch (e) {
|
|
451
|
-
|
|
452
|
-
`could not load the "${name}" database driver (package ${pkg}). Install it in your project, then re-run:
|
|
453
|
-
bun add ${pkg}
|
|
454
|
-
(${e instanceof Error ? e.message : String(e)})`
|
|
455
|
-
);
|
|
481
|
+
lastErr = e;
|
|
456
482
|
}
|
|
457
483
|
}
|
|
484
|
+
if (!loaded)
|
|
485
|
+
throw new Error(
|
|
486
|
+
`could not load the "${name}" database driver (package ${pkg}). Install it in your project, then re-run:
|
|
487
|
+
bun add ${pkg}
|
|
488
|
+
(${lastErr instanceof Error ? lastErr.message : String(lastErr)})`
|
|
489
|
+
);
|
|
458
490
|
if (!driverNames().includes(name))
|
|
459
491
|
throw new Error(`package ${pkg} did not register a "${name}" driver.`);
|
|
460
492
|
}
|
|
@@ -1285,7 +1317,7 @@ configFlag(
|
|
|
1285
1317
|
);
|
|
1286
1318
|
if (existsSync3(target))
|
|
1287
1319
|
throw new Error(`${relative2(config.root, target)} already exists.`);
|
|
1288
|
-
mkdirSync3(
|
|
1320
|
+
mkdirSync3(dirname3(target), { recursive: true });
|
|
1289
1321
|
writeFileSync3(target, content);
|
|
1290
1322
|
console.log(
|
|
1291
1323
|
`${ok2(relative2(config.root, target))} ${style2.dim("\u2014 author its fields, then `schemic gen`")}`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@schemic/cli",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.4",
|
|
4
4
|
"description": "The Schemic CLI — driver-agnostic schema migrations (gen/migrate/diff/push/pull/check).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Vertio Solutions",
|
|
@@ -35,14 +35,14 @@
|
|
|
35
35
|
"lint": "biome check ."
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@schemic/core": "0.1.0-alpha.
|
|
38
|
+
"@schemic/core": "0.1.0-alpha.4",
|
|
39
39
|
"commander": "^14.0.2"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@biomejs/biome": "^2.3.11",
|
|
43
43
|
"@electric-sql/pglite": "^0.5.2",
|
|
44
|
-
"@schemic/postgres": "0.1.0-alpha.
|
|
45
|
-
"@schemic/surrealdb": "0.1.0-alpha.
|
|
44
|
+
"@schemic/postgres": "0.1.0-alpha.4",
|
|
45
|
+
"@schemic/surrealdb": "0.1.0-alpha.4",
|
|
46
46
|
"@types/bun": "latest",
|
|
47
47
|
"surrealdb": "^2.0.3",
|
|
48
48
|
"tsup": "^8",
|
package/src/cli/resolve.ts
CHANGED
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
// connects the sibling on demand (the dependency graph falls out of access; cycles error) and we close
|
|
11
11
|
// anything it opened once resolution settles. The returned configs are connected FRESH by each command.
|
|
12
12
|
|
|
13
|
+
import { readFileSync } from "node:fs";
|
|
13
14
|
import { createRequire } from "node:module";
|
|
14
|
-
import { join } from "node:path";
|
|
15
|
+
import { dirname, join } from "node:path";
|
|
15
16
|
import { pathToFileURL } from "node:url";
|
|
16
17
|
import {
|
|
17
18
|
type ConnectionEntry,
|
|
@@ -32,27 +33,77 @@ import {
|
|
|
32
33
|
* (`@schemic/<name>`) that self-register with the core registry on import; the CLI itself contains no
|
|
33
34
|
* dialect code and discovers the driver from the project's connection config at runtime. Idempotent.
|
|
34
35
|
*/
|
|
36
|
+
/** Pick a package's COMPILED entry from its exports, deliberately skipping the `bun` condition. */
|
|
37
|
+
function pickCompiled(node: unknown): string | undefined {
|
|
38
|
+
if (typeof node === "string") return node;
|
|
39
|
+
if (node && typeof node === "object") {
|
|
40
|
+
const o = node as Record<string, unknown>;
|
|
41
|
+
// import/default/require are the published (compiled) conditions; never `bun` (raw src/*.ts).
|
|
42
|
+
return (
|
|
43
|
+
pickCompiled(o.import) ??
|
|
44
|
+
pickCompiled(o.default) ??
|
|
45
|
+
pickCompiled(o.require)
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Resolve a driver package to its COMPILED entry file, from `base`'s module scope. We read the
|
|
53
|
+
* manifest and pick the `import`/`default` export rather than letting the runtime choose the `bun`
|
|
54
|
+
* export condition (which points at raw `src/*.ts` for monorepo dev) — loading a PUBLISHED package's
|
|
55
|
+
* TypeScript source is fragile (every transitive src import must re-resolve at the consumer).
|
|
56
|
+
*/
|
|
57
|
+
function compiledEntry(pkg: string, base: string): string | null {
|
|
58
|
+
try {
|
|
59
|
+
const manifestPath = createRequire(base).resolve(`${pkg}/package.json`);
|
|
60
|
+
const m = JSON.parse(readFileSync(manifestPath, "utf8")) as {
|
|
61
|
+
exports?: Record<string, unknown>;
|
|
62
|
+
module?: string;
|
|
63
|
+
main?: string;
|
|
64
|
+
};
|
|
65
|
+
const rel =
|
|
66
|
+
pickCompiled(m.exports?.["."]) ?? m.module ?? m.main ?? "index.js";
|
|
67
|
+
return join(dirname(manifestPath), rel);
|
|
68
|
+
} catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
35
73
|
export async function ensureDriver(name: string): Promise<void> {
|
|
36
74
|
if (driverNames().includes(name)) return;
|
|
37
75
|
const pkg = `@schemic/${name}`;
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
76
|
+
// Try the USER's project (cwd) first, then the CLI's own module scope — the CLI is often run via
|
|
77
|
+
// `bunx`/`npx` from a temp dir, so a driver installed in the user's project must be found by cwd.
|
|
78
|
+
let lastErr: unknown;
|
|
79
|
+
let loaded = false;
|
|
80
|
+
for (const base of [join(process.cwd(), "noop.js"), import.meta.url]) {
|
|
81
|
+
const entry = compiledEntry(pkg, base);
|
|
82
|
+
if (!entry) continue;
|
|
83
|
+
try {
|
|
84
|
+
await import(pathToFileURL(entry).href);
|
|
85
|
+
loaded = true;
|
|
86
|
+
break;
|
|
87
|
+
} catch (e) {
|
|
88
|
+
lastErr = e;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Last resort: a plain specifier import (covers an unbuilt monorepo checkout, where lib is absent).
|
|
92
|
+
if (!loaded) {
|
|
45
93
|
try {
|
|
46
94
|
await import(pkg);
|
|
95
|
+
loaded = true;
|
|
47
96
|
} catch (e) {
|
|
48
|
-
|
|
49
|
-
`could not load the "${name}" database driver (package ${pkg}). ` +
|
|
50
|
-
`Install it in your project, then re-run:\n bun add ${pkg}\n (${
|
|
51
|
-
e instanceof Error ? e.message : String(e)
|
|
52
|
-
})`,
|
|
53
|
-
);
|
|
97
|
+
lastErr = e;
|
|
54
98
|
}
|
|
55
99
|
}
|
|
100
|
+
if (!loaded)
|
|
101
|
+
throw new Error(
|
|
102
|
+
`could not load the "${name}" database driver (package ${pkg}). ` +
|
|
103
|
+
`Install it in your project, then re-run:\n bun add ${pkg}\n (${
|
|
104
|
+
lastErr instanceof Error ? lastErr.message : String(lastErr)
|
|
105
|
+
})`,
|
|
106
|
+
);
|
|
56
107
|
if (!driverNames().includes(name))
|
|
57
108
|
throw new Error(`package ${pkg} did not register a "${name}" driver.`);
|
|
58
109
|
}
|