@dbx-tools/core 0.3.44 → 0.4.1
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/index.d.ts +11 -0
- package/lib/index.js +12 -0
- package/lib/src/brand.d.ts +105 -0
- package/lib/src/brand.js +66 -0
- package/lib/src/exec.d.ts +149 -0
- package/lib/src/exec.js +483 -0
- package/lib/src/file.d.ts +12 -0
- package/lib/src/file.js +21 -0
- package/lib/src/project.d.ts +54 -0
- package/lib/src/project.js +274 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/package.json +10 -6
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * as brand from "./src/brand.js";
|
|
2
|
+
export * as exec from "./src/exec.js";
|
|
3
|
+
export * as file from "./src/file.js";
|
|
4
|
+
export * as project from "./src/project.js";
|
|
5
|
+
export { BrandContextSchema, defaultBrandContext, parseBrandContext, brandContextJsonSchema, brandContextPrompt, findBrandContextFile, loadBrandContextFile, loadBrandContext, resolveBrandAssetPath } from "./src/brand.js";
|
|
6
|
+
export type { BrandContext, BrandContextInput } from "./src/brand.js";
|
|
7
|
+
export { spawn, spawnSync, shlex } from "./src/exec.js";
|
|
8
|
+
export type { ExecStdio, LineHandler, StdioOption, ExecResult, ExecOptions, SyncExecStdio, SyncExecOptions, SpawnArgs } from "./src/exec.js";
|
|
9
|
+
export { statSync } from "./src/file.js";
|
|
10
|
+
export { root, parseGitRemote, resolveProjectRoots, name, repositoryUrl, npmRegistry } from "./src/project.js";
|
|
11
|
+
export type { ProjectContext } from "./src/project.js";
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// GENERATED by projen watch - DO NOT EDIT.
|
|
2
|
+
// Regenerated from the exporting modules in ./src.
|
|
3
|
+
// Hand edits are overwritten on the next watch; this file is read-only.
|
|
4
|
+
export * as brand from "./src/brand.js";
|
|
5
|
+
export * as exec from "./src/exec.js";
|
|
6
|
+
export * as file from "./src/file.js";
|
|
7
|
+
export * as project from "./src/project.js";
|
|
8
|
+
export { BrandContextSchema, defaultBrandContext, parseBrandContext, brandContextJsonSchema, brandContextPrompt, findBrandContextFile, loadBrandContextFile, loadBrandContext, resolveBrandAssetPath } from "./src/brand.js";
|
|
9
|
+
export { spawn, spawnSync, shlex } from "./src/exec.js";
|
|
10
|
+
export { statSync } from "./src/file.js";
|
|
11
|
+
export { root, parseGitRemote, resolveProjectRoots, name, repositoryUrl, npmRegistry } from "./src/project.js";
|
|
12
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxPQUFPLEtBQUssS0FBSyxNQUFNLGFBQWEsQ0FBQztBQUNyQyxPQUFPLEtBQUssSUFBSSxNQUFNLFlBQVksQ0FBQztBQUNuQyxPQUFPLEtBQUssSUFBSSxNQUFNLFlBQVksQ0FBQztBQUNuQyxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsbUJBQW1CLEVBQUUsaUJBQWlCLEVBQUUsc0JBQXNCLEVBQUUsa0JBQWtCLEVBQUUsb0JBQW9CLEVBQUUsb0JBQW9CLEVBQUUsZ0JBQWdCLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFMU4sT0FBTyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRXJELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDdEMsT0FBTyxFQUFFLElBQUksRUFBRSxjQUFjLEVBQUUsbUJBQW1CLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxXQUFXLEVBQUUsTUFBTSxlQUFlLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBHRU5FUkFURUQgYnkgcHJvamVuIHdhdGNoIC0gRE8gTk9UIEVESVQuXG4vLyBSZWdlbmVyYXRlZCBmcm9tIHRoZSBleHBvcnRpbmcgbW9kdWxlcyBpbiAuL3NyYy5cbi8vIEhhbmQgZWRpdHMgYXJlIG92ZXJ3cml0dGVuIG9uIHRoZSBuZXh0IHdhdGNoOyB0aGlzIGZpbGUgaXMgcmVhZC1vbmx5LlxuXG5leHBvcnQgKiBhcyBicmFuZCBmcm9tIFwiLi9zcmMvYnJhbmRcIjtcbmV4cG9ydCAqIGFzIGV4ZWMgZnJvbSBcIi4vc3JjL2V4ZWNcIjtcbmV4cG9ydCAqIGFzIGZpbGUgZnJvbSBcIi4vc3JjL2ZpbGVcIjtcbmV4cG9ydCAqIGFzIHByb2plY3QgZnJvbSBcIi4vc3JjL3Byb2plY3RcIjtcbmV4cG9ydCB7IEJyYW5kQ29udGV4dFNjaGVtYSwgZGVmYXVsdEJyYW5kQ29udGV4dCwgcGFyc2VCcmFuZENvbnRleHQsIGJyYW5kQ29udGV4dEpzb25TY2hlbWEsIGJyYW5kQ29udGV4dFByb21wdCwgZmluZEJyYW5kQ29udGV4dEZpbGUsIGxvYWRCcmFuZENvbnRleHRGaWxlLCBsb2FkQnJhbmRDb250ZXh0LCByZXNvbHZlQnJhbmRBc3NldFBhdGggfSBmcm9tIFwiLi9zcmMvYnJhbmRcIjtcbmV4cG9ydCB0eXBlIHsgQnJhbmRDb250ZXh0LCBCcmFuZENvbnRleHRJbnB1dCB9IGZyb20gXCIuL3NyYy9icmFuZFwiO1xuZXhwb3J0IHsgc3Bhd24sIHNwYXduU3luYywgc2hsZXggfSBmcm9tIFwiLi9zcmMvZXhlY1wiO1xuZXhwb3J0IHR5cGUgeyBFeGVjU3RkaW8sIExpbmVIYW5kbGVyLCBTdGRpb09wdGlvbiwgRXhlY1Jlc3VsdCwgRXhlY09wdGlvbnMsIFN5bmNFeGVjU3RkaW8sIFN5bmNFeGVjT3B0aW9ucywgU3Bhd25BcmdzIH0gZnJvbSBcIi4vc3JjL2V4ZWNcIjtcbmV4cG9ydCB7IHN0YXRTeW5jIH0gZnJvbSBcIi4vc3JjL2ZpbGVcIjtcbmV4cG9ydCB7IHJvb3QsIHBhcnNlR2l0UmVtb3RlLCByZXNvbHZlUHJvamVjdFJvb3RzLCBuYW1lLCByZXBvc2l0b3J5VXJsLCBucG1SZWdpc3RyeSB9IGZyb20gXCIuL3NyYy9wcm9qZWN0XCI7XG5leHBvcnQgdHlwZSB7IFByb2plY3RDb250ZXh0IH0gZnJvbSBcIi4vc3JjL3Byb2plY3RcIjtcbiJdfQ==
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { brand as sharedBrand } from "@dbx-tools/shared-core";
|
|
2
|
+
export type BrandContext = sharedBrand.BrandContext;
|
|
3
|
+
export type BrandContextInput = sharedBrand.BrandContextInput;
|
|
4
|
+
export declare const BrandContextSchema: import("zod").ZodObject<{
|
|
5
|
+
schemaVersion: import("zod").ZodDefault<import("zod").ZodLiteral<"1">>;
|
|
6
|
+
name: import("zod").ZodDefault<import("zod").ZodString>;
|
|
7
|
+
shortName: import("zod").ZodDefault<import("zod").ZodString>;
|
|
8
|
+
tagline: import("zod").ZodDefault<import("zod").ZodString>;
|
|
9
|
+
description: import("zod").ZodDefault<import("zod").ZodString>;
|
|
10
|
+
assets: import("zod").ZodDefault<import("zod").ZodObject<{
|
|
11
|
+
icon: import("zod").ZodDefault<import("zod").ZodObject<{
|
|
12
|
+
light: import("zod").ZodString;
|
|
13
|
+
dark: import("zod").ZodOptional<import("zod").ZodString>;
|
|
14
|
+
}, import("zod/v4/core").$strict>>;
|
|
15
|
+
logo: import("zod").ZodDefault<import("zod").ZodObject<{
|
|
16
|
+
light: import("zod").ZodString;
|
|
17
|
+
dark: import("zod").ZodOptional<import("zod").ZodString>;
|
|
18
|
+
}, import("zod/v4/core").$strict>>;
|
|
19
|
+
favicon: import("zod").ZodDefault<import("zod").ZodString>;
|
|
20
|
+
}, import("zod/v4/core").$strict>>;
|
|
21
|
+
colors: import("zod").ZodPrefault<import("zod").ZodObject<{
|
|
22
|
+
primary: import("zod").ZodDefault<import("zod").ZodString>;
|
|
23
|
+
primaryHover: import("zod").ZodDefault<import("zod").ZodString>;
|
|
24
|
+
accent: import("zod").ZodDefault<import("zod").ZodString>;
|
|
25
|
+
foreground: import("zod").ZodDefault<import("zod").ZodString>;
|
|
26
|
+
background: import("zod").ZodDefault<import("zod").ZodString>;
|
|
27
|
+
surface: import("zod").ZodDefault<import("zod").ZodString>;
|
|
28
|
+
muted: import("zod").ZodDefault<import("zod").ZodString>;
|
|
29
|
+
border: import("zod").ZodDefault<import("zod").ZodString>;
|
|
30
|
+
}, import("zod/v4/core").$strict>>;
|
|
31
|
+
typography: import("zod").ZodPrefault<import("zod").ZodObject<{
|
|
32
|
+
sans: import("zod").ZodDefault<import("zod").ZodString>;
|
|
33
|
+
mono: import("zod").ZodDefault<import("zod").ZodString>;
|
|
34
|
+
}, import("zod/v4/core").$strict>>;
|
|
35
|
+
voice: import("zod").ZodPrefault<import("zod").ZodObject<{
|
|
36
|
+
audience: import("zod").ZodDefault<import("zod").ZodArray<import("zod").ZodString>>;
|
|
37
|
+
tone: import("zod").ZodDefault<import("zod").ZodArray<import("zod").ZodString>>;
|
|
38
|
+
principles: import("zod").ZodDefault<import("zod").ZodArray<import("zod").ZodString>>;
|
|
39
|
+
avoid: import("zod").ZodDefault<import("zod").ZodArray<import("zod").ZodString>>;
|
|
40
|
+
}, import("zod/v4/core").$strict>>;
|
|
41
|
+
links: import("zod").ZodDefault<import("zod").ZodObject<{
|
|
42
|
+
website: import("zod").ZodOptional<import("zod").ZodString>;
|
|
43
|
+
repository: import("zod").ZodOptional<import("zod").ZodString>;
|
|
44
|
+
documentation: import("zod").ZodOptional<import("zod").ZodString>;
|
|
45
|
+
}, import("zod/v4/core").$strict>>;
|
|
46
|
+
extensions: import("zod").ZodDefault<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
47
|
+
}, import("zod/v4/core").$strict>;
|
|
48
|
+
export declare const defaultBrandContext: {
|
|
49
|
+
schemaVersion: "1";
|
|
50
|
+
name: string;
|
|
51
|
+
shortName: string;
|
|
52
|
+
tagline: string;
|
|
53
|
+
description: string;
|
|
54
|
+
assets: {
|
|
55
|
+
icon: {
|
|
56
|
+
light: string;
|
|
57
|
+
dark?: string | undefined;
|
|
58
|
+
};
|
|
59
|
+
logo: {
|
|
60
|
+
light: string;
|
|
61
|
+
dark?: string | undefined;
|
|
62
|
+
};
|
|
63
|
+
favicon: string;
|
|
64
|
+
};
|
|
65
|
+
colors: {
|
|
66
|
+
primary: string;
|
|
67
|
+
primaryHover: string;
|
|
68
|
+
accent: string;
|
|
69
|
+
foreground: string;
|
|
70
|
+
background: string;
|
|
71
|
+
surface: string;
|
|
72
|
+
muted: string;
|
|
73
|
+
border: string;
|
|
74
|
+
};
|
|
75
|
+
typography: {
|
|
76
|
+
sans: string;
|
|
77
|
+
mono: string;
|
|
78
|
+
};
|
|
79
|
+
voice: {
|
|
80
|
+
audience: string[];
|
|
81
|
+
tone: string[];
|
|
82
|
+
principles: string[];
|
|
83
|
+
avoid: string[];
|
|
84
|
+
};
|
|
85
|
+
links: {
|
|
86
|
+
website?: string | undefined;
|
|
87
|
+
repository?: string | undefined;
|
|
88
|
+
documentation?: string | undefined;
|
|
89
|
+
};
|
|
90
|
+
extensions: Record<string, unknown>;
|
|
91
|
+
};
|
|
92
|
+
export declare const parseBrandContext: typeof sharedBrand.parseBrandContext;
|
|
93
|
+
export declare const brandContextJsonSchema: typeof sharedBrand.brandContextJsonSchema;
|
|
94
|
+
export declare const brandContextPrompt: typeof sharedBrand.brandContextPrompt;
|
|
95
|
+
/** Find a conventional YAML or JSON brand file from known project roots. */
|
|
96
|
+
export declare function findBrandContextFile(cwd?: string): string | undefined;
|
|
97
|
+
/** Read and validate one `.yaml`, `.yml`, or `.json` brand context file. */
|
|
98
|
+
export declare function loadBrandContextFile(path: string): Promise<BrandContext>;
|
|
99
|
+
/**
|
|
100
|
+
* Discover and load a brand context. Missing files resolve to dbx tools defaults;
|
|
101
|
+
* malformed files fail with their parser or Zod validation error.
|
|
102
|
+
*/
|
|
103
|
+
export declare function loadBrandContext(cwd?: string): Promise<BrandContext>;
|
|
104
|
+
/** Resolve a relative asset reference against the brand file that declared it. */
|
|
105
|
+
export declare function resolveBrandAssetPath(brandFile: string, asset: string): string;
|
package/lib/src/brand.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/** Node-only discovery and file loading for the shared brand context. */
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, extname, isAbsolute, resolve } from "node:path";
|
|
4
|
+
import { brand as sharedBrand } from "@dbx-tools/shared-core";
|
|
5
|
+
import { statSync } from "./file.js";
|
|
6
|
+
import { resolveProjectRoots } from "./project.js";
|
|
7
|
+
const BRAND_CONTEXT_FILES = [
|
|
8
|
+
"branding/brand.yaml",
|
|
9
|
+
"branding/brand.yml",
|
|
10
|
+
"branding/brand.json",
|
|
11
|
+
"brand.yaml",
|
|
12
|
+
"brand.yml",
|
|
13
|
+
"brand.json",
|
|
14
|
+
];
|
|
15
|
+
export const BrandContextSchema = sharedBrand.BrandContextSchema;
|
|
16
|
+
export const defaultBrandContext = sharedBrand.defaultBrandContext;
|
|
17
|
+
export const parseBrandContext = sharedBrand.parseBrandContext;
|
|
18
|
+
export const brandContextJsonSchema = sharedBrand.brandContextJsonSchema;
|
|
19
|
+
export const brandContextPrompt = sharedBrand.brandContextPrompt;
|
|
20
|
+
/** Find a conventional YAML or JSON brand file from known project roots. */
|
|
21
|
+
export function findBrandContextFile(cwd = process.cwd()) {
|
|
22
|
+
for (const root of resolveProjectRoots(cwd)) {
|
|
23
|
+
for (const candidate of BRAND_CONTEXT_FILES) {
|
|
24
|
+
const path = resolve(root, candidate);
|
|
25
|
+
if (statSync(path)?.isFile())
|
|
26
|
+
return path;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
/** Read and validate one `.yaml`, `.yml`, or `.json` brand context file. */
|
|
32
|
+
export async function loadBrandContextFile(path) {
|
|
33
|
+
const source = await readFile(path, "utf8");
|
|
34
|
+
const extension = extname(path).toLowerCase();
|
|
35
|
+
let input;
|
|
36
|
+
if (extension === ".json") {
|
|
37
|
+
input = JSON.parse(source);
|
|
38
|
+
}
|
|
39
|
+
else if (extension === ".yaml" || extension === ".yml") {
|
|
40
|
+
const { parse } = await import("yaml");
|
|
41
|
+
input = parse(source);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
throw new Error(`Unsupported brand context format: ${extension || "no extension"}`);
|
|
45
|
+
}
|
|
46
|
+
return sharedBrand.parseBrandContext(input);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Discover and load a brand context. Missing files resolve to dbx tools defaults;
|
|
50
|
+
* malformed files fail with their parser or Zod validation error.
|
|
51
|
+
*/
|
|
52
|
+
export async function loadBrandContext(cwd = process.cwd()) {
|
|
53
|
+
const path = findBrandContextFile(cwd);
|
|
54
|
+
return path ? loadBrandContextFile(path) : sharedBrand.defaultBrandContext;
|
|
55
|
+
}
|
|
56
|
+
/** Resolve a relative asset reference against the brand file that declared it. */
|
|
57
|
+
export function resolveBrandAssetPath(brandFile, asset) {
|
|
58
|
+
if (isAbsolute(asset) ||
|
|
59
|
+
asset.startsWith("@") ||
|
|
60
|
+
asset.startsWith("//") ||
|
|
61
|
+
/^[a-z][a-z\d+.-]*:/i.test(asset)) {
|
|
62
|
+
return asset;
|
|
63
|
+
}
|
|
64
|
+
return resolve(dirname(brandFile), asset);
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJhbmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYnJhbmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEseUVBQXlFO0FBQ3pFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM1QyxPQUFPLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ2xFLE9BQU8sRUFBRSxLQUFLLElBQUksV0FBVyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDOUQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUNsQyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFaEQsTUFBTSxtQkFBbUIsR0FBRztJQUMxQixxQkFBcUI7SUFDckIsb0JBQW9CO0lBQ3BCLHFCQUFxQjtJQUNyQixZQUFZO0lBQ1osV0FBVztJQUNYLFlBQVk7Q0FDSixDQUFDO0FBSVgsTUFBTSxDQUFDLE1BQU0sa0JBQWtCLEdBQUcsV0FBVyxDQUFDLGtCQUFrQixDQUFDO0FBQ2pFLE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFHLFdBQVcsQ0FBQyxtQkFBbUIsQ0FBQztBQUNuRSxNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBRyxXQUFXLENBQUMsaUJBQWlCLENBQUM7QUFDL0QsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQUcsV0FBVyxDQUFDLHNCQUFzQixDQUFDO0FBQ3pFLE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFHLFdBQVcsQ0FBQyxrQkFBa0IsQ0FBQztBQUVqRSw0RUFBNEU7QUFDNUUsTUFBTSxVQUFVLG9CQUFvQixDQUFDLE1BQWMsT0FBTyxDQUFDLEdBQUcsRUFBRTtJQUM5RCxLQUFLLE1BQU0sSUFBSSxJQUFJLG1CQUFtQixDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDNUMsS0FBSyxNQUFNLFNBQVMsSUFBSSxtQkFBbUIsRUFBRSxDQUFDO1lBQzVDLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFJLEVBQUUsU0FBUyxDQUFDLENBQUM7WUFDdEMsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxFQUFFO2dCQUFFLE9BQU8sSUFBSSxDQUFDO1FBQzVDLENBQUM7SUFDSCxDQUFDO0lBQ0QsT0FBTyxTQUFTLENBQUM7QUFDbkIsQ0FBQztBQUVELDRFQUE0RTtBQUM1RSxNQUFNLENBQUMsS0FBSyxVQUFVLG9CQUFvQixDQUFDLElBQVk7SUFDckQsTUFBTSxNQUFNLEdBQUcsTUFBTSxRQUFRLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQzVDLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUM5QyxJQUFJLEtBQWMsQ0FBQztJQUVuQixJQUFJLFNBQVMsS0FBSyxPQUFPLEVBQUUsQ0FBQztRQUMxQixLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQVksQ0FBQztJQUN4QyxDQUFDO1NBQU0sSUFBSSxTQUFTLEtBQUssT0FBTyxJQUFJLFNBQVMsS0FBSyxNQUFNLEVBQUUsQ0FBQztRQUN6RCxNQUFNLEVBQUUsS0FBSyxFQUFFLEdBQUcsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdkMsS0FBSyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQVksQ0FBQztJQUNuQyxDQUFDO1NBQU0sQ0FBQztRQUNOLE1BQU0sSUFBSSxLQUFLLENBQUMscUNBQXFDLFNBQVMsSUFBSSxjQUFjLEVBQUUsQ0FBQyxDQUFDO0lBQ3RGLENBQUM7SUFFRCxPQUFPLFdBQVcsQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUM5QyxDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxnQkFBZ0IsQ0FBQyxNQUFjLE9BQU8sQ0FBQyxHQUFHLEVBQUU7SUFDaEUsTUFBTSxJQUFJLEdBQUcsb0JBQW9CLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdkMsT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsbUJBQW1CLENBQUM7QUFDN0UsQ0FBQztBQUVELGtGQUFrRjtBQUNsRixNQUFNLFVBQVUscUJBQXFCLENBQUMsU0FBaUIsRUFBRSxLQUFhO0lBQ3BFLElBQ0UsVUFBVSxDQUFDLEtBQUssQ0FBQztRQUNqQixLQUFLLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQztRQUNyQixLQUFLLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQztRQUN0QixxQkFBcUIsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQ2pDLENBQUM7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFDRCxPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDNUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKiBOb2RlLW9ubHkgZGlzY292ZXJ5IGFuZCBmaWxlIGxvYWRpbmcgZm9yIHRoZSBzaGFyZWQgYnJhbmQgY29udGV4dC4gKi9cbmltcG9ydCB7IHJlYWRGaWxlIH0gZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIjtcbmltcG9ydCB7IGRpcm5hbWUsIGV4dG5hbWUsIGlzQWJzb2x1dGUsIHJlc29sdmUgfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgeyBicmFuZCBhcyBzaGFyZWRCcmFuZCB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgeyBzdGF0U3luYyB9IGZyb20gXCIuL2ZpbGVcIjtcbmltcG9ydCB7IHJlc29sdmVQcm9qZWN0Um9vdHMgfSBmcm9tIFwiLi9wcm9qZWN0XCI7XG5cbmNvbnN0IEJSQU5EX0NPTlRFWFRfRklMRVMgPSBbXG4gIFwiYnJhbmRpbmcvYnJhbmQueWFtbFwiLFxuICBcImJyYW5kaW5nL2JyYW5kLnltbFwiLFxuICBcImJyYW5kaW5nL2JyYW5kLmpzb25cIixcbiAgXCJicmFuZC55YW1sXCIsXG4gIFwiYnJhbmQueW1sXCIsXG4gIFwiYnJhbmQuanNvblwiLFxuXSBhcyBjb25zdDtcblxuZXhwb3J0IHR5cGUgQnJhbmRDb250ZXh0ID0gc2hhcmVkQnJhbmQuQnJhbmRDb250ZXh0O1xuZXhwb3J0IHR5cGUgQnJhbmRDb250ZXh0SW5wdXQgPSBzaGFyZWRCcmFuZC5CcmFuZENvbnRleHRJbnB1dDtcbmV4cG9ydCBjb25zdCBCcmFuZENvbnRleHRTY2hlbWEgPSBzaGFyZWRCcmFuZC5CcmFuZENvbnRleHRTY2hlbWE7XG5leHBvcnQgY29uc3QgZGVmYXVsdEJyYW5kQ29udGV4dCA9IHNoYXJlZEJyYW5kLmRlZmF1bHRCcmFuZENvbnRleHQ7XG5leHBvcnQgY29uc3QgcGFyc2VCcmFuZENvbnRleHQgPSBzaGFyZWRCcmFuZC5wYXJzZUJyYW5kQ29udGV4dDtcbmV4cG9ydCBjb25zdCBicmFuZENvbnRleHRKc29uU2NoZW1hID0gc2hhcmVkQnJhbmQuYnJhbmRDb250ZXh0SnNvblNjaGVtYTtcbmV4cG9ydCBjb25zdCBicmFuZENvbnRleHRQcm9tcHQgPSBzaGFyZWRCcmFuZC5icmFuZENvbnRleHRQcm9tcHQ7XG5cbi8qKiBGaW5kIGEgY29udmVudGlvbmFsIFlBTUwgb3IgSlNPTiBicmFuZCBmaWxlIGZyb20ga25vd24gcHJvamVjdCByb290cy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaW5kQnJhbmRDb250ZXh0RmlsZShjd2Q6IHN0cmluZyA9IHByb2Nlc3MuY3dkKCkpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBmb3IgKGNvbnN0IHJvb3Qgb2YgcmVzb2x2ZVByb2plY3RSb290cyhjd2QpKSB7XG4gICAgZm9yIChjb25zdCBjYW5kaWRhdGUgb2YgQlJBTkRfQ09OVEVYVF9GSUxFUykge1xuICAgICAgY29uc3QgcGF0aCA9IHJlc29sdmUocm9vdCwgY2FuZGlkYXRlKTtcbiAgICAgIGlmIChzdGF0U3luYyhwYXRoKT8uaXNGaWxlKCkpIHJldHVybiBwYXRoO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG4vKiogUmVhZCBhbmQgdmFsaWRhdGUgb25lIGAueWFtbGAsIGAueW1sYCwgb3IgYC5qc29uYCBicmFuZCBjb250ZXh0IGZpbGUuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbG9hZEJyYW5kQ29udGV4dEZpbGUocGF0aDogc3RyaW5nKTogUHJvbWlzZTxCcmFuZENvbnRleHQ+IHtcbiAgY29uc3Qgc291cmNlID0gYXdhaXQgcmVhZEZpbGUocGF0aCwgXCJ1dGY4XCIpO1xuICBjb25zdCBleHRlbnNpb24gPSBleHRuYW1lKHBhdGgpLnRvTG93ZXJDYXNlKCk7XG4gIGxldCBpbnB1dDogdW5rbm93bjtcblxuICBpZiAoZXh0ZW5zaW9uID09PSBcIi5qc29uXCIpIHtcbiAgICBpbnB1dCA9IEpTT04ucGFyc2Uoc291cmNlKSBhcyB1bmtub3duO1xuICB9IGVsc2UgaWYgKGV4dGVuc2lvbiA9PT0gXCIueWFtbFwiIHx8IGV4dGVuc2lvbiA9PT0gXCIueW1sXCIpIHtcbiAgICBjb25zdCB7IHBhcnNlIH0gPSBhd2FpdCBpbXBvcnQoXCJ5YW1sXCIpO1xuICAgIGlucHV0ID0gcGFyc2Uoc291cmNlKSBhcyB1bmtub3duO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgYnJhbmQgY29udGV4dCBmb3JtYXQ6ICR7ZXh0ZW5zaW9uIHx8IFwibm8gZXh0ZW5zaW9uXCJ9YCk7XG4gIH1cblxuICByZXR1cm4gc2hhcmVkQnJhbmQucGFyc2VCcmFuZENvbnRleHQoaW5wdXQpO1xufVxuXG4vKipcbiAqIERpc2NvdmVyIGFuZCBsb2FkIGEgYnJhbmQgY29udGV4dC4gTWlzc2luZyBmaWxlcyByZXNvbHZlIHRvIGRieCB0b29scyBkZWZhdWx0cztcbiAqIG1hbGZvcm1lZCBmaWxlcyBmYWlsIHdpdGggdGhlaXIgcGFyc2VyIG9yIFpvZCB2YWxpZGF0aW9uIGVycm9yLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbG9hZEJyYW5kQ29udGV4dChjd2Q6IHN0cmluZyA9IHByb2Nlc3MuY3dkKCkpOiBQcm9taXNlPEJyYW5kQ29udGV4dD4ge1xuICBjb25zdCBwYXRoID0gZmluZEJyYW5kQ29udGV4dEZpbGUoY3dkKTtcbiAgcmV0dXJuIHBhdGggPyBsb2FkQnJhbmRDb250ZXh0RmlsZShwYXRoKSA6IHNoYXJlZEJyYW5kLmRlZmF1bHRCcmFuZENvbnRleHQ7XG59XG5cbi8qKiBSZXNvbHZlIGEgcmVsYXRpdmUgYXNzZXQgcmVmZXJlbmNlIGFnYWluc3QgdGhlIGJyYW5kIGZpbGUgdGhhdCBkZWNsYXJlZCBpdC4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlQnJhbmRBc3NldFBhdGgoYnJhbmRGaWxlOiBzdHJpbmcsIGFzc2V0OiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAoXG4gICAgaXNBYnNvbHV0ZShhc3NldCkgfHxcbiAgICBhc3NldC5zdGFydHNXaXRoKFwiQFwiKSB8fFxuICAgIGFzc2V0LnN0YXJ0c1dpdGgoXCIvL1wiKSB8fFxuICAgIC9eW2Etel1bYS16XFxkKy4tXSo6L2kudGVzdChhc3NldClcbiAgKSB7XG4gICAgcmV0dXJuIGFzc2V0O1xuICB9XG4gIHJldHVybiByZXNvbHZlKGRpcm5hbWUoYnJhbmRGaWxlKSwgYXNzZXQpO1xufVxuIl19
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portable subprocess helper built on `child_process.spawn` and line streaming.
|
|
3
|
+
*
|
|
4
|
+
* Ported from `dbx-tools-js/packages/cli/src/exec.ts`. Each stdio fd defaults to
|
|
5
|
+
* `"inherit"`. {@link spawn} streams output line-by-line into {@link ExecResult.stdoutLines}
|
|
6
|
+
* / {@link ExecResult.stderrLines}; its `stdout` / `stderr` getters join those lines.
|
|
7
|
+
* {@link spawnSync} keeps the captured string; its `stdout` / `stderr` getters read
|
|
8
|
+
* that string directly (line arrays split lazily on read).
|
|
9
|
+
* Omitted `trim` (default) applies adaptive normalization: {@link spawnSync} drops
|
|
10
|
+
* at most one trailing empty line / newline `spawnSync` adds; {@link spawn} does
|
|
11
|
+
* not (readline never emits that extra line). `trim: true` strips all leading/
|
|
12
|
+
* trailing whitespace in both modes; `trim: false` leaves output unchanged.
|
|
13
|
+
*
|
|
14
|
+
* @example Capture command output
|
|
15
|
+
* ```ts
|
|
16
|
+
* const { stdout } = await exec("git", ["rev-parse", "--show-toplevel"], {
|
|
17
|
+
* stdout: "capture",
|
|
18
|
+
* stderr: "ignore",
|
|
19
|
+
* stdin: "ignore",
|
|
20
|
+
* });
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @example Stream and capture together
|
|
24
|
+
* ```ts
|
|
25
|
+
* await exec("pnpm", ["install"], {
|
|
26
|
+
* stdout: [(line) => console.log(line), "capture"],
|
|
27
|
+
* check: true,
|
|
28
|
+
* });
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @example Synchronous capture (no line callbacks)
|
|
32
|
+
* ```ts
|
|
33
|
+
* const { stdout } = execSync("git", ["rev-parse", "--show-toplevel"], {
|
|
34
|
+
* stdout: "capture",
|
|
35
|
+
* stderr: "ignore",
|
|
36
|
+
* stdin: "ignore",
|
|
37
|
+
* });
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @module
|
|
41
|
+
*/
|
|
42
|
+
import { type SpawnOptions } from "node:child_process";
|
|
43
|
+
/** Stdio mode for a subprocess fd. */
|
|
44
|
+
export type ExecStdio = "inherit" | "pipe" | "ignore";
|
|
45
|
+
/** Invoked once per output line when a fd is piped. */
|
|
46
|
+
export type LineHandler = (line: string) => void;
|
|
47
|
+
/**
|
|
48
|
+
* Stdio config for one fd.
|
|
49
|
+
*
|
|
50
|
+
* - `"inherit"` / `"pipe"` / `"ignore"` — pass through to `spawn`
|
|
51
|
+
* - `"capture"` — pipe the fd and append each line to the result
|
|
52
|
+
* - {@link LineHandler} — pipe and invoke the handler per line (lines are still captured)
|
|
53
|
+
* - `(LineHandler | "capture")[]` — pipe; `"capture"` is a no-op marker, handlers run per line
|
|
54
|
+
*/
|
|
55
|
+
export type StdioOption = ExecStdio | LineHandler | "capture" | (LineHandler | "capture")[];
|
|
56
|
+
/** Outcome of {@link spawn} / {@link spawnSync}: exit code, captured output, and line views. */
|
|
57
|
+
export type ExecResult = {
|
|
58
|
+
exitCode: number;
|
|
59
|
+
/**
|
|
60
|
+
* Captured stdout lines. For {@link spawn} these are built while the process runs;
|
|
61
|
+
* for {@link spawnSync} they are split from the captured string on first read.
|
|
62
|
+
*/
|
|
63
|
+
readonly stdoutLines: string[];
|
|
64
|
+
/**
|
|
65
|
+
* Captured stderr lines. For {@link spawn} these are built while the process runs;
|
|
66
|
+
* for {@link spawnSync} they are split from the captured string on first read.
|
|
67
|
+
*/
|
|
68
|
+
readonly stderrLines: string[];
|
|
69
|
+
/**
|
|
70
|
+
* Captured stdout text. {@link spawnSync} reads the captured string;
|
|
71
|
+
* {@link spawn} joins {@link stdoutLines}. See `trim` for normalization.
|
|
72
|
+
*/
|
|
73
|
+
readonly stdout: string;
|
|
74
|
+
/**
|
|
75
|
+
* Captured stderr text. {@link spawnSync} reads the captured string;
|
|
76
|
+
* {@link spawn} joins {@link stderrLines}. See `trim` for normalization.
|
|
77
|
+
*/
|
|
78
|
+
readonly stderr: string;
|
|
79
|
+
};
|
|
80
|
+
/** Options for {@link spawn}. Extends `SpawnOptions` except `stdio`, which is driven by `stdin` / `stdout` / `stderr`. */
|
|
81
|
+
export type ExecOptions = Omit<SpawnOptions, "stdio"> & {
|
|
82
|
+
/** `"inherit"` by default, or a string written to the process stdin. */
|
|
83
|
+
stdin?: ExecStdio | string;
|
|
84
|
+
stdout?: StdioOption;
|
|
85
|
+
stderr?: StdioOption;
|
|
86
|
+
/** Throw when the process exits with a non-zero code. */
|
|
87
|
+
check?: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Omitted — adaptive trim ({@link spawnSync} drops one spawn trailing newline,
|
|
90
|
+
* {@link spawn} does not); `true` — strip all leading/trailing whitespace;
|
|
91
|
+
* `false` — leave captured output unchanged.
|
|
92
|
+
*/
|
|
93
|
+
trim?: boolean;
|
|
94
|
+
};
|
|
95
|
+
/** Stdio mode for {@link spawnSync} (no per-line callbacks). */
|
|
96
|
+
export type SyncExecStdio = ExecStdio | "capture";
|
|
97
|
+
/** Options for {@link spawnSync}. Same shape as {@link ExecOptions} but without line-handler stdio. */
|
|
98
|
+
export type SyncExecOptions = Omit<SpawnOptions, "stdio"> & {
|
|
99
|
+
/** `"inherit"` by default, or a string written to the process stdin. */
|
|
100
|
+
stdin?: ExecStdio | string;
|
|
101
|
+
stdout?: SyncExecStdio;
|
|
102
|
+
stderr?: SyncExecStdio;
|
|
103
|
+
/** Throw when the process exits with a non-zero code. */
|
|
104
|
+
check?: boolean;
|
|
105
|
+
/**
|
|
106
|
+
* Omitted — adaptive trim ({@link spawnSync} drops one spawn trailing newline,
|
|
107
|
+
* {@link spawn} does not); `true` — strip all leading/trailing whitespace;
|
|
108
|
+
* `false` — leave captured output unchanged.
|
|
109
|
+
*/
|
|
110
|
+
trim?: boolean;
|
|
111
|
+
};
|
|
112
|
+
export type SpawnArgs<T extends SpawnOptions> = [command: string, ...args: string[]] | [command: string, args: readonly string[]] | [command: string, args: readonly string[], options: T] | [command: string, ...argsAndOptions: [...string[], T]];
|
|
113
|
+
/**
|
|
114
|
+
* Spawn a subprocess and wait for exit.
|
|
115
|
+
*
|
|
116
|
+
* @param command - Executable to run (resolved on `PATH` when `shell` is set on options)
|
|
117
|
+
* @param args - Arguments passed verbatim to the executable
|
|
118
|
+
* @param options - Spawn, stdio, and check options
|
|
119
|
+
* @returns Exit code, captured line arrays, and trimmed `stdout` / `stderr` getters
|
|
120
|
+
* @throws When spawn fails, line reads fail, or `check` is true and exit code is non-zero
|
|
121
|
+
*/
|
|
122
|
+
export declare function spawn(...args: SpawnArgs<ExecOptions>): Promise<ExecResult>;
|
|
123
|
+
/**
|
|
124
|
+
* Spawn a subprocess synchronously and wait for exit.
|
|
125
|
+
*
|
|
126
|
+
* Unlike {@link spawn}, stdio options are limited to `"inherit"`, `"pipe"`,
|
|
127
|
+
* `"ignore"`, and `"capture"` — no per-line callbacks.
|
|
128
|
+
*
|
|
129
|
+
* @param command - Executable to run (resolved on `PATH` when `shell` is set on options)
|
|
130
|
+
* @param args - Arguments passed verbatim to the executable
|
|
131
|
+
* @param spawnSync - Spawn, stdio, and check options
|
|
132
|
+
* @returns Exit code, captured line arrays, and trimmed `stdout` / `stderr` getters
|
|
133
|
+
* @throws When spawn fails or `check` is true and exit code is non-zero
|
|
134
|
+
*/
|
|
135
|
+
export declare function spawnSync(...args: SpawnArgs<SyncExecOptions>): ExecResult;
|
|
136
|
+
/**
|
|
137
|
+
* Splits a shell-like command into argv.
|
|
138
|
+
*
|
|
139
|
+
* Supports:
|
|
140
|
+
* - whitespace separators
|
|
141
|
+
* - single and double quotes
|
|
142
|
+
* - backslash escaping
|
|
143
|
+
* - escaped spaces
|
|
144
|
+
* - empty quoted strings
|
|
145
|
+
*
|
|
146
|
+
* If the input is malformed (for example, an unterminated quote),
|
|
147
|
+
* returns the original string as a single argument.
|
|
148
|
+
*/
|
|
149
|
+
export declare function shlex(command: string): string[];
|