@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/dist/cli/index.d.cts
CHANGED
|
@@ -1,6 +1,25 @@
|
|
|
1
|
+
import { r as runSchemaGenerator } from '../pipeline-CA2aexDl.cjs';
|
|
2
|
+
import '../types-v6UyGg-x.cjs';
|
|
3
|
+
|
|
4
|
+
interface GenerateCommand {
|
|
5
|
+
command: 'generate';
|
|
6
|
+
configPath?: string;
|
|
7
|
+
dryRun: boolean;
|
|
8
|
+
}
|
|
9
|
+
interface HelpCommand {
|
|
10
|
+
command: 'help';
|
|
11
|
+
topic: 'root' | 'generate';
|
|
12
|
+
}
|
|
13
|
+
type CliCommand = GenerateCommand | HelpCommand;
|
|
14
|
+
interface CliRuntime {
|
|
15
|
+
runGenerator?: typeof runSchemaGenerator;
|
|
16
|
+
log?: (message: string) => void;
|
|
17
|
+
}
|
|
18
|
+
declare function usage(topic?: HelpCommand['topic']): string;
|
|
19
|
+
declare function parseCommand(argv: string[]): CliCommand;
|
|
1
20
|
/**
|
|
2
21
|
* CLI entrypoint used by `bin/athena-js.js`.
|
|
3
22
|
*/
|
|
4
|
-
declare function runCLI(argv: string[]): Promise<void>;
|
|
23
|
+
declare function runCLI(argv: string[], runtime?: CliRuntime): Promise<void>;
|
|
5
24
|
|
|
6
|
-
export { runCLI };
|
|
25
|
+
export { type CliRuntime, parseCommand, runCLI, usage };
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -1,6 +1,25 @@
|
|
|
1
|
+
import { r as runSchemaGenerator } from '../pipeline-BQzpSLD3.js';
|
|
2
|
+
import '../types-v6UyGg-x.js';
|
|
3
|
+
|
|
4
|
+
interface GenerateCommand {
|
|
5
|
+
command: 'generate';
|
|
6
|
+
configPath?: string;
|
|
7
|
+
dryRun: boolean;
|
|
8
|
+
}
|
|
9
|
+
interface HelpCommand {
|
|
10
|
+
command: 'help';
|
|
11
|
+
topic: 'root' | 'generate';
|
|
12
|
+
}
|
|
13
|
+
type CliCommand = GenerateCommand | HelpCommand;
|
|
14
|
+
interface CliRuntime {
|
|
15
|
+
runGenerator?: typeof runSchemaGenerator;
|
|
16
|
+
log?: (message: string) => void;
|
|
17
|
+
}
|
|
18
|
+
declare function usage(topic?: HelpCommand['topic']): string;
|
|
19
|
+
declare function parseCommand(argv: string[]): CliCommand;
|
|
1
20
|
/**
|
|
2
21
|
* CLI entrypoint used by `bin/athena-js.js`.
|
|
3
22
|
*/
|
|
4
|
-
declare function runCLI(argv: string[]): Promise<void>;
|
|
23
|
+
declare function runCLI(argv: string[], runtime?: CliRuntime): Promise<void>;
|
|
5
24
|
|
|
6
|
-
export { runCLI };
|
|
25
|
+
export { type CliRuntime, parseCommand, runCLI, usage };
|
package/dist/cli/index.js
CHANGED
|
@@ -298,10 +298,10 @@ var DEFAULT_CONFIG_CANDIDATES = [
|
|
|
298
298
|
".athena.config.js"
|
|
299
299
|
];
|
|
300
300
|
var DEFAULT_TARGETS = {
|
|
301
|
-
model: "
|
|
302
|
-
schema: "
|
|
303
|
-
database: "
|
|
304
|
-
registry: "
|
|
301
|
+
model: "athena/models/{model_kebab}.ts",
|
|
302
|
+
schema: "athena/schema.ts",
|
|
303
|
+
database: "athena/relations.ts",
|
|
304
|
+
registry: "athena/config.ts"
|
|
305
305
|
};
|
|
306
306
|
var DEFAULT_NAMING = {
|
|
307
307
|
modelType: "pascal",
|
|
@@ -2057,6 +2057,58 @@ function toTypeKind(code) {
|
|
|
2057
2057
|
function escapeSqlLiteral(value) {
|
|
2058
2058
|
return value.replace(/'/g, "''");
|
|
2059
2059
|
}
|
|
2060
|
+
function parsePostgresArrayLiteral(text) {
|
|
2061
|
+
const body = text.slice(1, -1).trim();
|
|
2062
|
+
if (!body) return [];
|
|
2063
|
+
const values = [];
|
|
2064
|
+
let current = "";
|
|
2065
|
+
let inQuotes = false;
|
|
2066
|
+
let escaped = false;
|
|
2067
|
+
for (const char of body) {
|
|
2068
|
+
if (escaped) {
|
|
2069
|
+
current += char;
|
|
2070
|
+
escaped = false;
|
|
2071
|
+
continue;
|
|
2072
|
+
}
|
|
2073
|
+
if (char === "\\") {
|
|
2074
|
+
escaped = true;
|
|
2075
|
+
continue;
|
|
2076
|
+
}
|
|
2077
|
+
if (char === '"') {
|
|
2078
|
+
inQuotes = !inQuotes;
|
|
2079
|
+
continue;
|
|
2080
|
+
}
|
|
2081
|
+
if (char === "," && !inQuotes) {
|
|
2082
|
+
values.push(current);
|
|
2083
|
+
current = "";
|
|
2084
|
+
continue;
|
|
2085
|
+
}
|
|
2086
|
+
current += char;
|
|
2087
|
+
}
|
|
2088
|
+
values.push(current);
|
|
2089
|
+
return values.map((value) => value.trim()).filter((value) => value.length > 0);
|
|
2090
|
+
}
|
|
2091
|
+
function coerceStringArray(value) {
|
|
2092
|
+
if (Array.isArray(value)) {
|
|
2093
|
+
return value.map((item) => typeof item === "string" ? item : String(item)).map((item) => item.trim()).filter((item) => item.length > 0);
|
|
2094
|
+
}
|
|
2095
|
+
if (typeof value === "string") {
|
|
2096
|
+
const trimmed = value.trim();
|
|
2097
|
+
if (!trimmed) return [];
|
|
2098
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
2099
|
+
try {
|
|
2100
|
+
const parsed = JSON.parse(trimmed);
|
|
2101
|
+
return coerceStringArray(parsed);
|
|
2102
|
+
} catch {
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
|
|
2106
|
+
return parsePostgresArrayLiteral(trimmed);
|
|
2107
|
+
}
|
|
2108
|
+
return trimmed.split(",").map((item) => item.trim()).filter((item) => item.length > 0);
|
|
2109
|
+
}
|
|
2110
|
+
return [];
|
|
2111
|
+
}
|
|
2060
2112
|
function buildSchemaArrayLiteral(schemas) {
|
|
2061
2113
|
const normalized = schemas.length > 0 ? schemas : ["public"];
|
|
2062
2114
|
const literals = normalized.map((schema) => `'${escapeSqlLiteral(schema)}'`).join(", ");
|
|
@@ -2096,8 +2148,10 @@ var PostgresCatalogSnapshotAssembler = class {
|
|
|
2096
2148
|
addPrimaryKeyRows(primaryKeyRows) {
|
|
2097
2149
|
for (const row of primaryKeyRows) {
|
|
2098
2150
|
const table = this.ensureTable(row.schema_name, row.table_name);
|
|
2099
|
-
|
|
2100
|
-
|
|
2151
|
+
const primaryKeyColumns = coerceStringArray(row.columns);
|
|
2152
|
+
row.columns = primaryKeyColumns;
|
|
2153
|
+
table.primaryKey = primaryKeyColumns;
|
|
2154
|
+
for (const columnName of primaryKeyColumns) {
|
|
2101
2155
|
const column = table.columns[columnName];
|
|
2102
2156
|
if (column) {
|
|
2103
2157
|
column.isPrimaryKey = true;
|
|
@@ -2109,23 +2163,27 @@ var PostgresCatalogSnapshotAssembler = class {
|
|
|
2109
2163
|
for (const row of foreignKeyRows) {
|
|
2110
2164
|
const sourceTable = this.ensureTable(row.source_schema, row.source_table);
|
|
2111
2165
|
const targetTable = this.ensureTable(row.target_schema, row.target_table);
|
|
2166
|
+
const sourceColumns = coerceStringArray(row.source_columns);
|
|
2167
|
+
const targetColumns = coerceStringArray(row.target_columns);
|
|
2168
|
+
row.source_columns = sourceColumns;
|
|
2169
|
+
row.target_columns = targetColumns;
|
|
2112
2170
|
const sourceRelationKind = row.source_is_unique ? "one-to-one" : "many-to-one";
|
|
2113
2171
|
this.upsertRelation(sourceTable, relationKey(row.constraint_name, row.target_table), {
|
|
2114
2172
|
name: row.constraint_name,
|
|
2115
2173
|
kind: sourceRelationKind,
|
|
2116
|
-
sourceColumns
|
|
2174
|
+
sourceColumns,
|
|
2117
2175
|
targetSchema: row.target_schema,
|
|
2118
2176
|
targetModel: row.target_table,
|
|
2119
|
-
targetColumns
|
|
2177
|
+
targetColumns
|
|
2120
2178
|
});
|
|
2121
2179
|
const targetRelationKind = row.source_is_unique ? "one-to-one" : "one-to-many";
|
|
2122
2180
|
this.upsertRelation(targetTable, relationKey(row.source_table), {
|
|
2123
2181
|
name: relationKey(row.source_table, row.constraint_name),
|
|
2124
2182
|
kind: targetRelationKind,
|
|
2125
|
-
sourceColumns:
|
|
2183
|
+
sourceColumns: targetColumns,
|
|
2126
2184
|
targetSchema: row.source_schema,
|
|
2127
2185
|
targetModel: row.source_table,
|
|
2128
|
-
targetColumns:
|
|
2186
|
+
targetColumns: sourceColumns
|
|
2129
2187
|
});
|
|
2130
2188
|
}
|
|
2131
2189
|
}
|
|
@@ -2427,7 +2485,7 @@ async function runSchemaGenerator(options = {}) {
|
|
|
2427
2485
|
}
|
|
2428
2486
|
|
|
2429
2487
|
// src/cli/index.ts
|
|
2430
|
-
function
|
|
2488
|
+
function rootUsage() {
|
|
2431
2489
|
return [
|
|
2432
2490
|
"athena-js CLI",
|
|
2433
2491
|
"",
|
|
@@ -2436,12 +2494,42 @@ function usage() {
|
|
|
2436
2494
|
"",
|
|
2437
2495
|
"Examples:",
|
|
2438
2496
|
" athena-js generate",
|
|
2497
|
+
" athena-js generate --config ./athena.config.ts --dry-run",
|
|
2498
|
+
" athena-js generate --help"
|
|
2499
|
+
].join("\n");
|
|
2500
|
+
}
|
|
2501
|
+
function generateUsage() {
|
|
2502
|
+
return [
|
|
2503
|
+
"athena-js generate",
|
|
2504
|
+
"",
|
|
2505
|
+
"Usage:",
|
|
2506
|
+
" athena-js generate [--config <path>] [--dry-run]",
|
|
2507
|
+
"",
|
|
2508
|
+
"Options:",
|
|
2509
|
+
" --config <path> Explicit path to athena.config.ts or athena-js.config.ts",
|
|
2510
|
+
" --dry-run Build generated files in memory without writing them to disk",
|
|
2511
|
+
" -h, --help Show help for generate",
|
|
2512
|
+
"",
|
|
2513
|
+
"Examples:",
|
|
2514
|
+
" athena-js generate",
|
|
2439
2515
|
" athena-js generate --config ./athena.config.ts --dry-run"
|
|
2440
2516
|
].join("\n");
|
|
2441
2517
|
}
|
|
2518
|
+
function usage(topic = "root") {
|
|
2519
|
+
return topic === "generate" ? generateUsage() : rootUsage();
|
|
2520
|
+
}
|
|
2442
2521
|
function parseCommand(argv) {
|
|
2443
|
-
if (argv.length === 0 || argv[0] === "
|
|
2444
|
-
return { command: "help" };
|
|
2522
|
+
if (argv.length === 0 || argv[0] === "--help" || argv[0] === "-h") {
|
|
2523
|
+
return { command: "help", topic: "root" };
|
|
2524
|
+
}
|
|
2525
|
+
if (argv[0] === "help") {
|
|
2526
|
+
if (argv.length === 1) {
|
|
2527
|
+
return { command: "help", topic: "root" };
|
|
2528
|
+
}
|
|
2529
|
+
if (argv[1] === "generate") {
|
|
2530
|
+
return { command: "help", topic: "generate" };
|
|
2531
|
+
}
|
|
2532
|
+
throw new Error(`Unknown command "${argv[1]}".`);
|
|
2445
2533
|
}
|
|
2446
2534
|
const [command, ...rest] = argv;
|
|
2447
2535
|
if (command !== "generate") {
|
|
@@ -2451,13 +2539,16 @@ function parseCommand(argv) {
|
|
|
2451
2539
|
let dryRun = false;
|
|
2452
2540
|
for (let index = 0; index < rest.length; index += 1) {
|
|
2453
2541
|
const token = rest[index];
|
|
2542
|
+
if (token === "--help" || token === "-h") {
|
|
2543
|
+
return { command: "help", topic: "generate" };
|
|
2544
|
+
}
|
|
2454
2545
|
if (token === "--dry-run") {
|
|
2455
2546
|
dryRun = true;
|
|
2456
2547
|
continue;
|
|
2457
2548
|
}
|
|
2458
2549
|
if (token === "--config") {
|
|
2459
2550
|
const nextValue = rest[index + 1];
|
|
2460
|
-
if (!nextValue) {
|
|
2551
|
+
if (!nextValue || nextValue.startsWith("-")) {
|
|
2461
2552
|
throw new Error("Missing value for --config option.");
|
|
2462
2553
|
}
|
|
2463
2554
|
configPath = nextValue;
|
|
@@ -2472,29 +2563,70 @@ function parseCommand(argv) {
|
|
|
2472
2563
|
dryRun
|
|
2473
2564
|
};
|
|
2474
2565
|
}
|
|
2475
|
-
|
|
2566
|
+
function normalizeErrorMessage(error) {
|
|
2567
|
+
if (error instanceof Error) {
|
|
2568
|
+
return error.message;
|
|
2569
|
+
}
|
|
2570
|
+
if (typeof error === "string") {
|
|
2571
|
+
return error;
|
|
2572
|
+
}
|
|
2573
|
+
return "Unknown generator error.";
|
|
2574
|
+
}
|
|
2575
|
+
function extractMissingDatabaseName(message) {
|
|
2576
|
+
const match = message.match(/database "([^"]+)" does not exist/i);
|
|
2577
|
+
return match?.[1];
|
|
2578
|
+
}
|
|
2579
|
+
function isErrorWithCode(error) {
|
|
2580
|
+
return typeof error === "object" && error !== null && "code" in error;
|
|
2581
|
+
}
|
|
2582
|
+
function formatGeneratorError(error, configPath) {
|
|
2583
|
+
if (isErrorWithCode(error) && error.code === "3D000") {
|
|
2584
|
+
const message = normalizeErrorMessage(error);
|
|
2585
|
+
const databaseName = extractMissingDatabaseName(message);
|
|
2586
|
+
const databaseLabel = databaseName ? `PostgreSQL database "${databaseName}" does not exist` : "The target PostgreSQL database does not exist";
|
|
2587
|
+
const configLabel = configPath ? `config "${configPath}"` : "the resolved athena config";
|
|
2588
|
+
return new Error(
|
|
2589
|
+
[
|
|
2590
|
+
`${databaseLabel} (code 3D000).`,
|
|
2591
|
+
`Update provider.connectionString (and provider.database, if set) in ${configLabel}, or create that database before running generate.`
|
|
2592
|
+
].join("\n")
|
|
2593
|
+
);
|
|
2594
|
+
}
|
|
2595
|
+
if (error instanceof Error) {
|
|
2596
|
+
return error;
|
|
2597
|
+
}
|
|
2598
|
+
return new Error(normalizeErrorMessage(error));
|
|
2599
|
+
}
|
|
2600
|
+
async function runCLI(argv, runtime = {}) {
|
|
2601
|
+
const log = runtime.log ?? console.log;
|
|
2602
|
+
const runGenerator = runtime.runGenerator ?? runSchemaGenerator;
|
|
2476
2603
|
const parsed = parseCommand(argv);
|
|
2477
2604
|
if (parsed.command === "help") {
|
|
2478
|
-
|
|
2605
|
+
log(usage(parsed.topic));
|
|
2479
2606
|
return;
|
|
2480
2607
|
}
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2608
|
+
let result;
|
|
2609
|
+
try {
|
|
2610
|
+
result = await runGenerator({
|
|
2611
|
+
configPath: parsed.configPath,
|
|
2612
|
+
dryRun: parsed.dryRun
|
|
2613
|
+
});
|
|
2614
|
+
} catch (error) {
|
|
2615
|
+
throw formatGeneratorError(error, parsed.configPath);
|
|
2616
|
+
}
|
|
2485
2617
|
if (parsed.dryRun) {
|
|
2486
|
-
|
|
2618
|
+
log(`[dry-run] Generated ${result.files.length} files from ${result.configPath}`);
|
|
2487
2619
|
for (const file of result.files) {
|
|
2488
|
-
|
|
2620
|
+
log(` - ${file.path}`);
|
|
2489
2621
|
}
|
|
2490
2622
|
return;
|
|
2491
2623
|
}
|
|
2492
|
-
|
|
2624
|
+
log(`Generated ${result.writtenFiles.length} files from ${result.configPath}`);
|
|
2493
2625
|
for (const filePath of result.writtenFiles) {
|
|
2494
|
-
|
|
2626
|
+
log(` - ${filePath}`);
|
|
2495
2627
|
}
|
|
2496
2628
|
}
|
|
2497
2629
|
|
|
2498
|
-
export { runCLI };
|
|
2630
|
+
export { parseCommand, runCLI, usage };
|
|
2499
2631
|
//# sourceMappingURL=index.js.map
|
|
2500
2632
|
//# sourceMappingURL=index.js.map
|