@xylex-group/athena 1.6.0 → 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.
@@ -0,0 +1,31 @@
1
+ import { m as AthenaGatewayErrorCode, u as AthenaGatewayEndpointPath, v as AthenaGatewayMethod, e as AthenaGatewayErrorDetails, t as AthenaGatewayResponse } from './types-v6UyGg-x.js';
2
+
3
+ interface AthenaGatewayErrorInput {
4
+ code: AthenaGatewayErrorCode;
5
+ message: string;
6
+ status?: number;
7
+ endpoint?: AthenaGatewayEndpointPath;
8
+ method?: AthenaGatewayMethod;
9
+ requestId?: string;
10
+ hint?: string;
11
+ cause?: string;
12
+ }
13
+ /**
14
+ * Canonical error for gateway failures.
15
+ * Holds request context and machine-readable classification.
16
+ */
17
+ declare class AthenaGatewayError extends Error {
18
+ readonly code: AthenaGatewayErrorCode;
19
+ readonly status: number;
20
+ readonly endpoint?: AthenaGatewayEndpointPath;
21
+ readonly method?: AthenaGatewayMethod;
22
+ readonly requestId?: string;
23
+ readonly hint?: string;
24
+ readonly causeDetail?: string;
25
+ constructor(input: AthenaGatewayErrorInput);
26
+ toDetails(): AthenaGatewayErrorDetails;
27
+ static fromResponse<T>(response: AthenaGatewayResponse<T>, fallback: Omit<AthenaGatewayErrorInput, 'code' | 'message' | 'status'>): AthenaGatewayError;
28
+ }
29
+ declare function isAthenaGatewayError(error: unknown): error is AthenaGatewayError;
30
+
31
+ export { AthenaGatewayError as A, isAthenaGatewayError as i };
@@ -0,0 +1,31 @@
1
+ import { m as AthenaGatewayErrorCode, u as AthenaGatewayEndpointPath, v as AthenaGatewayMethod, e as AthenaGatewayErrorDetails, t as AthenaGatewayResponse } from './types-v6UyGg-x.cjs';
2
+
3
+ interface AthenaGatewayErrorInput {
4
+ code: AthenaGatewayErrorCode;
5
+ message: string;
6
+ status?: number;
7
+ endpoint?: AthenaGatewayEndpointPath;
8
+ method?: AthenaGatewayMethod;
9
+ requestId?: string;
10
+ hint?: string;
11
+ cause?: string;
12
+ }
13
+ /**
14
+ * Canonical error for gateway failures.
15
+ * Holds request context and machine-readable classification.
16
+ */
17
+ declare class AthenaGatewayError extends Error {
18
+ readonly code: AthenaGatewayErrorCode;
19
+ readonly status: number;
20
+ readonly endpoint?: AthenaGatewayEndpointPath;
21
+ readonly method?: AthenaGatewayMethod;
22
+ readonly requestId?: string;
23
+ readonly hint?: string;
24
+ readonly causeDetail?: string;
25
+ constructor(input: AthenaGatewayErrorInput);
26
+ toDetails(): AthenaGatewayErrorDetails;
27
+ static fromResponse<T>(response: AthenaGatewayResponse<T>, fallback: Omit<AthenaGatewayErrorInput, 'code' | 'message' | 'status'>): AthenaGatewayError;
28
+ }
29
+ declare function isAthenaGatewayError(error: unknown): error is AthenaGatewayError;
30
+
31
+ export { AthenaGatewayError as A, isAthenaGatewayError as i };
package/dist/index.cjs CHANGED
@@ -1968,6 +1968,58 @@ function toTypeKind(code) {
1968
1968
  function escapeSqlLiteral(value) {
1969
1969
  return value.replace(/'/g, "''");
1970
1970
  }
1971
+ function parsePostgresArrayLiteral(text) {
1972
+ const body = text.slice(1, -1).trim();
1973
+ if (!body) return [];
1974
+ const values = [];
1975
+ let current = "";
1976
+ let inQuotes = false;
1977
+ let escaped = false;
1978
+ for (const char of body) {
1979
+ if (escaped) {
1980
+ current += char;
1981
+ escaped = false;
1982
+ continue;
1983
+ }
1984
+ if (char === "\\") {
1985
+ escaped = true;
1986
+ continue;
1987
+ }
1988
+ if (char === '"') {
1989
+ inQuotes = !inQuotes;
1990
+ continue;
1991
+ }
1992
+ if (char === "," && !inQuotes) {
1993
+ values.push(current);
1994
+ current = "";
1995
+ continue;
1996
+ }
1997
+ current += char;
1998
+ }
1999
+ values.push(current);
2000
+ return values.map((value) => value.trim()).filter((value) => value.length > 0);
2001
+ }
2002
+ function coerceStringArray(value) {
2003
+ if (Array.isArray(value)) {
2004
+ return value.map((item) => typeof item === "string" ? item : String(item)).map((item) => item.trim()).filter((item) => item.length > 0);
2005
+ }
2006
+ if (typeof value === "string") {
2007
+ const trimmed = value.trim();
2008
+ if (!trimmed) return [];
2009
+ if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
2010
+ try {
2011
+ const parsed = JSON.parse(trimmed);
2012
+ return coerceStringArray(parsed);
2013
+ } catch {
2014
+ }
2015
+ }
2016
+ if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
2017
+ return parsePostgresArrayLiteral(trimmed);
2018
+ }
2019
+ return trimmed.split(",").map((item) => item.trim()).filter((item) => item.length > 0);
2020
+ }
2021
+ return [];
2022
+ }
1971
2023
  function buildSchemaArrayLiteral(schemas) {
1972
2024
  const normalized = schemas.length > 0 ? schemas : ["public"];
1973
2025
  const literals = normalized.map((schema) => `'${escapeSqlLiteral(schema)}'`).join(", ");
@@ -2007,8 +2059,10 @@ var PostgresCatalogSnapshotAssembler = class {
2007
2059
  addPrimaryKeyRows(primaryKeyRows) {
2008
2060
  for (const row of primaryKeyRows) {
2009
2061
  const table = this.ensureTable(row.schema_name, row.table_name);
2010
- table.primaryKey = row.columns;
2011
- for (const columnName of row.columns) {
2062
+ const primaryKeyColumns = coerceStringArray(row.columns);
2063
+ row.columns = primaryKeyColumns;
2064
+ table.primaryKey = primaryKeyColumns;
2065
+ for (const columnName of primaryKeyColumns) {
2012
2066
  const column = table.columns[columnName];
2013
2067
  if (column) {
2014
2068
  column.isPrimaryKey = true;
@@ -2020,23 +2074,27 @@ var PostgresCatalogSnapshotAssembler = class {
2020
2074
  for (const row of foreignKeyRows) {
2021
2075
  const sourceTable = this.ensureTable(row.source_schema, row.source_table);
2022
2076
  const targetTable = this.ensureTable(row.target_schema, row.target_table);
2077
+ const sourceColumns = coerceStringArray(row.source_columns);
2078
+ const targetColumns = coerceStringArray(row.target_columns);
2079
+ row.source_columns = sourceColumns;
2080
+ row.target_columns = targetColumns;
2023
2081
  const sourceRelationKind = row.source_is_unique ? "one-to-one" : "many-to-one";
2024
2082
  this.upsertRelation(sourceTable, relationKey(row.constraint_name, row.target_table), {
2025
2083
  name: row.constraint_name,
2026
2084
  kind: sourceRelationKind,
2027
- sourceColumns: row.source_columns,
2085
+ sourceColumns,
2028
2086
  targetSchema: row.target_schema,
2029
2087
  targetModel: row.target_table,
2030
- targetColumns: row.target_columns
2088
+ targetColumns
2031
2089
  });
2032
2090
  const targetRelationKind = row.source_is_unique ? "one-to-one" : "one-to-many";
2033
2091
  this.upsertRelation(targetTable, relationKey(row.source_table), {
2034
2092
  name: relationKey(row.source_table, row.constraint_name),
2035
2093
  kind: targetRelationKind,
2036
- sourceColumns: row.target_columns,
2094
+ sourceColumns: targetColumns,
2037
2095
  targetSchema: row.source_schema,
2038
2096
  targetModel: row.source_table,
2039
- targetColumns: row.source_columns
2097
+ targetColumns: sourceColumns
2040
2098
  });
2041
2099
  }
2042
2100
  }
@@ -2209,10 +2267,10 @@ var DEFAULT_CONFIG_CANDIDATES = [
2209
2267
  ".athena.config.js"
2210
2268
  ];
2211
2269
  var DEFAULT_TARGETS = {
2212
- model: "src/generated/{database_kebab}/{schema_kebab}/{model_kebab}.model.ts",
2213
- schema: "src/generated/{database_kebab}/{schema_kebab}/index.ts",
2214
- database: "src/generated/{database_kebab}/index.ts",
2215
- registry: "src/generated/index.ts"
2270
+ model: "athena/models/{model_kebab}.ts",
2271
+ schema: "athena/schema.ts",
2272
+ database: "athena/relations.ts",
2273
+ registry: "athena/config.ts"
2216
2274
  };
2217
2275
  var DEFAULT_NAMING = {
2218
2276
  modelType: "pascal",
@@ -2240,6 +2298,13 @@ function normalizeOutputConfig(output) {
2240
2298
  }
2241
2299
  };
2242
2300
  }
2301
+ function isAthenaGeneratorConfig(value) {
2302
+ if (!value || typeof value !== "object") {
2303
+ return false;
2304
+ }
2305
+ const record = value;
2306
+ return Boolean(record.provider && typeof record.provider === "object") && Boolean(record.output && typeof record.output === "object");
2307
+ }
2243
2308
  function normalizeGeneratorConfig(input) {
2244
2309
  return {
2245
2310
  provider: input.provider,
@@ -2271,18 +2336,41 @@ function findGeneratorConfigPath(cwd = process.cwd()) {
2271
2336
  return void 0;
2272
2337
  }
2273
2338
  function extractConfigExport(module) {
2274
- if (module && typeof module === "object") {
2275
- const record = module;
2339
+ const visited = /* @__PURE__ */ new Set();
2340
+ const queue = [module];
2341
+ while (queue.length > 0) {
2342
+ const current = queue.shift();
2343
+ if (!current || typeof current !== "object" || visited.has(current)) {
2344
+ continue;
2345
+ }
2346
+ visited.add(current);
2347
+ const record = current;
2348
+ if (isAthenaGeneratorConfig(record)) {
2349
+ return record;
2350
+ }
2276
2351
  const defaultExport = record.default;
2277
2352
  if (defaultExport && typeof defaultExport === "object") {
2278
- return defaultExport;
2353
+ queue.push(defaultExport);
2279
2354
  }
2280
2355
  const namedConfigExport = record.config;
2281
2356
  if (namedConfigExport && typeof namedConfigExport === "object") {
2282
- return namedConfigExport;
2357
+ queue.push(namedConfigExport);
2358
+ }
2359
+ const moduleExports = record["module.exports"];
2360
+ if (moduleExports && typeof moduleExports === "object") {
2361
+ queue.push(moduleExports);
2283
2362
  }
2284
2363
  }
2285
- throw new Error("Generator config file must export a config object as default export or `config`.");
2364
+ throw new Error(
2365
+ "Generator config file must export a config object as default export or `config`."
2366
+ );
2367
+ }
2368
+ function importConfigModule(moduleSpecifier) {
2369
+ const runtimeImport = new Function(
2370
+ "moduleSpecifier",
2371
+ "return import(moduleSpecifier)"
2372
+ );
2373
+ return runtimeImport(moduleSpecifier);
2286
2374
  }
2287
2375
  async function loadGeneratorConfig(options = {}) {
2288
2376
  const cwd = options.cwd ?? process.cwd();
@@ -2293,7 +2381,7 @@ async function loadGeneratorConfig(options = {}) {
2293
2381
  );
2294
2382
  }
2295
2383
  const moduleUrl = url.pathToFileURL(resolvedPath);
2296
- const module = await import(`${moduleUrl.href}?cacheBust=${Date.now()}`);
2384
+ const module = await importConfigModule(`${moduleUrl.href}?cacheBust=${Date.now()}`);
2297
2385
  const rawConfig = extractConfigExport(module);
2298
2386
  return {
2299
2387
  configPath: resolvedPath,