@askdb/config 1.0.0-beta.17 → 1.0.0-beta.18

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.
Files changed (47) hide show
  1. package/README.md +11 -0
  2. package/dist/bootstrap.d.ts +6 -4
  3. package/dist/bootstrap.d.ts.map +1 -1
  4. package/dist/bootstrap.js +6 -17
  5. package/dist/bootstrap.js.map +1 -1
  6. package/dist/defaults.d.ts +6 -1
  7. package/dist/defaults.d.ts.map +1 -1
  8. package/dist/defaults.js +6 -1
  9. package/dist/defaults.js.map +1 -1
  10. package/dist/env.d.ts +2 -1
  11. package/dist/env.d.ts.map +1 -1
  12. package/dist/env.js +2 -1
  13. package/dist/env.js.map +1 -1
  14. package/dist/load-merge.js.map +1 -1
  15. package/dist/projection.d.ts +8 -4
  16. package/dist/projection.d.ts.map +1 -1
  17. package/dist/projection.js +9 -4
  18. package/dist/projection.js.map +1 -1
  19. package/dist/resolve.d.ts +3 -3
  20. package/dist/resolve.d.ts.map +1 -1
  21. package/dist/resolve.js +8 -11
  22. package/dist/resolve.js.map +1 -1
  23. package/dist/runtime-config.js.map +1 -1
  24. package/dist/runtime-store.d.ts +0 -1
  25. package/dist/runtime-store.d.ts.map +1 -1
  26. package/dist/runtime-store.js +1 -4
  27. package/dist/runtime-store.js.map +1 -1
  28. package/dist/runtime-types.d.ts +1 -1
  29. package/dist/scaffold/ai.d.ts +3 -0
  30. package/dist/scaffold/ai.d.ts.map +1 -1
  31. package/dist/scaffold/ai.js +3 -0
  32. package/dist/scaffold/ai.js.map +1 -1
  33. package/dist/scaffold/index.d.ts +12 -3
  34. package/dist/scaffold/index.d.ts.map +1 -1
  35. package/dist/scaffold/index.js +10 -3
  36. package/dist/scaffold/index.js.map +1 -1
  37. package/dist/scaffold/package-manager.d.ts +93 -0
  38. package/dist/scaffold/package-manager.d.ts.map +1 -0
  39. package/dist/scaffold/package-manager.js +200 -0
  40. package/dist/scaffold/package-manager.js.map +1 -0
  41. package/dist/scaffold/plan.d.ts +110 -0
  42. package/dist/scaffold/plan.d.ts.map +1 -0
  43. package/dist/scaffold/plan.js +301 -0
  44. package/dist/scaffold/plan.js.map +1 -0
  45. package/dist/types.d.ts +6 -13
  46. package/dist/types.d.ts.map +1 -1
  47. package/package.json +1 -1
@@ -127,7 +127,7 @@ export type AskDbRuntimeStudioConfig = {
127
127
  /**
128
128
  * Resolved execute provider. Falls back to the active introspection provider when it
129
129
  * is a live engine (`postgres`, `mysql`, `sqlite`, `sqlserver`), then defaults to
130
- * `"postgres"` for backward compatibility.
130
+ * `"postgres"`.
131
131
  */
132
132
  provider: AskDbStudioExecuteProvider;
133
133
  /** Connection URL used by the Studio playground query runner for network databases. */
@@ -25,6 +25,9 @@ export type AskDbAiConfigScaffold = {
25
25
  *
26
26
  * Every value is emitted as a JSON string literal: the generated file is
27
27
  * executed when the config loads, so a raw quote in a name must not inject code.
28
+ *
29
+ * @experimental Tooling for `askdb init` and AskDB Studio: a minor release of
30
+ * `@askdb/config` may change it (ADR 0030).
28
31
  */
29
32
  export declare function renderAskDbAiConfigScaffold(input: AskDbAiConfigScaffoldInput): AskDbAiConfigScaffold;
30
33
  //# sourceMappingURL=ai.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../src/scaffold/ai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAE7E,4DAA4D;AAC5D,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,oHAAoH;IACpH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,sFAAsF;IACtF,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,OAAO,EAAE,mBAAmB,EAAE,CAAC;CAChC,CAAC;AAYF;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,0BAA0B,GAAG,qBAAqB,CAmCpG"}
1
+ {"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../src/scaffold/ai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAE7E,4DAA4D;AAC5D,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,oHAAoH;IACpH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,sFAAsF;IACtF,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,OAAO,EAAE,mBAAmB,EAAE,CAAC;CAChC,CAAC;AAYF;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,0BAA0B,GAAG,qBAAqB,CAmCpG"}
@@ -14,6 +14,9 @@ const AZURE_RESOURCE_NAME_ENV = "AZURE_RESOURCE_NAME";
14
14
  *
15
15
  * Every value is emitted as a JSON string literal: the generated file is
16
16
  * executed when the config loads, so a raw quote in a name must not inject code.
17
+ *
18
+ * @experimental Tooling for `askdb init` and AskDB Studio: a minor release of
19
+ * `@askdb/config` may change it (ADR 0030).
17
20
  */
18
21
  export function renderAskDbAiConfigScaffold(input) {
19
22
  const { provider, keyEnv, modelEnv } = input;
@@ -1 +1 @@
1
- {"version":3,"file":"ai.js","sourceRoot":"","sources":["../../src/scaffold/ai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA0B,MAAM,iBAAiB,CAAC;AAwB7E,SAAS,YAAY,CAAC,QAAgB;IACpC,OAAQ,kBAAwC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACtE,CAAC;AAED;;;GAGG;AACH,MAAM,uBAAuB,GAAG,qBAAqB,CAAC;AAEtD;;;;;;;GAOG;AACH,MAAM,UAAU,2BAA2B,CAAC,KAAiC;IAC3E,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IAC7C,8EAA8E;IAC9E,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,MAAM,OAAO,GAA0B,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,QAAQ,UAAU,EAAE,CAAC,CAAC;IAC1F,MAAM,MAAM,GAAG,CAAC,eAAe,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3D,oGAAoG;IACpG,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,QAAQ,iBAAiB,EAAE,CAAC,CAAC;QACxE,QAAQ,GAAG;;mBAEI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;OACpC,CAAC;IACN,CAAC;IACD,gFAAgF;IAChF,yEAAyE;IACzE,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,uBAAuB;YAC7B,OAAO,EAAE,kFAAkF;SAC5F,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,qBAAqB,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC;IAChF,CAAC;IACD,MAAM,MAAM,GAAG;gBACD,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;;QAEhC,QAAQ;EACd,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;QAE9C,QAAQ;KACX,CAAC;IACJ,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC7B,CAAC"}
1
+ {"version":3,"file":"ai.js","sourceRoot":"","sources":["../../src/scaffold/ai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA0B,MAAM,iBAAiB,CAAC;AAwB7E,SAAS,YAAY,CAAC,QAAgB;IACpC,OAAQ,kBAAwC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACtE,CAAC;AAED;;;GAGG;AACH,MAAM,uBAAuB,GAAG,qBAAqB,CAAC;AAEtD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,2BAA2B,CAAC,KAAiC;IAC3E,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IAC7C,8EAA8E;IAC9E,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,MAAM,OAAO,GAA0B,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,QAAQ,UAAU,EAAE,CAAC,CAAC;IAC1F,MAAM,MAAM,GAAG,CAAC,eAAe,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3D,oGAAoG;IACpG,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,QAAQ,iBAAiB,EAAE,CAAC,CAAC;QACxE,QAAQ,GAAG;;mBAEI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;OACpC,CAAC;IACN,CAAC;IACD,gFAAgF;IAChF,yEAAyE;IACzE,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,uBAAuB;YAC7B,OAAO,EAAE,kFAAkF;SAC5F,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,qBAAqB,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC;IAChF,CAAC;IACD,MAAM,MAAM,GAAG;gBACD,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;;QAEhC,QAAQ;EACd,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;QAE9C,QAAQ;KACX,CAAC;IACJ,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC7B,CAAC"}
@@ -1,8 +1,17 @@
1
1
  /**
2
- * `@askdb/config/scaffold`: helpers for tools that write a new `askdb.config.ts`
3
- * (`askdb init`, Studio's setup wizard). Kept off the main entry, which user
4
- * configs import, so tooling can change without touching the config API.
2
+ * `@askdb/config/scaffold`: helpers for tools that set up a project and write a new
3
+ * `askdb.config.ts` (`askdb init`, Studio's setup wizard): the planner, which turns a
4
+ * project's answers into its config, `.env.example` and installs, and the package-manager
5
+ * helpers that run the installs. Kept off the main entry, which user configs import, so
6
+ * tooling can change without touching the config API.
7
+ *
8
+ * @experimental Tooling for `askdb init` and AskDB Studio: a minor release of
9
+ * `@askdb/config` may change these exports (ADR 0030).
5
10
  */
6
11
  export { renderAskDbAiConfigScaffold } from "./ai.js";
7
12
  export type { AskDbAiConfigScaffold, AskDbAiConfigScaffoldInput, AskDbScaffoldEnvVar } from "./ai.js";
13
+ export { AskDbScaffoldInputError, isAskDbScaffoldEnvName, planAskDbScaffold } from "./plan.js";
14
+ export type { AskDbScaffoldAnswers, AskDbScaffoldPlan, ScaffoldValue } from "./plan.js";
15
+ export { detectPackageManager, findNearestPackageJsonDir, formatInstallCommand, isLikelyWorkspaceRoot, lockfilePackageManager, packageManagerAddArgs, packageManagerSpawnSpec, supportedBuildApprovals, } from "./package-manager.js";
16
+ export type { PackageManager, PackageManagerSpawnSpec } from "./package-manager.js";
8
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scaffold/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC;AACtD,YAAY,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scaffold/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC;AACtD,YAAY,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AACtG,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC/F,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACxF,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -1,7 +1,14 @@
1
1
  /**
2
- * `@askdb/config/scaffold`: helpers for tools that write a new `askdb.config.ts`
3
- * (`askdb init`, Studio's setup wizard). Kept off the main entry, which user
4
- * configs import, so tooling can change without touching the config API.
2
+ * `@askdb/config/scaffold`: helpers for tools that set up a project and write a new
3
+ * `askdb.config.ts` (`askdb init`, Studio's setup wizard): the planner, which turns a
4
+ * project's answers into its config, `.env.example` and installs, and the package-manager
5
+ * helpers that run the installs. Kept off the main entry, which user configs import, so
6
+ * tooling can change without touching the config API.
7
+ *
8
+ * @experimental Tooling for `askdb init` and AskDB Studio: a minor release of
9
+ * `@askdb/config` may change these exports (ADR 0030).
5
10
  */
6
11
  export { renderAskDbAiConfigScaffold } from "./ai.js";
12
+ export { AskDbScaffoldInputError, isAskDbScaffoldEnvName, planAskDbScaffold } from "./plan.js";
13
+ export { detectPackageManager, findNearestPackageJsonDir, formatInstallCommand, isLikelyWorkspaceRoot, lockfilePackageManager, packageManagerAddArgs, packageManagerSpawnSpec, supportedBuildApprovals, } from "./package-manager.js";
7
14
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scaffold/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scaffold/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC;AAEtD,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE/F,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Package-manager helpers for the tools that set up a project: `askdb init` and
3
+ * Studio's setup wizard and execute-driver install. One copy, so the two front
4
+ * ends detect, format and spawn the same way.
5
+ *
6
+ * @experimental Tooling for `askdb init` and AskDB Studio: a minor release of
7
+ * `@askdb/config` may change these exports (ADR 0030).
8
+ *
9
+ * Only allowlisted package names ever reach these helpers, never user- or
10
+ * browser-supplied strings, but {@link packageManagerSpawnSpec} re-checks every
11
+ * argument anyway because Windows needs `shell: true` (see below).
12
+ */
13
+ /** @experimental See the module note. */
14
+ export type PackageManager = "pnpm" | "npm" | "yarn" | "bun";
15
+ /**
16
+ * The nearest directory at or above `startDir` that holds a `package.json`.
17
+ *
18
+ * @experimental See the module note.
19
+ */
20
+ export declare function findNearestPackageJsonDir(startDir: string): string | undefined;
21
+ /**
22
+ * Whether `packageDir` looks like a monorepo or workspace root (a `pnpm-workspace.yaml`,
23
+ * or a `workspaces` field), whose `package.json` setup tools leave alone.
24
+ *
25
+ * @experimental See the module note.
26
+ */
27
+ export declare function isLikelyWorkspaceRoot(packageDir: string): boolean;
28
+ /**
29
+ * The package manager implied by a lockfile directly inside `dir`, if any.
30
+ *
31
+ * @experimental See the module note.
32
+ */
33
+ export declare function lockfilePackageManager(dir: string): PackageManager | null;
34
+ /**
35
+ * The package manager to install with in `packageDir`, from the first of these that
36
+ * names one:
37
+ *
38
+ * 1. a lockfile in `packageDir` or a parent (pnpm, then Bun, Yarn, npm in one directory);
39
+ * 2. the nearest `package.json`, walking up, that declares a manager: its `packageManager`
40
+ * field (Corepack's `pnpm@11.28.10`), then `devEngines.packageManager` (`{ name }` or a
41
+ * list of them; `pnpm init` writes it);
42
+ * 3. `npm_config_user_agent` in `env`, which `pnpm dlx`, `yarn dlx`, `npx` and `bunx` set;
43
+ * 4. npm.
44
+ *
45
+ * An existing lockfile wins, so a project's install never switches managers.
46
+ *
47
+ * @experimental See the module note.
48
+ */
49
+ export declare function detectPackageManager(packageDir: string, env?: Readonly<Record<string, string | undefined>>): PackageManager;
50
+ /**
51
+ * Arguments that add `packages` as dependencies with the given package manager.
52
+ * `allowBuilds` are dependencies whose install scripts pnpm must be told to run
53
+ * (`--allow-build=<name>`; pnpm 11 exits 1 on an unapproved one). npm and Yarn
54
+ * run install scripts, and Bun skips untrusted ones without failing, so only
55
+ * pnpm gets them.
56
+ *
57
+ * @experimental See the module note.
58
+ */
59
+ export declare function packageManagerAddArgs(pm: PackageManager, packages: readonly string[], allowBuilds?: readonly string[]): string[];
60
+ /**
61
+ * The build approvals to pass `pm` in `dir`: `allowBuilds`, or none for a pnpm older
62
+ * than 10.4.0, whose `add` rejects `--allow-build` (pnpm 9 runs install scripts, and
63
+ * 10.0 to 10.3 skip unapproved ones without failing). A pnpm whose version can't be
64
+ * read keeps them.
65
+ *
66
+ * @experimental See the module note.
67
+ */
68
+ export declare function supportedBuildApprovals(pm: PackageManager, dir: string, allowBuilds: readonly string[]): string[];
69
+ /**
70
+ * Human-readable install command, e.g. `pnpm add pg`.
71
+ *
72
+ * @experimental See the module note.
73
+ */
74
+ export declare function formatInstallCommand(pm: PackageManager, packages: readonly string[], allowBuilds?: readonly string[]): string;
75
+ /** @experimental See the module note. */
76
+ export type PackageManagerSpawnSpec = {
77
+ command: string;
78
+ args: string[];
79
+ shell: boolean;
80
+ };
81
+ /**
82
+ * How to spawn a package manager on this platform.
83
+ *
84
+ * On Windows, package managers are `.cmd` shims, and Node refuses to spawn
85
+ * `.cmd`/`.bat` files without a shell (EINVAL since Node 18.20.2 / 20.12.2,
86
+ * CVE-2024-27980). So Windows gets `shell: true` with the bare command name.
87
+ * Arguments are validated against a strict allowlist pattern first, so the
88
+ * shell never sees anything it could interpret.
89
+ *
90
+ * @experimental See the module note.
91
+ */
92
+ export declare function packageManagerSpawnSpec(pm: PackageManager, args: readonly string[], platform?: NodeJS.Platform): PackageManagerSpawnSpec;
93
+ //# sourceMappingURL=package-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-manager.d.ts","sourceRoot":"","sources":["../../src/scaffold/package-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,yCAAyC;AACzC,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;AAK7D;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE9E;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAUjE;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAMzE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,MAAM,EAClB,GAAG,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAe,GAC9D,cAAc,CAWhB;AAuCD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,EAAE,EAAE,cAAc,EAClB,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,WAAW,GAAE,SAAS,MAAM,EAAO,GAClC,MAAM,EAAE,CAIV;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAMjH;AAQD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,cAAc,EAClB,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,WAAW,GAAE,SAAS,MAAM,EAAO,GAClC,MAAM,CAER;AAED,yCAAyC;AACzC,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAQF;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,EAAE,EAAE,cAAc,EAClB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,uBAAuB,CAUzB"}
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Package-manager helpers for the tools that set up a project: `askdb init` and
3
+ * Studio's setup wizard and execute-driver install. One copy, so the two front
4
+ * ends detect, format and spawn the same way.
5
+ *
6
+ * @experimental Tooling for `askdb init` and AskDB Studio: a minor release of
7
+ * `@askdb/config` may change these exports (ADR 0030).
8
+ *
9
+ * Only allowlisted package names ever reach these helpers, never user- or
10
+ * browser-supplied strings, but {@link packageManagerSpawnSpec} re-checks every
11
+ * argument anyway because Windows needs `shell: true` (see below).
12
+ */
13
+ import { spawnSync } from "node:child_process";
14
+ import { existsSync, readFileSync } from "node:fs";
15
+ import { dirname, join, resolve } from "node:path";
16
+ /** How far up the helpers walk looking for a `package.json` or lockfile. */
17
+ const MAX_WALK_UP = 40;
18
+ /**
19
+ * The nearest directory at or above `startDir` that holds a `package.json`.
20
+ *
21
+ * @experimental See the module note.
22
+ */
23
+ export function findNearestPackageJsonDir(startDir) {
24
+ return ancestors(startDir).find((dir) => existsSync(join(dir, "package.json")));
25
+ }
26
+ /**
27
+ * Whether `packageDir` looks like a monorepo or workspace root (a `pnpm-workspace.yaml`,
28
+ * or a `workspaces` field), whose `package.json` setup tools leave alone.
29
+ *
30
+ * @experimental See the module note.
31
+ */
32
+ export function isLikelyWorkspaceRoot(packageDir) {
33
+ if (existsSync(join(packageDir, "pnpm-workspace.yaml")) || existsSync(join(packageDir, "pnpm-workspace.yml"))) {
34
+ return true;
35
+ }
36
+ try {
37
+ const pkg = JSON.parse(readFileSync(join(packageDir, "package.json"), "utf8"));
38
+ return pkg.workspaces !== undefined && pkg.workspaces !== null;
39
+ }
40
+ catch {
41
+ return false;
42
+ }
43
+ }
44
+ /**
45
+ * The package manager implied by a lockfile directly inside `dir`, if any.
46
+ *
47
+ * @experimental See the module note.
48
+ */
49
+ export function lockfilePackageManager(dir) {
50
+ if (existsSync(join(dir, "pnpm-lock.yaml")))
51
+ return "pnpm";
52
+ if (existsSync(join(dir, "bun.lockb")) || existsSync(join(dir, "bun.lock")))
53
+ return "bun";
54
+ if (existsSync(join(dir, "yarn.lock")))
55
+ return "yarn";
56
+ if (existsSync(join(dir, "package-lock.json")))
57
+ return "npm";
58
+ return null;
59
+ }
60
+ /**
61
+ * The package manager to install with in `packageDir`, from the first of these that
62
+ * names one:
63
+ *
64
+ * 1. a lockfile in `packageDir` or a parent (pnpm, then Bun, Yarn, npm in one directory);
65
+ * 2. the nearest `package.json`, walking up, that declares a manager: its `packageManager`
66
+ * field (Corepack's `pnpm@11.28.10`), then `devEngines.packageManager` (`{ name }` or a
67
+ * list of them; `pnpm init` writes it);
68
+ * 3. `npm_config_user_agent` in `env`, which `pnpm dlx`, `yarn dlx`, `npx` and `bunx` set;
69
+ * 4. npm.
70
+ *
71
+ * An existing lockfile wins, so a project's install never switches managers.
72
+ *
73
+ * @experimental See the module note.
74
+ */
75
+ export function detectPackageManager(packageDir, env = process.env) {
76
+ const dirs = ancestors(packageDir);
77
+ for (const dir of dirs) {
78
+ const pm = lockfilePackageManager(dir);
79
+ if (pm)
80
+ return pm;
81
+ }
82
+ for (const dir of dirs) {
83
+ const pm = declaredPackageManager(dir);
84
+ if (pm)
85
+ return pm;
86
+ }
87
+ return knownPackageManager(env.npm_config_user_agent?.split("/")[0]) ?? "npm";
88
+ }
89
+ /** `dir` and its parents, nearest first, at most {@link MAX_WALK_UP} of them. */
90
+ function ancestors(dir) {
91
+ const dirs = [resolve(dir)];
92
+ while (dirs.length < MAX_WALK_UP) {
93
+ const parent = dirname(dirs[dirs.length - 1]);
94
+ if (parent === dirs[dirs.length - 1])
95
+ break;
96
+ dirs.push(parent);
97
+ }
98
+ return dirs;
99
+ }
100
+ /** The manager `dir/package.json` declares in `packageManager` or `devEngines.packageManager`. */
101
+ function declaredPackageManager(dir) {
102
+ let pkg;
103
+ try {
104
+ pkg = JSON.parse(readFileSync(join(dir, "package.json"), "utf8"));
105
+ }
106
+ catch {
107
+ return null;
108
+ }
109
+ if (pkg === null || typeof pkg !== "object")
110
+ return null;
111
+ if (typeof pkg.packageManager === "string") {
112
+ const pm = knownPackageManager(pkg.packageManager.split("@")[0]);
113
+ if (pm)
114
+ return pm;
115
+ }
116
+ const devEngine = pkg.devEngines?.packageManager;
117
+ for (const entry of Array.isArray(devEngine) ? devEngine : [devEngine]) {
118
+ const name = entry !== null && typeof entry === "object" ? entry.name : undefined;
119
+ const pm = knownPackageManager(name);
120
+ if (pm)
121
+ return pm;
122
+ }
123
+ return null;
124
+ }
125
+ function knownPackageManager(name) {
126
+ return name === "pnpm" || name === "npm" || name === "yarn" || name === "bun" ? name : null;
127
+ }
128
+ /**
129
+ * Arguments that add `packages` as dependencies with the given package manager.
130
+ * `allowBuilds` are dependencies whose install scripts pnpm must be told to run
131
+ * (`--allow-build=<name>`; pnpm 11 exits 1 on an unapproved one). npm and Yarn
132
+ * run install scripts, and Bun skips untrusted ones without failing, so only
133
+ * pnpm gets them.
134
+ *
135
+ * @experimental See the module note.
136
+ */
137
+ export function packageManagerAddArgs(pm, packages, allowBuilds = []) {
138
+ if (pm === "npm")
139
+ return ["install", "--save", ...packages];
140
+ if (pm === "pnpm")
141
+ return ["add", ...allowBuilds.map((name) => `--allow-build=${name}`), ...packages];
142
+ return ["add", ...packages];
143
+ }
144
+ /**
145
+ * The build approvals to pass `pm` in `dir`: `allowBuilds`, or none for a pnpm older
146
+ * than 10.4.0, whose `add` rejects `--allow-build` (pnpm 9 runs install scripts, and
147
+ * 10.0 to 10.3 skip unapproved ones without failing). A pnpm whose version can't be
148
+ * read keeps them.
149
+ *
150
+ * @experimental See the module note.
151
+ */
152
+ export function supportedBuildApprovals(pm, dir, allowBuilds) {
153
+ if (pm !== "pnpm" || allowBuilds.length === 0)
154
+ return [...allowBuilds];
155
+ const match = /^(\d+)\.(\d+)\./.exec(pnpmVersion(dir) ?? "");
156
+ if (!match)
157
+ return [...allowBuilds];
158
+ const [major, minor] = [Number(match[1]), Number(match[2])];
159
+ return major > 10 || (major === 10 && minor >= 4) ? [...allowBuilds] : [];
160
+ }
161
+ function pnpmVersion(dir) {
162
+ const { command, args, shell } = packageManagerSpawnSpec("pnpm", ["--version"]);
163
+ const result = spawnSync(command, args, { cwd: dir, encoding: "utf8", shell, stdio: ["ignore", "pipe", "ignore"], timeout: 15_000 });
164
+ return result.status === 0 ? result.stdout.trim() : null;
165
+ }
166
+ /**
167
+ * Human-readable install command, e.g. `pnpm add pg`.
168
+ *
169
+ * @experimental See the module note.
170
+ */
171
+ export function formatInstallCommand(pm, packages, allowBuilds = []) {
172
+ return [pm, ...packageManagerAddArgs(pm, packages, allowBuilds)].join(" ");
173
+ }
174
+ // npm package names (optionally scoped, optionally with a version/range suffix),
175
+ // simple `--flag` arguments, and pnpm's `--allow-build=<package name>`. Nothing a
176
+ // shell would interpret.
177
+ const SAFE_ARG = /^(?:--[a-z][a-z-]*|--allow-build=(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*|(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*(?:@[a-z0-9.^~<>=*_-]+)?|add|install)$/i;
178
+ /**
179
+ * How to spawn a package manager on this platform.
180
+ *
181
+ * On Windows, package managers are `.cmd` shims, and Node refuses to spawn
182
+ * `.cmd`/`.bat` files without a shell (EINVAL since Node 18.20.2 / 20.12.2,
183
+ * CVE-2024-27980). So Windows gets `shell: true` with the bare command name.
184
+ * Arguments are validated against a strict allowlist pattern first, so the
185
+ * shell never sees anything it could interpret.
186
+ *
187
+ * @experimental See the module note.
188
+ */
189
+ export function packageManagerSpawnSpec(pm, args, platform = process.platform) {
190
+ for (const arg of args) {
191
+ if (!SAFE_ARG.test(arg)) {
192
+ throw new Error(`Refusing to pass unsafe argument to ${pm}: ${JSON.stringify(arg)}`);
193
+ }
194
+ }
195
+ if (platform === "win32") {
196
+ return { command: pm, args: [...args], shell: true };
197
+ }
198
+ return { command: pm, args: [...args], shell: false };
199
+ }
200
+ //# sourceMappingURL=package-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-manager.js","sourceRoot":"","sources":["../../src/scaffold/package-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * The scaffold planner: answers about a new project in, the files and installs it needs out.
3
+ * `askdb init` and Studio's setup wizard both call {@link planAskDbScaffold}, so the per-engine
4
+ * facts (config keys, URL formats, driver packages) and the config and `.env.example` layouts
5
+ * live here once. Each front end keeps its own defaults, how it asks, and how files land.
6
+ *
7
+ * @experimental Tooling for `askdb init` and AskDB Studio: a minor release of
8
+ * `@askdb/config` may change these exports (ADR 0030).
9
+ */
10
+ import { type AskDbIntrospectionProvider, type AskDbRagStore, type AskDbStudioExecuteProvider } from "../constants.js";
11
+ import { type AskDbAiConfigScaffoldInput } from "./ai.js";
12
+ /**
13
+ * A setting a config reads either as a literal path or from an env var: `{ path }` is written
14
+ * as a string, `{ env }` as `env("NAME")`.
15
+ *
16
+ * @experimental See the module note.
17
+ */
18
+ export type ScaffoldValue = {
19
+ path: string;
20
+ } | {
21
+ env: string;
22
+ };
23
+ /**
24
+ * What a new project uses. Env var fields take NAMES, never values. Defaults are the
25
+ * caller's: every field the chosen engine, store or execute provider reads must be given.
26
+ *
27
+ * @experimental See the module note.
28
+ */
29
+ export type AskDbScaffoldAnswers = {
30
+ database: AskDbIntrospectionProvider;
31
+ /** Env var NAME for the connection URL. Postgres, MySQL and SQL Server. */
32
+ connectionEnv?: string;
33
+ /** The SQLite database file. SQLite only. */
34
+ sqliteFile?: ScaffoldValue;
35
+ /** Path to `schema.prisma`. Prisma only; omit to let `@askdb/prisma` find it. */
36
+ prismaSchemaPath?: string;
37
+ /** Schema artifact directory (`introspection.outputDir`). */
38
+ schemaOut: string;
39
+ ai: AskDbAiConfigScaffoldInput;
40
+ /** `pgvectorEnv` names the connection URL's env var, for the pgvector store. */
41
+ rag: {
42
+ store: AskDbRagStore;
43
+ pgvectorEnv?: string;
44
+ };
45
+ /** Turns on Studio execute against this live database. `connectionEnv` for a URL engine, `sqliteFile` for SQLite. */
46
+ studioExecute?: {
47
+ provider: AskDbStudioExecuteProvider;
48
+ connectionEnv?: string;
49
+ sqliteFile?: ScaffoldValue;
50
+ };
51
+ };
52
+ /**
53
+ * Everything a new project needs, ready for a front end to write and install.
54
+ *
55
+ * @experimental See the module note.
56
+ */
57
+ export type AskDbScaffoldPlan = {
58
+ /** The `askdb.config.ts` source. */
59
+ configSource: string;
60
+ /** The `.env.example` source: a `# purpose` line above each `NAME=`, every value empty. */
61
+ envExample: string;
62
+ /** Every env var the config reads, once each, database variables first. */
63
+ envVars: {
64
+ name: string;
65
+ purpose: string;
66
+ requiredForIntrospection: boolean;
67
+ }[];
68
+ /** `packages` are `name@spec`, or a bare name for a driver at its latest version. `allowBuilds` are the builds pnpm must approve. */
69
+ install: {
70
+ packages: string[];
71
+ allowBuilds: string[];
72
+ };
73
+ };
74
+ /**
75
+ * An answer {@link planAskDbScaffold} can't use. `field` is the answer's path, such as
76
+ * `connectionEnv` or `studioExecute.sqliteFile`; `reason` says what's wrong without naming
77
+ * it, so a front end can name the field its own way (a flag, a form field).
78
+ *
79
+ * @experimental See the module note.
80
+ */
81
+ export declare class AskDbScaffoldInputError extends Error {
82
+ readonly field: string;
83
+ readonly reason: string;
84
+ constructor(field: string, reason: string);
85
+ }
86
+ /**
87
+ * Plans a new project's `askdb.config.ts`, `.env.example` and installs from `answers`.
88
+ * `versions` are the `@askdb/config` and `@askdb/prisma` specs to install, which each front
89
+ * end reads from its own manifest. Pure: it reads and writes nothing.
90
+ *
91
+ * Every value lands in the config as a JSON string literal, and ids that become object
92
+ * keys are checked against their lists: the config runs when it loads.
93
+ *
94
+ * @throws {AskDbScaffoldInputError} for an env var name that isn't `^[A-Z_][A-Z0-9_]*$`,
95
+ * a control character in a path, an unknown id, or a missing answer.
96
+ * @experimental See the module note.
97
+ */
98
+ export declare function planAskDbScaffold(answers: AskDbScaffoldAnswers, versions: {
99
+ config: string;
100
+ prisma: string;
101
+ }): AskDbScaffoldPlan;
102
+ /**
103
+ * Whether `name` is an env var name the planner accepts: POSIX, uppercase
104
+ * (`^[A-Z_][A-Z0-9_]*$`). A leading `_` is allowed. `askdb init` uses it to tell an env
105
+ * var name from a path in `--sqlite-file`.
106
+ *
107
+ * @experimental See the module note.
108
+ */
109
+ export declare function isAskDbScaffoldEnvName(name: string): boolean;
110
+ //# sourceMappingURL=plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/scaffold/plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAKL,KAAK,0BAA0B,EAC/B,KAAK,aAAa,EAClB,KAAK,0BAA0B,EAChC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAA+B,KAAK,0BAA0B,EAA4B,MAAM,SAAS,CAAC;AAEjH;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,0BAA0B,CAAC;IACrC,2EAA2E;IAC3E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,0BAA0B,CAAC;IAC/B,gFAAgF;IAChF,GAAG,EAAE;QAAE,KAAK,EAAE,aAAa,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,qHAAqH;IACrH,aAAa,CAAC,EAAE;QAAE,QAAQ,EAAE,0BAA0B,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,aAAa,CAAA;KAAE,CAAC;CAC9G,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,oCAAoC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,2FAA2F;IAC3F,UAAU,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,wBAAwB,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAChF,qIAAqI;IACrI,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CACxD,CAAC;AAEF;;;;;;GAMG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAE9C,QAAQ,CAAC,KAAK,EAAE,MAAM;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM;gBADd,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM;CAK1B;AA0CD;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,oBAAoB,EAC7B,QAAQ,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC3C,iBAAiB,CAUnB;AA2ID;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE5D"}