@tokens-studio/tokenscript-schemas 0.1.3 → 0.2.0
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/README.md +5 -0
- package/dist/cli/index.cjs +128 -81
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +127 -80
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/commands/build-dir.test.ts +354 -0
- package/src/cli/commands/build-dir.ts +90 -0
- package/src/cli/commands/bundle.ts +11 -14
- package/src/cli/index.ts +15 -0
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { buildSchemaDir } from "./build-dir.js";
|
|
6
|
+
|
|
7
|
+
// Mock ulog to silence logs during tests
|
|
8
|
+
vi.mock("ulog", () => {
|
|
9
|
+
const mockLogger = () => {};
|
|
10
|
+
mockLogger.error = () => {};
|
|
11
|
+
mockLogger.warn = () => {};
|
|
12
|
+
mockLogger.info = () => {};
|
|
13
|
+
mockLogger.log = () => {};
|
|
14
|
+
mockLogger.debug = () => {};
|
|
15
|
+
mockLogger.trace = () => {};
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
default: () => mockLogger,
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// Mock console.log to capture stdout
|
|
23
|
+
const originalConsoleLog = console.log;
|
|
24
|
+
let capturedOutput: string[] = [];
|
|
25
|
+
|
|
26
|
+
function mockConsoleLog(...args: any[]) {
|
|
27
|
+
capturedOutput.push(args.join(" "));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
describe("Build Command", () => {
|
|
31
|
+
// Test with real existing schemas
|
|
32
|
+
describe("with real schemas", () => {
|
|
33
|
+
it("should build css-color type schema", async () => {
|
|
34
|
+
const cssColorDir = join(process.cwd(), "src/schemas/types/css-color");
|
|
35
|
+
|
|
36
|
+
// Capture console output
|
|
37
|
+
capturedOutput = [];
|
|
38
|
+
console.log = mockConsoleLog;
|
|
39
|
+
|
|
40
|
+
await buildSchemaDir(cssColorDir);
|
|
41
|
+
|
|
42
|
+
// Restore console
|
|
43
|
+
console.log = originalConsoleLog;
|
|
44
|
+
|
|
45
|
+
const output = capturedOutput[0];
|
|
46
|
+
const result = JSON.parse(output);
|
|
47
|
+
|
|
48
|
+
expect(result.name).toBe("CSS");
|
|
49
|
+
expect(result.type).toBe("color");
|
|
50
|
+
expect(result.initializers).toBeDefined();
|
|
51
|
+
expect(result.conversions).toBeDefined();
|
|
52
|
+
|
|
53
|
+
// Verify scripts are inlined
|
|
54
|
+
expect(result.initializers[0].script.script).toContain("variable");
|
|
55
|
+
expect(result.conversions[0].script.script).toContain("variable");
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("should build darken function schema", async () => {
|
|
59
|
+
const darkenDir = join(process.cwd(), "src/schemas/functions/darken");
|
|
60
|
+
|
|
61
|
+
// Capture console output
|
|
62
|
+
capturedOutput = [];
|
|
63
|
+
console.log = mockConsoleLog;
|
|
64
|
+
|
|
65
|
+
await buildSchemaDir(darkenDir);
|
|
66
|
+
|
|
67
|
+
// Restore console
|
|
68
|
+
console.log = originalConsoleLog;
|
|
69
|
+
|
|
70
|
+
const output = capturedOutput[0];
|
|
71
|
+
const result = JSON.parse(output);
|
|
72
|
+
|
|
73
|
+
expect(result.name).toBe("Darken");
|
|
74
|
+
expect(result.type).toBe("function");
|
|
75
|
+
expect(result.keyword).toBe("darken");
|
|
76
|
+
expect(result.script).toBeDefined();
|
|
77
|
+
expect(result.requirements).toBeDefined();
|
|
78
|
+
|
|
79
|
+
// Verify script is inlined
|
|
80
|
+
expect(result.script.script).toContain("darken");
|
|
81
|
+
expect(result.script.script).toContain("OKLab");
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe("with custom test schemas", () => {
|
|
86
|
+
const customSchemasDir = join(process.cwd(), "test-build-schemas");
|
|
87
|
+
const customTypeDir = join(customSchemasDir, "custom-color");
|
|
88
|
+
const customFunctionDir = join(customSchemasDir, "custom-function");
|
|
89
|
+
|
|
90
|
+
beforeAll(async () => {
|
|
91
|
+
// Create custom color type schema
|
|
92
|
+
await mkdir(customTypeDir, { recursive: true });
|
|
93
|
+
|
|
94
|
+
const colorSchemaJson = {
|
|
95
|
+
name: "TestColor",
|
|
96
|
+
type: "color" as const,
|
|
97
|
+
description: "A test color type",
|
|
98
|
+
slug: "test-color",
|
|
99
|
+
schema: {
|
|
100
|
+
type: "object" as const,
|
|
101
|
+
properties: {
|
|
102
|
+
value: { type: "string" as const },
|
|
103
|
+
},
|
|
104
|
+
required: ["value"],
|
|
105
|
+
},
|
|
106
|
+
initializers: [
|
|
107
|
+
{
|
|
108
|
+
title: "Test Initializer",
|
|
109
|
+
keyword: "testcolor",
|
|
110
|
+
description: "Creates a test color",
|
|
111
|
+
script: {
|
|
112
|
+
type: "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
|
|
113
|
+
script: "./test-initializer.tokenscript",
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
conversions: [
|
|
118
|
+
{
|
|
119
|
+
source: "$self",
|
|
120
|
+
target: "$self",
|
|
121
|
+
description: "Test conversion",
|
|
122
|
+
lossless: true,
|
|
123
|
+
script: {
|
|
124
|
+
type: "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
|
|
125
|
+
script: "./test-conversion.tokenscript",
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
await writeFile(join(customTypeDir, "schema.json"), JSON.stringify(colorSchemaJson, null, 2));
|
|
132
|
+
|
|
133
|
+
const initializerScript = `// Test initializer
|
|
134
|
+
variable input: List = {input};
|
|
135
|
+
variable value: String = input.get(0);
|
|
136
|
+
variable output: Color.TestColor;
|
|
137
|
+
output.value = value;
|
|
138
|
+
return output;`;
|
|
139
|
+
|
|
140
|
+
await writeFile(join(customTypeDir, "test-initializer.tokenscript"), initializerScript);
|
|
141
|
+
|
|
142
|
+
const conversionScript = `// Test conversion
|
|
143
|
+
variable input: Color.TestColor = {input};
|
|
144
|
+
variable output: Color.TestColor;
|
|
145
|
+
output.value = input.value;
|
|
146
|
+
return output;`;
|
|
147
|
+
|
|
148
|
+
await writeFile(join(customTypeDir, "test-conversion.tokenscript"), conversionScript);
|
|
149
|
+
|
|
150
|
+
// Create custom function schema
|
|
151
|
+
await mkdir(customFunctionDir, { recursive: true });
|
|
152
|
+
|
|
153
|
+
const functionSchemaJson = {
|
|
154
|
+
name: "TestFunction",
|
|
155
|
+
type: "function" as const,
|
|
156
|
+
description: "A test function",
|
|
157
|
+
keyword: "testfunc",
|
|
158
|
+
input: {
|
|
159
|
+
type: "object" as const,
|
|
160
|
+
properties: {
|
|
161
|
+
value: { type: "number" as const },
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
script: {
|
|
165
|
+
type: "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
|
|
166
|
+
script: "./test-function.tokenscript",
|
|
167
|
+
},
|
|
168
|
+
requirements: [] as string[],
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
await writeFile(
|
|
172
|
+
join(customFunctionDir, "schema.json"),
|
|
173
|
+
JSON.stringify(functionSchemaJson, null, 2),
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
const functionScript = `// Test function
|
|
177
|
+
variable input: List = {input};
|
|
178
|
+
variable value: Number = input.get(0);
|
|
179
|
+
return value * 2;`;
|
|
180
|
+
|
|
181
|
+
await writeFile(join(customFunctionDir, "test-function.tokenscript"), functionScript);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
afterAll(async () => {
|
|
185
|
+
// Clean up
|
|
186
|
+
try {
|
|
187
|
+
await rm(customSchemasDir, { recursive: true, force: true });
|
|
188
|
+
} catch {
|
|
189
|
+
// Ignore
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it("should build color type schema with inlined scripts", async () => {
|
|
194
|
+
capturedOutput = [];
|
|
195
|
+
console.log = mockConsoleLog;
|
|
196
|
+
|
|
197
|
+
await buildSchemaDir(customTypeDir);
|
|
198
|
+
|
|
199
|
+
console.log = originalConsoleLog;
|
|
200
|
+
|
|
201
|
+
const output = capturedOutput[0];
|
|
202
|
+
const result = JSON.parse(output);
|
|
203
|
+
|
|
204
|
+
expect(result.name).toBe("TestColor");
|
|
205
|
+
expect(result.type).toBe("color");
|
|
206
|
+
expect(result.initializers[0].script.script).toContain("variable input: List");
|
|
207
|
+
expect(result.conversions[0].script.script).toContain("variable input: Color.TestColor");
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it("should build function schema with inlined script", async () => {
|
|
211
|
+
capturedOutput = [];
|
|
212
|
+
console.log = mockConsoleLog;
|
|
213
|
+
|
|
214
|
+
await buildSchemaDir(customFunctionDir);
|
|
215
|
+
|
|
216
|
+
console.log = originalConsoleLog;
|
|
217
|
+
|
|
218
|
+
const output = capturedOutput[0];
|
|
219
|
+
const result = JSON.parse(output);
|
|
220
|
+
|
|
221
|
+
expect(result.name).toBe("TestFunction");
|
|
222
|
+
expect(result.type).toBe("function");
|
|
223
|
+
expect(result.script.script).toContain("variable input: List");
|
|
224
|
+
expect(result.script.script).toContain("return value * 2");
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it("should output pretty JSON with --pretty option", async () => {
|
|
228
|
+
capturedOutput = [];
|
|
229
|
+
console.log = mockConsoleLog;
|
|
230
|
+
|
|
231
|
+
await buildSchemaDir(customTypeDir, { pretty: true });
|
|
232
|
+
|
|
233
|
+
console.log = originalConsoleLog;
|
|
234
|
+
|
|
235
|
+
const output = capturedOutput[0];
|
|
236
|
+
|
|
237
|
+
// Pretty JSON should have newlines and indentation
|
|
238
|
+
expect(output).toContain("\n");
|
|
239
|
+
expect(output).toContain(" ");
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
it("should output compact JSON without --pretty option", async () => {
|
|
243
|
+
capturedOutput = [];
|
|
244
|
+
console.log = mockConsoleLog;
|
|
245
|
+
|
|
246
|
+
await buildSchemaDir(customTypeDir, { pretty: false });
|
|
247
|
+
|
|
248
|
+
console.log = originalConsoleLog;
|
|
249
|
+
|
|
250
|
+
const output = capturedOutput[0];
|
|
251
|
+
|
|
252
|
+
// Compact JSON should not have newlines (except maybe trailing)
|
|
253
|
+
const lineCount = output.split("\n").length;
|
|
254
|
+
expect(lineCount).toBeLessThan(5);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it("should write to file when --output is specified", async () => {
|
|
258
|
+
const outputFile = join(customSchemasDir, "output.json");
|
|
259
|
+
|
|
260
|
+
await buildSchemaDir(customTypeDir, { output: outputFile });
|
|
261
|
+
|
|
262
|
+
expect(existsSync(outputFile)).toBe(true);
|
|
263
|
+
|
|
264
|
+
const content = await readFile(outputFile, "utf-8");
|
|
265
|
+
const result = JSON.parse(content);
|
|
266
|
+
|
|
267
|
+
expect(result.name).toBe("TestColor");
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it("should write pretty JSON to file with --pretty and --output", async () => {
|
|
271
|
+
const outputFile = join(customSchemasDir, "output-pretty.json");
|
|
272
|
+
|
|
273
|
+
await buildSchemaDir(customTypeDir, { output: outputFile, pretty: true });
|
|
274
|
+
|
|
275
|
+
const content = await readFile(outputFile, "utf-8");
|
|
276
|
+
|
|
277
|
+
// Pretty JSON should have newlines and indentation
|
|
278
|
+
expect(content).toContain("\n");
|
|
279
|
+
expect(content).toContain(" ");
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
describe("error handling", () => {
|
|
284
|
+
it("should throw error for non-existent directory", async () => {
|
|
285
|
+
await expect(buildSchemaDir("/non-existent/directory")).rejects.toThrow(
|
|
286
|
+
/Directory not found|not found/,
|
|
287
|
+
);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it("should throw error for directory without schema.json", async () => {
|
|
291
|
+
const emptyDir = join(process.cwd(), "test-empty-dir");
|
|
292
|
+
|
|
293
|
+
await mkdir(emptyDir, { recursive: true });
|
|
294
|
+
|
|
295
|
+
try {
|
|
296
|
+
await expect(buildSchemaDir(emptyDir)).rejects.toThrow(/schema.json not found/);
|
|
297
|
+
} finally {
|
|
298
|
+
await rm(emptyDir, { recursive: true, force: true });
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
describe("path resolution", () => {
|
|
304
|
+
const testSchemasDir = join(process.cwd(), "test-path-schemas");
|
|
305
|
+
const testSchemaDir = join(testSchemasDir, "test-schema");
|
|
306
|
+
|
|
307
|
+
beforeAll(async () => {
|
|
308
|
+
await mkdir(testSchemaDir, { recursive: true });
|
|
309
|
+
|
|
310
|
+
const schemaJson = {
|
|
311
|
+
name: "PathTest",
|
|
312
|
+
type: "color" as const,
|
|
313
|
+
description: "Path test schema",
|
|
314
|
+
slug: "path-test",
|
|
315
|
+
schema: {
|
|
316
|
+
type: "object" as const,
|
|
317
|
+
properties: {
|
|
318
|
+
value: { type: "string" as const },
|
|
319
|
+
},
|
|
320
|
+
required: ["value"],
|
|
321
|
+
},
|
|
322
|
+
initializers: [] as any[],
|
|
323
|
+
conversions: [] as any[],
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
await writeFile(join(testSchemaDir, "schema.json"), JSON.stringify(schemaJson, null, 2));
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
afterAll(async () => {
|
|
330
|
+
try {
|
|
331
|
+
await rm(testSchemasDir, { recursive: true, force: true });
|
|
332
|
+
} catch {
|
|
333
|
+
// Ignore
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
it("should resolve relative paths from current working directory", async () => {
|
|
338
|
+
// Use a relative path
|
|
339
|
+
const relativePath = "test-path-schemas/test-schema";
|
|
340
|
+
|
|
341
|
+
capturedOutput = [];
|
|
342
|
+
console.log = mockConsoleLog;
|
|
343
|
+
|
|
344
|
+
await buildSchemaDir(relativePath);
|
|
345
|
+
|
|
346
|
+
console.log = originalConsoleLog;
|
|
347
|
+
|
|
348
|
+
const output = capturedOutput[0];
|
|
349
|
+
const result = JSON.parse(output);
|
|
350
|
+
|
|
351
|
+
expect(result.name).toBe("PathTest");
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build command - Build individual schema directories
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/// <reference types="../../../types/ulog" />
|
|
6
|
+
|
|
7
|
+
import { existsSync } from "node:fs";
|
|
8
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
9
|
+
import { dirname, join } from "node:path";
|
|
10
|
+
import anylogger from "ulog";
|
|
11
|
+
import { buildSchemaFromDirectory } from "@/bundler/build-schema.js";
|
|
12
|
+
|
|
13
|
+
const log = anylogger("build-dir");
|
|
14
|
+
|
|
15
|
+
export interface BuildDirOptions {
|
|
16
|
+
output?: string;
|
|
17
|
+
pretty?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Build a schema from a directory containing schema.json
|
|
22
|
+
*/
|
|
23
|
+
export async function buildSchemaDir(
|
|
24
|
+
schemaDir: string,
|
|
25
|
+
options: BuildDirOptions = {},
|
|
26
|
+
): Promise<void> {
|
|
27
|
+
const resolvedDir = resolveSchemaDir(schemaDir);
|
|
28
|
+
|
|
29
|
+
if (!existsSync(resolvedDir)) {
|
|
30
|
+
throw new Error(`Directory not found: ${resolvedDir}`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const schemaJsonPath = join(resolvedDir, "schema.json");
|
|
34
|
+
if (!existsSync(schemaJsonPath)) {
|
|
35
|
+
throw new Error(`schema.json not found in: ${resolvedDir}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
log.info(`Building schema from: ${resolvedDir}`);
|
|
39
|
+
|
|
40
|
+
// Build the schema using shared bundler logic
|
|
41
|
+
const schema = await buildSchemaFromDirectory(resolvedDir);
|
|
42
|
+
|
|
43
|
+
// Generate output
|
|
44
|
+
const output = options.pretty ? JSON.stringify(schema, null, 2) : JSON.stringify(schema);
|
|
45
|
+
|
|
46
|
+
// Write to stdout or file
|
|
47
|
+
if (options.output) {
|
|
48
|
+
await mkdir(dirname(options.output), { recursive: true });
|
|
49
|
+
await writeFile(options.output, output, "utf-8");
|
|
50
|
+
log.info(`Output written to: ${options.output}`);
|
|
51
|
+
console.log(`✓ Built ${schema.type}:${schema.name} → ${options.output}`);
|
|
52
|
+
} else {
|
|
53
|
+
console.log(output);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Resolve schema directory - handles relative paths
|
|
59
|
+
*/
|
|
60
|
+
function resolveSchemaDir(schemaDir: string): string {
|
|
61
|
+
// If absolute path, use as-is
|
|
62
|
+
if (existsSync(schemaDir)) {
|
|
63
|
+
return schemaDir;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Try relative to current working directory
|
|
67
|
+
const cwd = process.cwd();
|
|
68
|
+
const fromCwd = join(cwd, schemaDir);
|
|
69
|
+
if (existsSync(fromCwd)) {
|
|
70
|
+
return fromCwd;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Return as-is and let error handling catch it
|
|
74
|
+
return schemaDir;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* CLI action handler for build command
|
|
79
|
+
*/
|
|
80
|
+
export async function handleBuildCommand(
|
|
81
|
+
schemaDir: string,
|
|
82
|
+
options: BuildDirOptions = {},
|
|
83
|
+
): Promise<void> {
|
|
84
|
+
try {
|
|
85
|
+
await buildSchemaDir(schemaDir, options);
|
|
86
|
+
} catch (error) {
|
|
87
|
+
log.error("Build failed:", error);
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/// <reference types="../../../types/ulog" />
|
|
6
6
|
|
|
7
|
+
import { existsSync } from "node:fs";
|
|
7
8
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
8
9
|
import { dirname, join } from "node:path";
|
|
9
10
|
import { fileURLToPath } from "node:url";
|
|
@@ -119,27 +120,23 @@ function findSchemasDir(): string {
|
|
|
119
120
|
const __filename = fileURLToPath(import.meta.url);
|
|
120
121
|
const __dirname = dirname(__filename);
|
|
121
122
|
|
|
122
|
-
// From compiled dist/cli/
|
|
123
|
+
// From compiled dist/cli/commands/bundle.js to src/schemas
|
|
123
124
|
const fromDist = join(__dirname, "../../src/schemas");
|
|
124
125
|
|
|
125
126
|
// From source src/cli/commands/bundle.ts to src/schemas (for tests/dev)
|
|
126
127
|
const fromSource = join(__dirname, "../../schemas");
|
|
127
128
|
|
|
128
|
-
//
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
return fromSource;
|
|
136
|
-
}
|
|
137
|
-
} catch {
|
|
138
|
-
// If fs checks fail, default to dist structure
|
|
129
|
+
// Check source first (for development), then dist (for installed package)
|
|
130
|
+
if (existsSync(fromSource)) {
|
|
131
|
+
return fromSource;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (existsSync(fromDist)) {
|
|
135
|
+
return fromDist;
|
|
139
136
|
}
|
|
140
137
|
|
|
141
|
-
// Default to
|
|
142
|
-
return
|
|
138
|
+
// Default to source structure (for development)
|
|
139
|
+
return fromSource;
|
|
143
140
|
}
|
|
144
141
|
|
|
145
142
|
/**
|
package/src/cli/index.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import cac from "cac";
|
|
10
10
|
import anylogger from "ulog";
|
|
11
|
+
import { type BuildDirOptions, handleBuildCommand } from "./commands/build-dir.js";
|
|
11
12
|
import { type BundleOptions, handleBundleCommand } from "./commands/bundle.js";
|
|
12
13
|
import { handleListCommand, type ListOptions } from "./commands/list.js";
|
|
13
14
|
import { handlePresetsCommand } from "./commands/presets.js";
|
|
@@ -32,6 +33,20 @@ cli
|
|
|
32
33
|
}
|
|
33
34
|
});
|
|
34
35
|
|
|
36
|
+
// Build command
|
|
37
|
+
cli
|
|
38
|
+
.command("build <directory>", "Build an individual schema directory")
|
|
39
|
+
.option("-o, --output <path>", "Output file path (defaults to stdout)")
|
|
40
|
+
.option("-p, --pretty", "Pretty print JSON output")
|
|
41
|
+
.action(async (directory: string, options: BuildDirOptions) => {
|
|
42
|
+
try {
|
|
43
|
+
await handleBuildCommand(directory, options);
|
|
44
|
+
} catch (error) {
|
|
45
|
+
log.error("Error:", error);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
35
50
|
// List command
|
|
36
51
|
cli
|
|
37
52
|
.command("list", "List available schemas")
|