@xylex-group/athena 2.7.0 → 2.8.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.
Files changed (36) hide show
  1. package/README.md +210 -17
  2. package/dist/browser.cjs +1253 -401
  3. package/dist/browser.cjs.map +1 -1
  4. package/dist/browser.d.cts +8 -7
  5. package/dist/browser.d.ts +8 -7
  6. package/dist/browser.js +1247 -402
  7. package/dist/browser.js.map +1 -1
  8. package/dist/cli/index.cjs +1285 -451
  9. package/dist/cli/index.cjs.map +1 -1
  10. package/dist/cli/index.d.cts +3 -3
  11. package/dist/cli/index.d.ts +3 -3
  12. package/dist/cli/index.js +1285 -451
  13. package/dist/cli/index.js.map +1 -1
  14. package/dist/index.cjs +1921 -698
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +8 -7
  17. package/dist/index.d.ts +8 -7
  18. package/dist/index.js +1915 -699
  19. package/dist/index.js.map +1 -1
  20. package/dist/{model-form-AKYrgede.d.ts → model-form-DMed05gE.d.cts} +347 -82
  21. package/dist/{model-form-ehfqLuG7.d.cts → model-form-DXPlOnlI.d.ts} +347 -82
  22. package/dist/{pipeline-BUsR9XlO.d.ts → pipeline-CkMnhwPI.d.ts} +1 -1
  23. package/dist/{pipeline-BfCWSRYl.d.cts → pipeline-D4sJRKqN.d.cts} +1 -1
  24. package/dist/{react-email-BQzmXBDE.d.cts → react-email-DZhDDlEl.d.cts} +121 -8
  25. package/dist/{react-email-BrVRp80B.d.ts → react-email-Lrz9A-BW.d.ts} +121 -8
  26. package/dist/react.cjs +1 -1
  27. package/dist/react.cjs.map +1 -1
  28. package/dist/react.d.cts +4 -4
  29. package/dist/react.d.ts +4 -4
  30. package/dist/react.js +1 -1
  31. package/dist/react.js.map +1 -1
  32. package/dist/{types-BSIsyss1.d.cts → types-BzY6fETM.d.ts} +47 -5
  33. package/dist/{types-t_TVqnmp.d.ts → types-CAtTGGoz.d.cts} +47 -5
  34. package/dist/{types-BsyRW49r.d.cts → types-vikz9YIO.d.cts} +23 -1
  35. package/dist/{types-BsyRW49r.d.ts → types-vikz9YIO.d.ts} +23 -1
  36. package/package.json +3 -2
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { z } from 'zod';
1
2
  import { existsSync, readFileSync } from 'fs';
2
3
  import { resolve, dirname, posix } from 'path';
3
4
  import { pathToFileURL } from 'url';
@@ -803,7 +804,7 @@ var getCookieCache = async (request, config) => {
803
804
 
804
805
  // package.json
805
806
  var package_default = {
806
- version: "2.7.0"
807
+ version: "2.8.0"
807
808
  };
808
809
 
809
810
  // src/sdk-version.ts
@@ -3120,7 +3121,7 @@ function normalizeAthenaError(resultOrError, context) {
3120
3121
  const details = resultOrError.errorDetails;
3121
3122
  const message2 = messageFromUnknownError(resultOrError.error) ?? details?.message ?? `Athena ${context?.operation ?? operationFromDetails(details) ?? "request"} failed`;
3122
3123
  const operation = context?.operation ?? operationFromDetails(details);
3123
- const table = context?.table ?? extractTable(message2);
3124
+ const table2 = context?.table ?? extractTable(message2);
3124
3125
  const constraint = extractConstraint(message2);
3125
3126
  const gatewayCode = details?.code ?? gatewayCodeFromUnknownError(resultOrError.error);
3126
3127
  const kind2 = classifyKind(resultOrError.status, gatewayCode, message2);
@@ -3133,7 +3134,7 @@ function normalizeAthenaError(resultOrError, context) {
3133
3134
  retryable: isRetryable(kind2, resultOrError.status),
3134
3135
  status: resultOrError.status,
3135
3136
  constraint,
3136
- table,
3137
+ table: table2,
3137
3138
  operation,
3138
3139
  message: message2,
3139
3140
  raw: resultOrError.raw
@@ -3142,7 +3143,7 @@ function normalizeAthenaError(resultOrError, context) {
3142
3143
  if (isAthenaGatewayError(resultOrError)) {
3143
3144
  const details = resultOrError.toDetails();
3144
3145
  const operation = context?.operation ?? operationFromDetails(details);
3145
- const table = context?.table ?? extractTable(resultOrError.message);
3146
+ const table2 = context?.table ?? extractTable(resultOrError.message);
3146
3147
  const constraint = extractConstraint(resultOrError.message);
3147
3148
  const kind2 = classifyKind(resultOrError.status, resultOrError.code, resultOrError.message);
3148
3149
  const code = toAthenaErrorCode(kind2, resultOrError.status, resultOrError.code);
@@ -3154,7 +3155,7 @@ function normalizeAthenaError(resultOrError, context) {
3154
3155
  retryable: isRetryable(kind2, resultOrError.status),
3155
3156
  status: resultOrError.status,
3156
3157
  constraint,
3157
- table,
3158
+ table: table2,
3158
3159
  operation,
3159
3160
  message: resultOrError.message,
3160
3161
  raw: resultOrError
@@ -3350,23 +3351,24 @@ async function withRetry(config, fn) {
3350
3351
  // src/db/module.ts
3351
3352
  function createDbModule(input) {
3352
3353
  const db = {
3353
- from(table, options) {
3354
- return input.from(table, options);
3355
- },
3356
- select(table, columns, options) {
3357
- return input.from(table).select(columns, options);
3354
+ from: input.from,
3355
+ select(table2, first, second) {
3356
+ if (first && typeof first === "object" && !Array.isArray(first)) {
3357
+ return input.from(table2).select(void 0, first);
3358
+ }
3359
+ return input.from(table2).select(first, second);
3358
3360
  },
3359
- insert(table, values, options) {
3360
- return Array.isArray(values) ? input.from(table).insert(values, options) : input.from(table).insert(values, options);
3361
+ insert(table2, values, options) {
3362
+ return Array.isArray(values) ? input.from(table2).insert(values, options) : input.from(table2).insert(values, options);
3361
3363
  },
3362
- upsert(table, values, options) {
3363
- return Array.isArray(values) ? input.from(table).upsert(values, options) : input.from(table).upsert(values, options);
3364
+ upsert(table2, values, options) {
3365
+ return Array.isArray(values) ? input.from(table2).upsert(values, options) : input.from(table2).upsert(values, options);
3364
3366
  },
3365
- update(table, values, options) {
3366
- return input.from(table).update(values, options);
3367
+ update(table2, values, options) {
3368
+ return input.from(table2).update(values, options);
3367
3369
  },
3368
- delete(table, options) {
3369
- return input.from(table).delete(options);
3370
+ delete(table2, options) {
3371
+ return input.from(table2).delete(options);
3370
3372
  },
3371
3373
  rpc(fn, args, options) {
3372
3374
  return input.rpc(fn, args, options);
@@ -4035,6 +4037,15 @@ function appendQuery(path, query) {
4035
4037
  function storagePath(path) {
4036
4038
  return path;
4037
4039
  }
4040
+ function resolveStorageEndpointPath(endpoint, runtimeOptions) {
4041
+ if (!runtimeOptions?.stripBasePath) {
4042
+ return endpoint;
4043
+ }
4044
+ const [pathname, queryText] = String(endpoint).split("?", 2);
4045
+ const trimmedPathname = pathname.startsWith("/storage/") ? pathname.slice("/storage".length) : pathname === "/storage" ? "/" : pathname;
4046
+ const resolvedPath = trimmedPathname.startsWith("/") ? trimmedPathname : `/${trimmedPathname}`;
4047
+ return storagePath(queryText ? `${resolvedPath}?${queryText}` : resolvedPath);
4048
+ }
4038
4049
  function withPathParam(path, name, value) {
4039
4050
  return path.replace(`{${name}}`, encodeURIComponent(value));
4040
4051
  }
@@ -4073,8 +4084,8 @@ async function callStorageEndpoint(gateway, endpoint, method, envelope, payload,
4073
4084
  let url;
4074
4085
  let headers;
4075
4086
  try {
4076
- const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : gateway.baseUrl;
4077
- url = buildAthenaGatewayUrl(baseUrl, endpoint);
4087
+ const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : runtimeOptions?.baseUrl ? normalizeAthenaGatewayBaseUrl(runtimeOptions.baseUrl) : gateway.baseUrl;
4088
+ url = buildAthenaGatewayUrl(baseUrl, resolveStorageEndpointPath(endpoint, runtimeOptions));
4078
4089
  headers = gateway.buildHeaders(options);
4079
4090
  } catch (error) {
4080
4091
  return rejectStorageError(
@@ -4198,8 +4209,8 @@ async function callStorageBinaryEndpoint(gateway, endpoint, method, options, run
4198
4209
  let url;
4199
4210
  let headers;
4200
4211
  try {
4201
- const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : gateway.baseUrl;
4202
- url = buildAthenaGatewayUrl(baseUrl, endpoint);
4212
+ const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : runtimeOptions?.baseUrl ? normalizeAthenaGatewayBaseUrl(runtimeOptions.baseUrl) : gateway.baseUrl;
4213
+ url = buildAthenaGatewayUrl(baseUrl, resolveStorageEndpointPath(endpoint, runtimeOptions));
4203
4214
  headers = gateway.buildHeaders(options);
4204
4215
  } catch (error) {
4205
4216
  return rejectStorageError(
@@ -4360,8 +4371,8 @@ async function callStorageUploadBinaryEndpoint(gateway, endpoint, body, options,
4360
4371
  let url;
4361
4372
  let headers;
4362
4373
  try {
4363
- const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : gateway.baseUrl;
4364
- url = buildAthenaGatewayUrl(baseUrl, endpoint);
4374
+ const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : runtimeOptions?.baseUrl ? normalizeAthenaGatewayBaseUrl(runtimeOptions.baseUrl) : gateway.baseUrl;
4375
+ url = buildAthenaGatewayUrl(baseUrl, resolveStorageEndpointPath(endpoint, runtimeOptions));
4365
4376
  headers = gateway.buildHeaders(options);
4366
4377
  } catch (error) {
4367
4378
  return rejectStorageError(
@@ -4485,6 +4496,7 @@ async function callStorageUploadBinaryEndpoint(gateway, endpoint, body, options,
4485
4496
  return parsedBody.parsed.data;
4486
4497
  }
4487
4498
  function createStorageModule(gateway, runtimeOptions) {
4499
+ const resolvedRuntimeOptions = runtimeOptions;
4488
4500
  const callRaw = (path, method, payload, options) => callStorageEndpoint(
4489
4501
  gateway,
4490
4502
  storagePath(path),
@@ -4492,7 +4504,7 @@ function createStorageModule(gateway, runtimeOptions) {
4492
4504
  "raw",
4493
4505
  payload,
4494
4506
  options,
4495
- runtimeOptions
4507
+ resolvedRuntimeOptions
4496
4508
  );
4497
4509
  const callAthena2 = (path, method, payload, options) => callStorageEndpoint(
4498
4510
  gateway,
@@ -4501,7 +4513,7 @@ function createStorageModule(gateway, runtimeOptions) {
4501
4513
  "athena",
4502
4514
  payload,
4503
4515
  options,
4504
- runtimeOptions
4516
+ resolvedRuntimeOptions
4505
4517
  );
4506
4518
  const base = {
4507
4519
  listStorageCatalogs(options) {
@@ -4543,7 +4555,7 @@ function createStorageModule(gateway, runtimeOptions) {
4543
4555
  withPathParam("/storage/files/{file_id}/proxy", "file_id", fileId),
4544
4556
  query
4545
4557
  );
4546
- return callStorageBinaryEndpoint(gateway, storagePath(path), "GET", options, runtimeOptions);
4558
+ return callStorageBinaryEndpoint(gateway, storagePath(path), "GET", options, resolvedRuntimeOptions);
4547
4559
  },
4548
4560
  updateStorageFile(fileId, input, options) {
4549
4561
  return callAthena2(withPathParam("/storage/files/{file_id}", "file_id", fileId), "PATCH", input, options);
@@ -4590,7 +4602,7 @@ function createStorageModule(gateway, runtimeOptions) {
4590
4602
  storagePath(withPathParam("/storage/files/{file_id}/upload", "file_id", fileId)),
4591
4603
  body,
4592
4604
  options,
4593
- runtimeOptions
4605
+ resolvedRuntimeOptions
4594
4606
  );
4595
4607
  },
4596
4608
  search(input, options) {
@@ -4786,6 +4798,176 @@ function createStorageModule(gateway, runtimeOptions) {
4786
4798
  };
4787
4799
  }
4788
4800
 
4801
+ // src/client-builder.ts
4802
+ var DEFAULT_BACKEND = { type: "athena" };
4803
+ function toBackendConfig(value) {
4804
+ if (!value) return DEFAULT_BACKEND;
4805
+ return typeof value === "string" ? { type: value } : value;
4806
+ }
4807
+ function mergeHeaders(current, next) {
4808
+ return {
4809
+ ...current ?? {},
4810
+ ...next
4811
+ };
4812
+ }
4813
+ function mergeAuthClientConfig(current, next) {
4814
+ const merged = {
4815
+ ...current ?? {},
4816
+ ...next
4817
+ };
4818
+ if (current?.headers || next.headers) {
4819
+ merged.headers = mergeHeaders(current?.headers, next.headers ?? {});
4820
+ }
4821
+ return merged;
4822
+ }
4823
+ function mergeExperimentalOptions(current, next) {
4824
+ const merged = {
4825
+ ...current ?? {},
4826
+ ...next
4827
+ };
4828
+ if (current?.traceQueries && typeof current.traceQueries === "object" && next.traceQueries && typeof next.traceQueries === "object") {
4829
+ merged.traceQueries = {
4830
+ ...current.traceQueries,
4831
+ ...next.traceQueries
4832
+ };
4833
+ }
4834
+ if (current?.storage || next.storage) {
4835
+ merged.storage = {
4836
+ ...current?.storage ?? {},
4837
+ ...next.storage ?? {}
4838
+ };
4839
+ }
4840
+ return merged;
4841
+ }
4842
+ function resolveBuilderReturn(builder, storageEnabled, strictEnabled) {
4843
+ return builder;
4844
+ }
4845
+ var AthenaClientBuilderImpl = class {
4846
+ constructor(buildClient) {
4847
+ this.buildClient = buildClient;
4848
+ }
4849
+ rootUrl;
4850
+ apiKey;
4851
+ backendConfig = DEFAULT_BACKEND;
4852
+ clientName;
4853
+ defaultHeaders;
4854
+ authConfig;
4855
+ dbUrlOverride;
4856
+ gatewayUrlOverride;
4857
+ authUrlOverride;
4858
+ storageUrlOverride;
4859
+ experimentalOptions;
4860
+ url(url) {
4861
+ this.rootUrl = url;
4862
+ return this;
4863
+ }
4864
+ key(apiKey) {
4865
+ this.apiKey = apiKey;
4866
+ return this;
4867
+ }
4868
+ backend(backend) {
4869
+ this.backendConfig = toBackendConfig(backend);
4870
+ return this;
4871
+ }
4872
+ client(clientName) {
4873
+ this.clientName = clientName;
4874
+ return this;
4875
+ }
4876
+ headers(headers) {
4877
+ this.defaultHeaders = headers;
4878
+ return this;
4879
+ }
4880
+ auth(config) {
4881
+ this.authConfig = mergeAuthClientConfig(this.authConfig, config);
4882
+ return this;
4883
+ }
4884
+ experimental(options) {
4885
+ this.experimentalOptions = mergeExperimentalOptions(this.experimentalOptions, options);
4886
+ if (options.athenaStorageBackend && options.typecheckColumns) {
4887
+ return resolveBuilderReturn(this);
4888
+ }
4889
+ if (options.athenaStorageBackend) {
4890
+ return resolveBuilderReturn(this);
4891
+ }
4892
+ if (options.typecheckColumns) {
4893
+ return resolveBuilderReturn(this);
4894
+ }
4895
+ return this;
4896
+ }
4897
+ options(options) {
4898
+ if (options.client !== void 0) {
4899
+ this.clientName = options.client;
4900
+ }
4901
+ if (options.backend !== void 0) {
4902
+ this.backendConfig = toBackendConfig(options.backend);
4903
+ }
4904
+ if (options.headers !== void 0) {
4905
+ this.defaultHeaders = mergeHeaders(this.defaultHeaders, options.headers);
4906
+ }
4907
+ if (options.auth !== void 0) {
4908
+ this.authConfig = mergeAuthClientConfig(this.authConfig, options.auth);
4909
+ }
4910
+ if (options.db?.url !== void 0 && options.db.url !== null) {
4911
+ this.dbUrlOverride = options.db.url;
4912
+ }
4913
+ if (options.gateway?.url !== void 0 && options.gateway.url !== null) {
4914
+ this.gatewayUrlOverride = options.gateway.url;
4915
+ }
4916
+ if (options.dbUrl !== void 0 && options.dbUrl !== null) {
4917
+ this.dbUrlOverride = options.dbUrl;
4918
+ }
4919
+ if (options.gatewayUrl !== void 0 && options.gatewayUrl !== null) {
4920
+ this.gatewayUrlOverride = options.gatewayUrl;
4921
+ }
4922
+ if (options.authUrl !== void 0 && options.authUrl !== null) {
4923
+ this.authUrlOverride = options.authUrl;
4924
+ }
4925
+ if (options.storage?.url !== void 0 && options.storage.url !== null) {
4926
+ this.storageUrlOverride = options.storage.url;
4927
+ }
4928
+ if (options.storageUrl !== void 0 && options.storageUrl !== null) {
4929
+ this.storageUrlOverride = options.storageUrl;
4930
+ }
4931
+ if (options.experimental !== void 0) {
4932
+ this.experimentalOptions = mergeExperimentalOptions(this.experimentalOptions, options.experimental);
4933
+ }
4934
+ if (options.experimental?.athenaStorageBackend && options.experimental.typecheckColumns) {
4935
+ return resolveBuilderReturn(this);
4936
+ }
4937
+ if (options.experimental?.athenaStorageBackend) {
4938
+ return resolveBuilderReturn(this);
4939
+ }
4940
+ if (options.experimental?.typecheckColumns) {
4941
+ return resolveBuilderReturn(this);
4942
+ }
4943
+ return this;
4944
+ }
4945
+ build() {
4946
+ if (!this.rootUrl && !this.dbUrlOverride && !this.gatewayUrlOverride || !this.apiKey) {
4947
+ throw new Error(
4948
+ "AthenaClient requires key plus either .url() or a db/gateway override before .build()"
4949
+ );
4950
+ }
4951
+ return this.buildClient({
4952
+ url: this.rootUrl,
4953
+ key: this.apiKey,
4954
+ client: this.clientName,
4955
+ backend: this.backendConfig,
4956
+ headers: this.defaultHeaders,
4957
+ db: this.dbUrlOverride ? { url: this.dbUrlOverride } : void 0,
4958
+ gateway: this.gatewayUrlOverride ? { url: this.gatewayUrlOverride } : void 0,
4959
+ auth: this.authConfig,
4960
+ authUrl: this.authUrlOverride,
4961
+ storage: this.storageUrlOverride ? { url: this.storageUrlOverride } : void 0,
4962
+ storageUrl: this.storageUrlOverride,
4963
+ experimental: this.experimentalOptions
4964
+ });
4965
+ }
4966
+ };
4967
+ function createAthenaClientBuilder(buildClient) {
4968
+ return new AthenaClientBuilderImpl(buildClient);
4969
+ }
4970
+
4789
4971
  // src/query-ast.ts
4790
4972
  var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
4791
4973
  var FILTER_OPERATORS = /* @__PURE__ */ new Set([
@@ -5408,161 +5590,258 @@ function createSelectTransportPlan(input) {
5408
5590
  };
5409
5591
  }
5410
5592
 
5411
- // src/client.ts
5412
- var DEFAULT_COLUMNS = "*";
5413
- var SAFE_CAST_PATTERN = /^[a-z_][a-z0-9_]*(?:\[\])?$/i;
5414
- var ATHENA_NORMALIZED_ERROR_KEY = "__athenaNormalizedError";
5415
- var QUERY_TRACE_STACK_SKIP_PATTERNS = [
5416
- "src\\client.ts",
5417
- "src/client.ts",
5418
- "dist\\client.",
5419
- "dist/client.",
5420
- "node_modules\\@xylex-group\\athena",
5421
- "node_modules/@xylex-group/athena",
5422
- "node:internal",
5423
- "internal/process"
5424
- ];
5425
- function formatResult(response) {
5426
- const result = {
5427
- data: response.data ?? null,
5428
- error: null,
5429
- errorDetails: response.errorDetails ?? null,
5430
- status: response.status,
5431
- statusText: response.statusText ?? null,
5432
- raw: response.raw
5593
+ // src/query-debug-ast.ts
5594
+ var ATHENA_DEBUG_AST_KEY = "__athenaDebugAst";
5595
+ function cloneConditions(conditions) {
5596
+ return conditions.map((condition) => ({ ...condition }));
5597
+ }
5598
+ function cloneTableBuilderStateAst(state) {
5599
+ return {
5600
+ conditions: cloneConditions(state.conditions),
5601
+ limit: state.limit,
5602
+ offset: state.offset,
5603
+ order: state.order ? { ...state.order } : void 0,
5604
+ currentPage: state.currentPage,
5605
+ pageSize: state.pageSize,
5606
+ totalPages: state.totalPages
5433
5607
  };
5434
- if (response.count !== void 0) {
5435
- result.count = response.count;
5608
+ }
5609
+ function cloneRpcBuilderStateAst(state) {
5610
+ return {
5611
+ filters: state.filters.map((filter) => ({ ...filter })),
5612
+ limit: state.limit,
5613
+ offset: state.offset,
5614
+ order: state.order ? { ...state.order } : void 0
5615
+ };
5616
+ }
5617
+ function toSelectTransportAst(plan) {
5618
+ if (plan.kind === "query") {
5619
+ return {
5620
+ mode: "typed-query",
5621
+ endpoint: "/gateway/query",
5622
+ payload: plan.payload
5623
+ };
5436
5624
  }
5437
- return result;
5625
+ return {
5626
+ mode: plan.payload.select !== void 0 ? "structured-fetch" : "compiled-fetch",
5627
+ endpoint: "/gateway/fetch",
5628
+ payload: plan.payload
5629
+ };
5438
5630
  }
5439
- var EXPERIMENTAL_READ_RETRY_CONFIG = {
5440
- retries: 2,
5441
- baseDelayMs: 100,
5442
- maxDelayMs: 1e3,
5443
- backoff: "exponential",
5444
- jitter: true
5445
- };
5446
- function attachNormalizedError(result, normalizedError) {
5447
- Object.defineProperty(result, ATHENA_NORMALIZED_ERROR_KEY, {
5448
- value: normalizedError,
5449
- enumerable: false,
5450
- configurable: true,
5451
- writable: false
5452
- });
5631
+ function resolveDebugTableName(tableName) {
5632
+ return tableName ?? "__unknown_table__";
5453
5633
  }
5454
- function createResultFormatter(experimental) {
5455
- return (response, context) => {
5456
- const result = formatResult(response);
5457
- if (response.error == null && response.errorDetails == null) {
5458
- return result;
5634
+ function buildSelectDebugAst(input) {
5635
+ return {
5636
+ version: 1,
5637
+ kind: "select",
5638
+ tableName: input.tableName,
5639
+ input: {
5640
+ columns: input.columns,
5641
+ state: cloneTableBuilderStateAst(input.state)
5642
+ },
5643
+ transport: toSelectTransportAst(input.plan)
5644
+ };
5645
+ }
5646
+ function buildFindManyCompiledDebugAst(input) {
5647
+ return {
5648
+ version: 1,
5649
+ kind: "findMany",
5650
+ tableName: input.tableName,
5651
+ input: {
5652
+ select: input.options.select,
5653
+ where: input.options.where,
5654
+ orderBy: input.options.orderBy,
5655
+ limit: input.options.limit
5656
+ },
5657
+ compiled: {
5658
+ columns: input.compiledColumns,
5659
+ baseState: cloneTableBuilderStateAst(input.baseState),
5660
+ executionState: cloneTableBuilderStateAst(input.executionState)
5661
+ },
5662
+ transport: planToFindManyTransport(input.plan)
5663
+ };
5664
+ }
5665
+ function buildFindManyDirectDebugAst(input) {
5666
+ return {
5667
+ version: 1,
5668
+ kind: "findMany",
5669
+ tableName: input.tableName,
5670
+ input: {
5671
+ select: input.options.select,
5672
+ where: input.options.where,
5673
+ orderBy: input.options.orderBy,
5674
+ limit: input.options.limit
5675
+ },
5676
+ compiled: {
5677
+ columns: input.compiledColumns,
5678
+ baseState: cloneTableBuilderStateAst(input.baseState),
5679
+ executionState: cloneTableBuilderStateAst(input.executionState)
5680
+ },
5681
+ transport: {
5682
+ mode: "direct-ast-fetch",
5683
+ endpoint: "/gateway/fetch",
5684
+ payload: input.payload
5459
5685
  }
5460
- const normalizedError = normalizeAthenaError(
5461
- {
5462
- ...result,
5463
- error: response.error ?? response.errorDetails?.message ?? null
5464
- },
5465
- context
5466
- );
5467
- result.error = createResultError(response, result, normalizedError);
5468
- attachNormalizedError(result, normalizedError);
5469
- return result;
5470
5686
  };
5471
5687
  }
5472
- async function executeExperimentalRead(experimental, runner) {
5473
- if (!experimental?.retryReads) {
5474
- return runner();
5688
+ function planToFindManyTransport(plan) {
5689
+ if (plan.kind === "query") {
5690
+ return {
5691
+ mode: "compiled-query",
5692
+ endpoint: "/gateway/query",
5693
+ payload: plan.payload
5694
+ };
5475
5695
  }
5476
- let lastRetryableResult;
5477
- let lastRetrySignal = null;
5478
- try {
5479
- return await withRetry(
5480
- {
5481
- ...EXPERIMENTAL_READ_RETRY_CONFIG,
5482
- shouldRetry: (error) => error === lastRetrySignal || normalizeAthenaError(error).retryable
5483
- },
5484
- async () => {
5485
- const result = await runner();
5486
- if (result.error?.retryable) {
5487
- lastRetryableResult = result;
5488
- lastRetrySignal = result.error;
5489
- throw lastRetrySignal;
5490
- }
5491
- return result;
5492
- }
5493
- );
5494
- } catch (error) {
5495
- if (lastRetryableResult && error === lastRetrySignal) {
5496
- return lastRetryableResult;
5696
+ return {
5697
+ mode: plan.payload.select !== void 0 ? "structured-fetch" : "compiled-fetch",
5698
+ endpoint: "/gateway/fetch",
5699
+ payload: plan.payload
5700
+ };
5701
+ }
5702
+ function buildInsertDebugAst(payload) {
5703
+ return {
5704
+ version: 1,
5705
+ kind: "insert",
5706
+ tableName: payload.table_name,
5707
+ input: {
5708
+ values: payload.insert_body,
5709
+ returning: payload.columns,
5710
+ count: payload.count,
5711
+ head: payload.head,
5712
+ defaultToNull: payload.default_to_null
5713
+ },
5714
+ transport: {
5715
+ mode: "insert",
5716
+ endpoint: "/gateway/insert",
5717
+ payload
5497
5718
  }
5498
- throw error;
5499
- }
5719
+ };
5500
5720
  }
5501
- function isRecord9(value) {
5502
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
5721
+ function buildUpsertDebugAst(payload) {
5722
+ return {
5723
+ version: 1,
5724
+ kind: "upsert",
5725
+ tableName: payload.table_name,
5726
+ input: {
5727
+ values: payload.insert_body,
5728
+ updateBody: payload.update_body,
5729
+ onConflict: payload.on_conflict,
5730
+ returning: payload.columns,
5731
+ count: payload.count,
5732
+ head: payload.head,
5733
+ defaultToNull: payload.default_to_null
5734
+ },
5735
+ transport: {
5736
+ mode: "upsert",
5737
+ endpoint: "/gateway/insert",
5738
+ payload
5739
+ }
5740
+ };
5503
5741
  }
5504
- function firstNonEmptyString2(...values) {
5505
- for (const value of values) {
5506
- if (typeof value === "string" && value.trim().length > 0) {
5507
- return value.trim();
5742
+ function buildUpdateDebugAst(input) {
5743
+ return {
5744
+ version: 1,
5745
+ kind: "update",
5746
+ tableName: resolveDebugTableName(input.payload.table_name),
5747
+ input: {
5748
+ values: input.payload.set,
5749
+ state: cloneTableBuilderStateAst(input.state),
5750
+ returning: input.payload.columns
5751
+ },
5752
+ transport: {
5753
+ mode: "update",
5754
+ endpoint: "/gateway/update",
5755
+ payload: input.payload
5508
5756
  }
5509
- }
5510
- return void 0;
5757
+ };
5511
5758
  }
5512
- function resolveStructuredErrorPayload2(raw) {
5513
- if (!isRecord9(raw)) return null;
5514
- return isRecord9(raw.error) ? raw.error : raw;
5759
+ function buildDeleteDebugAst(input) {
5760
+ return {
5761
+ version: 1,
5762
+ kind: "delete",
5763
+ tableName: input.payload.table_name,
5764
+ input: {
5765
+ resourceId: input.payload.resource_id,
5766
+ state: cloneTableBuilderStateAst(input.state),
5767
+ returning: input.payload.columns
5768
+ },
5769
+ transport: {
5770
+ mode: "delete",
5771
+ endpoint: "/gateway/delete",
5772
+ payload: input.payload
5773
+ }
5774
+ };
5515
5775
  }
5516
- function resolveStructuredErrorDetails(payload, message) {
5517
- if (!payload || !("details" in payload)) {
5518
- return null;
5776
+ function buildRpcDebugAst(input) {
5777
+ return {
5778
+ version: 1,
5779
+ kind: "rpc",
5780
+ functionName: input.functionName,
5781
+ input: {
5782
+ args: input.args,
5783
+ select: input.selectedColumns,
5784
+ state: cloneRpcBuilderStateAst(input.state)
5785
+ },
5786
+ transport: {
5787
+ mode: input.endpoint === "/gateway/rpc" ? "rpc-post" : "rpc-get",
5788
+ endpoint: input.endpoint,
5789
+ payload: input.payload
5790
+ }
5791
+ };
5792
+ }
5793
+ function buildRawQueryDebugAst(query) {
5794
+ return {
5795
+ version: 1,
5796
+ kind: "query",
5797
+ input: {
5798
+ query
5799
+ },
5800
+ transport: {
5801
+ mode: "raw-query",
5802
+ endpoint: "/gateway/query",
5803
+ payload: {
5804
+ query
5805
+ }
5806
+ }
5807
+ };
5808
+ }
5809
+ function attachAthenaDebugAst(target, ast) {
5810
+ if (!ast) {
5811
+ return;
5519
5812
  }
5520
- const details = payload.details;
5521
- if (details == null) {
5522
- return null;
5813
+ if (!target || typeof target !== "object" && typeof target !== "function") {
5814
+ return;
5523
5815
  }
5524
- if (typeof details === "string" && details.trim() === message.trim()) {
5816
+ Object.defineProperty(target, ATHENA_DEBUG_AST_KEY, {
5817
+ value: ast,
5818
+ enumerable: false,
5819
+ configurable: true,
5820
+ writable: false
5821
+ });
5822
+ }
5823
+ function getAthenaDebugAst(value) {
5824
+ if (!value || typeof value !== "object" && typeof value !== "function") {
5525
5825
  return null;
5526
5826
  }
5527
- return details;
5528
- }
5529
- function createResultError(response, result, normalized) {
5530
- const rawRecord = isRecord9(response.raw) ? response.raw : null;
5531
- const payload = resolveStructuredErrorPayload2(response.raw);
5532
- const message = firstNonEmptyString2(
5533
- response.error,
5534
- payload?.message,
5535
- payload?.error,
5536
- payload?.details,
5537
- response.errorDetails?.message,
5538
- normalized.message
5539
- ) ?? normalized.message;
5540
- const statusText = firstNonEmptyString2(response.statusText, rawRecord?.statusText) ?? null;
5541
- const hint = firstNonEmptyString2(payload?.hint, response.errorDetails?.hint) ?? null;
5542
- const code = firstNonEmptyString2(payload?.code) ?? normalized.code;
5543
- const details = resolveStructuredErrorDetails(payload, message) ?? response.errorDetails?.cause ?? null;
5544
- return {
5545
- message,
5546
- code,
5547
- athenaCode: normalized.code,
5548
- gatewayCode: response.errorDetails?.code ?? null,
5549
- kind: normalized.kind,
5550
- category: normalized.category,
5551
- retryable: normalized.retryable,
5552
- details,
5553
- hint,
5554
- status: result.status,
5555
- statusText,
5556
- constraint: normalized.constraint,
5557
- table: normalized.table,
5558
- operation: normalized.operation,
5559
- endpoint: response.errorDetails?.endpoint,
5560
- method: response.errorDetails?.method,
5561
- requestId: response.errorDetails?.requestId,
5562
- cause: response.errorDetails?.cause,
5563
- raw: result.raw
5564
- };
5827
+ return value[ATHENA_DEBUG_AST_KEY] ?? null;
5565
5828
  }
5829
+
5830
+ // src/query-tracing.ts
5831
+ var QUERY_TRACE_STACK_SKIP_PATTERNS = [
5832
+ "src\\client.ts",
5833
+ "src/client.ts",
5834
+ "src\\query-tracing.ts",
5835
+ "src/query-tracing.ts",
5836
+ "dist\\client.",
5837
+ "dist/client.",
5838
+ "dist\\query-tracing.",
5839
+ "dist/query-tracing.",
5840
+ "node_modules\\@xylex-group\\athena",
5841
+ "node_modules/@xylex-group/athena",
5842
+ "node:internal",
5843
+ "internal/process"
5844
+ ];
5566
5845
  function parseQueryTraceCallsiteFrame(frame) {
5567
5846
  const trimmed = frame.trim();
5568
5847
  if (!trimmed) {
@@ -5667,6 +5946,7 @@ function createQueryTracer(experimental) {
5667
5946
  functionName: context.functionName,
5668
5947
  sql: context.sql,
5669
5948
  payload: context.payload,
5949
+ ast: context.ast,
5670
5950
  options: context.options,
5671
5951
  callsite,
5672
5952
  outcome: {
@@ -5689,6 +5969,7 @@ function createQueryTracer(experimental) {
5689
5969
  functionName: context.functionName,
5690
5970
  sql: context.sql,
5691
5971
  payload: context.payload,
5972
+ ast: context.ast,
5692
5973
  options: context.options,
5693
5974
  callsite,
5694
5975
  thrownError: error
@@ -5697,20 +5978,196 @@ function createQueryTracer(experimental) {
5697
5978
  };
5698
5979
  }
5699
5980
  async function executeWithQueryTrace(tracer, context, runner, callsiteOverride) {
5700
- if (!tracer) {
5701
- return runner();
5702
- }
5703
- const callsite = callsiteOverride ?? tracer.captureCallsite();
5704
- const startedAt = Date.now();
5981
+ const callsite = tracer ? callsiteOverride ?? tracer.captureCallsite() : null;
5982
+ const startedAt = tracer ? Date.now() : 0;
5705
5983
  try {
5706
5984
  const result = await runner();
5707
- tracer.publishSuccess(context, result, Date.now() - startedAt, callsite);
5985
+ attachAthenaDebugAst(result, context.ast);
5986
+ if (tracer) {
5987
+ tracer.publishSuccess(context, result, Date.now() - startedAt, callsite);
5988
+ }
5989
+ return result;
5990
+ } catch (error) {
5991
+ attachAthenaDebugAst(error, context.ast);
5992
+ if (tracer) {
5993
+ tracer.publishFailure(context, error, Date.now() - startedAt, callsite);
5994
+ }
5995
+ throw error;
5996
+ }
5997
+ }
5998
+
5999
+ // src/schema/model-target.ts
6000
+ function normalizeOptionalName(value) {
6001
+ const normalized = value?.trim();
6002
+ return normalized ? normalized : void 0;
6003
+ }
6004
+ function isAthenaModelTarget(value) {
6005
+ if (!value || typeof value !== "object") {
6006
+ return false;
6007
+ }
6008
+ const candidate = value;
6009
+ return Boolean(candidate.meta && Array.isArray(candidate.meta.primaryKey));
6010
+ }
6011
+ function resolveAthenaModelTargetTableName(target, options = {}) {
6012
+ const explicitTableName = normalizeOptionalName(target.meta.tableName);
6013
+ if (explicitTableName) {
6014
+ return explicitTableName;
6015
+ }
6016
+ const schemaName = normalizeOptionalName(target.meta.schema ?? options.fallbackSchema);
6017
+ const modelName = normalizeOptionalName(target.meta.model ?? options.fallbackModel);
6018
+ if (!modelName) {
6019
+ throw new Error(
6020
+ "Athena model target is missing meta.model or meta.tableName. Provide one of those before calling from(model)."
6021
+ );
6022
+ }
6023
+ return schemaName ? `${schemaName}.${modelName}` : modelName;
6024
+ }
6025
+
6026
+ // src/client.ts
6027
+ var DEFAULT_COLUMNS = "*";
6028
+ var SAFE_CAST_PATTERN = /^[a-z_][a-z0-9_]*(?:\[\])?$/i;
6029
+ var ATHENA_NORMALIZED_ERROR_KEY = "__athenaNormalizedError";
6030
+ function formatResult(response) {
6031
+ const result = {
6032
+ data: response.data ?? null,
6033
+ error: null,
6034
+ errorDetails: response.errorDetails ?? null,
6035
+ status: response.status,
6036
+ statusText: response.statusText ?? null,
6037
+ raw: response.raw
6038
+ };
6039
+ if (response.count !== void 0) {
6040
+ result.count = response.count;
6041
+ }
6042
+ return result;
6043
+ }
6044
+ var EXPERIMENTAL_READ_RETRY_CONFIG = {
6045
+ retries: 2,
6046
+ baseDelayMs: 100,
6047
+ maxDelayMs: 1e3,
6048
+ backoff: "exponential",
6049
+ jitter: true
6050
+ };
6051
+ function attachNormalizedError(result, normalizedError) {
6052
+ Object.defineProperty(result, ATHENA_NORMALIZED_ERROR_KEY, {
6053
+ value: normalizedError,
6054
+ enumerable: false,
6055
+ configurable: true,
6056
+ writable: false
6057
+ });
6058
+ }
6059
+ function createResultFormatter(experimental) {
6060
+ return (response, context) => {
6061
+ const result = formatResult(response);
6062
+ if (response.error == null && response.errorDetails == null) {
6063
+ return result;
6064
+ }
6065
+ const normalizedError = normalizeAthenaError(
6066
+ {
6067
+ ...result,
6068
+ error: response.error ?? response.errorDetails?.message ?? null
6069
+ },
6070
+ context
6071
+ );
6072
+ result.error = createResultError(response, result, normalizedError);
6073
+ attachNormalizedError(result, normalizedError);
5708
6074
  return result;
6075
+ };
6076
+ }
6077
+ async function executeExperimentalRead(experimental, runner) {
6078
+ if (!experimental?.retryReads) {
6079
+ return runner();
6080
+ }
6081
+ let lastRetryableResult;
6082
+ let lastRetrySignal = null;
6083
+ try {
6084
+ return await withRetry(
6085
+ {
6086
+ ...EXPERIMENTAL_READ_RETRY_CONFIG,
6087
+ shouldRetry: (error) => error === lastRetrySignal || normalizeAthenaError(error).retryable
6088
+ },
6089
+ async () => {
6090
+ const result = await runner();
6091
+ if (result.error?.retryable) {
6092
+ lastRetryableResult = result;
6093
+ lastRetrySignal = result.error;
6094
+ throw lastRetrySignal;
6095
+ }
6096
+ return result;
6097
+ }
6098
+ );
5709
6099
  } catch (error) {
5710
- tracer.publishFailure(context, error, Date.now() - startedAt, callsite);
6100
+ if (lastRetryableResult && error === lastRetrySignal) {
6101
+ return lastRetryableResult;
6102
+ }
5711
6103
  throw error;
5712
6104
  }
5713
6105
  }
6106
+ function isRecord9(value) {
6107
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
6108
+ }
6109
+ function firstNonEmptyString2(...values) {
6110
+ for (const value of values) {
6111
+ if (typeof value === "string" && value.trim().length > 0) {
6112
+ return value.trim();
6113
+ }
6114
+ }
6115
+ return void 0;
6116
+ }
6117
+ function resolveStructuredErrorPayload2(raw) {
6118
+ if (!isRecord9(raw)) return null;
6119
+ return isRecord9(raw.error) ? raw.error : raw;
6120
+ }
6121
+ function resolveStructuredErrorDetails(payload, message) {
6122
+ if (!payload || !("details" in payload)) {
6123
+ return null;
6124
+ }
6125
+ const details = payload.details;
6126
+ if (details == null) {
6127
+ return null;
6128
+ }
6129
+ if (typeof details === "string" && details.trim() === message.trim()) {
6130
+ return null;
6131
+ }
6132
+ return details;
6133
+ }
6134
+ function createResultError(response, result, normalized) {
6135
+ const rawRecord = isRecord9(response.raw) ? response.raw : null;
6136
+ const payload = resolveStructuredErrorPayload2(response.raw);
6137
+ const message = firstNonEmptyString2(
6138
+ response.error,
6139
+ payload?.message,
6140
+ payload?.error,
6141
+ payload?.details,
6142
+ response.errorDetails?.message,
6143
+ normalized.message
6144
+ ) ?? normalized.message;
6145
+ const statusText = firstNonEmptyString2(response.statusText, rawRecord?.statusText) ?? null;
6146
+ const hint = firstNonEmptyString2(payload?.hint, response.errorDetails?.hint) ?? null;
6147
+ const code = firstNonEmptyString2(payload?.code) ?? normalized.code;
6148
+ const details = resolveStructuredErrorDetails(payload, message) ?? response.errorDetails?.cause ?? null;
6149
+ return {
6150
+ message,
6151
+ code,
6152
+ athenaCode: normalized.code,
6153
+ gatewayCode: response.errorDetails?.code ?? null,
6154
+ kind: normalized.kind,
6155
+ category: normalized.category,
6156
+ retryable: normalized.retryable,
6157
+ details,
6158
+ hint,
6159
+ status: result.status,
6160
+ statusText,
6161
+ constraint: normalized.constraint,
6162
+ table: normalized.table,
6163
+ operation: normalized.operation,
6164
+ endpoint: response.errorDetails?.endpoint,
6165
+ method: response.errorDetails?.method,
6166
+ requestId: response.errorDetails?.requestId,
6167
+ cause: response.errorDetails?.cause,
6168
+ raw: result.raw
6169
+ };
6170
+ }
5714
6171
  function toSingleResult(response) {
5715
6172
  const payload = response.data;
5716
6173
  const singleData = Array.isArray(payload) ? payload.length ? payload[0] : null : payload ?? null;
@@ -5738,6 +6195,15 @@ function asAthenaJsonObject(value) {
5738
6195
  function asAthenaJsonObjectArray(values) {
5739
6196
  return values;
5740
6197
  }
6198
+ function normalizeSelectColumnsInput(columns) {
6199
+ if (columns === void 0) {
6200
+ return void 0;
6201
+ }
6202
+ if (typeof columns === "string") {
6203
+ return columns;
6204
+ }
6205
+ return [...columns];
6206
+ }
5741
6207
  function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS, tracer, initialCallsite) {
5742
6208
  let selectedColumns = defaultColumns === null ? void 0 : defaultColumns;
5743
6209
  let selectedOptions;
@@ -5747,25 +6213,29 @@ function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS, tracer,
5747
6213
  const payloadColumns = columns ?? selectedColumns;
5748
6214
  const payloadOptions = options ?? selectedOptions;
5749
6215
  if (!promise) {
5750
- promise = executor(payloadColumns, payloadOptions, callsiteStore.resolve(callsite));
6216
+ promise = executor(
6217
+ normalizeSelectColumnsInput(payloadColumns),
6218
+ payloadOptions,
6219
+ callsiteStore.resolve(callsite)
6220
+ );
5751
6221
  }
5752
6222
  return promise;
5753
6223
  };
5754
6224
  const mutationQuery = {
5755
- select(columns = selectedColumns, options) {
6225
+ select(columns, options) {
5756
6226
  selectedColumns = columns;
5757
6227
  selectedOptions = options ?? selectedOptions;
5758
6228
  return run(columns, options, captureTraceCallsite(tracer));
5759
6229
  },
5760
- returning(columns = selectedColumns, options) {
6230
+ returning(columns, options) {
5761
6231
  return mutationQuery.select(columns, options);
5762
6232
  },
5763
- single(columns = selectedColumns, options) {
6233
+ single(columns, options) {
5764
6234
  selectedColumns = columns;
5765
6235
  selectedOptions = options ?? selectedOptions;
5766
6236
  return run(columns, options, captureTraceCallsite(tracer)).then(toSingleResult);
5767
6237
  },
5768
- maybeSingle(columns = selectedColumns, options) {
6238
+ maybeSingle(columns, options) {
5769
6239
  return mutationQuery.single(columns, options);
5770
6240
  },
5771
6241
  then(onfulfilled, onrejected) {
@@ -6322,7 +6792,10 @@ function createFilterMethods(state, addCondition, self) {
6322
6792
  }
6323
6793
  function toRpcSelect(columns) {
6324
6794
  if (!columns) return void 0;
6325
- return Array.isArray(columns) ? columns.join(",") : columns;
6795
+ if (typeof columns === "string") {
6796
+ return columns;
6797
+ }
6798
+ return columns.join(",");
6326
6799
  }
6327
6800
  function createRpcFilterMethods(filters, self) {
6328
6801
  const addFilter = (operator, column, value) => {
@@ -6371,7 +6844,7 @@ function createRpcFilterMethods(filters, self) {
6371
6844
  }
6372
6845
  };
6373
6846
  }
6374
- function createRpcBuilder(functionName, args, baseOptions, client, formatGatewayResult, tracer, initialCallsite) {
6847
+ function createRpcBuilder(functionName, args, baseOptions, client, formatGatewayResult, tracer, initialCallsite, debugAstEnabled = false) {
6375
6848
  const state = {
6376
6849
  filters: []
6377
6850
  };
@@ -6381,6 +6854,7 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
6381
6854
  const callsiteStore = createTraceCallsiteStore(tracer, initialCallsite);
6382
6855
  const executeRpc = async (columns, options, callsite) => {
6383
6856
  const mergedOptions = mergeOptions(baseOptions, options);
6857
+ const normalizedSelectedColumns = normalizeSelectColumnsInput(columns);
6384
6858
  const payload = {
6385
6859
  function: functionName,
6386
6860
  args,
@@ -6395,6 +6869,14 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
6395
6869
  };
6396
6870
  const endpoint = mergedOptions?.get ? `/rpc/${functionName}` : "/gateway/rpc";
6397
6871
  const sql = buildRpcDebugSql(payload);
6872
+ const debugAst = debugAstEnabled ? buildRpcDebugAst({
6873
+ functionName,
6874
+ args,
6875
+ selectedColumns: normalizedSelectedColumns,
6876
+ state,
6877
+ payload,
6878
+ endpoint
6879
+ }) : void 0;
6398
6880
  return executeWithQueryTrace(
6399
6881
  tracer,
6400
6882
  {
@@ -6403,6 +6885,7 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
6403
6885
  functionName,
6404
6886
  sql,
6405
6887
  payload,
6888
+ ast: debugAst,
6406
6889
  options: mergedOptions
6407
6890
  },
6408
6891
  async () => {
@@ -6423,7 +6906,7 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
6423
6906
  const builder = {};
6424
6907
  const filterMethods = createRpcFilterMethods(state.filters, builder);
6425
6908
  Object.assign(builder, filterMethods, {
6426
- select(columns = selectedColumns, options) {
6909
+ select(columns, options) {
6427
6910
  selectedColumns = columns;
6428
6911
  selectedOptions = options ?? selectedOptions;
6429
6912
  return run(columns, options, captureTraceCallsite(tracer));
@@ -6468,6 +6951,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6468
6951
  const state = {
6469
6952
  conditions: []
6470
6953
  };
6954
+ const debugAstEnabled = Boolean(experimental?.debugAst);
6471
6955
  const addCondition = (operator, column, value, hints) => {
6472
6956
  const condition = { operator };
6473
6957
  if (column) {
@@ -6511,15 +6995,27 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6511
6995
  addCondition,
6512
6996
  builder
6513
6997
  );
6514
- const runSelect = async (columns = DEFAULT_COLUMNS, options, executionState = snapshotState(), callsite) => {
6998
+ const runSelect = async (columns = DEFAULT_COLUMNS, options, executionState = snapshotState(), callsite, debugAstFactory) => {
6999
+ const runtimeColumns = normalizeSelectColumnsInput(columns) ?? DEFAULT_COLUMNS;
6515
7000
  const resolvedTableName = resolveTableNameForCall(tableName, options?.schema);
6516
7001
  const plan = createSelectTransportPlan({
6517
7002
  tableName: resolvedTableName,
6518
- columns,
7003
+ columns: runtimeColumns,
6519
7004
  state: executionState,
6520
7005
  options,
6521
7006
  buildTypedSelectQuery
6522
7007
  });
7008
+ const debugAst = debugAstEnabled ? debugAstFactory?.({
7009
+ tableName: resolvedTableName,
7010
+ columns: runtimeColumns,
7011
+ executionState,
7012
+ plan
7013
+ }) ?? buildSelectDebugAst({
7014
+ tableName: resolvedTableName,
7015
+ columns: runtimeColumns,
7016
+ state: executionState,
7017
+ plan
7018
+ }) : void 0;
6523
7019
  if (plan.kind === "query") {
6524
7020
  return executeExperimentalRead(
6525
7021
  experimental,
@@ -6531,6 +7027,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6531
7027
  table: resolvedTableName,
6532
7028
  sql: plan.query,
6533
7029
  payload: plan.payload,
7030
+ ast: debugAst,
6534
7031
  options
6535
7032
  },
6536
7033
  async () => {
@@ -6555,6 +7052,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6555
7052
  table: resolvedTableName,
6556
7053
  sql,
6557
7054
  payload: plan.payload,
7055
+ ast: debugAst,
6558
7056
  options
6559
7057
  },
6560
7058
  async () => {
@@ -6568,7 +7066,11 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6568
7066
  const createSelectChain = (columns, options, initialCallsite) => {
6569
7067
  const chain = {};
6570
7068
  const callsiteStore = createTraceCallsiteStore(tracer, initialCallsite);
6571
- const filterMethods2 = createFilterMethods(state, addCondition, chain);
7069
+ const filterMethods2 = createFilterMethods(
7070
+ state,
7071
+ addCondition,
7072
+ chain
7073
+ );
6572
7074
  Object.assign(chain, filterMethods2, {
6573
7075
  async single(cols, opts) {
6574
7076
  const r = await runSelect(
@@ -6655,6 +7157,14 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6655
7157
  limit: executionState.limit,
6656
7158
  order: executionState.order
6657
7159
  });
7160
+ const debugAst = debugAstEnabled ? buildFindManyDirectDebugAst({
7161
+ tableName: resolvedTableName,
7162
+ options,
7163
+ compiledColumns: columns,
7164
+ baseState,
7165
+ executionState,
7166
+ payload
7167
+ }) : void 0;
6658
7168
  return executeExperimentalRead(
6659
7169
  experimental,
6660
7170
  () => executeWithQueryTrace(
@@ -6664,7 +7174,8 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6664
7174
  endpoint: "/gateway/fetch",
6665
7175
  table: resolvedTableName,
6666
7176
  sql,
6667
- payload
7177
+ payload,
7178
+ ast: debugAst
6668
7179
  },
6669
7180
  async () => {
6670
7181
  const response = await client.fetchGateway(
@@ -6680,8 +7191,16 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6680
7191
  columns,
6681
7192
  void 0,
6682
7193
  executionState,
6683
- callsite
6684
- );
7194
+ callsite,
7195
+ debugAstEnabled ? ({ tableName: resolvedTableName, executionState: tracedState, plan }) => buildFindManyCompiledDebugAst({
7196
+ tableName: resolvedTableName,
7197
+ options,
7198
+ compiledColumns: columns,
7199
+ baseState,
7200
+ executionState: tracedState,
7201
+ plan
7202
+ }) : void 0
7203
+ );
6685
7204
  },
6686
7205
  insert(values, options) {
6687
7206
  const mutationCallsite = captureTraceCallsite(tracer);
@@ -6700,6 +7219,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6700
7219
  payload.default_to_null = mergedOptions.defaultToNull;
6701
7220
  }
6702
7221
  const sql = buildInsertDebugSql(payload);
7222
+ const debugAst = debugAstEnabled ? buildInsertDebugAst(payload) : void 0;
6703
7223
  return executeWithQueryTrace(
6704
7224
  tracer,
6705
7225
  {
@@ -6708,6 +7228,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6708
7228
  table: resolvedTableName,
6709
7229
  sql,
6710
7230
  payload,
7231
+ ast: debugAst,
6711
7232
  options: mergedOptions
6712
7233
  },
6713
7234
  async () => {
@@ -6733,6 +7254,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6733
7254
  payload.default_to_null = mergedOptions.defaultToNull;
6734
7255
  }
6735
7256
  const sql = buildInsertDebugSql(payload);
7257
+ const debugAst = debugAstEnabled ? buildInsertDebugAst(payload) : void 0;
6736
7258
  return executeWithQueryTrace(
6737
7259
  tracer,
6738
7260
  {
@@ -6741,6 +7263,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6741
7263
  table: resolvedTableName,
6742
7264
  sql,
6743
7265
  payload,
7266
+ ast: debugAst,
6744
7267
  options: mergedOptions
6745
7268
  },
6746
7269
  async () => {
@@ -6771,6 +7294,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6771
7294
  payload.default_to_null = mergedOptions.defaultToNull;
6772
7295
  }
6773
7296
  const sql = buildInsertDebugSql(payload);
7297
+ const debugAst = debugAstEnabled ? buildUpsertDebugAst(payload) : void 0;
6774
7298
  return executeWithQueryTrace(
6775
7299
  tracer,
6776
7300
  {
@@ -6779,6 +7303,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6779
7303
  table: resolvedTableName,
6780
7304
  sql,
6781
7305
  payload,
7306
+ ast: debugAst,
6782
7307
  options: mergedOptions
6783
7308
  },
6784
7309
  async () => {
@@ -6806,6 +7331,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6806
7331
  payload.default_to_null = mergedOptions.defaultToNull;
6807
7332
  }
6808
7333
  const sql = buildInsertDebugSql(payload);
7334
+ const debugAst = debugAstEnabled ? buildUpsertDebugAst(payload) : void 0;
6809
7335
  return executeWithQueryTrace(
6810
7336
  tracer,
6811
7337
  {
@@ -6814,6 +7340,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6814
7340
  table: resolvedTableName,
6815
7341
  sql,
6816
7342
  payload,
7343
+ ast: debugAst,
6817
7344
  options: mergedOptions
6818
7345
  },
6819
7346
  async () => {
@@ -6828,7 +7355,8 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6828
7355
  update(values, options) {
6829
7356
  const mutationCallsite = captureTraceCallsite(tracer);
6830
7357
  const executeUpdate = async (columns, selectOptions, callsite) => {
6831
- const filters = state.conditions.length ? [...state.conditions] : void 0;
7358
+ const executionState = snapshotState();
7359
+ const filters = executionState.conditions.length ? [...executionState.conditions] : void 0;
6832
7360
  const mergedOptions = mergeOptions(options, selectOptions);
6833
7361
  const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
6834
7362
  const payload = {
@@ -6837,12 +7365,16 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6837
7365
  conditions: filters,
6838
7366
  strip_nulls: mergedOptions?.stripNulls ?? true
6839
7367
  };
6840
- if (state.order) payload.sort_by = state.order;
6841
- if (state.currentPage !== void 0) payload.current_page = state.currentPage;
6842
- if (state.pageSize !== void 0) payload.page_size = state.pageSize;
6843
- if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
7368
+ if (executionState.order) payload.sort_by = executionState.order;
7369
+ if (executionState.currentPage !== void 0) payload.current_page = executionState.currentPage;
7370
+ if (executionState.pageSize !== void 0) payload.page_size = executionState.pageSize;
7371
+ if (executionState.totalPages !== void 0) payload.total_pages = executionState.totalPages;
6844
7372
  if (columns) payload.columns = columns;
6845
7373
  const sql = buildUpdateDebugSql(payload);
7374
+ const debugAst = debugAstEnabled ? buildUpdateDebugAst({
7375
+ state: executionState,
7376
+ payload
7377
+ }) : void 0;
6846
7378
  return executeWithQueryTrace(
6847
7379
  tracer,
6848
7380
  {
@@ -6851,6 +7383,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6851
7383
  table: resolvedTableName,
6852
7384
  sql,
6853
7385
  payload,
7386
+ ast: debugAst,
6854
7387
  options: mergedOptions
6855
7388
  },
6856
7389
  async () => {
@@ -6874,6 +7407,11 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6874
7407
  }
6875
7408
  const mutationCallsite = captureTraceCallsite(tracer);
6876
7409
  const executeDelete = async (columns, selectOptions, callsite) => {
7410
+ const executionState = snapshotState();
7411
+ const debugState = {
7412
+ ...executionState,
7413
+ conditions: filters ? filters.map((condition) => ({ ...condition })) : []
7414
+ };
6877
7415
  const mergedOptions = mergeOptions(options, selectOptions);
6878
7416
  const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
6879
7417
  const payload = {
@@ -6881,12 +7419,16 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6881
7419
  resource_id: resourceId,
6882
7420
  conditions: filters
6883
7421
  };
6884
- if (state.order) payload.sort_by = state.order;
6885
- if (state.currentPage !== void 0) payload.current_page = state.currentPage;
6886
- if (state.pageSize !== void 0) payload.page_size = state.pageSize;
6887
- if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
7422
+ if (executionState.order) payload.sort_by = executionState.order;
7423
+ if (executionState.currentPage !== void 0) payload.current_page = executionState.currentPage;
7424
+ if (executionState.pageSize !== void 0) payload.page_size = executionState.pageSize;
7425
+ if (executionState.totalPages !== void 0) payload.total_pages = executionState.totalPages;
6888
7426
  if (columns) payload.columns = columns;
6889
7427
  const sql = buildDeleteDebugSql(payload);
7428
+ const debugAst = debugAstEnabled ? buildDeleteDebugAst({
7429
+ state: debugState,
7430
+ payload
7431
+ }) : void 0;
6890
7432
  return executeWithQueryTrace(
6891
7433
  tracer,
6892
7434
  {
@@ -6895,6 +7437,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6895
7437
  table: resolvedTableName,
6896
7438
  sql,
6897
7439
  payload,
7440
+ ast: debugAst,
6898
7441
  options: mergedOptions
6899
7442
  },
6900
7443
  async () => {
@@ -6922,6 +7465,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6922
7465
  return builder;
6923
7466
  }
6924
7467
  function createQueryBuilder(client, formatGatewayResult, experimental, tracer) {
7468
+ const debugAstEnabled = Boolean(experimental?.debugAst);
6925
7469
  return async function query(query, options) {
6926
7470
  const normalizedQuery = query.trim();
6927
7471
  if (!normalizedQuery) {
@@ -6938,6 +7482,7 @@ function createQueryBuilder(client, formatGatewayResult, experimental, tracer) {
6938
7482
  endpoint: "/gateway/query",
6939
7483
  sql: normalizedQuery,
6940
7484
  payload,
7485
+ ast: debugAstEnabled ? buildRawQueryDebugAst(normalizedQuery) : void 0,
6941
7486
  options
6942
7487
  },
6943
7488
  async () => {
@@ -6949,6 +7494,63 @@ function createQueryBuilder(client, formatGatewayResult, experimental, tracer) {
6949
7494
  );
6950
7495
  };
6951
7496
  }
7497
+ function resolveClientServiceBaseUrl(value, label) {
7498
+ if (value === void 0 || value === null) {
7499
+ return void 0;
7500
+ }
7501
+ return normalizeAthenaGatewayBaseUrl(value, { label });
7502
+ }
7503
+ function appendServicePath(baseUrl, segment) {
7504
+ const normalizedBaseUrl = normalizeAthenaGatewayBaseUrl(baseUrl, { label: "Athena public base URL" });
7505
+ return `${normalizedBaseUrl}/${segment.replace(/^\/+/, "")}`;
7506
+ }
7507
+ function resolveServiceUrlOverride(value, label) {
7508
+ return resolveClientServiceBaseUrl(value, label);
7509
+ }
7510
+ function resolveServiceUrls(config) {
7511
+ const baseUrl = resolveClientServiceBaseUrl(config.url, "Athena public base URL");
7512
+ return {
7513
+ dbUrl: resolveServiceUrlOverride(config.db?.url, "Athena DB base URL") ?? resolveServiceUrlOverride(config.gateway?.url, "Athena gateway base URL") ?? resolveServiceUrlOverride(config.dbUrl, "Athena DB base URL") ?? resolveServiceUrlOverride(config.gatewayUrl, "Athena gateway base URL") ?? (baseUrl ? appendServicePath(baseUrl, "db") : void 0),
7514
+ authUrl: resolveServiceUrlOverride(config.auth?.url, "Athena auth base URL") ?? resolveServiceUrlOverride(config.auth?.baseUrl, "Athena auth base URL") ?? resolveServiceUrlOverride(config.authUrl, "Athena auth base URL") ?? (baseUrl ? appendServicePath(baseUrl, "auth") : void 0),
7515
+ storageUrl: resolveServiceUrlOverride(config.storage?.url, "Athena storage base URL") ?? resolveServiceUrlOverride(config.storageUrl, "Athena storage base URL") ?? (baseUrl ? appendServicePath(baseUrl, "storage") : void 0)
7516
+ };
7517
+ }
7518
+ function normalizeAuthClientConfig(auth, defaultBaseUrl) {
7519
+ if (!auth && defaultBaseUrl === void 0) {
7520
+ return void 0;
7521
+ }
7522
+ const { url, ...rest } = auth ?? {};
7523
+ const normalized = {
7524
+ ...rest
7525
+ };
7526
+ const resolvedBaseUrl = resolveClientServiceBaseUrl(
7527
+ url ?? rest.baseUrl ?? defaultBaseUrl,
7528
+ "Athena auth base URL"
7529
+ );
7530
+ if (resolvedBaseUrl !== void 0) {
7531
+ normalized.baseUrl = resolvedBaseUrl;
7532
+ }
7533
+ return normalized;
7534
+ }
7535
+ function resolveCreateClientConfig(config) {
7536
+ const resolvedUrls = resolveServiceUrls(config);
7537
+ if (!resolvedUrls.dbUrl) {
7538
+ throw new Error(
7539
+ "Athena DB base URL is required. Pass createClient(url, key) for a unified root, or set db.url / gateway.url / gatewayUrl explicitly."
7540
+ );
7541
+ }
7542
+ return {
7543
+ baseUrl: resolvedUrls.dbUrl,
7544
+ apiKey: config.key,
7545
+ client: config.client,
7546
+ backend: toBackendConfig(config.backend),
7547
+ headers: config.headers,
7548
+ auth: config.auth,
7549
+ authUrl: resolvedUrls.authUrl,
7550
+ storageUrl: resolvedUrls.storageUrl,
7551
+ experimental: config.experimental
7552
+ };
7553
+ }
6952
7554
  function createClientFromConfig(config) {
6953
7555
  const gatewayHeaders = {
6954
7556
  ...config.headers ?? {}
@@ -6965,14 +7567,31 @@ function createClientFromConfig(config) {
6965
7567
  });
6966
7568
  const formatGatewayResult = createResultFormatter(config.experimental);
6967
7569
  const queryTracer = createQueryTracer(config.experimental);
6968
- const auth = createAuthClient(config.auth);
6969
- const from = (table, options) => createTableBuilder(
6970
- resolveTableNameForCall(table, options?.schema),
6971
- gateway,
6972
- formatGatewayResult,
6973
- queryTracer,
6974
- config.experimental
6975
- );
7570
+ const auth = createAuthClient(normalizeAuthClientConfig(config.auth, config.authUrl));
7571
+ function from(tableOrModel, options) {
7572
+ if (isAthenaModelTarget(tableOrModel)) {
7573
+ if (options?.schema !== void 0) {
7574
+ throw new Error(
7575
+ "from(model) does not accept a schema override because the model already defines its target."
7576
+ );
7577
+ }
7578
+ return createTableBuilder(
7579
+ resolveAthenaModelTargetTableName(tableOrModel),
7580
+ gateway,
7581
+ formatGatewayResult,
7582
+ queryTracer,
7583
+ config.experimental
7584
+ );
7585
+ }
7586
+ const resolvedTableName = resolveTableNameForCall(tableOrModel, options?.schema);
7587
+ return createTableBuilder(
7588
+ resolvedTableName,
7589
+ gateway,
7590
+ formatGatewayResult,
7591
+ queryTracer,
7592
+ config.experimental
7593
+ );
7594
+ }
6976
7595
  const rpc = (fn, args, options) => {
6977
7596
  const normalizedFn = fn.trim();
6978
7597
  if (!normalizedFn) {
@@ -6985,10 +7604,16 @@ function createClientFromConfig(config) {
6985
7604
  gateway,
6986
7605
  formatGatewayResult,
6987
7606
  queryTracer,
6988
- captureTraceCallsite(queryTracer)
7607
+ captureTraceCallsite(queryTracer),
7608
+ Boolean(config.experimental?.debugAst)
6989
7609
  );
6990
7610
  };
6991
- const query = createQueryBuilder(gateway, formatGatewayResult, config.experimental, queryTracer);
7611
+ const query = createQueryBuilder(
7612
+ gateway,
7613
+ formatGatewayResult,
7614
+ config.experimental,
7615
+ queryTracer
7616
+ );
6992
7617
  const db = createDbModule({ from, rpc, query });
6993
7618
  const sdkClient = {
6994
7619
  from,
@@ -7001,148 +7626,53 @@ function createClientFromConfig(config) {
7001
7626
  if (config.experimental?.athenaStorageBackend) {
7002
7627
  const storageClient = {
7003
7628
  ...sdkClient,
7004
- storage: createStorageModule(gateway, config.experimental.storage)
7629
+ storage: createStorageModule(gateway, {
7630
+ ...config.experimental.storage,
7631
+ ...config.storageUrl ? {
7632
+ baseUrl: config.storageUrl,
7633
+ stripBasePath: true
7634
+ } : {}
7635
+ })
7005
7636
  };
7006
7637
  return storageClient;
7007
7638
  }
7008
7639
  return sdkClient;
7009
7640
  }
7010
- var DEFAULT_BACKEND = { type: "athena" };
7011
- function toBackendConfig(b) {
7012
- if (!b) return DEFAULT_BACKEND;
7013
- return typeof b === "string" ? { type: b } : b;
7014
- }
7015
- function mergeAuthClientConfig(current, next) {
7016
- const merged = {
7017
- ...current ?? {},
7018
- ...next
7019
- };
7020
- if (current?.headers || next.headers) {
7021
- merged.headers = {
7022
- ...current?.headers ?? {},
7023
- ...next.headers ?? {}
7024
- };
7025
- }
7026
- return merged;
7027
- }
7028
- function mergeExperimentalOptions(current, next) {
7029
- const merged = {
7030
- ...current ?? {},
7031
- ...next
7032
- };
7033
- if (current?.traceQueries && typeof current.traceQueries === "object" && next.traceQueries && typeof next.traceQueries === "object") {
7034
- merged.traceQueries = {
7035
- ...current.traceQueries,
7036
- ...next.traceQueries
7037
- };
7038
- }
7039
- if (current?.storage || next.storage) {
7040
- merged.storage = {
7041
- ...current?.storage ?? {},
7042
- ...next.storage ?? {}
7043
- };
7044
- }
7045
- return merged;
7046
- }
7047
- var AthenaClientBuilderImpl = class {
7048
- baseUrl;
7049
- apiKey;
7050
- backendConfig = DEFAULT_BACKEND;
7051
- clientName;
7052
- defaultHeaders;
7053
- authConfig;
7054
- experimentalOptions;
7055
- url(url) {
7056
- this.baseUrl = url;
7057
- return this;
7058
- }
7059
- key(apiKey) {
7060
- this.apiKey = apiKey;
7061
- return this;
7062
- }
7063
- backend(backend) {
7064
- this.backendConfig = toBackendConfig(backend);
7065
- return this;
7066
- }
7067
- client(clientName) {
7068
- this.clientName = clientName;
7069
- return this;
7070
- }
7071
- headers(headers) {
7072
- this.defaultHeaders = headers;
7073
- return this;
7074
- }
7075
- auth(config) {
7076
- this.authConfig = mergeAuthClientConfig(this.authConfig, config);
7077
- return this;
7078
- }
7079
- experimental(options) {
7080
- this.experimentalOptions = mergeExperimentalOptions(this.experimentalOptions, options);
7081
- return options.athenaStorageBackend ? this : this;
7082
- }
7083
- options(options) {
7084
- if (options.client !== void 0) {
7085
- this.clientName = options.client;
7086
- }
7087
- if (options.backend !== void 0) {
7088
- this.backendConfig = toBackendConfig(options.backend);
7089
- }
7090
- if (options.headers !== void 0) {
7091
- this.defaultHeaders = {
7092
- ...this.defaultHeaders ?? {},
7093
- ...options.headers
7094
- };
7095
- }
7096
- if (options.auth !== void 0) {
7097
- this.authConfig = mergeAuthClientConfig(this.authConfig, options.auth);
7098
- }
7099
- if (options.experimental !== void 0) {
7100
- this.experimentalOptions = mergeExperimentalOptions(this.experimentalOptions, options.experimental);
7101
- }
7102
- return options.experimental?.athenaStorageBackend ? this : this;
7103
- }
7104
- build() {
7105
- if (!this.baseUrl || !this.apiKey) {
7106
- throw new Error("AthenaClient requires url and key; call .url() and .key() before .build()");
7107
- }
7108
- return createClientFromConfig({
7109
- baseUrl: this.baseUrl,
7110
- apiKey: this.apiKey,
7111
- client: this.clientName,
7112
- backend: this.backendConfig,
7113
- headers: this.defaultHeaders,
7114
- auth: this.authConfig,
7115
- experimental: this.experimentalOptions
7116
- });
7117
- }
7118
- };
7119
- var AthenaClient = class _AthenaClient {
7641
+ var AthenaClient = class {
7120
7642
  /** Create a fluent builder for a strongly-typed Athena SDK client. */
7121
7643
  static builder() {
7122
- return new AthenaClientBuilderImpl();
7644
+ return createAthenaClientBuilder((config) => createClientFromConfig(resolveCreateClientConfig(config)));
7123
7645
  }
7124
7646
  /** Build a client from process environment variables. */
7125
7647
  static fromEnvironment() {
7126
- const url = process.env.ATHENA_URL ?? process.env.ATHENA_GATEWAY_URL;
7648
+ const url = process.env.ATHENA_URL;
7649
+ const gatewayUrl = process.env.ATHENA_DB_URL ?? process.env.ATHENA_GATEWAY_URL;
7650
+ const authUrl = process.env.ATHENA_AUTH_URL;
7651
+ const storageUrl = process.env.ATHENA_STORAGE_URL;
7127
7652
  const key = process.env.ATHENA_API_KEY ?? process.env.ATHENA_GATEWAY_API_KEY;
7128
- if (!url || !key) {
7653
+ if (!url && !gatewayUrl || !key) {
7129
7654
  throw new Error(
7130
- "ATHENA_URL and ATHENA_API_KEY (or ATHENA_GATEWAY_URL and ATHENA_GATEWAY_API_KEY) are required"
7655
+ "ATHENA_API_KEY plus ATHENA_URL or ATHENA_GATEWAY_URL (optionally ATHENA_DB_URL, ATHENA_AUTH_URL, ATHENA_STORAGE_URL) are required"
7131
7656
  );
7132
7657
  }
7133
- return _AthenaClient.builder().url(url).key(key).build();
7658
+ return createClient({
7659
+ url,
7660
+ gatewayUrl,
7661
+ authUrl,
7662
+ storageUrl,
7663
+ key
7664
+ });
7134
7665
  }
7135
7666
  };
7136
- function createClient(url, apiKey, options) {
7137
- return createClientFromConfig({
7138
- baseUrl: url,
7139
- apiKey,
7140
- client: options?.client,
7141
- backend: toBackendConfig(options?.backend),
7142
- headers: options?.headers,
7143
- auth: options?.auth,
7144
- experimental: options?.experimental
7145
- });
7667
+ function createClient(configOrUrl, apiKey, options) {
7668
+ if (typeof configOrUrl === "string") {
7669
+ return createClientFromConfig(resolveCreateClientConfig({
7670
+ url: configOrUrl,
7671
+ key: apiKey ?? "",
7672
+ ...options
7673
+ }));
7674
+ }
7675
+ return createClientFromConfig(resolveCreateClientConfig(configOrUrl));
7146
7676
  }
7147
7677
 
7148
7678
  // src/gateway/types.ts
@@ -7167,57 +7697,428 @@ function defineRegistry(databases) {
7167
7697
  return databases;
7168
7698
  }
7169
7699
 
7170
- // src/schema/typed-client.ts
7171
- var TenantHeaderMapper = class {
7172
- constructor(tenantKeyMap) {
7173
- this.tenantKeyMap = tenantKeyMap;
7700
+ // src/schema/model-form.ts
7701
+ function resolveNullishValue(mode) {
7702
+ if (mode === "undefined") return void 0;
7703
+ if (mode === "null") return null;
7704
+ return "";
7705
+ }
7706
+ function isRecord10(value) {
7707
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
7708
+ }
7709
+ function isNullableColumn(model, key) {
7710
+ const nullable = model.meta.nullable;
7711
+ return nullable?.[key] === true;
7712
+ }
7713
+ function toModelFormDefaults(model, values, options) {
7714
+ const source = values;
7715
+ if (!isRecord10(source)) {
7716
+ return {};
7174
7717
  }
7175
- apply(baseHeaders, tenantContext) {
7176
- const headers = {
7177
- ...baseHeaders ?? {}
7178
- };
7179
- for (const [tenantKey, headerName] of Object.entries(this.tenantKeyMap)) {
7180
- const tenantValue = tenantContext[tenantKey];
7181
- if (tenantValue === void 0 || tenantValue === null) {
7182
- continue;
7183
- }
7184
- headers[headerName] = String(tenantValue);
7718
+ const mode = options?.nullishMode ?? "empty-string";
7719
+ const nullishValue = resolveNullishValue(mode);
7720
+ const result = {};
7721
+ for (const [key, value] of Object.entries(source)) {
7722
+ if (value === null && isNullableColumn(model, key)) {
7723
+ result[key] = nullishValue;
7724
+ continue;
7185
7725
  }
7186
- return Object.keys(headers).length > 0 ? headers : void 0;
7187
- }
7188
- };
7189
- var RegistryNavigator = class {
7190
- constructor(registry) {
7191
- this.registry = registry;
7726
+ result[key] = value;
7192
7727
  }
7193
- resolveModel(database, schema, model) {
7194
- const databaseDef = this.registry[database];
7195
- if (!databaseDef) {
7196
- throw new Error(`Unknown database "${database}"`);
7197
- }
7198
- const schemaDef = databaseDef.schemas[schema];
7199
- if (!schemaDef) {
7200
- throw new Error(`Unknown schema "${schema}" in database "${database}"`);
7728
+ return result;
7729
+ }
7730
+ function toModelPayload(model, formValues, options) {
7731
+ const emptyStringAsNull = options?.emptyStringAsNull ?? true;
7732
+ const stripUndefined = options?.stripUndefined ?? true;
7733
+ const result = {};
7734
+ for (const [key, rawValue] of Object.entries(formValues)) {
7735
+ if (rawValue === void 0 && stripUndefined) {
7736
+ continue;
7201
7737
  }
7202
- const modelDef = schemaDef.models[model];
7203
- if (!modelDef) {
7204
- throw new Error(`Unknown model "${model}" in schema "${schema}"`);
7738
+ if (emptyStringAsNull && rawValue === "" && isNullableColumn(model, key)) {
7739
+ result[key] = null;
7740
+ continue;
7205
7741
  }
7206
- return modelDef;
7742
+ result[key] = rawValue;
7207
7743
  }
7208
- resolveTableName(schema, model, modelDef) {
7209
- if (modelDef.meta.tableName) {
7210
- return modelDef.meta.tableName;
7744
+ return result;
7745
+ }
7746
+ function createModelFormAdapter(model) {
7747
+ return {
7748
+ model,
7749
+ toDefaults(values, options) {
7750
+ return toModelFormDefaults(model, values, options);
7751
+ },
7752
+ toInsert(values, options) {
7753
+ return toModelPayload(model, values, options);
7754
+ },
7755
+ toUpdate(values, options) {
7756
+ return toModelPayload(model, values, options);
7757
+ }
7758
+ };
7759
+ }
7760
+
7761
+ // src/schema/table-columns.ts
7762
+ var COLUMN_CONFIG = /* @__PURE__ */ Symbol("athena.column.config");
7763
+ function createColumnBuilder(config) {
7764
+ return {
7765
+ [COLUMN_CONFIG]: config,
7766
+ optional() {
7767
+ return createColumnBuilder({
7768
+ ...config,
7769
+ nullable: true
7770
+ });
7771
+ },
7772
+ from(columnName) {
7773
+ return createColumnBuilder({
7774
+ ...config,
7775
+ columnName
7776
+ });
7777
+ },
7778
+ defaulted() {
7779
+ return createColumnBuilder({
7780
+ ...config,
7781
+ hasDefault: true
7782
+ });
7783
+ },
7784
+ generated() {
7785
+ return createColumnBuilder({
7786
+ ...config,
7787
+ isGenerated: true
7788
+ });
7211
7789
  }
7212
- const schemaName = modelDef.meta.schema ?? schema;
7213
- const modelName = modelDef.meta.model ?? model;
7214
- return `${schemaName}.${modelName}`;
7790
+ };
7791
+ }
7792
+ function isColumnBuilder(value) {
7793
+ return value !== null && typeof value === "object" && COLUMN_CONFIG in value;
7794
+ }
7795
+ function getColumnConfig(column) {
7796
+ return column[COLUMN_CONFIG];
7797
+ }
7798
+ function string() {
7799
+ return createColumnBuilder({
7800
+ kind: "string",
7801
+ nullable: false,
7802
+ hasDefault: false,
7803
+ isGenerated: false
7804
+ });
7805
+ }
7806
+ function number() {
7807
+ return createColumnBuilder({
7808
+ kind: "number",
7809
+ nullable: false,
7810
+ hasDefault: false,
7811
+ isGenerated: false
7812
+ });
7813
+ }
7814
+ function boolean() {
7815
+ return createColumnBuilder({
7816
+ kind: "boolean",
7817
+ nullable: false,
7818
+ hasDefault: false,
7819
+ isGenerated: false
7820
+ });
7821
+ }
7822
+ function json(schema) {
7823
+ return createColumnBuilder({
7824
+ kind: "json",
7825
+ nullable: false,
7826
+ hasDefault: false,
7827
+ isGenerated: false,
7828
+ jsonSchema: schema
7829
+ });
7830
+ }
7831
+ function enumeration(values) {
7832
+ if (values.length === 0) {
7833
+ throw new Error("enumeration() requires at least one value");
7215
7834
  }
7216
- };
7217
- var TypedAthenaClientImpl = class _TypedAthenaClientImpl {
7218
- registry;
7219
- tenantKeyMap;
7220
- tenantContext;
7835
+ return createColumnBuilder({
7836
+ kind: "enumeration",
7837
+ nullable: false,
7838
+ hasDefault: false,
7839
+ isGenerated: false,
7840
+ enumValues: values
7841
+ });
7842
+ }
7843
+
7844
+ // src/schema/table-schemas.ts
7845
+ function isScalarFormKind(kind) {
7846
+ return kind === "string" || kind === "number" || kind === "boolean" || kind === "enumeration";
7847
+ }
7848
+ function createBaseSchema(column) {
7849
+ const config = getColumnConfig(column);
7850
+ switch (config.kind) {
7851
+ case "boolean":
7852
+ return z.boolean();
7853
+ case "number":
7854
+ return z.number();
7855
+ case "json":
7856
+ return config.jsonSchema ?? z.unknown();
7857
+ case "enumeration":
7858
+ if (!config.enumValues || config.enumValues.length === 0) {
7859
+ return z.string();
7860
+ }
7861
+ return z.enum(config.enumValues);
7862
+ case "string":
7863
+ default:
7864
+ return z.string();
7865
+ }
7866
+ }
7867
+ function applyNullable(schema, column) {
7868
+ const config = getColumnConfig(column);
7869
+ return config.nullable ? schema.nullable() : schema;
7870
+ }
7871
+ function applyInsertOptional(schema, column) {
7872
+ const config = getColumnConfig(column);
7873
+ return config.nullable || config.hasDefault ? schema.optional() : schema;
7874
+ }
7875
+ function createFormFieldSchema(column) {
7876
+ const config = getColumnConfig(column);
7877
+ const base = createBaseSchema(column);
7878
+ let schema;
7879
+ if (config.nullable && isScalarFormKind(config.kind)) {
7880
+ schema = z.union([base, z.literal("")]).transform((value) => value === "" ? null : value);
7881
+ } else {
7882
+ schema = applyNullable(base, column);
7883
+ }
7884
+ if (config.nullable || config.hasDefault) {
7885
+ schema = schema.optional();
7886
+ }
7887
+ return schema;
7888
+ }
7889
+ function buildTableSchemaBundle(model, columns) {
7890
+ const rowShape = {};
7891
+ const insertShape = {};
7892
+ const updateShape = {};
7893
+ const formShape = {};
7894
+ for (const [columnName, column] of Object.entries(columns)) {
7895
+ const config = getColumnConfig(column);
7896
+ const base = createBaseSchema(column);
7897
+ rowShape[columnName] = applyNullable(base, column);
7898
+ if (config.isGenerated) {
7899
+ continue;
7900
+ }
7901
+ insertShape[columnName] = applyInsertOptional(applyNullable(base, column), column);
7902
+ updateShape[columnName] = applyNullable(base, column).optional();
7903
+ formShape[columnName] = createFormFieldSchema(column);
7904
+ }
7905
+ const rowSchema = z.object(rowShape);
7906
+ const insertSchema = z.object(insertShape);
7907
+ const updateSchema = z.object(updateShape);
7908
+ const formSchema = z.object(formShape).transform((value) => toModelPayload(model, value));
7909
+ return {
7910
+ row: rowSchema,
7911
+ insert: insertSchema,
7912
+ update: updateSchema,
7913
+ form: formSchema
7914
+ };
7915
+ }
7916
+
7917
+ // src/schema/table-builder.ts
7918
+ function assertColumnRecord(columns) {
7919
+ for (const [columnName, column] of Object.entries(columns)) {
7920
+ if (!isColumnBuilder(column)) {
7921
+ throw new Error(`Invalid column definition for "${columnName}"`);
7922
+ }
7923
+ }
7924
+ }
7925
+ function normalizeMappedNameInput(mappedName) {
7926
+ const normalized = mappedName.trim();
7927
+ if (!normalized) {
7928
+ throw new Error("table.from() requires a non-empty table name");
7929
+ }
7930
+ return normalized;
7931
+ }
7932
+ function normalizeSchemaNameInput(schemaName) {
7933
+ const normalized = schemaName.trim();
7934
+ if (!normalized) {
7935
+ throw new Error("table.schema() requires a non-empty schema name");
7936
+ }
7937
+ if (normalized.includes(".")) {
7938
+ throw new Error(
7939
+ 'table.schema() expects a schema name without dots. Use .schema("schema").from("table") or .from("schema.table").'
7940
+ );
7941
+ }
7942
+ return normalized;
7943
+ }
7944
+ function resolveTableTarget(logicalName, mappedName, explicitSchemaName) {
7945
+ const physicalName = (mappedName ?? logicalName).trim();
7946
+ if (!physicalName) {
7947
+ throw new Error("table() requires a non-empty name");
7948
+ }
7949
+ const firstDot = physicalName.indexOf(".");
7950
+ const lastDot = physicalName.lastIndexOf(".");
7951
+ if (firstDot > 0 && firstDot === lastDot) {
7952
+ const inlineSchema = physicalName.slice(0, firstDot).trim();
7953
+ const inlineModel = physicalName.slice(firstDot + 1).trim();
7954
+ if (!inlineSchema || !inlineModel) {
7955
+ throw new Error('table.from() schema-qualified names must look like "schema.table"');
7956
+ }
7957
+ if (explicitSchemaName && explicitSchemaName !== inlineSchema) {
7958
+ throw new Error(
7959
+ `table schema "${explicitSchemaName}" conflicts with mapped table "${physicalName}"`
7960
+ );
7961
+ }
7962
+ return {
7963
+ schema: explicitSchemaName ?? inlineSchema,
7964
+ model: inlineModel,
7965
+ qualifiedName: `${explicitSchemaName ?? inlineSchema}.${inlineModel}`
7966
+ };
7967
+ }
7968
+ if (explicitSchemaName) {
7969
+ return {
7970
+ schema: explicitSchemaName,
7971
+ model: physicalName,
7972
+ qualifiedName: `${explicitSchemaName}.${physicalName}`
7973
+ };
7974
+ }
7975
+ return {
7976
+ model: physicalName,
7977
+ qualifiedName: physicalName
7978
+ };
7979
+ }
7980
+ function toColumnMetadata(column) {
7981
+ const config = getColumnConfig(column);
7982
+ return {
7983
+ kind: config.kind,
7984
+ columnName: config.columnName,
7985
+ nullable: config.nullable,
7986
+ hasDefault: config.hasDefault,
7987
+ isGenerated: config.isGenerated,
7988
+ enumValues: config.enumValues
7989
+ };
7990
+ }
7991
+ function buildNullableMap(columns) {
7992
+ return Object.fromEntries(
7993
+ Object.entries(columns).map(([columnName, column]) => [columnName, getColumnConfig(column).nullable])
7994
+ );
7995
+ }
7996
+ function buildColumnMetadataMap(columns) {
7997
+ return Object.fromEntries(
7998
+ Object.entries(columns).map(([columnName, column]) => [columnName, toColumnMetadata(column)])
7999
+ );
8000
+ }
8001
+ function finalizeTable(name, mappedName, schemaName, columns, primaryKey) {
8002
+ const target = resolveTableTarget(name, mappedName, schemaName);
8003
+ const model = defineModel({
8004
+ meta: {
8005
+ schema: target.schema,
8006
+ model: target.model,
8007
+ primaryKey: [...primaryKey],
8008
+ nullable: buildNullableMap(columns),
8009
+ columns: buildColumnMetadataMap(columns)
8010
+ }
8011
+ });
8012
+ const schemas = buildTableSchemaBundle(model, columns);
8013
+ return Object.assign(model, {
8014
+ kind: "table",
8015
+ name,
8016
+ mappedName,
8017
+ schemaName: target.schema,
8018
+ tableName: target.model,
8019
+ qualifiedName: target.qualifiedName,
8020
+ columns,
8021
+ schemas
8022
+ });
8023
+ }
8024
+ function createColumnsBuilder(name, mappedName, schemaName, columns) {
8025
+ assertColumnRecord(columns);
8026
+ return {
8027
+ name,
8028
+ mappedName,
8029
+ schemaName,
8030
+ columns,
8031
+ from(tableName) {
8032
+ const normalizedTableName = normalizeMappedNameInput(tableName);
8033
+ resolveTableTarget(name, normalizedTableName, schemaName);
8034
+ return createColumnsBuilder(name, normalizedTableName, schemaName, columns);
8035
+ },
8036
+ schema(nextSchemaName) {
8037
+ const normalizedSchemaName = normalizeSchemaNameInput(nextSchemaName);
8038
+ resolveTableTarget(name, mappedName, normalizedSchemaName);
8039
+ return createColumnsBuilder(name, mappedName, normalizedSchemaName, columns);
8040
+ },
8041
+ primaryKey(...keys) {
8042
+ return finalizeTable(name, mappedName, schemaName, columns, keys);
8043
+ }
8044
+ };
8045
+ }
8046
+ function createTableBuilder2(name, mappedName, schemaName) {
8047
+ return {
8048
+ name,
8049
+ mappedName,
8050
+ schemaName,
8051
+ from(tableName) {
8052
+ const normalizedTableName = normalizeMappedNameInput(tableName);
8053
+ resolveTableTarget(name, normalizedTableName, schemaName);
8054
+ return createTableBuilder2(name, normalizedTableName, schemaName);
8055
+ },
8056
+ schema(nextSchemaName) {
8057
+ const normalizedSchemaName = normalizeSchemaNameInput(nextSchemaName);
8058
+ resolveTableTarget(name, mappedName, normalizedSchemaName);
8059
+ return createTableBuilder2(name, mappedName, normalizedSchemaName);
8060
+ },
8061
+ columns(columns) {
8062
+ return createColumnsBuilder(name, mappedName, schemaName, columns);
8063
+ }
8064
+ };
8065
+ }
8066
+ function table(name) {
8067
+ if (!name.trim()) {
8068
+ throw new Error("table() requires a non-empty name");
8069
+ }
8070
+ return createTableBuilder2(name, void 0, void 0);
8071
+ }
8072
+
8073
+ // src/schema/typed-client.ts
8074
+ var TenantHeaderMapper = class {
8075
+ constructor(tenantKeyMap) {
8076
+ this.tenantKeyMap = tenantKeyMap;
8077
+ }
8078
+ apply(baseHeaders, tenantContext) {
8079
+ const headers = {
8080
+ ...baseHeaders ?? {}
8081
+ };
8082
+ for (const [tenantKey, headerName] of Object.entries(this.tenantKeyMap)) {
8083
+ const tenantValue = tenantContext[tenantKey];
8084
+ if (tenantValue === void 0 || tenantValue === null) {
8085
+ continue;
8086
+ }
8087
+ headers[headerName] = String(tenantValue);
8088
+ }
8089
+ return Object.keys(headers).length > 0 ? headers : void 0;
8090
+ }
8091
+ };
8092
+ var RegistryNavigator = class {
8093
+ constructor(registry) {
8094
+ this.registry = registry;
8095
+ }
8096
+ resolveModel(database, schema, model) {
8097
+ const databaseDef = this.registry[database];
8098
+ if (!databaseDef) {
8099
+ throw new Error(`Unknown database "${database}"`);
8100
+ }
8101
+ const schemaDef = databaseDef.schemas[schema];
8102
+ if (!schemaDef) {
8103
+ throw new Error(`Unknown schema "${schema}" in database "${database}"`);
8104
+ }
8105
+ const modelDef = schemaDef.models[model];
8106
+ if (!modelDef) {
8107
+ throw new Error(`Unknown model "${model}" in schema "${schema}"`);
8108
+ }
8109
+ return modelDef;
8110
+ }
8111
+ resolveTableName(schema, model, modelDef) {
8112
+ return resolveAthenaModelTargetTableName(modelDef, {
8113
+ fallbackSchema: schema,
8114
+ fallbackModel: model
8115
+ });
8116
+ }
8117
+ };
8118
+ var TypedAthenaClientImpl = class _TypedAthenaClientImpl {
8119
+ registry;
8120
+ tenantKeyMap;
8121
+ tenantContext;
7221
8122
  db;
7222
8123
  baseClient;
7223
8124
  registryNavigator;
@@ -7238,17 +8139,20 @@ var TypedAthenaClientImpl = class _TypedAthenaClientImpl {
7238
8139
  this.clientOptions = {
7239
8140
  backend: input.options?.backend,
7240
8141
  client: input.options?.client,
7241
- headers: input.options?.headers
8142
+ headers: input.options?.headers,
8143
+ experimental: input.options?.experimental
7242
8144
  };
7243
8145
  this.baseClient = createClient(this.url, this.apiKey, {
7244
8146
  backend: this.clientOptions.backend,
7245
8147
  client: this.clientOptions.client,
7246
- headers: this.tenantHeaderMapper.apply(this.clientOptions.headers, tenantContext)
8148
+ headers: this.tenantHeaderMapper.apply(this.clientOptions.headers, tenantContext),
8149
+ experimental: this.clientOptions.experimental
7247
8150
  });
7248
8151
  this.db = this.baseClient.db;
7249
8152
  }
7250
- from(table, options) {
7251
- return this.baseClient.from(table, options);
8153
+ from(tableOrModel, options) {
8154
+ const from = this.baseClient.from;
8155
+ return from(tableOrModel, options);
7252
8156
  }
7253
8157
  rpc(fn, args, options) {
7254
8158
  return this.baseClient.rpc(fn, args, options);
@@ -7270,7 +8174,8 @@ var TypedAthenaClientImpl = class _TypedAthenaClientImpl {
7270
8174
  tenantContext: {
7271
8175
  ...this.tenantContext,
7272
8176
  ...context ?? {}
7273
- }
8177
+ },
8178
+ experimental: this.clientOptions.experimental
7274
8179
  }
7275
8180
  });
7276
8181
  }
@@ -7376,8 +8281,8 @@ var POSTGRES_CATALOG_SQL = {
7376
8281
  ORDER BY sn.nspname, sc.relname, con.conname;
7377
8282
  `
7378
8283
  };
7379
- function tableKey(schema, table) {
7380
- return `${schema}.${table}`;
8284
+ function tableKey(schema, table2) {
8285
+ return `${schema}.${table2}`;
7381
8286
  }
7382
8287
  function relationKey(...parts) {
7383
8288
  const base = parts.join("_").replace(/[^A-Za-z0-9_]+/g, "_").replace(/^_+|_+$/g, "");
@@ -7488,8 +8393,8 @@ var PostgresCatalogSnapshotAssembler = class {
7488
8393
  schemas = {};
7489
8394
  addColumnRows(columnRows, enumMap) {
7490
8395
  for (const row of columnRows) {
7491
- const table = this.ensureTable(row.schema_name, row.table_name);
7492
- table.columns[row.column_name] = {
8396
+ const table2 = this.ensureTable(row.schema_name, row.table_name);
8397
+ table2.columns[row.column_name] = {
7493
8398
  name: row.column_name,
7494
8399
  dataType: row.data_type,
7495
8400
  udtName: row.udt_name,
@@ -7505,12 +8410,12 @@ var PostgresCatalogSnapshotAssembler = class {
7505
8410
  }
7506
8411
  addPrimaryKeyRows(primaryKeyRows) {
7507
8412
  for (const row of primaryKeyRows) {
7508
- const table = this.ensureTable(row.schema_name, row.table_name);
8413
+ const table2 = this.ensureTable(row.schema_name, row.table_name);
7509
8414
  const primaryKeyColumns = coerceStringArray(row.columns);
7510
8415
  row.columns = primaryKeyColumns;
7511
- table.primaryKey = primaryKeyColumns;
8416
+ table2.primaryKey = primaryKeyColumns;
7512
8417
  for (const columnName of primaryKeyColumns) {
7513
- const column = table.columns[columnName];
8418
+ const column = table2.columns[columnName];
7514
8419
  if (column) {
7515
8420
  column.isPrimaryKey = true;
7516
8421
  }
@@ -7626,14 +8531,14 @@ var PostgresCatalogSnapshotAssembler = class {
7626
8531
  }
7627
8532
  return schema.tables[tableName];
7628
8533
  }
7629
- upsertRelation(table, baseKey, relation) {
8534
+ upsertRelation(table2, baseKey, relation) {
7630
8535
  let key = baseKey;
7631
8536
  let suffix = 2;
7632
- while (table.relations[key]) {
8537
+ while (table2.relations[key]) {
7633
8538
  key = `${baseKey}_${suffix}`;
7634
8539
  suffix += 1;
7635
8540
  }
7636
- table.relations[key] = relation;
8541
+ table2.relations[key] = relation;
7637
8542
  }
7638
8543
  };
7639
8544
 
@@ -7724,67 +8629,6 @@ function createPostgresIntrospectionProvider(options) {
7724
8629
  return new PostgresIntrospectionProvider(options);
7725
8630
  }
7726
8631
 
7727
- // src/schema/model-form.ts
7728
- function resolveNullishValue(mode) {
7729
- if (mode === "undefined") return void 0;
7730
- if (mode === "null") return null;
7731
- return "";
7732
- }
7733
- function isRecord10(value) {
7734
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
7735
- }
7736
- function isNullableColumn(model, key) {
7737
- const nullable = model.meta.nullable;
7738
- return nullable?.[key] === true;
7739
- }
7740
- function toModelFormDefaults(model, values, options) {
7741
- const source = values;
7742
- if (!isRecord10(source)) {
7743
- return {};
7744
- }
7745
- const mode = options?.nullishMode ?? "empty-string";
7746
- const nullishValue = resolveNullishValue(mode);
7747
- const result = {};
7748
- for (const [key, value] of Object.entries(source)) {
7749
- if (value === null && isNullableColumn(model, key)) {
7750
- result[key] = nullishValue;
7751
- continue;
7752
- }
7753
- result[key] = value;
7754
- }
7755
- return result;
7756
- }
7757
- function toModelPayload(model, formValues, options) {
7758
- const emptyStringAsNull = options?.emptyStringAsNull ?? true;
7759
- const stripUndefined = options?.stripUndefined ?? true;
7760
- const result = {};
7761
- for (const [key, rawValue] of Object.entries(formValues)) {
7762
- if (rawValue === void 0 && stripUndefined) {
7763
- continue;
7764
- }
7765
- if (emptyStringAsNull && rawValue === "" && isNullableColumn(model, key)) {
7766
- result[key] = null;
7767
- continue;
7768
- }
7769
- result[key] = rawValue;
7770
- }
7771
- return result;
7772
- }
7773
- function createModelFormAdapter(model) {
7774
- return {
7775
- model,
7776
- toDefaults(values, options) {
7777
- return toModelFormDefaults(model, values, options);
7778
- },
7779
- toInsert(values, options) {
7780
- return toModelPayload(model, values, options);
7781
- },
7782
- toUpdate(values, options) {
7783
- return toModelPayload(model, values, options);
7784
- }
7785
- };
7786
- }
7787
-
7788
8632
  // src/generator/schema-selection.ts
7789
8633
  var DEFAULT_POSTGRES_SCHEMAS = ["public"];
7790
8634
  function collectSchemaNames(input) {
@@ -7830,6 +8674,7 @@ var DEFAULT_TARGETS = {
7830
8674
  database: "athena/relations.ts",
7831
8675
  registry: "athena/config.ts"
7832
8676
  };
8677
+ var DEFAULT_OUTPUT_FORMAT = "define-model";
7833
8678
  var DEFAULT_NAMING = {
7834
8679
  modelType: "pascal",
7835
8680
  modelConst: "camel",
@@ -7845,6 +8690,9 @@ var DEFAULT_EXPERIMENTAL_FLAGS = {
7845
8690
  postgresGatewayIntrospection: false,
7846
8691
  scyllaProviderContracts: true
7847
8692
  };
8693
+ var DEFAULT_INTERNAL_CONFIG = {
8694
+ schemaVersion: 1
8695
+ };
7848
8696
  var PROJECT_ENV_FILENAMES = [".env", ".env.local"];
7849
8697
  var DIRECT_CONNECTION_STRING_ENV_KEYS = [
7850
8698
  "ATHENA_GENERATOR_PG_URL",
@@ -7861,6 +8709,27 @@ var GATEWAY_API_KEY_ENV_KEYS = [
7861
8709
  "ATHENA_GATEWAY_API_KEY",
7862
8710
  "ATHENA_GENERATOR_API_KEY"
7863
8711
  ];
8712
+ var GENERATOR_SCHEMA_ENV_KEYS = ["ATHENA_GENERATOR_SCHEMAS"];
8713
+ var OUTPUT_FORMAT_ENV_KEYS = ["ATHENA_GENERATOR_OUTPUT_FORMAT"];
8714
+ var MODEL_TARGET_ENV_KEYS = ["ATHENA_GENERATOR_MODEL_TARGET"];
8715
+ var SCHEMA_TARGET_ENV_KEYS = ["ATHENA_GENERATOR_SCHEMA_TARGET"];
8716
+ var DATABASE_TARGET_ENV_KEYS = ["ATHENA_GENERATOR_DATABASE_TARGET"];
8717
+ var REGISTRY_TARGET_ENV_KEYS = ["ATHENA_GENERATOR_REGISTRY_TARGET"];
8718
+ var PLACEHOLDER_MAP_ENV_KEYS = ["ATHENA_GENERATOR_PLACEHOLDER_MAP"];
8719
+ var MODEL_TYPE_ENV_KEYS = ["ATHENA_GENERATOR_MODEL_TYPE", "ATHENA_GENERATOR_MODEL_STYLE"];
8720
+ var MODEL_CONST_ENV_KEYS = ["ATHENA_GENERATOR_MODEL_CONST"];
8721
+ var SCHEMA_CONST_ENV_KEYS = ["ATHENA_GENERATOR_SCHEMA_CONST"];
8722
+ var DATABASE_CONST_ENV_KEYS = ["ATHENA_GENERATOR_DATABASE_CONST"];
8723
+ var REGISTRY_CONST_ENV_KEYS = ["ATHENA_GENERATOR_REGISTRY_CONST"];
8724
+ var EMIT_RELATIONS_ENV_KEYS = ["ATHENA_GENERATOR_EMIT_RELATIONS"];
8725
+ var EMIT_REGISTRY_ENV_KEYS = ["ATHENA_GENERATOR_EMIT_REGISTRY"];
8726
+ var GATEWAY_BACKEND_ENV_KEYS = ["ATHENA_GENERATOR_BACKEND"];
8727
+ var GATEWAY_EXPERIMENTAL_ENV_KEYS = ["ATHENA_GENERATOR_GATEWAY_EXPERIMENTAL"];
8728
+ var SCYLLA_PROVIDER_CONTRACTS_ENV_KEYS = ["ATHENA_GENERATOR_SCYLLA_PROVIDER_CONTRACTS"];
8729
+ var ENV_ONLY_CONFIG_PATH = "[environment defaults]";
8730
+ var NAMING_STYLE_VALUES = ["preserve", "camel", "pascal", "snake", "kebab"];
8731
+ var OUTPUT_FORMAT_VALUES = ["define-model", "table-builder"];
8732
+ var BACKEND_TYPE_VALUES = ["athena", "postgrest", "postgresql", "scylladb"];
7864
8733
  function normalizeRawEnvValue(rawValue) {
7865
8734
  if (rawValue.startsWith('"') && rawValue.endsWith('"') && rawValue.length >= 2) {
7866
8735
  const inner = rawValue.slice(1, -1);
@@ -7952,6 +8821,50 @@ function resolveFallbackValue(fallbackKeys) {
7952
8821
  }
7953
8822
  return void 0;
7954
8823
  }
8824
+ function normalizeOneOfValue(rawValue, allowedValues, envKeys) {
8825
+ if (!rawValue) {
8826
+ return void 0;
8827
+ }
8828
+ if (allowedValues.includes(rawValue)) {
8829
+ return rawValue;
8830
+ }
8831
+ throw new Error(
8832
+ `Generator config env vars ${envKeys.join(", ")} must resolve to one of: ${allowedValues.join(", ")}. Received: ${rawValue}.`
8833
+ );
8834
+ }
8835
+ function resolveOptionalOneOf(envKeys, allowedValues) {
8836
+ return normalizeOneOfValue(resolveFallbackValue(envKeys), allowedValues, envKeys);
8837
+ }
8838
+ function resolveOptionalBoolean(envKeys) {
8839
+ const rawValue = resolveFallbackValue(envKeys);
8840
+ return rawValue === void 0 ? void 0 : parseBooleanFlag2(rawValue, false);
8841
+ }
8842
+ function resolveOptionalJson(envKeys) {
8843
+ const rawValue = resolveFallbackValue(envKeys);
8844
+ if (rawValue === void 0) {
8845
+ return void 0;
8846
+ }
8847
+ try {
8848
+ return JSON.parse(rawValue);
8849
+ } catch (error) {
8850
+ const message = error instanceof Error ? error.message : String(error);
8851
+ throw new Error(
8852
+ `Generator config env vars ${envKeys.join(", ")} must contain valid JSON. ${message}`
8853
+ );
8854
+ }
8855
+ }
8856
+ function deriveDatabaseNameFromConnectionString(connectionString) {
8857
+ try {
8858
+ const parsedUrl = new URL(connectionString);
8859
+ if (!POSTGRES_PROTOCOLS.has(parsedUrl.protocol)) {
8860
+ return void 0;
8861
+ }
8862
+ const pathname = parsedUrl.pathname.replace(/^\/+/, "").trim();
8863
+ return pathname.length > 0 ? decodeURIComponent(pathname) : void 0;
8864
+ } catch {
8865
+ return void 0;
8866
+ }
8867
+ }
7955
8868
  function normalizeOptionalString(value, fallbackKeys) {
7956
8869
  if (typeof value === "string") {
7957
8870
  const trimmed = value.trim();
@@ -8025,12 +8938,13 @@ function normalizeExperimentalFlags(input) {
8025
8938
  }
8026
8939
  function normalizeOutputConfig(output) {
8027
8940
  return {
8941
+ format: output?.format ?? DEFAULT_OUTPUT_FORMAT,
8028
8942
  targets: {
8029
8943
  ...DEFAULT_TARGETS,
8030
- ...output.targets ?? {}
8944
+ ...output?.targets ?? {}
8031
8945
  },
8032
8946
  placeholderMap: {
8033
- ...output.placeholderMap ?? {}
8947
+ ...output?.placeholderMap ?? {}
8034
8948
  }
8035
8949
  };
8036
8950
  }
@@ -8041,7 +8955,7 @@ function normalizeProviderConfig(provider) {
8041
8955
  "provider.connectionString",
8042
8956
  DIRECT_CONNECTION_STRING_ENV_KEYS
8043
8957
  );
8044
- const database = normalizeOptionalString(provider.database, POSTGRES_DATABASE_ENV_KEYS);
8958
+ const database = normalizeOptionalString(provider.database, POSTGRES_DATABASE_ENV_KEYS) ?? deriveDatabaseNameFromConnectionString(connectionString);
8045
8959
  return {
8046
8960
  ...provider,
8047
8961
  connectionString: applyPostgresPasswordFallback(connectionString),
@@ -8060,11 +8974,7 @@ function normalizeProviderConfig(provider) {
8060
8974
  "provider.apiKey",
8061
8975
  GATEWAY_API_KEY_ENV_KEYS
8062
8976
  );
8063
- const database = normalizeRequiredString(
8064
- provider.database,
8065
- "provider.database",
8066
- POSTGRES_DATABASE_ENV_KEYS
8067
- );
8977
+ const database = normalizeOptionalString(provider.database, POSTGRES_DATABASE_ENV_KEYS) ?? "postgres";
8068
8978
  return {
8069
8979
  ...provider,
8070
8980
  gatewayUrl,
@@ -8073,6 +8983,26 @@ function normalizeProviderConfig(provider) {
8073
8983
  schemas: normalizeSchemaSelection(provider.schemas)
8074
8984
  };
8075
8985
  }
8986
+ if (provider.kind === "scylla" && provider.mode === "direct") {
8987
+ if (!provider.contactPoints?.length) {
8988
+ throw new Error(
8989
+ "Generator config is missing provider.contactPoints for scylla direct mode."
8990
+ );
8991
+ }
8992
+ const keyspace = normalizeOptionalString(provider.keyspace, []);
8993
+ if (!keyspace) {
8994
+ throw new Error(
8995
+ "Generator config is missing provider.keyspace for scylla direct mode."
8996
+ );
8997
+ }
8998
+ return {
8999
+ kind: "scylla",
9000
+ mode: "direct",
9001
+ contactPoints: provider.contactPoints.slice(),
9002
+ keyspace,
9003
+ datacenter: normalizeOptionalString(provider.datacenter, [])
9004
+ };
9005
+ }
8076
9006
  return provider;
8077
9007
  }
8078
9008
  function isAthenaGeneratorConfig(value) {
@@ -8080,7 +9010,7 @@ function isAthenaGeneratorConfig(value) {
8080
9010
  return false;
8081
9011
  }
8082
9012
  const record = value;
8083
- return Boolean(record.provider && typeof record.provider === "object") && Boolean(record.output && typeof record.output === "object");
9013
+ return Boolean(record.provider && typeof record.provider === "object") && (record.output === void 0 || typeof record.output === "object");
8084
9014
  }
8085
9015
  function normalizeGeneratorConfig(input) {
8086
9016
  return {
@@ -8091,7 +9021,10 @@ function normalizeGeneratorConfig(input) {
8091
9021
  ...input.naming ?? {}
8092
9022
  },
8093
9023
  features: normalizeFeatureFlags(input.features),
8094
- experimental: normalizeExperimentalFlags(input.experimental)
9024
+ experimental: normalizeExperimentalFlags(input.experimental),
9025
+ internal: {
9026
+ ...DEFAULT_INTERNAL_CONFIG
9027
+ }
8095
9028
  };
8096
9029
  }
8097
9030
  function defineGeneratorConfig(config) {
@@ -8148,44 +9081,151 @@ function importConfigModule(moduleSpecifier) {
8148
9081
  );
8149
9082
  return runtimeImport(moduleSpecifier);
8150
9083
  }
8151
- async function loadGeneratorConfig(options = {}) {
8152
- const cwd = options.cwd ?? process.cwd();
8153
- const restoreProjectEnv = applyProjectEnv(cwd);
8154
- const resolvedPath = options.configPath ? resolve(cwd, options.configPath) : findGeneratorConfigPath(cwd);
8155
- if (!resolvedPath) {
8156
- throw new Error(
8157
- `No generator config found in ${cwd}. Expected one of: ${DEFAULT_CONFIG_CANDIDATES.join(", ")}`
8158
- );
8159
- }
8160
- try {
8161
- const moduleUrl = pathToFileURL(resolvedPath);
8162
- const module = await importConfigModule(`${moduleUrl.href}?cacheBust=${Date.now()}`);
8163
- const rawConfig = extractConfigExport(module);
8164
- return {
8165
- configPath: resolvedPath,
8166
- config: normalizeGeneratorConfig(rawConfig)
8167
- };
8168
- } finally {
8169
- restoreProjectEnv();
9084
+ function buildEnvironmentOutputConfig() {
9085
+ const format = resolveOptionalOneOf(OUTPUT_FORMAT_ENV_KEYS, OUTPUT_FORMAT_VALUES);
9086
+ const modelTarget = resolveFallbackValue(MODEL_TARGET_ENV_KEYS);
9087
+ const schemaTarget = resolveFallbackValue(SCHEMA_TARGET_ENV_KEYS);
9088
+ const databaseTarget = resolveFallbackValue(DATABASE_TARGET_ENV_KEYS);
9089
+ const registryTarget = resolveFallbackValue(REGISTRY_TARGET_ENV_KEYS);
9090
+ const placeholderMap = resolveOptionalJson(PLACEHOLDER_MAP_ENV_KEYS);
9091
+ if (format === void 0 && modelTarget === void 0 && schemaTarget === void 0 && databaseTarget === void 0 && registryTarget === void 0 && placeholderMap === void 0) {
9092
+ return void 0;
8170
9093
  }
9094
+ return {
9095
+ format,
9096
+ targets: {
9097
+ ...modelTarget ? { model: modelTarget } : {},
9098
+ ...schemaTarget ? { schema: schemaTarget } : {},
9099
+ ...databaseTarget ? { database: databaseTarget } : {},
9100
+ ...registryTarget ? { registry: registryTarget } : {}
9101
+ },
9102
+ placeholderMap
9103
+ };
8171
9104
  }
8172
-
8173
- // src/generator/env.ts
8174
- function readEnvStringValue2(key) {
8175
- if (typeof process === "undefined" || !process.env) {
9105
+ function buildEnvironmentNamingConfig() {
9106
+ const modelType = resolveOptionalOneOf(MODEL_TYPE_ENV_KEYS, NAMING_STYLE_VALUES);
9107
+ const modelConst = resolveOptionalOneOf(MODEL_CONST_ENV_KEYS, NAMING_STYLE_VALUES);
9108
+ const schemaConst = resolveOptionalOneOf(SCHEMA_CONST_ENV_KEYS, NAMING_STYLE_VALUES);
9109
+ const databaseConst = resolveOptionalOneOf(DATABASE_CONST_ENV_KEYS, NAMING_STYLE_VALUES);
9110
+ const registryConst = resolveOptionalOneOf(REGISTRY_CONST_ENV_KEYS, NAMING_STYLE_VALUES);
9111
+ if (modelType === void 0 && modelConst === void 0 && schemaConst === void 0 && databaseConst === void 0 && registryConst === void 0) {
8176
9112
  return void 0;
8177
9113
  }
8178
- const value = process.env[key];
8179
- if (typeof value !== "string") {
9114
+ return {
9115
+ ...modelType ? { modelType } : {},
9116
+ ...modelConst ? { modelConst } : {},
9117
+ ...schemaConst ? { schemaConst } : {},
9118
+ ...databaseConst ? { databaseConst } : {},
9119
+ ...registryConst ? { registryConst } : {}
9120
+ };
9121
+ }
9122
+ function buildEnvironmentFeatureFlags() {
9123
+ const emitRelations = resolveOptionalBoolean(EMIT_RELATIONS_ENV_KEYS);
9124
+ const emitRegistry = resolveOptionalBoolean(EMIT_REGISTRY_ENV_KEYS);
9125
+ if (emitRelations === void 0 && emitRegistry === void 0) {
8180
9126
  return void 0;
8181
9127
  }
8182
- const trimmed = value.trim();
8183
- return trimmed.length > 0 ? trimmed : void 0;
9128
+ return {
9129
+ ...emitRelations !== void 0 ? { emitRelations } : {},
9130
+ ...emitRegistry !== void 0 ? { emitRegistry } : {}
9131
+ };
8184
9132
  }
8185
- function throwMissingEnvVar(key) {
8186
- throw new Error(
8187
- `Generator config env var ${key} is missing or empty. Set ${key} or provide a default value.`
8188
- );
9133
+ function buildEnvironmentExperimentalFlags() {
9134
+ const postgresGatewayIntrospection = resolveOptionalBoolean(GATEWAY_EXPERIMENTAL_ENV_KEYS);
9135
+ const scyllaProviderContracts = resolveOptionalBoolean(SCYLLA_PROVIDER_CONTRACTS_ENV_KEYS);
9136
+ if (postgresGatewayIntrospection === void 0 && scyllaProviderContracts === void 0) {
9137
+ return void 0;
9138
+ }
9139
+ return {
9140
+ ...postgresGatewayIntrospection !== void 0 ? { postgresGatewayIntrospection } : {},
9141
+ ...scyllaProviderContracts !== void 0 ? { scyllaProviderContracts } : {}
9142
+ };
9143
+ }
9144
+ function buildEnvironmentProviderConfig() {
9145
+ const directConnectionString = resolveFallbackValue(DIRECT_CONNECTION_STRING_ENV_KEYS);
9146
+ if (directConnectionString) {
9147
+ return {
9148
+ kind: "postgres",
9149
+ mode: "direct",
9150
+ connectionString: directConnectionString,
9151
+ database: normalizeOptionalString(void 0, POSTGRES_DATABASE_ENV_KEYS),
9152
+ schemas: normalizeSchemaSelection(resolveFallbackValue(GENERATOR_SCHEMA_ENV_KEYS))
9153
+ };
9154
+ }
9155
+ const gatewayUrl = resolveFallbackValue(GATEWAY_URL_ENV_KEYS);
9156
+ const apiKey = resolveFallbackValue(GATEWAY_API_KEY_ENV_KEYS);
9157
+ if (gatewayUrl && apiKey) {
9158
+ const backend = resolveOptionalOneOf(GATEWAY_BACKEND_ENV_KEYS, BACKEND_TYPE_VALUES);
9159
+ return {
9160
+ kind: "postgres",
9161
+ mode: "gateway",
9162
+ gatewayUrl,
9163
+ apiKey,
9164
+ database: normalizeOptionalString(void 0, POSTGRES_DATABASE_ENV_KEYS),
9165
+ schemas: normalizeSchemaSelection(resolveFallbackValue(GENERATOR_SCHEMA_ENV_KEYS)),
9166
+ backend
9167
+ };
9168
+ }
9169
+ return void 0;
9170
+ }
9171
+ function createEnvironmentGeneratorConfig() {
9172
+ const provider = buildEnvironmentProviderConfig();
9173
+ if (!provider) {
9174
+ return void 0;
9175
+ }
9176
+ return {
9177
+ provider,
9178
+ output: buildEnvironmentOutputConfig(),
9179
+ naming: buildEnvironmentNamingConfig(),
9180
+ features: buildEnvironmentFeatureFlags(),
9181
+ experimental: buildEnvironmentExperimentalFlags()
9182
+ };
9183
+ }
9184
+ async function loadGeneratorConfig(options = {}) {
9185
+ const cwd = options.cwd ?? process.cwd();
9186
+ const restoreProjectEnv = applyProjectEnv(cwd);
9187
+ try {
9188
+ const resolvedPath = options.configPath ? resolve(cwd, options.configPath) : findGeneratorConfigPath(cwd);
9189
+ if (!resolvedPath) {
9190
+ const environmentConfig = createEnvironmentGeneratorConfig();
9191
+ if (environmentConfig) {
9192
+ return {
9193
+ configPath: ENV_ONLY_CONFIG_PATH,
9194
+ config: normalizeGeneratorConfig(environmentConfig)
9195
+ };
9196
+ }
9197
+ throw new Error(
9198
+ `No generator config found in ${cwd}. Expected one of: ${DEFAULT_CONFIG_CANDIDATES.join(", ")}. To run without a config file, set DATABASE_URL (direct mode) or ATHENA_URL + ATHENA_API_KEY (gateway mode).`
9199
+ );
9200
+ }
9201
+ const moduleUrl = pathToFileURL(resolvedPath);
9202
+ const module = await importConfigModule(`${moduleUrl.href}?cacheBust=${Date.now()}`);
9203
+ const rawConfig = extractConfigExport(module);
9204
+ return {
9205
+ configPath: resolvedPath,
9206
+ config: normalizeGeneratorConfig(rawConfig)
9207
+ };
9208
+ } finally {
9209
+ restoreProjectEnv();
9210
+ }
9211
+ }
9212
+
9213
+ // src/generator/env.ts
9214
+ function readEnvStringValue2(key) {
9215
+ if (typeof process === "undefined" || !process.env) {
9216
+ return void 0;
9217
+ }
9218
+ const value = process.env[key];
9219
+ if (typeof value !== "string") {
9220
+ return void 0;
9221
+ }
9222
+ const trimmed = value.trim();
9223
+ return trimmed.length > 0 ? trimmed : void 0;
9224
+ }
9225
+ function throwMissingEnvVar(key) {
9226
+ throw new Error(
9227
+ `Generator config env var ${key} is missing or empty. Set ${key} or provide a default value.`
9228
+ );
8189
9229
  }
8190
9230
  function resolveEnvValue(key, options, resolver) {
8191
9231
  const rawValue = readEnvStringValue2(key);
@@ -8378,59 +9418,6 @@ function escapeStringLiteral(value) {
8378
9418
  return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
8379
9419
  }
8380
9420
 
8381
- // src/generator/placeholders.ts
8382
- function createStyleTokens(prefix, value) {
8383
- return {
8384
- [prefix]: value,
8385
- [`${prefix}_camel`]: applyNamingStyle(value, "camel"),
8386
- [`${prefix}_pascal`]: applyNamingStyle(value, "pascal"),
8387
- [`${prefix}_snake`]: applyNamingStyle(value, "snake"),
8388
- [`${prefix}_kebab`]: applyNamingStyle(value, "kebab")
8389
- };
8390
- }
8391
- function renderTemplate(template, tokenMap) {
8392
- return template.replace(/\{([A-Za-z0-9_]+)\}/g, (_match, token) => {
8393
- if (!(token in tokenMap)) {
8394
- throw new Error(`Unknown placeholder token "${token}" in template "${template}"`);
8395
- }
8396
- return tokenMap[token];
8397
- });
8398
- }
8399
- function resolvePlaceholderMap(baseTokens, outputConfig) {
8400
- const resolved = {
8401
- ...baseTokens
8402
- };
8403
- const reservedTokenKeys = new Set(Object.keys(baseTokens));
8404
- const entries = Object.entries(outputConfig.placeholderMap ?? {});
8405
- for (let index = 0; index < entries.length; index += 1) {
8406
- const [key, value] = entries[index];
8407
- if (reservedTokenKeys.has(key)) {
8408
- continue;
8409
- }
8410
- let current = value;
8411
- for (let depth = 0; depth < 8; depth += 1) {
8412
- const next = renderTemplate(current, resolved);
8413
- if (next === current) {
8414
- break;
8415
- }
8416
- current = next;
8417
- }
8418
- resolved[key] = current;
8419
- }
8420
- return resolved;
8421
- }
8422
- function renderOutputPath(template, context, outputConfig) {
8423
- const baseTokens = {
8424
- provider: context.provider,
8425
- kind: context.kind,
8426
- ...createStyleTokens("database", context.database),
8427
- ...createStyleTokens("schema", context.schema),
8428
- ...createStyleTokens("model", context.model)
8429
- };
8430
- const tokens = resolvePlaceholderMap(baseTokens, outputConfig);
8431
- return renderTemplate(template, tokens);
8432
- }
8433
-
8434
9421
  // src/generator/postgres-type-mapping.ts
8435
9422
  var NUMBER_TYPES = /* @__PURE__ */ new Set([
8436
9423
  "int2",
@@ -8547,7 +9534,60 @@ function resolvePostgresColumnType(column) {
8547
9534
  return wrapArrayType(baseType, column.arrayDimensions);
8548
9535
  }
8549
9536
 
8550
- // src/generator/renderer.ts
9537
+ // src/generator/placeholders.ts
9538
+ function createStyleTokens(prefix, value) {
9539
+ return {
9540
+ [prefix]: value,
9541
+ [`${prefix}_camel`]: applyNamingStyle(value, "camel"),
9542
+ [`${prefix}_pascal`]: applyNamingStyle(value, "pascal"),
9543
+ [`${prefix}_snake`]: applyNamingStyle(value, "snake"),
9544
+ [`${prefix}_kebab`]: applyNamingStyle(value, "kebab")
9545
+ };
9546
+ }
9547
+ function renderTemplate(template, tokenMap) {
9548
+ return template.replace(/\{([A-Za-z0-9_]+)\}/g, (_match, token) => {
9549
+ if (!(token in tokenMap)) {
9550
+ throw new Error(`Unknown placeholder token "${token}" in template "${template}"`);
9551
+ }
9552
+ return tokenMap[token];
9553
+ });
9554
+ }
9555
+ function resolvePlaceholderMap(baseTokens, outputConfig) {
9556
+ const resolved = {
9557
+ ...baseTokens
9558
+ };
9559
+ const reservedTokenKeys = new Set(Object.keys(baseTokens));
9560
+ const entries = Object.entries(outputConfig.placeholderMap ?? {});
9561
+ for (let index = 0; index < entries.length; index += 1) {
9562
+ const [key, value] = entries[index];
9563
+ if (reservedTokenKeys.has(key)) {
9564
+ continue;
9565
+ }
9566
+ let current = value;
9567
+ for (let depth = 0; depth < 8; depth += 1) {
9568
+ const next = renderTemplate(current, resolved);
9569
+ if (next === current) {
9570
+ break;
9571
+ }
9572
+ current = next;
9573
+ }
9574
+ resolved[key] = current;
9575
+ }
9576
+ return resolved;
9577
+ }
9578
+ function renderOutputPath(template, context, outputConfig) {
9579
+ const baseTokens = {
9580
+ provider: context.provider,
9581
+ kind: context.kind,
9582
+ ...createStyleTokens("database", context.database),
9583
+ ...createStyleTokens("schema", context.schema),
9584
+ ...createStyleTokens("model", context.model)
9585
+ };
9586
+ const tokens = resolvePlaceholderMap(baseTokens, outputConfig);
9587
+ return renderTemplate(template, tokens);
9588
+ }
9589
+
9590
+ // src/generator/render-shared.ts
8551
9591
  function normalizePath(pathValue) {
8552
9592
  return pathValue.replace(/\\/g, "/");
8553
9593
  }
@@ -8560,11 +9600,13 @@ function toModuleImportPath(fromFile, targetFile) {
8560
9600
  );
8561
9601
  return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
8562
9602
  }
9603
+ function resolveOutputPath(target, tokens, config) {
9604
+ return normalizePath(renderOutputPath(target, tokens, config.output));
9605
+ }
8563
9606
  function renderObjectKey(key) {
8564
- const escaped = escapeTypePropertyName(key);
8565
- return escaped.startsWith("'") ? escaped : escaped;
9607
+ return escapeTypePropertyName(key);
8566
9608
  }
8567
- function renderRelation(relation) {
9609
+ function renderRelationLiteral(relation) {
8568
9610
  const through = relation.through ? `,
8569
9611
  through: {
8570
9612
  schema: ${escapeStringLiteral(relation.through.schema)},
@@ -8580,54 +9622,12 @@ function renderRelation(relation) {
8580
9622
  targetColumns: [${relation.targetColumns.map((value) => escapeStringLiteral(value)).join(", ")}]${through}
8581
9623
  }`;
8582
9624
  }
8583
- function renderModelArtifact(snapshot, descriptor, config) {
8584
- const columnLines = Object.values(descriptor.table.columns).map((column) => {
8585
- const propertyName = escapeTypePropertyName(column.name);
8586
- const baseType = resolvePostgresColumnType(column);
8587
- const isOptional = column.isNullable;
8588
- const typeWithNullability = column.isNullable ? `${baseType} | null` : baseType;
8589
- return ` ${propertyName}${isOptional ? "?" : ""}: ${typeWithNullability}`;
8590
- }).join("\n");
8591
- const nullableLines = Object.values(descriptor.table.columns).map((column) => ` ${renderObjectKey(column.name)}: ${column.isNullable ? "true" : "false"}`).join(",\n");
8592
- const relationEntries = Object.entries(descriptor.table.relations);
8593
- const relationBlock = config.features.emitRelations && relationEntries.length > 0 ? `,
8594
- relations: {
8595
- ${relationEntries.map(([relationKey2, relationValue]) => ` ${renderObjectKey(relationKey2)}: ${renderRelation(relationValue)}`).join(",\n")}
8596
- }` : "";
8597
- const content = `import { defineModel } from '@xylex-group/athena'
8598
-
8599
- export interface ${descriptor.rowTypeName} {
8600
- ${columnLines}
8601
- }
8602
-
8603
- export type ${descriptor.insertTypeName} = Partial<${descriptor.rowTypeName}>
8604
- export type ${descriptor.updateTypeName} = Partial<${descriptor.insertTypeName}>
8605
-
8606
- export const ${descriptor.modelConstName} = defineModel<${descriptor.rowTypeName}, ${descriptor.insertTypeName}, ${descriptor.updateTypeName}>({
8607
- meta: {
8608
- database: ${escapeStringLiteral(snapshot.database)},
8609
- schema: ${escapeStringLiteral(descriptor.schemaName)},
8610
- model: ${escapeStringLiteral(descriptor.tableName)},
8611
- tableName: ${escapeStringLiteral(`${descriptor.schemaName}.${descriptor.tableName}`)},
8612
- primaryKey: [${descriptor.table.primaryKey.map((value) => escapeStringLiteral(value)).join(", ")}],
8613
- nullable: {
8614
- ${nullableLines}
8615
- }${relationBlock}
8616
- }
8617
- })
8618
- `;
8619
- return {
8620
- kind: "model",
8621
- path: descriptor.filePath,
8622
- content
8623
- };
8624
- }
8625
9625
  function renderSchemaArtifact(descriptor) {
8626
9626
  const importLines = descriptor.models.map((modelDescriptor) => {
8627
9627
  const importPath = toModuleImportPath(descriptor.filePath, modelDescriptor.filePath);
8628
- return `import { ${modelDescriptor.modelConstName} } from '${importPath}'`;
9628
+ return `import { ${modelDescriptor.exportConstName} } from '${importPath}'`;
8629
9629
  }).join("\n");
8630
- const modelEntries = descriptor.models.map((modelDescriptor) => ` ${renderObjectKey(modelDescriptor.tableName)}: ${modelDescriptor.modelConstName}`).join(",\n");
9630
+ const modelEntries = descriptor.models.map((modelDescriptor) => ` ${renderObjectKey(modelDescriptor.tableName)}: ${modelDescriptor.exportConstName}`).join(",\n");
8631
9631
  const content = `import { defineSchema } from '@xylex-group/athena'
8632
9632
  ${importLines ? `
8633
9633
  ${importLines}
@@ -8662,11 +9662,18 @@ ${schemaEntries}
8662
9662
  content
8663
9663
  };
8664
9664
  }
8665
- function renderRegistryArtifact(registryPath, databasePath, databaseConstName, registryConstName, databaseName) {
9665
+ function renderRegistryArtifact(registryPath, databasePath, databaseConstName, registryConstName, databaseName, generatedAt, outputFormat, schemaVersion) {
8666
9666
  const databaseImportPath = toModuleImportPath(registryPath, databasePath);
8667
9667
  const content = `import { defineRegistry } from '@xylex-group/athena'
8668
9668
  import { ${databaseConstName} } from '${databaseImportPath}'
8669
9669
 
9670
+ export const __athena_schema_meta = {
9671
+ schemaVersion: ${schemaVersion},
9672
+ generatedAt: ${escapeStringLiteral(generatedAt)},
9673
+ database: ${escapeStringLiteral(databaseName)},
9674
+ outputFormat: ${escapeStringLiteral(outputFormat)},
9675
+ } as const
9676
+
8670
9677
  export const ${registryConstName} = defineRegistry({
8671
9678
  ${renderObjectKey(databaseName)}: ${databaseConstName}
8672
9679
  })
@@ -8745,123 +9752,332 @@ function scopeDuplicateDescriptorPathsBySchema(descriptors) {
8745
9752
  }
8746
9753
  return nextDescriptors;
8747
9754
  }
8748
- var ArtifactComposer = class {
8749
- constructor(snapshot, config) {
8750
- this.snapshot = snapshot;
8751
- this.config = config;
8752
- }
8753
- compose() {
8754
- const providerName = this.snapshot.backend;
8755
- const databaseName = this.snapshot.database;
8756
- const modelDescriptors = [];
8757
- for (const schemaName of Object.keys(this.snapshot.schemas).sort()) {
8758
- const schema = this.snapshot.schemas[schemaName];
8759
- for (const tableName of Object.keys(schema.tables).sort()) {
8760
- const table = schema.tables[tableName];
8761
- const rowTypeName = `${toSafeIdentifier(`${schemaName} ${tableName}`, this.config.naming.modelType, "Model")}Row`;
8762
- const insertTypeName = `${toSafeIdentifier(`${schemaName} ${tableName}`, this.config.naming.modelType, "Model")}Insert`;
8763
- const updateTypeName = `${toSafeIdentifier(`${schemaName} ${tableName}`, this.config.naming.modelType, "Model")}Update`;
8764
- const modelConstName = `${toSafeIdentifier(`${schemaName} ${tableName} model`, this.config.naming.modelConst, "model")}`;
8765
- const modelPath = normalizePath(
8766
- renderOutputPath(this.config.output.targets.model, {
8767
- provider: providerName,
8768
- kind: "model",
8769
- database: databaseName,
8770
- schema: schemaName,
8771
- model: tableName
8772
- }, this.config.output)
8773
- );
8774
- modelDescriptors.push({
9755
+ function composeGeneratorArtifacts(input) {
9756
+ const { snapshot, config, createModelDescriptor, renderModelArtifact: renderModelArtifact3 } = input;
9757
+ const providerName = snapshot.backend;
9758
+ const databaseName = snapshot.database;
9759
+ const modelDescriptors = [];
9760
+ for (const schemaName of Object.keys(snapshot.schemas).sort()) {
9761
+ const schema = snapshot.schemas[schemaName];
9762
+ for (const tableName of Object.keys(schema.tables).sort()) {
9763
+ modelDescriptors.push(
9764
+ createModelDescriptor({
9765
+ providerName,
9766
+ databaseName,
8775
9767
  schemaName,
8776
9768
  tableName,
8777
- filePath: modelPath,
8778
- rowTypeName,
8779
- insertTypeName,
8780
- updateTypeName,
8781
- modelConstName,
8782
- table
8783
- });
8784
- }
8785
- }
8786
- const scopedModelDescriptors = scopeDuplicateDescriptorPathsBySchema(modelDescriptors);
8787
- let schemaDescriptors = Object.keys(this.snapshot.schemas).sort().map((schemaName) => {
8788
- const schemaPath = normalizePath(
8789
- renderOutputPath(this.config.output.targets.schema, {
8790
- provider: providerName,
8791
- kind: "schema",
8792
- database: databaseName,
8793
- schema: schemaName,
8794
- model: "index"
8795
- }, this.config.output)
9769
+ table: schema.tables[tableName]
9770
+ })
8796
9771
  );
8797
- return {
8798
- schemaName,
8799
- filePath: schemaPath,
8800
- schemaConstName: toSafeIdentifier(
8801
- `${schemaName} schema`,
8802
- this.config.naming.schemaConst,
8803
- "schema"
8804
- ),
8805
- models: scopedModelDescriptors.filter((model) => model.schemaName === schemaName)
8806
- };
8807
- });
8808
- schemaDescriptors = scopeDuplicateDescriptorPathsBySchema(schemaDescriptors);
8809
- const databasePath = normalizePath(
8810
- renderOutputPath(this.config.output.targets.database, {
9772
+ }
9773
+ }
9774
+ const scopedModelDescriptors = scopeDuplicateDescriptorPathsBySchema(modelDescriptors);
9775
+ let schemaDescriptors = Object.keys(snapshot.schemas).sort().map((schemaName) => ({
9776
+ schemaName,
9777
+ filePath: resolveOutputPath(
9778
+ config.output.targets.schema,
9779
+ {
9780
+ provider: providerName,
9781
+ kind: "schema",
9782
+ database: databaseName,
9783
+ schema: schemaName,
9784
+ model: "index"
9785
+ },
9786
+ config
9787
+ ),
9788
+ schemaConstName: toSafeIdentifier(
9789
+ `${schemaName} schema`,
9790
+ config.naming.schemaConst,
9791
+ "schema"
9792
+ ),
9793
+ models: scopedModelDescriptors.filter((model) => model.schemaName === schemaName)
9794
+ }));
9795
+ schemaDescriptors = scopeDuplicateDescriptorPathsBySchema(schemaDescriptors);
9796
+ const databaseDescriptor = {
9797
+ filePath: resolveOutputPath(
9798
+ config.output.targets.database,
9799
+ {
8811
9800
  provider: providerName,
8812
9801
  kind: "database",
8813
9802
  database: databaseName,
8814
9803
  schema: "index",
8815
9804
  model: "index"
8816
- }, this.config.output)
9805
+ },
9806
+ config
9807
+ ),
9808
+ databaseConstName: toSafeIdentifier(
9809
+ `${databaseName} database`,
9810
+ config.naming.databaseConst,
9811
+ "database"
9812
+ ),
9813
+ schemas: schemaDescriptors
9814
+ };
9815
+ const files = [];
9816
+ for (const modelDescriptor of scopedModelDescriptors) {
9817
+ files.push(renderModelArtifact3(modelDescriptor));
9818
+ }
9819
+ for (const schemaDescriptor of schemaDescriptors) {
9820
+ files.push(renderSchemaArtifact(schemaDescriptor));
9821
+ }
9822
+ files.push(renderDatabaseArtifact(databaseDescriptor));
9823
+ if (config.features.emitRegistry) {
9824
+ const registryPath = resolveOutputPath(
9825
+ config.output.targets.registry,
9826
+ {
9827
+ provider: providerName,
9828
+ kind: "registry",
9829
+ database: databaseName,
9830
+ schema: "index",
9831
+ model: "index"
9832
+ },
9833
+ config
9834
+ );
9835
+ files.push(
9836
+ renderRegistryArtifact(
9837
+ registryPath,
9838
+ databaseDescriptor.filePath,
9839
+ databaseDescriptor.databaseConstName,
9840
+ toSafeIdentifier("registry", config.naming.registryConst, "registry"),
9841
+ databaseName,
9842
+ snapshot.generatedAt,
9843
+ config.output.format,
9844
+ config.internal.schemaVersion
9845
+ )
8817
9846
  );
8818
- const databaseDescriptor = {
8819
- filePath: databasePath,
8820
- databaseConstName: toSafeIdentifier(
8821
- `${databaseName} database`,
8822
- this.config.naming.databaseConst,
8823
- "database"
8824
- ),
8825
- schemas: schemaDescriptors
8826
- };
8827
- const files = [];
8828
- for (const modelDescriptor of scopedModelDescriptors) {
8829
- files.push(renderModelArtifact(this.snapshot, modelDescriptor, this.config));
8830
- }
8831
- for (const schemaDescriptor of schemaDescriptors) {
8832
- files.push(renderSchemaArtifact(schemaDescriptor));
8833
- }
8834
- files.push(renderDatabaseArtifact(databaseDescriptor));
8835
- if (this.config.features.emitRegistry) {
8836
- const registryPath = normalizePath(
8837
- renderOutputPath(this.config.output.targets.registry, {
8838
- provider: providerName,
8839
- kind: "registry",
8840
- database: databaseName,
8841
- schema: "index",
8842
- model: "index"
8843
- }, this.config.output)
8844
- );
8845
- files.push(
8846
- renderRegistryArtifact(
8847
- registryPath,
8848
- databaseDescriptor.filePath,
8849
- databaseDescriptor.databaseConstName,
8850
- toSafeIdentifier("registry", this.config.naming.registryConst, "registry"),
8851
- databaseName
8852
- )
8853
- );
8854
- }
8855
- assertNoDuplicatePaths(files);
8856
- return {
8857
- snapshot: this.snapshot,
8858
- files
8859
- };
8860
9847
  }
8861
- };
9848
+ assertNoDuplicatePaths(files);
9849
+ return {
9850
+ snapshot,
9851
+ files
9852
+ };
9853
+ }
9854
+
9855
+ // src/generator/table-builder-renderer.ts
9856
+ var SAFE_NUMBER_TYPES = /* @__PURE__ */ new Set([
9857
+ "int2",
9858
+ "int4",
9859
+ "float4",
9860
+ "float8",
9861
+ "smallint",
9862
+ "integer",
9863
+ "real",
9864
+ "double precision"
9865
+ ]);
9866
+ var JSON_TYPES = /* @__PURE__ */ new Set(["json", "jsonb"]);
9867
+ var BOOLEAN_TYPES = /* @__PURE__ */ new Set(["bool", "boolean"]);
9868
+ var STRING_TYPES = /* @__PURE__ */ new Set([
9869
+ "int8",
9870
+ "bigint",
9871
+ "serial8",
9872
+ "bigserial",
9873
+ "numeric",
9874
+ "decimal",
9875
+ "money",
9876
+ "bytea"
9877
+ ]);
9878
+ function normalizeTypeLabel2(column) {
9879
+ const preferred = (column.udtName || column.dataType).toLowerCase().trim();
9880
+ if (column.arrayDimensions > 0 && preferred.startsWith("_")) {
9881
+ return preferred.slice(1);
9882
+ }
9883
+ return preferred;
9884
+ }
9885
+ function renderColumnBuilder(column) {
9886
+ const label = normalizeTypeLabel2(column);
9887
+ let helper;
9888
+ let expression;
9889
+ if (column.typeKind === "enum" && column.enumValues && column.enumValues.length > 0) {
9890
+ helper = "enumeration";
9891
+ expression = `enumeration([${column.enumValues.map((value) => escapeStringLiteral(value)).join(", ")}] as const)`;
9892
+ } else if (column.arrayDimensions > 0 || JSON_TYPES.has(label) || column.typeKind === "composite") {
9893
+ helper = "json";
9894
+ expression = `json<${resolvePostgresColumnType(column)}>()`;
9895
+ } else if (BOOLEAN_TYPES.has(label)) {
9896
+ helper = "boolean";
9897
+ expression = "boolean()";
9898
+ } else if (SAFE_NUMBER_TYPES.has(label)) {
9899
+ helper = "number";
9900
+ expression = "number()";
9901
+ } else if (STRING_TYPES.has(label)) {
9902
+ helper = "string";
9903
+ expression = "string()";
9904
+ } else {
9905
+ helper = "string";
9906
+ expression = "string()";
9907
+ }
9908
+ if (column.isNullable) {
9909
+ expression = `${expression}.optional()`;
9910
+ }
9911
+ if (column.hasDefault) {
9912
+ expression = `${expression}.defaulted()`;
9913
+ }
9914
+ if (column.isGenerated) {
9915
+ expression = `${expression}.generated()`;
9916
+ }
9917
+ return { helper, expression };
9918
+ }
9919
+ function renderModelArtifact(descriptor, config) {
9920
+ const helperImports = /* @__PURE__ */ new Set(["table"]);
9921
+ const columnLines = Object.entries(descriptor.table.columns).map(([columnName, column]) => {
9922
+ const propertyName = escapeTypePropertyName(columnName);
9923
+ const rendered = renderColumnBuilder(column);
9924
+ helperImports.add(rendered.helper);
9925
+ return ` ${propertyName}: ${rendered.expression}`;
9926
+ }).join(",\n");
9927
+ const helperImportLine = Array.from(helperImports).sort().join(", ");
9928
+ const rowSchemaConstName = `${descriptor.tableConstName}_row_schema`;
9929
+ const insertSchemaConstName = `${descriptor.tableConstName}_insert_schema`;
9930
+ const updateSchemaConstName = `${descriptor.tableConstName}_update_schema`;
9931
+ const formSchemaConstName = `${descriptor.tableConstName}_form_schema`;
9932
+ const relationEntries = Object.entries(descriptor.table.relations);
9933
+ const relationsAssignment = config.features.emitRelations && relationEntries.length > 0 ? `
9934
+ Object.assign(${descriptor.tableConstName}.meta, {
9935
+ relations: {
9936
+ ${relationEntries.map(([relationKey2, relationValue]) => ` ${renderObjectKey(relationKey2)}: ${renderRelationLiteral(relationValue)}`).join(",\n")}
9937
+ }
9938
+ })
9939
+ ` : "";
9940
+ const content = `import { ${helperImportLine} } from '@xylex-group/athena'
9941
+ import type { FormValuesOf, InsertOf, RowOf, UpdateOf } from '@xylex-group/athena'
9942
+
9943
+ export const ${descriptor.tableConstName} = table(${escapeStringLiteral(descriptor.tableName)})
9944
+ .schema(${escapeStringLiteral(descriptor.schemaName)})
9945
+ .columns({
9946
+ ${columnLines}
9947
+ })
9948
+ .primaryKey(${descriptor.table.primaryKey.map((value) => escapeStringLiteral(value)).join(", ")})
9949
+ ${relationsAssignment ? `${relationsAssignment}` : ""}
9950
+ export type ${descriptor.rowTypeName} = RowOf<typeof ${descriptor.tableConstName}>
9951
+ export type ${descriptor.insertTypeName} = InsertOf<typeof ${descriptor.tableConstName}>
9952
+ export type ${descriptor.updateTypeName} = UpdateOf<typeof ${descriptor.tableConstName}>
9953
+ export type ${descriptor.formValuesTypeName} = FormValuesOf<typeof ${descriptor.tableConstName}>
9954
+
9955
+ export const ${rowSchemaConstName} = ${descriptor.tableConstName}.schemas.row
9956
+ export const ${insertSchemaConstName} = ${descriptor.tableConstName}.schemas.insert
9957
+ export const ${updateSchemaConstName} = ${descriptor.tableConstName}.schemas.update
9958
+ export const ${formSchemaConstName} = ${descriptor.tableConstName}.schemas.form
9959
+ `;
9960
+ return {
9961
+ kind: "model",
9962
+ path: descriptor.filePath,
9963
+ content
9964
+ };
9965
+ }
9966
+ function generateTableBuilderArtifactsFromSnapshot(snapshot, config) {
9967
+ const normalizedConfig = "internal" in config ? config : normalizeGeneratorConfig(config);
9968
+ return composeGeneratorArtifacts({
9969
+ snapshot,
9970
+ config: normalizedConfig,
9971
+ createModelDescriptor({ providerName, databaseName, schemaName, tableName, table: table2 }) {
9972
+ const tableConstName = toSafeIdentifier(tableName, "preserve", "table");
9973
+ return {
9974
+ schemaName,
9975
+ tableName,
9976
+ filePath: resolveOutputPath(
9977
+ normalizedConfig.output.targets.model,
9978
+ {
9979
+ provider: providerName,
9980
+ kind: "model",
9981
+ database: databaseName,
9982
+ schema: schemaName,
9983
+ model: tableName
9984
+ },
9985
+ normalizedConfig
9986
+ ),
9987
+ rowTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}Row`,
9988
+ insertTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}Insert`,
9989
+ updateTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}Update`,
9990
+ formValuesTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}FormValues`,
9991
+ tableConstName,
9992
+ exportConstName: tableConstName,
9993
+ table: table2
9994
+ };
9995
+ },
9996
+ renderModelArtifact: (descriptor) => renderModelArtifact(descriptor, normalizedConfig)
9997
+ });
9998
+ }
9999
+
10000
+ // src/generator/renderer.ts
10001
+ function renderModelArtifact2(databaseName, descriptor, config) {
10002
+ const columnLines = Object.values(descriptor.table.columns).map((column) => {
10003
+ const propertyName = escapeTypePropertyName(column.name);
10004
+ const baseType = resolvePostgresColumnType(column);
10005
+ const isOptional = column.isNullable;
10006
+ const typeWithNullability = column.isNullable ? `${baseType} | null` : baseType;
10007
+ return ` ${propertyName}${isOptional ? "?" : ""}: ${typeWithNullability}`;
10008
+ }).join("\n");
10009
+ const nullableLines = Object.values(descriptor.table.columns).map((column) => ` ${renderObjectKey(column.name)}: ${column.isNullable ? "true" : "false"}`).join(",\n");
10010
+ const relationEntries = Object.entries(descriptor.table.relations);
10011
+ const relationBlock = config.features.emitRelations && relationEntries.length > 0 ? `,
10012
+ relations: {
10013
+ ${relationEntries.map(([relationKey2, relationValue]) => ` ${renderObjectKey(relationKey2)}: ${renderRelationLiteral(relationValue)}`).join(",\n")}
10014
+ }` : "";
10015
+ const content = `import { defineModel } from '@xylex-group/athena'
10016
+
10017
+ export interface ${descriptor.rowTypeName} {
10018
+ ${columnLines}
10019
+ }
10020
+
10021
+ export type ${descriptor.insertTypeName} = Partial<${descriptor.rowTypeName}>
10022
+ export type ${descriptor.updateTypeName} = Partial<${descriptor.insertTypeName}>
10023
+
10024
+ export const ${descriptor.modelConstName} = defineModel<${descriptor.rowTypeName}, ${descriptor.insertTypeName}, ${descriptor.updateTypeName}>({
10025
+ meta: {
10026
+ database: ${escapeStringLiteral(databaseName)},
10027
+ schema: ${escapeStringLiteral(descriptor.schemaName)},
10028
+ model: ${escapeStringLiteral(descriptor.tableName)},
10029
+ tableName: ${escapeStringLiteral(`${descriptor.schemaName}.${descriptor.tableName}`)},
10030
+ primaryKey: [${descriptor.table.primaryKey.map((value) => escapeStringLiteral(value)).join(", ")}],
10031
+ nullable: {
10032
+ ${nullableLines}
10033
+ }${relationBlock}
10034
+ }
10035
+ })
10036
+ `;
10037
+ return {
10038
+ kind: "model",
10039
+ path: descriptor.filePath,
10040
+ content
10041
+ };
10042
+ }
8862
10043
  function generateArtifactsFromSnapshot(snapshot, config) {
8863
- const normalizedConfig = "naming" in config && "features" in config && "experimental" in config ? config : normalizeGeneratorConfig(config);
8864
- return new ArtifactComposer(snapshot, normalizedConfig).compose();
10044
+ const normalizedConfig = "internal" in config ? config : normalizeGeneratorConfig(config);
10045
+ if (normalizedConfig.output.format === "table-builder") {
10046
+ return generateTableBuilderArtifactsFromSnapshot(snapshot, normalizedConfig);
10047
+ }
10048
+ return composeGeneratorArtifacts({
10049
+ snapshot,
10050
+ config: normalizedConfig,
10051
+ createModelDescriptor({ providerName, databaseName, schemaName, tableName, table: table2 }) {
10052
+ const modelConstName = toSafeIdentifier(
10053
+ `${schemaName} ${tableName} model`,
10054
+ normalizedConfig.naming.modelConst,
10055
+ "model"
10056
+ );
10057
+ return {
10058
+ schemaName,
10059
+ tableName,
10060
+ filePath: resolveOutputPath(
10061
+ normalizedConfig.output.targets.model,
10062
+ {
10063
+ provider: providerName,
10064
+ kind: "model",
10065
+ database: databaseName,
10066
+ schema: schemaName,
10067
+ model: tableName
10068
+ },
10069
+ normalizedConfig
10070
+ ),
10071
+ rowTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}Row`,
10072
+ insertTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}Insert`,
10073
+ updateTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}Update`,
10074
+ modelConstName,
10075
+ exportConstName: modelConstName,
10076
+ table: table2
10077
+ };
10078
+ },
10079
+ renderModelArtifact: (descriptor) => renderModelArtifact2(snapshot.database, descriptor, normalizedConfig)
10080
+ });
8865
10081
  }
8866
10082
 
8867
10083
  // src/generator/providers.ts
@@ -9438,6 +10654,6 @@ function athenaAuth(config) {
9438
10654
  return auth;
9439
10655
  }
9440
10656
 
9441
- export { ATHENA_AUTH_BASE_ERROR_CODES, AthenaClient, AthenaError, AthenaErrorCategory, AthenaErrorCode, AthenaErrorKind, AthenaGatewayError, AthenaStorageError, AthenaStorageErrorCode, Backend, DEFAULT_POSTGRES_SCHEMAS, assertInt, athenaAuth, coerceInt, createAthenaStorageError, createAuthClient, createAuthReactEmailInput, createClient, createModelFormAdapter, createPostgresIntrospectionProvider, createTypedClient, defineAthenaAuthConfig, defineAuthEmailTemplate, defineDatabase, defineGeneratorConfig, defineModel, defineRegistry, defineSchema, findGeneratorConfigPath, generateArtifactsFromSnapshot, generatorEnv, identifier, isAthenaGatewayError, isOk, loadGeneratorConfig, normalizeAthenaError, normalizeAthenaGatewayBaseUrl, normalizeGeneratorConfig, normalizeSchemaSelection, parseBooleanFlag2 as parseBooleanFlag, renderAthenaReactEmail, requireAffected, requireSuccess, resolveGeneratorProvider, resolvePostgresColumnType, resolveProviderSchemas, runSchemaGenerator, storageSdkManifest, toModelFormDefaults, toModelPayload, unwrap, unwrapOne, unwrapRows, verifyAthenaGatewayUrl, withRetry };
10657
+ export { ATHENA_AUTH_BASE_ERROR_CODES, AthenaClient, AthenaError, AthenaErrorCategory, AthenaErrorCode, AthenaErrorKind, AthenaGatewayError, AthenaStorageError, AthenaStorageErrorCode, Backend, DEFAULT_POSTGRES_SCHEMAS, assertInt, athenaAuth, boolean, coerceInt, createAthenaStorageError, createAuthClient, createAuthReactEmailInput, createClient, createModelFormAdapter, createPostgresIntrospectionProvider, createTypedClient, defineAthenaAuthConfig, defineAuthEmailTemplate, defineDatabase, defineGeneratorConfig, defineModel, defineRegistry, defineSchema, enumeration, findGeneratorConfigPath, generateArtifactsFromSnapshot, generatorEnv, getAthenaDebugAst, identifier, isAthenaGatewayError, isOk, json, loadGeneratorConfig, normalizeAthenaError, normalizeAthenaGatewayBaseUrl, normalizeGeneratorConfig, normalizeSchemaSelection, number, parseBooleanFlag2 as parseBooleanFlag, renderAthenaReactEmail, requireAffected, requireSuccess, resolveGeneratorProvider, resolvePostgresColumnType, resolveProviderSchemas, runSchemaGenerator, storageSdkManifest, string, table, toModelFormDefaults, toModelPayload, unwrap, unwrapOne, unwrapRows, verifyAthenaGatewayUrl, withRetry };
9442
10658
  //# sourceMappingURL=index.js.map
9443
10659
  //# sourceMappingURL=index.js.map