@xylex-group/athena 1.6.1 → 1.6.2
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 +31 -6
- package/bin/athena-js.js +74 -6
- package/dist/cli/index.cjs +158 -24
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +21 -2
- package/dist/cli/index.d.ts +21 -2
- package/dist/cli/index.js +157 -25
- package/dist/cli/index.js.map +1 -1
- package/dist/errors-1b-LSTum.d.ts +31 -0
- package/dist/errors-BYRK5phv.d.cts +31 -0
- package/dist/index.cjs +68 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -338
- package/dist/index.d.ts +6 -338
- package/dist/index.js +68 -10
- package/dist/index.js.map +1 -1
- package/dist/pipeline-BQzpSLD3.d.ts +338 -0
- package/dist/pipeline-CA2aexDl.d.cts +338 -0
- package/dist/react.d.cts +3 -2
- package/dist/react.d.ts +3 -2
- package/dist/{errors-C4GJaFI_.d.cts → types-v6UyGg-x.d.cts} +1 -29
- package/dist/{errors-C4GJaFI_.d.ts → types-v6UyGg-x.d.ts} +1 -29
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# athena-js
|
|
2
2
|
|
|
3
|
-
current version: `1.6.
|
|
3
|
+
current version: `1.6.2`
|
|
4
4
|
`@xylex-group/athena` is a database driver and API gateway SDK that lets you interact with SQL backends over HTTP through a fluent builder API. It ships a typed query builder for Node.js / server environments plus Athena-native React hooks for client-side use.
|
|
5
5
|
|
|
6
6
|
## Install
|
|
@@ -83,22 +83,45 @@ await typed
|
|
|
83
83
|
|
|
84
84
|
For full details, see [`docs/typed-schema-registry.md`](./docs/typed-schema-registry.md).
|
|
85
85
|
|
|
86
|
-
### Typed schema generator
|
|
86
|
+
### Typed schema generator
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
Schema generation is additive. Existing `createClient(...).from<T>(...)` usage remains valid while teams migrate to generated registry files.
|
|
89
|
+
|
|
90
|
+
CLI:
|
|
89
91
|
|
|
90
92
|
```bash
|
|
91
93
|
athena-js generate
|
|
92
94
|
athena-js generate --dry-run
|
|
93
95
|
athena-js generate --config ./athena.config.ts
|
|
96
|
+
athena-js generate --help
|
|
97
|
+
athena-js help generate
|
|
94
98
|
```
|
|
95
99
|
|
|
96
|
-
Generator
|
|
97
|
-
|
|
100
|
+
Generator supports:
|
|
101
|
+
|
|
102
|
+
- PostgreSQL direct introspection (`provider.mode = "direct"`, `provider.connectionString` from your `PG_URL`/`DATABASE_URL`)
|
|
103
|
+
- PostgreSQL gateway-only introspection (`provider.mode = "gateway"` via Athena `POST /gateway/query`)
|
|
104
|
+
- Placeholder-driven output paths
|
|
105
|
+
- Feature flags (`features.emitRegistry`, `features.emitRelations`)
|
|
98
106
|
|
|
99
|
-
For full generator configuration, see [`docs/generator-config.md`](./docs/generator-config.md).
|
|
107
|
+
For full generator configuration and troubleshooting, see [`docs/generator-config.md`](./docs/generator-config.md).
|
|
108
|
+
For full CLI commands, help behavior, and troubleshooting, see [`docs/cli-command-reference.md`](./docs/cli-command-reference.md).
|
|
109
|
+
For CI/CD pipelines and generated-file branch policy, see [`docs/generator-cicd.md`](./docs/generator-cicd.md).
|
|
100
110
|
For prompt-ready documentation handoff text, see [`docs/generator-codex-handoff-prompt-pack.md`](./docs/generator-codex-handoff-prompt-pack.md).
|
|
101
111
|
|
|
112
|
+
### Athena JS and Athena RS
|
|
113
|
+
|
|
114
|
+
`athena-js` is designed to be standalone for TypeScript/Node and React-native workflows:
|
|
115
|
+
|
|
116
|
+
- query builder + hooks
|
|
117
|
+
- typed registry and generator pipeline
|
|
118
|
+
- CLI-driven codegen in JS/TS projects
|
|
119
|
+
|
|
120
|
+
`athena-rs` remains the faster fit for Rust service execution paths. Teams can run both in parallel:
|
|
121
|
+
|
|
122
|
+
- `athena-rs` for Rust backend throughput
|
|
123
|
+
- `athena-js` for app/tooling layers that need TypeScript contracts and frontend-facing ergonomics
|
|
124
|
+
|
|
102
125
|
Every query resolves to `{ data, error, errorDetails?, status, count?, raw }`. `data` is `null` on error; `error` is `null` on success.
|
|
103
126
|
|
|
104
127
|
For richer handling, inspect `errorDetails` (`code`, `status`, `endpoint`, `method`, `requestId`, etc.) or use `AthenaGatewayError` / `isAthenaGatewayError` from the package exports.
|
|
@@ -666,6 +689,8 @@ CI and publish workflows run `typecheck` before build/publish.
|
|
|
666
689
|
|
|
667
690
|
- [Documentation index](docs/index.md) — complete documentation map
|
|
668
691
|
- [Getting started](docs/getting-started.md) — step-by-step walkthrough
|
|
692
|
+
- [CLI command reference](docs/cli-command-reference.md) — all `athena-js` commands, help flows, and troubleshooting
|
|
669
693
|
- [Typed schema registry](docs/typed-schema-registry.md) — typed contracts and migration path
|
|
670
694
|
- [Generator config](docs/generator-config.md) — generator provider and output pipeline
|
|
695
|
+
- [Generator CI/CD](docs/generator-cicd.md) — pipeline patterns, secret mapping, retries, and branch policy
|
|
671
696
|
- [API reference](docs/api-reference.md) — complete method and type reference
|
package/bin/athena-js.js
CHANGED
|
@@ -1,8 +1,76 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
4
|
+
import path from 'node:path'
|
|
5
|
+
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
6
|
+
|
|
7
|
+
const binPath = fileURLToPath(import.meta.url)
|
|
8
|
+
const packageRoot = path.resolve(path.dirname(binPath), '..')
|
|
9
|
+
const cliEntrypointPath = path.resolve(packageRoot, 'dist', 'cli', 'index.js')
|
|
10
|
+
const packageJsonPath = path.resolve(packageRoot, 'package.json')
|
|
11
|
+
|
|
12
|
+
function getInstalledVersion() {
|
|
13
|
+
try {
|
|
14
|
+
const packageJsonRaw = readFileSync(packageJsonPath, 'utf8')
|
|
15
|
+
const packageJson = JSON.parse(packageJsonRaw)
|
|
16
|
+
return typeof packageJson.version === 'string' ? packageJson.version : 'unknown'
|
|
17
|
+
} catch {
|
|
18
|
+
return 'unknown'
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function printMissingEntrypointError() {
|
|
23
|
+
const installedVersion = getInstalledVersion()
|
|
24
|
+
console.error(
|
|
25
|
+
[
|
|
26
|
+
'Failed to start athena-js CLI: package install is missing the generated CLI entrypoint.',
|
|
27
|
+
`Expected file: ${cliEntrypointPath}`,
|
|
28
|
+
`Installed package version: ${installedVersion}`,
|
|
29
|
+
'',
|
|
30
|
+
'Fix by reinstalling the latest package:',
|
|
31
|
+
' pnpm add -g @xylex-group/athena@latest',
|
|
32
|
+
].join('\n'),
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function formatRuntimeError(error) {
|
|
37
|
+
if (error instanceof Error) {
|
|
38
|
+
if (process.env.ATHENA_JS_DEBUG === '1') {
|
|
39
|
+
return error.stack ?? error.message;
|
|
40
|
+
}
|
|
41
|
+
return error.message;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (typeof error === 'string') {
|
|
45
|
+
return error;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return 'Unknown error.';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function main() {
|
|
52
|
+
if (!existsSync(cliEntrypointPath)) {
|
|
53
|
+
printMissingEntrypointError();
|
|
54
|
+
process.exit(1);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const cliEntrypointUrl = pathToFileURL(cliEntrypointPath).href;
|
|
60
|
+
const cliModule = await import(cliEntrypointUrl);
|
|
61
|
+
if (typeof cliModule.runCLI !== 'function') {
|
|
62
|
+
throw new Error('CLI module does not export runCLI.');
|
|
63
|
+
}
|
|
64
|
+
await cliModule.runCLI(process.argv.slice(2));
|
|
65
|
+
} catch (err) {
|
|
66
|
+
const errorDetail = formatRuntimeError(err);
|
|
67
|
+
if (errorDetail.includes('\n')) {
|
|
68
|
+
console.error(`Failed to start athena-js CLI:\n${errorDetail}`);
|
|
69
|
+
} else {
|
|
70
|
+
console.error(`Failed to start athena-js CLI: ${errorDetail}`);
|
|
71
|
+
}
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
void main()
|
package/dist/cli/index.cjs
CHANGED
|
@@ -300,10 +300,10 @@ var DEFAULT_CONFIG_CANDIDATES = [
|
|
|
300
300
|
".athena.config.js"
|
|
301
301
|
];
|
|
302
302
|
var DEFAULT_TARGETS = {
|
|
303
|
-
model: "
|
|
304
|
-
schema: "
|
|
305
|
-
database: "
|
|
306
|
-
registry: "
|
|
303
|
+
model: "athena/models/{model_kebab}.ts",
|
|
304
|
+
schema: "athena/schema.ts",
|
|
305
|
+
database: "athena/relations.ts",
|
|
306
|
+
registry: "athena/config.ts"
|
|
307
307
|
};
|
|
308
308
|
var DEFAULT_NAMING = {
|
|
309
309
|
modelType: "pascal",
|
|
@@ -2059,6 +2059,58 @@ function toTypeKind(code) {
|
|
|
2059
2059
|
function escapeSqlLiteral(value) {
|
|
2060
2060
|
return value.replace(/'/g, "''");
|
|
2061
2061
|
}
|
|
2062
|
+
function parsePostgresArrayLiteral(text) {
|
|
2063
|
+
const body = text.slice(1, -1).trim();
|
|
2064
|
+
if (!body) return [];
|
|
2065
|
+
const values = [];
|
|
2066
|
+
let current = "";
|
|
2067
|
+
let inQuotes = false;
|
|
2068
|
+
let escaped = false;
|
|
2069
|
+
for (const char of body) {
|
|
2070
|
+
if (escaped) {
|
|
2071
|
+
current += char;
|
|
2072
|
+
escaped = false;
|
|
2073
|
+
continue;
|
|
2074
|
+
}
|
|
2075
|
+
if (char === "\\") {
|
|
2076
|
+
escaped = true;
|
|
2077
|
+
continue;
|
|
2078
|
+
}
|
|
2079
|
+
if (char === '"') {
|
|
2080
|
+
inQuotes = !inQuotes;
|
|
2081
|
+
continue;
|
|
2082
|
+
}
|
|
2083
|
+
if (char === "," && !inQuotes) {
|
|
2084
|
+
values.push(current);
|
|
2085
|
+
current = "";
|
|
2086
|
+
continue;
|
|
2087
|
+
}
|
|
2088
|
+
current += char;
|
|
2089
|
+
}
|
|
2090
|
+
values.push(current);
|
|
2091
|
+
return values.map((value) => value.trim()).filter((value) => value.length > 0);
|
|
2092
|
+
}
|
|
2093
|
+
function coerceStringArray(value) {
|
|
2094
|
+
if (Array.isArray(value)) {
|
|
2095
|
+
return value.map((item) => typeof item === "string" ? item : String(item)).map((item) => item.trim()).filter((item) => item.length > 0);
|
|
2096
|
+
}
|
|
2097
|
+
if (typeof value === "string") {
|
|
2098
|
+
const trimmed = value.trim();
|
|
2099
|
+
if (!trimmed) return [];
|
|
2100
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
2101
|
+
try {
|
|
2102
|
+
const parsed = JSON.parse(trimmed);
|
|
2103
|
+
return coerceStringArray(parsed);
|
|
2104
|
+
} catch {
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
|
|
2108
|
+
return parsePostgresArrayLiteral(trimmed);
|
|
2109
|
+
}
|
|
2110
|
+
return trimmed.split(",").map((item) => item.trim()).filter((item) => item.length > 0);
|
|
2111
|
+
}
|
|
2112
|
+
return [];
|
|
2113
|
+
}
|
|
2062
2114
|
function buildSchemaArrayLiteral(schemas) {
|
|
2063
2115
|
const normalized = schemas.length > 0 ? schemas : ["public"];
|
|
2064
2116
|
const literals = normalized.map((schema) => `'${escapeSqlLiteral(schema)}'`).join(", ");
|
|
@@ -2098,8 +2150,10 @@ var PostgresCatalogSnapshotAssembler = class {
|
|
|
2098
2150
|
addPrimaryKeyRows(primaryKeyRows) {
|
|
2099
2151
|
for (const row of primaryKeyRows) {
|
|
2100
2152
|
const table = this.ensureTable(row.schema_name, row.table_name);
|
|
2101
|
-
|
|
2102
|
-
|
|
2153
|
+
const primaryKeyColumns = coerceStringArray(row.columns);
|
|
2154
|
+
row.columns = primaryKeyColumns;
|
|
2155
|
+
table.primaryKey = primaryKeyColumns;
|
|
2156
|
+
for (const columnName of primaryKeyColumns) {
|
|
2103
2157
|
const column = table.columns[columnName];
|
|
2104
2158
|
if (column) {
|
|
2105
2159
|
column.isPrimaryKey = true;
|
|
@@ -2111,23 +2165,27 @@ var PostgresCatalogSnapshotAssembler = class {
|
|
|
2111
2165
|
for (const row of foreignKeyRows) {
|
|
2112
2166
|
const sourceTable = this.ensureTable(row.source_schema, row.source_table);
|
|
2113
2167
|
const targetTable = this.ensureTable(row.target_schema, row.target_table);
|
|
2168
|
+
const sourceColumns = coerceStringArray(row.source_columns);
|
|
2169
|
+
const targetColumns = coerceStringArray(row.target_columns);
|
|
2170
|
+
row.source_columns = sourceColumns;
|
|
2171
|
+
row.target_columns = targetColumns;
|
|
2114
2172
|
const sourceRelationKind = row.source_is_unique ? "one-to-one" : "many-to-one";
|
|
2115
2173
|
this.upsertRelation(sourceTable, relationKey(row.constraint_name, row.target_table), {
|
|
2116
2174
|
name: row.constraint_name,
|
|
2117
2175
|
kind: sourceRelationKind,
|
|
2118
|
-
sourceColumns
|
|
2176
|
+
sourceColumns,
|
|
2119
2177
|
targetSchema: row.target_schema,
|
|
2120
2178
|
targetModel: row.target_table,
|
|
2121
|
-
targetColumns
|
|
2179
|
+
targetColumns
|
|
2122
2180
|
});
|
|
2123
2181
|
const targetRelationKind = row.source_is_unique ? "one-to-one" : "one-to-many";
|
|
2124
2182
|
this.upsertRelation(targetTable, relationKey(row.source_table), {
|
|
2125
2183
|
name: relationKey(row.source_table, row.constraint_name),
|
|
2126
2184
|
kind: targetRelationKind,
|
|
2127
|
-
sourceColumns:
|
|
2185
|
+
sourceColumns: targetColumns,
|
|
2128
2186
|
targetSchema: row.source_schema,
|
|
2129
2187
|
targetModel: row.source_table,
|
|
2130
|
-
targetColumns:
|
|
2188
|
+
targetColumns: sourceColumns
|
|
2131
2189
|
});
|
|
2132
2190
|
}
|
|
2133
2191
|
}
|
|
@@ -2429,7 +2487,7 @@ async function runSchemaGenerator(options = {}) {
|
|
|
2429
2487
|
}
|
|
2430
2488
|
|
|
2431
2489
|
// src/cli/index.ts
|
|
2432
|
-
function
|
|
2490
|
+
function rootUsage() {
|
|
2433
2491
|
return [
|
|
2434
2492
|
"athena-js CLI",
|
|
2435
2493
|
"",
|
|
@@ -2438,12 +2496,42 @@ function usage() {
|
|
|
2438
2496
|
"",
|
|
2439
2497
|
"Examples:",
|
|
2440
2498
|
" athena-js generate",
|
|
2499
|
+
" athena-js generate --config ./athena.config.ts --dry-run",
|
|
2500
|
+
" athena-js generate --help"
|
|
2501
|
+
].join("\n");
|
|
2502
|
+
}
|
|
2503
|
+
function generateUsage() {
|
|
2504
|
+
return [
|
|
2505
|
+
"athena-js generate",
|
|
2506
|
+
"",
|
|
2507
|
+
"Usage:",
|
|
2508
|
+
" athena-js generate [--config <path>] [--dry-run]",
|
|
2509
|
+
"",
|
|
2510
|
+
"Options:",
|
|
2511
|
+
" --config <path> Explicit path to athena.config.ts or athena-js.config.ts",
|
|
2512
|
+
" --dry-run Build generated files in memory without writing them to disk",
|
|
2513
|
+
" -h, --help Show help for generate",
|
|
2514
|
+
"",
|
|
2515
|
+
"Examples:",
|
|
2516
|
+
" athena-js generate",
|
|
2441
2517
|
" athena-js generate --config ./athena.config.ts --dry-run"
|
|
2442
2518
|
].join("\n");
|
|
2443
2519
|
}
|
|
2520
|
+
function usage(topic = "root") {
|
|
2521
|
+
return topic === "generate" ? generateUsage() : rootUsage();
|
|
2522
|
+
}
|
|
2444
2523
|
function parseCommand(argv) {
|
|
2445
|
-
if (argv.length === 0 || argv[0] === "
|
|
2446
|
-
return { command: "help" };
|
|
2524
|
+
if (argv.length === 0 || argv[0] === "--help" || argv[0] === "-h") {
|
|
2525
|
+
return { command: "help", topic: "root" };
|
|
2526
|
+
}
|
|
2527
|
+
if (argv[0] === "help") {
|
|
2528
|
+
if (argv.length === 1) {
|
|
2529
|
+
return { command: "help", topic: "root" };
|
|
2530
|
+
}
|
|
2531
|
+
if (argv[1] === "generate") {
|
|
2532
|
+
return { command: "help", topic: "generate" };
|
|
2533
|
+
}
|
|
2534
|
+
throw new Error(`Unknown command "${argv[1]}".`);
|
|
2447
2535
|
}
|
|
2448
2536
|
const [command, ...rest] = argv;
|
|
2449
2537
|
if (command !== "generate") {
|
|
@@ -2453,13 +2541,16 @@ function parseCommand(argv) {
|
|
|
2453
2541
|
let dryRun = false;
|
|
2454
2542
|
for (let index = 0; index < rest.length; index += 1) {
|
|
2455
2543
|
const token = rest[index];
|
|
2544
|
+
if (token === "--help" || token === "-h") {
|
|
2545
|
+
return { command: "help", topic: "generate" };
|
|
2546
|
+
}
|
|
2456
2547
|
if (token === "--dry-run") {
|
|
2457
2548
|
dryRun = true;
|
|
2458
2549
|
continue;
|
|
2459
2550
|
}
|
|
2460
2551
|
if (token === "--config") {
|
|
2461
2552
|
const nextValue = rest[index + 1];
|
|
2462
|
-
if (!nextValue) {
|
|
2553
|
+
if (!nextValue || nextValue.startsWith("-")) {
|
|
2463
2554
|
throw new Error("Missing value for --config option.");
|
|
2464
2555
|
}
|
|
2465
2556
|
configPath = nextValue;
|
|
@@ -2474,29 +2565,72 @@ function parseCommand(argv) {
|
|
|
2474
2565
|
dryRun
|
|
2475
2566
|
};
|
|
2476
2567
|
}
|
|
2477
|
-
|
|
2568
|
+
function normalizeErrorMessage(error) {
|
|
2569
|
+
if (error instanceof Error) {
|
|
2570
|
+
return error.message;
|
|
2571
|
+
}
|
|
2572
|
+
if (typeof error === "string") {
|
|
2573
|
+
return error;
|
|
2574
|
+
}
|
|
2575
|
+
return "Unknown generator error.";
|
|
2576
|
+
}
|
|
2577
|
+
function extractMissingDatabaseName(message) {
|
|
2578
|
+
const match = message.match(/database "([^"]+)" does not exist/i);
|
|
2579
|
+
return match?.[1];
|
|
2580
|
+
}
|
|
2581
|
+
function isErrorWithCode(error) {
|
|
2582
|
+
return typeof error === "object" && error !== null && "code" in error;
|
|
2583
|
+
}
|
|
2584
|
+
function formatGeneratorError(error, configPath) {
|
|
2585
|
+
if (isErrorWithCode(error) && error.code === "3D000") {
|
|
2586
|
+
const message = normalizeErrorMessage(error);
|
|
2587
|
+
const databaseName = extractMissingDatabaseName(message);
|
|
2588
|
+
const databaseLabel = databaseName ? `PostgreSQL database "${databaseName}" does not exist` : "The target PostgreSQL database does not exist";
|
|
2589
|
+
const configLabel = configPath ? `config "${configPath}"` : "the resolved athena config";
|
|
2590
|
+
return new Error(
|
|
2591
|
+
[
|
|
2592
|
+
`${databaseLabel} (code 3D000).`,
|
|
2593
|
+
`Update provider.connectionString (and provider.database, if set) in ${configLabel}, or create that database before running generate.`
|
|
2594
|
+
].join("\n")
|
|
2595
|
+
);
|
|
2596
|
+
}
|
|
2597
|
+
if (error instanceof Error) {
|
|
2598
|
+
return error;
|
|
2599
|
+
}
|
|
2600
|
+
return new Error(normalizeErrorMessage(error));
|
|
2601
|
+
}
|
|
2602
|
+
async function runCLI(argv, runtime = {}) {
|
|
2603
|
+
const log = runtime.log ?? console.log;
|
|
2604
|
+
const runGenerator = runtime.runGenerator ?? runSchemaGenerator;
|
|
2478
2605
|
const parsed = parseCommand(argv);
|
|
2479
2606
|
if (parsed.command === "help") {
|
|
2480
|
-
|
|
2607
|
+
log(usage(parsed.topic));
|
|
2481
2608
|
return;
|
|
2482
2609
|
}
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2610
|
+
let result;
|
|
2611
|
+
try {
|
|
2612
|
+
result = await runGenerator({
|
|
2613
|
+
configPath: parsed.configPath,
|
|
2614
|
+
dryRun: parsed.dryRun
|
|
2615
|
+
});
|
|
2616
|
+
} catch (error) {
|
|
2617
|
+
throw formatGeneratorError(error, parsed.configPath);
|
|
2618
|
+
}
|
|
2487
2619
|
if (parsed.dryRun) {
|
|
2488
|
-
|
|
2620
|
+
log(`[dry-run] Generated ${result.files.length} files from ${result.configPath}`);
|
|
2489
2621
|
for (const file of result.files) {
|
|
2490
|
-
|
|
2622
|
+
log(` - ${file.path}`);
|
|
2491
2623
|
}
|
|
2492
2624
|
return;
|
|
2493
2625
|
}
|
|
2494
|
-
|
|
2626
|
+
log(`Generated ${result.writtenFiles.length} files from ${result.configPath}`);
|
|
2495
2627
|
for (const filePath of result.writtenFiles) {
|
|
2496
|
-
|
|
2628
|
+
log(` - ${filePath}`);
|
|
2497
2629
|
}
|
|
2498
2630
|
}
|
|
2499
2631
|
|
|
2632
|
+
exports.parseCommand = parseCommand;
|
|
2500
2633
|
exports.runCLI = runCLI;
|
|
2634
|
+
exports.usage = usage;
|
|
2501
2635
|
//# sourceMappingURL=index.cjs.map
|
|
2502
2636
|
//# sourceMappingURL=index.cjs.map
|