@xylex-group/athena 2.6.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 (44) hide show
  1. package/README.md +210 -17
  2. package/dist/browser.cjs +2102 -527
  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 +2096 -528
  7. package/dist/browser.js.map +1 -1
  8. package/dist/cli/index.cjs +2116 -559
  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 +2116 -559
  13. package/dist/cli/index.js.map +1 -1
  14. package/dist/cookies.cjs +10 -3
  15. package/dist/cookies.cjs.map +1 -1
  16. package/dist/cookies.js +10 -3
  17. package/dist/cookies.js.map +1 -1
  18. package/dist/index.cjs +2694 -748
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +8 -7
  21. package/dist/index.d.ts +8 -7
  22. package/dist/index.js +2688 -749
  23. package/dist/index.js.map +1 -1
  24. package/dist/model-form-DMed05gE.d.cts +3037 -0
  25. package/dist/model-form-DXPlOnlI.d.ts +3037 -0
  26. package/dist/{pipeline-Ce3pTw5h.d.ts → pipeline-CkMnhwPI.d.ts} +1 -1
  27. package/dist/{pipeline-D1ZYeoH7.d.cts → pipeline-D4sJRKqN.d.cts} +1 -1
  28. package/dist/react-email-DZhDDlEl.d.cts +417 -0
  29. package/dist/react-email-Lrz9A-BW.d.ts +417 -0
  30. package/dist/react.cjs +178 -71
  31. package/dist/react.cjs.map +1 -1
  32. package/dist/react.d.cts +22 -5
  33. package/dist/react.d.ts +22 -5
  34. package/dist/react.js +92 -5
  35. package/dist/react.js.map +1 -1
  36. package/dist/{types-CUuo4NDi.d.cts → types-BzY6fETM.d.ts} +47 -5
  37. package/dist/{types-DapchQY5.d.ts → types-CAtTGGoz.d.cts} +47 -5
  38. package/dist/{types-DSX6AT5B.d.cts → types-vikz9YIO.d.cts} +23 -1
  39. package/dist/{types-DSX6AT5B.d.ts → types-vikz9YIO.d.ts} +23 -1
  40. package/package.json +194 -193
  41. package/dist/model-form-BaHWi3gm.d.cts +0 -1383
  42. package/dist/model-form-Dh6gWjL0.d.ts +0 -1383
  43. package/dist/react-email-B8O1Jeff.d.cts +0 -1230
  44. package/dist/react-email-CDEF0jij.d.ts +0 -1230
package/dist/cli/index.js CHANGED
@@ -129,59 +129,6 @@ function escapeStringLiteral(value) {
129
129
  return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
130
130
  }
131
131
 
132
- // src/generator/placeholders.ts
133
- function createStyleTokens(prefix, value) {
134
- return {
135
- [prefix]: value,
136
- [`${prefix}_camel`]: applyNamingStyle(value, "camel"),
137
- [`${prefix}_pascal`]: applyNamingStyle(value, "pascal"),
138
- [`${prefix}_snake`]: applyNamingStyle(value, "snake"),
139
- [`${prefix}_kebab`]: applyNamingStyle(value, "kebab")
140
- };
141
- }
142
- function renderTemplate(template, tokenMap) {
143
- return template.replace(/\{([A-Za-z0-9_]+)\}/g, (_match, token) => {
144
- if (!(token in tokenMap)) {
145
- throw new Error(`Unknown placeholder token "${token}" in template "${template}"`);
146
- }
147
- return tokenMap[token];
148
- });
149
- }
150
- function resolvePlaceholderMap(baseTokens, outputConfig) {
151
- const resolved = {
152
- ...baseTokens
153
- };
154
- const reservedTokenKeys = new Set(Object.keys(baseTokens));
155
- const entries = Object.entries(outputConfig.placeholderMap ?? {});
156
- for (let index = 0; index < entries.length; index += 1) {
157
- const [key, value] = entries[index];
158
- if (reservedTokenKeys.has(key)) {
159
- continue;
160
- }
161
- let current = value;
162
- for (let depth = 0; depth < 8; depth += 1) {
163
- const next = renderTemplate(current, resolved);
164
- if (next === current) {
165
- break;
166
- }
167
- current = next;
168
- }
169
- resolved[key] = current;
170
- }
171
- return resolved;
172
- }
173
- function renderOutputPath(template, context, outputConfig) {
174
- const baseTokens = {
175
- provider: context.provider,
176
- kind: context.kind,
177
- ...createStyleTokens("database", context.database),
178
- ...createStyleTokens("schema", context.schema),
179
- ...createStyleTokens("model", context.model)
180
- };
181
- const tokens = resolvePlaceholderMap(baseTokens, outputConfig);
182
- return renderTemplate(template, tokens);
183
- }
184
-
185
132
  // src/generator/postgres-type-mapping.ts
186
133
  var NUMBER_TYPES = /* @__PURE__ */ new Set([
187
134
  "int2",
@@ -755,6 +702,7 @@ var DEFAULT_TARGETS = {
755
702
  database: "athena/relations.ts",
756
703
  registry: "athena/config.ts"
757
704
  };
705
+ var DEFAULT_OUTPUT_FORMAT = "define-model";
758
706
  var DEFAULT_NAMING = {
759
707
  modelType: "pascal",
760
708
  modelConst: "camel",
@@ -770,6 +718,9 @@ var DEFAULT_EXPERIMENTAL_FLAGS = {
770
718
  postgresGatewayIntrospection: false,
771
719
  scyllaProviderContracts: true
772
720
  };
721
+ var DEFAULT_INTERNAL_CONFIG = {
722
+ schemaVersion: 1
723
+ };
773
724
  var PROJECT_ENV_FILENAMES = [".env", ".env.local"];
774
725
  var DIRECT_CONNECTION_STRING_ENV_KEYS = [
775
726
  "ATHENA_GENERATOR_PG_URL",
@@ -786,6 +737,27 @@ var GATEWAY_API_KEY_ENV_KEYS = [
786
737
  "ATHENA_GATEWAY_API_KEY",
787
738
  "ATHENA_GENERATOR_API_KEY"
788
739
  ];
740
+ var GENERATOR_SCHEMA_ENV_KEYS = ["ATHENA_GENERATOR_SCHEMAS"];
741
+ var OUTPUT_FORMAT_ENV_KEYS = ["ATHENA_GENERATOR_OUTPUT_FORMAT"];
742
+ var MODEL_TARGET_ENV_KEYS = ["ATHENA_GENERATOR_MODEL_TARGET"];
743
+ var SCHEMA_TARGET_ENV_KEYS = ["ATHENA_GENERATOR_SCHEMA_TARGET"];
744
+ var DATABASE_TARGET_ENV_KEYS = ["ATHENA_GENERATOR_DATABASE_TARGET"];
745
+ var REGISTRY_TARGET_ENV_KEYS = ["ATHENA_GENERATOR_REGISTRY_TARGET"];
746
+ var PLACEHOLDER_MAP_ENV_KEYS = ["ATHENA_GENERATOR_PLACEHOLDER_MAP"];
747
+ var MODEL_TYPE_ENV_KEYS = ["ATHENA_GENERATOR_MODEL_TYPE", "ATHENA_GENERATOR_MODEL_STYLE"];
748
+ var MODEL_CONST_ENV_KEYS = ["ATHENA_GENERATOR_MODEL_CONST"];
749
+ var SCHEMA_CONST_ENV_KEYS = ["ATHENA_GENERATOR_SCHEMA_CONST"];
750
+ var DATABASE_CONST_ENV_KEYS = ["ATHENA_GENERATOR_DATABASE_CONST"];
751
+ var REGISTRY_CONST_ENV_KEYS = ["ATHENA_GENERATOR_REGISTRY_CONST"];
752
+ var EMIT_RELATIONS_ENV_KEYS = ["ATHENA_GENERATOR_EMIT_RELATIONS"];
753
+ var EMIT_REGISTRY_ENV_KEYS = ["ATHENA_GENERATOR_EMIT_REGISTRY"];
754
+ var GATEWAY_BACKEND_ENV_KEYS = ["ATHENA_GENERATOR_BACKEND"];
755
+ var GATEWAY_EXPERIMENTAL_ENV_KEYS = ["ATHENA_GENERATOR_GATEWAY_EXPERIMENTAL"];
756
+ var SCYLLA_PROVIDER_CONTRACTS_ENV_KEYS = ["ATHENA_GENERATOR_SCYLLA_PROVIDER_CONTRACTS"];
757
+ var ENV_ONLY_CONFIG_PATH = "[environment defaults]";
758
+ var NAMING_STYLE_VALUES = ["preserve", "camel", "pascal", "snake", "kebab"];
759
+ var OUTPUT_FORMAT_VALUES = ["define-model", "table-builder"];
760
+ var BACKEND_TYPE_VALUES = ["athena", "postgrest", "postgresql", "scylladb"];
789
761
  function normalizeRawEnvValue(rawValue) {
790
762
  if (rawValue.startsWith('"') && rawValue.endsWith('"') && rawValue.length >= 2) {
791
763
  const inner = rawValue.slice(1, -1);
@@ -877,6 +849,50 @@ function resolveFallbackValue(fallbackKeys) {
877
849
  }
878
850
  return void 0;
879
851
  }
852
+ function normalizeOneOfValue(rawValue, allowedValues, envKeys) {
853
+ if (!rawValue) {
854
+ return void 0;
855
+ }
856
+ if (allowedValues.includes(rawValue)) {
857
+ return rawValue;
858
+ }
859
+ throw new Error(
860
+ `Generator config env vars ${envKeys.join(", ")} must resolve to one of: ${allowedValues.join(", ")}. Received: ${rawValue}.`
861
+ );
862
+ }
863
+ function resolveOptionalOneOf(envKeys, allowedValues) {
864
+ return normalizeOneOfValue(resolveFallbackValue(envKeys), allowedValues, envKeys);
865
+ }
866
+ function resolveOptionalBoolean(envKeys) {
867
+ const rawValue = resolveFallbackValue(envKeys);
868
+ return rawValue === void 0 ? void 0 : parseBooleanFlag2(rawValue, false);
869
+ }
870
+ function resolveOptionalJson(envKeys) {
871
+ const rawValue = resolveFallbackValue(envKeys);
872
+ if (rawValue === void 0) {
873
+ return void 0;
874
+ }
875
+ try {
876
+ return JSON.parse(rawValue);
877
+ } catch (error) {
878
+ const message = error instanceof Error ? error.message : String(error);
879
+ throw new Error(
880
+ `Generator config env vars ${envKeys.join(", ")} must contain valid JSON. ${message}`
881
+ );
882
+ }
883
+ }
884
+ function deriveDatabaseNameFromConnectionString(connectionString) {
885
+ try {
886
+ const parsedUrl = new URL(connectionString);
887
+ if (!POSTGRES_PROTOCOLS.has(parsedUrl.protocol)) {
888
+ return void 0;
889
+ }
890
+ const pathname = parsedUrl.pathname.replace(/^\/+/, "").trim();
891
+ return pathname.length > 0 ? decodeURIComponent(pathname) : void 0;
892
+ } catch {
893
+ return void 0;
894
+ }
895
+ }
880
896
  function normalizeOptionalString(value, fallbackKeys) {
881
897
  if (typeof value === "string") {
882
898
  const trimmed = value.trim();
@@ -950,12 +966,13 @@ function normalizeExperimentalFlags(input) {
950
966
  }
951
967
  function normalizeOutputConfig(output) {
952
968
  return {
969
+ format: output?.format ?? DEFAULT_OUTPUT_FORMAT,
953
970
  targets: {
954
971
  ...DEFAULT_TARGETS,
955
- ...output.targets ?? {}
972
+ ...output?.targets ?? {}
956
973
  },
957
974
  placeholderMap: {
958
- ...output.placeholderMap ?? {}
975
+ ...output?.placeholderMap ?? {}
959
976
  }
960
977
  };
961
978
  }
@@ -966,7 +983,7 @@ function normalizeProviderConfig(provider) {
966
983
  "provider.connectionString",
967
984
  DIRECT_CONNECTION_STRING_ENV_KEYS
968
985
  );
969
- const database = normalizeOptionalString(provider.database, POSTGRES_DATABASE_ENV_KEYS);
986
+ const database = normalizeOptionalString(provider.database, POSTGRES_DATABASE_ENV_KEYS) ?? deriveDatabaseNameFromConnectionString(connectionString);
970
987
  return {
971
988
  ...provider,
972
989
  connectionString: applyPostgresPasswordFallback(connectionString),
@@ -985,11 +1002,7 @@ function normalizeProviderConfig(provider) {
985
1002
  "provider.apiKey",
986
1003
  GATEWAY_API_KEY_ENV_KEYS
987
1004
  );
988
- const database = normalizeRequiredString(
989
- provider.database,
990
- "provider.database",
991
- POSTGRES_DATABASE_ENV_KEYS
992
- );
1005
+ const database = normalizeOptionalString(provider.database, POSTGRES_DATABASE_ENV_KEYS) ?? "postgres";
993
1006
  return {
994
1007
  ...provider,
995
1008
  gatewayUrl,
@@ -998,6 +1011,26 @@ function normalizeProviderConfig(provider) {
998
1011
  schemas: normalizeSchemaSelection(provider.schemas)
999
1012
  };
1000
1013
  }
1014
+ if (provider.kind === "scylla" && provider.mode === "direct") {
1015
+ if (!provider.contactPoints?.length) {
1016
+ throw new Error(
1017
+ "Generator config is missing provider.contactPoints for scylla direct mode."
1018
+ );
1019
+ }
1020
+ const keyspace = normalizeOptionalString(provider.keyspace, []);
1021
+ if (!keyspace) {
1022
+ throw new Error(
1023
+ "Generator config is missing provider.keyspace for scylla direct mode."
1024
+ );
1025
+ }
1026
+ return {
1027
+ kind: "scylla",
1028
+ mode: "direct",
1029
+ contactPoints: provider.contactPoints.slice(),
1030
+ keyspace,
1031
+ datacenter: normalizeOptionalString(provider.datacenter, [])
1032
+ };
1033
+ }
1001
1034
  return provider;
1002
1035
  }
1003
1036
  function isAthenaGeneratorConfig(value) {
@@ -1005,7 +1038,7 @@ function isAthenaGeneratorConfig(value) {
1005
1038
  return false;
1006
1039
  }
1007
1040
  const record = value;
1008
- return Boolean(record.provider && typeof record.provider === "object") && Boolean(record.output && typeof record.output === "object");
1041
+ return Boolean(record.provider && typeof record.provider === "object") && (record.output === void 0 || typeof record.output === "object");
1009
1042
  }
1010
1043
  function normalizeGeneratorConfig(input) {
1011
1044
  return {
@@ -1016,7 +1049,10 @@ function normalizeGeneratorConfig(input) {
1016
1049
  ...input.naming ?? {}
1017
1050
  },
1018
1051
  features: normalizeFeatureFlags(input.features),
1019
- experimental: normalizeExperimentalFlags(input.experimental)
1052
+ experimental: normalizeExperimentalFlags(input.experimental),
1053
+ internal: {
1054
+ ...DEFAULT_INTERNAL_CONFIG
1055
+ }
1020
1056
  };
1021
1057
  }
1022
1058
  function findGeneratorConfigPath(cwd = process.cwd()) {
@@ -1070,16 +1106,123 @@ function importConfigModule(moduleSpecifier) {
1070
1106
  );
1071
1107
  return runtimeImport(moduleSpecifier);
1072
1108
  }
1109
+ function buildEnvironmentOutputConfig() {
1110
+ const format = resolveOptionalOneOf(OUTPUT_FORMAT_ENV_KEYS, OUTPUT_FORMAT_VALUES);
1111
+ const modelTarget = resolveFallbackValue(MODEL_TARGET_ENV_KEYS);
1112
+ const schemaTarget = resolveFallbackValue(SCHEMA_TARGET_ENV_KEYS);
1113
+ const databaseTarget = resolveFallbackValue(DATABASE_TARGET_ENV_KEYS);
1114
+ const registryTarget = resolveFallbackValue(REGISTRY_TARGET_ENV_KEYS);
1115
+ const placeholderMap = resolveOptionalJson(PLACEHOLDER_MAP_ENV_KEYS);
1116
+ if (format === void 0 && modelTarget === void 0 && schemaTarget === void 0 && databaseTarget === void 0 && registryTarget === void 0 && placeholderMap === void 0) {
1117
+ return void 0;
1118
+ }
1119
+ return {
1120
+ format,
1121
+ targets: {
1122
+ ...modelTarget ? { model: modelTarget } : {},
1123
+ ...schemaTarget ? { schema: schemaTarget } : {},
1124
+ ...databaseTarget ? { database: databaseTarget } : {},
1125
+ ...registryTarget ? { registry: registryTarget } : {}
1126
+ },
1127
+ placeholderMap
1128
+ };
1129
+ }
1130
+ function buildEnvironmentNamingConfig() {
1131
+ const modelType = resolveOptionalOneOf(MODEL_TYPE_ENV_KEYS, NAMING_STYLE_VALUES);
1132
+ const modelConst = resolveOptionalOneOf(MODEL_CONST_ENV_KEYS, NAMING_STYLE_VALUES);
1133
+ const schemaConst = resolveOptionalOneOf(SCHEMA_CONST_ENV_KEYS, NAMING_STYLE_VALUES);
1134
+ const databaseConst = resolveOptionalOneOf(DATABASE_CONST_ENV_KEYS, NAMING_STYLE_VALUES);
1135
+ const registryConst = resolveOptionalOneOf(REGISTRY_CONST_ENV_KEYS, NAMING_STYLE_VALUES);
1136
+ if (modelType === void 0 && modelConst === void 0 && schemaConst === void 0 && databaseConst === void 0 && registryConst === void 0) {
1137
+ return void 0;
1138
+ }
1139
+ return {
1140
+ ...modelType ? { modelType } : {},
1141
+ ...modelConst ? { modelConst } : {},
1142
+ ...schemaConst ? { schemaConst } : {},
1143
+ ...databaseConst ? { databaseConst } : {},
1144
+ ...registryConst ? { registryConst } : {}
1145
+ };
1146
+ }
1147
+ function buildEnvironmentFeatureFlags() {
1148
+ const emitRelations = resolveOptionalBoolean(EMIT_RELATIONS_ENV_KEYS);
1149
+ const emitRegistry = resolveOptionalBoolean(EMIT_REGISTRY_ENV_KEYS);
1150
+ if (emitRelations === void 0 && emitRegistry === void 0) {
1151
+ return void 0;
1152
+ }
1153
+ return {
1154
+ ...emitRelations !== void 0 ? { emitRelations } : {},
1155
+ ...emitRegistry !== void 0 ? { emitRegistry } : {}
1156
+ };
1157
+ }
1158
+ function buildEnvironmentExperimentalFlags() {
1159
+ const postgresGatewayIntrospection = resolveOptionalBoolean(GATEWAY_EXPERIMENTAL_ENV_KEYS);
1160
+ const scyllaProviderContracts = resolveOptionalBoolean(SCYLLA_PROVIDER_CONTRACTS_ENV_KEYS);
1161
+ if (postgresGatewayIntrospection === void 0 && scyllaProviderContracts === void 0) {
1162
+ return void 0;
1163
+ }
1164
+ return {
1165
+ ...postgresGatewayIntrospection !== void 0 ? { postgresGatewayIntrospection } : {},
1166
+ ...scyllaProviderContracts !== void 0 ? { scyllaProviderContracts } : {}
1167
+ };
1168
+ }
1169
+ function buildEnvironmentProviderConfig() {
1170
+ const directConnectionString = resolveFallbackValue(DIRECT_CONNECTION_STRING_ENV_KEYS);
1171
+ if (directConnectionString) {
1172
+ return {
1173
+ kind: "postgres",
1174
+ mode: "direct",
1175
+ connectionString: directConnectionString,
1176
+ database: normalizeOptionalString(void 0, POSTGRES_DATABASE_ENV_KEYS),
1177
+ schemas: normalizeSchemaSelection(resolveFallbackValue(GENERATOR_SCHEMA_ENV_KEYS))
1178
+ };
1179
+ }
1180
+ const gatewayUrl = resolveFallbackValue(GATEWAY_URL_ENV_KEYS);
1181
+ const apiKey = resolveFallbackValue(GATEWAY_API_KEY_ENV_KEYS);
1182
+ if (gatewayUrl && apiKey) {
1183
+ const backend = resolveOptionalOneOf(GATEWAY_BACKEND_ENV_KEYS, BACKEND_TYPE_VALUES);
1184
+ return {
1185
+ kind: "postgres",
1186
+ mode: "gateway",
1187
+ gatewayUrl,
1188
+ apiKey,
1189
+ database: normalizeOptionalString(void 0, POSTGRES_DATABASE_ENV_KEYS),
1190
+ schemas: normalizeSchemaSelection(resolveFallbackValue(GENERATOR_SCHEMA_ENV_KEYS)),
1191
+ backend
1192
+ };
1193
+ }
1194
+ return void 0;
1195
+ }
1196
+ function createEnvironmentGeneratorConfig() {
1197
+ const provider = buildEnvironmentProviderConfig();
1198
+ if (!provider) {
1199
+ return void 0;
1200
+ }
1201
+ return {
1202
+ provider,
1203
+ output: buildEnvironmentOutputConfig(),
1204
+ naming: buildEnvironmentNamingConfig(),
1205
+ features: buildEnvironmentFeatureFlags(),
1206
+ experimental: buildEnvironmentExperimentalFlags()
1207
+ };
1208
+ }
1073
1209
  async function loadGeneratorConfig(options = {}) {
1074
1210
  const cwd = options.cwd ?? process.cwd();
1075
1211
  const restoreProjectEnv = applyProjectEnv(cwd);
1076
- const resolvedPath = options.configPath ? resolve(cwd, options.configPath) : findGeneratorConfigPath(cwd);
1077
- if (!resolvedPath) {
1078
- throw new Error(
1079
- `No generator config found in ${cwd}. Expected one of: ${DEFAULT_CONFIG_CANDIDATES.join(", ")}`
1080
- );
1081
- }
1082
1212
  try {
1213
+ const resolvedPath = options.configPath ? resolve(cwd, options.configPath) : findGeneratorConfigPath(cwd);
1214
+ if (!resolvedPath) {
1215
+ const environmentConfig = createEnvironmentGeneratorConfig();
1216
+ if (environmentConfig) {
1217
+ return {
1218
+ configPath: ENV_ONLY_CONFIG_PATH,
1219
+ config: normalizeGeneratorConfig(environmentConfig)
1220
+ };
1221
+ }
1222
+ throw new Error(
1223
+ `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).`
1224
+ );
1225
+ }
1083
1226
  const moduleUrl = pathToFileURL(resolvedPath);
1084
1227
  const module = await importConfigModule(`${moduleUrl.href}?cacheBust=${Date.now()}`);
1085
1228
  const rawConfig = extractConfigExport(module);
@@ -1092,7 +1235,60 @@ async function loadGeneratorConfig(options = {}) {
1092
1235
  }
1093
1236
  }
1094
1237
 
1095
- // src/generator/renderer.ts
1238
+ // src/generator/placeholders.ts
1239
+ function createStyleTokens(prefix, value) {
1240
+ return {
1241
+ [prefix]: value,
1242
+ [`${prefix}_camel`]: applyNamingStyle(value, "camel"),
1243
+ [`${prefix}_pascal`]: applyNamingStyle(value, "pascal"),
1244
+ [`${prefix}_snake`]: applyNamingStyle(value, "snake"),
1245
+ [`${prefix}_kebab`]: applyNamingStyle(value, "kebab")
1246
+ };
1247
+ }
1248
+ function renderTemplate(template, tokenMap) {
1249
+ return template.replace(/\{([A-Za-z0-9_]+)\}/g, (_match, token) => {
1250
+ if (!(token in tokenMap)) {
1251
+ throw new Error(`Unknown placeholder token "${token}" in template "${template}"`);
1252
+ }
1253
+ return tokenMap[token];
1254
+ });
1255
+ }
1256
+ function resolvePlaceholderMap(baseTokens, outputConfig) {
1257
+ const resolved = {
1258
+ ...baseTokens
1259
+ };
1260
+ const reservedTokenKeys = new Set(Object.keys(baseTokens));
1261
+ const entries = Object.entries(outputConfig.placeholderMap ?? {});
1262
+ for (let index = 0; index < entries.length; index += 1) {
1263
+ const [key, value] = entries[index];
1264
+ if (reservedTokenKeys.has(key)) {
1265
+ continue;
1266
+ }
1267
+ let current = value;
1268
+ for (let depth = 0; depth < 8; depth += 1) {
1269
+ const next = renderTemplate(current, resolved);
1270
+ if (next === current) {
1271
+ break;
1272
+ }
1273
+ current = next;
1274
+ }
1275
+ resolved[key] = current;
1276
+ }
1277
+ return resolved;
1278
+ }
1279
+ function renderOutputPath(template, context, outputConfig) {
1280
+ const baseTokens = {
1281
+ provider: context.provider,
1282
+ kind: context.kind,
1283
+ ...createStyleTokens("database", context.database),
1284
+ ...createStyleTokens("schema", context.schema),
1285
+ ...createStyleTokens("model", context.model)
1286
+ };
1287
+ const tokens = resolvePlaceholderMap(baseTokens, outputConfig);
1288
+ return renderTemplate(template, tokens);
1289
+ }
1290
+
1291
+ // src/generator/render-shared.ts
1096
1292
  function normalizePath(pathValue) {
1097
1293
  return pathValue.replace(/\\/g, "/");
1098
1294
  }
@@ -1105,11 +1301,13 @@ function toModuleImportPath(fromFile, targetFile) {
1105
1301
  );
1106
1302
  return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
1107
1303
  }
1304
+ function resolveOutputPath(target, tokens, config) {
1305
+ return normalizePath(renderOutputPath(target, tokens, config.output));
1306
+ }
1108
1307
  function renderObjectKey(key) {
1109
- const escaped = escapeTypePropertyName(key);
1110
- return escaped.startsWith("'") ? escaped : escaped;
1308
+ return escapeTypePropertyName(key);
1111
1309
  }
1112
- function renderRelation(relation) {
1310
+ function renderRelationLiteral(relation) {
1113
1311
  const through = relation.through ? `,
1114
1312
  through: {
1115
1313
  schema: ${escapeStringLiteral(relation.through.schema)},
@@ -1125,54 +1323,12 @@ function renderRelation(relation) {
1125
1323
  targetColumns: [${relation.targetColumns.map((value) => escapeStringLiteral(value)).join(", ")}]${through}
1126
1324
  }`;
1127
1325
  }
1128
- function renderModelArtifact(snapshot, descriptor, config) {
1129
- const columnLines = Object.values(descriptor.table.columns).map((column) => {
1130
- const propertyName = escapeTypePropertyName(column.name);
1131
- const baseType = resolvePostgresColumnType(column);
1132
- const isOptional = column.isNullable;
1133
- const typeWithNullability = column.isNullable ? `${baseType} | null` : baseType;
1134
- return ` ${propertyName}${isOptional ? "?" : ""}: ${typeWithNullability}`;
1135
- }).join("\n");
1136
- const nullableLines = Object.values(descriptor.table.columns).map((column) => ` ${renderObjectKey(column.name)}: ${column.isNullable ? "true" : "false"}`).join(",\n");
1137
- const relationEntries = Object.entries(descriptor.table.relations);
1138
- const relationBlock = config.features.emitRelations && relationEntries.length > 0 ? `,
1139
- relations: {
1140
- ${relationEntries.map(([relationKey2, relationValue]) => ` ${renderObjectKey(relationKey2)}: ${renderRelation(relationValue)}`).join(",\n")}
1141
- }` : "";
1142
- const content = `import { defineModel } from '@xylex-group/athena'
1143
-
1144
- export interface ${descriptor.rowTypeName} {
1145
- ${columnLines}
1146
- }
1147
-
1148
- export type ${descriptor.insertTypeName} = Partial<${descriptor.rowTypeName}>
1149
- export type ${descriptor.updateTypeName} = Partial<${descriptor.insertTypeName}>
1150
-
1151
- export const ${descriptor.modelConstName} = defineModel<${descriptor.rowTypeName}, ${descriptor.insertTypeName}, ${descriptor.updateTypeName}>({
1152
- meta: {
1153
- database: ${escapeStringLiteral(snapshot.database)},
1154
- schema: ${escapeStringLiteral(descriptor.schemaName)},
1155
- model: ${escapeStringLiteral(descriptor.tableName)},
1156
- tableName: ${escapeStringLiteral(`${descriptor.schemaName}.${descriptor.tableName}`)},
1157
- primaryKey: [${descriptor.table.primaryKey.map((value) => escapeStringLiteral(value)).join(", ")}],
1158
- nullable: {
1159
- ${nullableLines}
1160
- }${relationBlock}
1161
- }
1162
- })
1163
- `;
1164
- return {
1165
- kind: "model",
1166
- path: descriptor.filePath,
1167
- content
1168
- };
1169
- }
1170
1326
  function renderSchemaArtifact(descriptor) {
1171
1327
  const importLines = descriptor.models.map((modelDescriptor) => {
1172
1328
  const importPath = toModuleImportPath(descriptor.filePath, modelDescriptor.filePath);
1173
- return `import { ${modelDescriptor.modelConstName} } from '${importPath}'`;
1329
+ return `import { ${modelDescriptor.exportConstName} } from '${importPath}'`;
1174
1330
  }).join("\n");
1175
- const modelEntries = descriptor.models.map((modelDescriptor) => ` ${renderObjectKey(modelDescriptor.tableName)}: ${modelDescriptor.modelConstName}`).join(",\n");
1331
+ const modelEntries = descriptor.models.map((modelDescriptor) => ` ${renderObjectKey(modelDescriptor.tableName)}: ${modelDescriptor.exportConstName}`).join(",\n");
1176
1332
  const content = `import { defineSchema } from '@xylex-group/athena'
1177
1333
  ${importLines ? `
1178
1334
  ${importLines}
@@ -1207,11 +1363,18 @@ ${schemaEntries}
1207
1363
  content
1208
1364
  };
1209
1365
  }
1210
- function renderRegistryArtifact(registryPath, databasePath, databaseConstName, registryConstName, databaseName) {
1366
+ function renderRegistryArtifact(registryPath, databasePath, databaseConstName, registryConstName, databaseName, generatedAt, outputFormat, schemaVersion) {
1211
1367
  const databaseImportPath = toModuleImportPath(registryPath, databasePath);
1212
1368
  const content = `import { defineRegistry } from '@xylex-group/athena'
1213
1369
  import { ${databaseConstName} } from '${databaseImportPath}'
1214
1370
 
1371
+ export const __athena_schema_meta = {
1372
+ schemaVersion: ${schemaVersion},
1373
+ generatedAt: ${escapeStringLiteral(generatedAt)},
1374
+ database: ${escapeStringLiteral(databaseName)},
1375
+ outputFormat: ${escapeStringLiteral(outputFormat)},
1376
+ } as const
1377
+
1215
1378
  export const ${registryConstName} = defineRegistry({
1216
1379
  ${renderObjectKey(databaseName)}: ${databaseConstName}
1217
1380
  })
@@ -1290,123 +1453,332 @@ function scopeDuplicateDescriptorPathsBySchema(descriptors) {
1290
1453
  }
1291
1454
  return nextDescriptors;
1292
1455
  }
1293
- var ArtifactComposer = class {
1294
- constructor(snapshot, config) {
1295
- this.snapshot = snapshot;
1296
- this.config = config;
1297
- }
1298
- compose() {
1299
- const providerName = this.snapshot.backend;
1300
- const databaseName = this.snapshot.database;
1301
- const modelDescriptors = [];
1302
- for (const schemaName of Object.keys(this.snapshot.schemas).sort()) {
1303
- const schema = this.snapshot.schemas[schemaName];
1304
- for (const tableName of Object.keys(schema.tables).sort()) {
1305
- const table = schema.tables[tableName];
1306
- const rowTypeName = `${toSafeIdentifier(`${schemaName} ${tableName}`, this.config.naming.modelType, "Model")}Row`;
1307
- const insertTypeName = `${toSafeIdentifier(`${schemaName} ${tableName}`, this.config.naming.modelType, "Model")}Insert`;
1308
- const updateTypeName = `${toSafeIdentifier(`${schemaName} ${tableName}`, this.config.naming.modelType, "Model")}Update`;
1309
- const modelConstName = `${toSafeIdentifier(`${schemaName} ${tableName} model`, this.config.naming.modelConst, "model")}`;
1310
- const modelPath = normalizePath(
1311
- renderOutputPath(this.config.output.targets.model, {
1312
- provider: providerName,
1313
- kind: "model",
1314
- database: databaseName,
1315
- schema: schemaName,
1316
- model: tableName
1317
- }, this.config.output)
1318
- );
1319
- modelDescriptors.push({
1456
+ function composeGeneratorArtifacts(input) {
1457
+ const { snapshot, config, createModelDescriptor, renderModelArtifact: renderModelArtifact3 } = input;
1458
+ const providerName = snapshot.backend;
1459
+ const databaseName = snapshot.database;
1460
+ const modelDescriptors = [];
1461
+ for (const schemaName of Object.keys(snapshot.schemas).sort()) {
1462
+ const schema = snapshot.schemas[schemaName];
1463
+ for (const tableName of Object.keys(schema.tables).sort()) {
1464
+ modelDescriptors.push(
1465
+ createModelDescriptor({
1466
+ providerName,
1467
+ databaseName,
1320
1468
  schemaName,
1321
1469
  tableName,
1322
- filePath: modelPath,
1323
- rowTypeName,
1324
- insertTypeName,
1325
- updateTypeName,
1326
- modelConstName,
1327
- table
1328
- });
1329
- }
1330
- }
1331
- const scopedModelDescriptors = scopeDuplicateDescriptorPathsBySchema(modelDescriptors);
1332
- let schemaDescriptors = Object.keys(this.snapshot.schemas).sort().map((schemaName) => {
1333
- const schemaPath = normalizePath(
1334
- renderOutputPath(this.config.output.targets.schema, {
1335
- provider: providerName,
1336
- kind: "schema",
1337
- database: databaseName,
1338
- schema: schemaName,
1339
- model: "index"
1340
- }, this.config.output)
1470
+ table: schema.tables[tableName]
1471
+ })
1341
1472
  );
1342
- return {
1343
- schemaName,
1344
- filePath: schemaPath,
1345
- schemaConstName: toSafeIdentifier(
1346
- `${schemaName} schema`,
1347
- this.config.naming.schemaConst,
1348
- "schema"
1349
- ),
1350
- models: scopedModelDescriptors.filter((model) => model.schemaName === schemaName)
1351
- };
1352
- });
1353
- schemaDescriptors = scopeDuplicateDescriptorPathsBySchema(schemaDescriptors);
1354
- const databasePath = normalizePath(
1355
- renderOutputPath(this.config.output.targets.database, {
1473
+ }
1474
+ }
1475
+ const scopedModelDescriptors = scopeDuplicateDescriptorPathsBySchema(modelDescriptors);
1476
+ let schemaDescriptors = Object.keys(snapshot.schemas).sort().map((schemaName) => ({
1477
+ schemaName,
1478
+ filePath: resolveOutputPath(
1479
+ config.output.targets.schema,
1480
+ {
1356
1481
  provider: providerName,
1357
- kind: "database",
1482
+ kind: "schema",
1358
1483
  database: databaseName,
1359
- schema: "index",
1484
+ schema: schemaName,
1360
1485
  model: "index"
1361
- }, this.config.output)
1362
- );
1363
- const databaseDescriptor = {
1364
- filePath: databasePath,
1365
- databaseConstName: toSafeIdentifier(
1366
- `${databaseName} database`,
1367
- this.config.naming.databaseConst,
1368
- "database"
1369
- ),
1370
- schemas: schemaDescriptors
1371
- };
1372
- const files = [];
1373
- for (const modelDescriptor of scopedModelDescriptors) {
1374
- files.push(renderModelArtifact(this.snapshot, modelDescriptor, this.config));
1375
- }
1376
- for (const schemaDescriptor of schemaDescriptors) {
1377
- files.push(renderSchemaArtifact(schemaDescriptor));
1378
- }
1379
- files.push(renderDatabaseArtifact(databaseDescriptor));
1380
- if (this.config.features.emitRegistry) {
1381
- const registryPath = normalizePath(
1382
- renderOutputPath(this.config.output.targets.registry, {
1383
- provider: providerName,
1384
- kind: "registry",
1385
- database: databaseName,
1386
- schema: "index",
1387
- model: "index"
1388
- }, this.config.output)
1389
- );
1390
- files.push(
1391
- renderRegistryArtifact(
1392
- registryPath,
1393
- databaseDescriptor.filePath,
1394
- databaseDescriptor.databaseConstName,
1395
- toSafeIdentifier("registry", this.config.naming.registryConst, "registry"),
1396
- databaseName
1397
- )
1398
- );
1399
- }
1400
- assertNoDuplicatePaths(files);
1401
- return {
1402
- snapshot: this.snapshot,
1403
- files
1404
- };
1486
+ },
1487
+ config
1488
+ ),
1489
+ schemaConstName: toSafeIdentifier(
1490
+ `${schemaName} schema`,
1491
+ config.naming.schemaConst,
1492
+ "schema"
1493
+ ),
1494
+ models: scopedModelDescriptors.filter((model) => model.schemaName === schemaName)
1495
+ }));
1496
+ schemaDescriptors = scopeDuplicateDescriptorPathsBySchema(schemaDescriptors);
1497
+ const databaseDescriptor = {
1498
+ filePath: resolveOutputPath(
1499
+ config.output.targets.database,
1500
+ {
1501
+ provider: providerName,
1502
+ kind: "database",
1503
+ database: databaseName,
1504
+ schema: "index",
1505
+ model: "index"
1506
+ },
1507
+ config
1508
+ ),
1509
+ databaseConstName: toSafeIdentifier(
1510
+ `${databaseName} database`,
1511
+ config.naming.databaseConst,
1512
+ "database"
1513
+ ),
1514
+ schemas: schemaDescriptors
1515
+ };
1516
+ const files = [];
1517
+ for (const modelDescriptor of scopedModelDescriptors) {
1518
+ files.push(renderModelArtifact3(modelDescriptor));
1405
1519
  }
1406
- };
1520
+ for (const schemaDescriptor of schemaDescriptors) {
1521
+ files.push(renderSchemaArtifact(schemaDescriptor));
1522
+ }
1523
+ files.push(renderDatabaseArtifact(databaseDescriptor));
1524
+ if (config.features.emitRegistry) {
1525
+ const registryPath = resolveOutputPath(
1526
+ config.output.targets.registry,
1527
+ {
1528
+ provider: providerName,
1529
+ kind: "registry",
1530
+ database: databaseName,
1531
+ schema: "index",
1532
+ model: "index"
1533
+ },
1534
+ config
1535
+ );
1536
+ files.push(
1537
+ renderRegistryArtifact(
1538
+ registryPath,
1539
+ databaseDescriptor.filePath,
1540
+ databaseDescriptor.databaseConstName,
1541
+ toSafeIdentifier("registry", config.naming.registryConst, "registry"),
1542
+ databaseName,
1543
+ snapshot.generatedAt,
1544
+ config.output.format,
1545
+ config.internal.schemaVersion
1546
+ )
1547
+ );
1548
+ }
1549
+ assertNoDuplicatePaths(files);
1550
+ return {
1551
+ snapshot,
1552
+ files
1553
+ };
1554
+ }
1555
+
1556
+ // src/generator/table-builder-renderer.ts
1557
+ var SAFE_NUMBER_TYPES = /* @__PURE__ */ new Set([
1558
+ "int2",
1559
+ "int4",
1560
+ "float4",
1561
+ "float8",
1562
+ "smallint",
1563
+ "integer",
1564
+ "real",
1565
+ "double precision"
1566
+ ]);
1567
+ var JSON_TYPES = /* @__PURE__ */ new Set(["json", "jsonb"]);
1568
+ var BOOLEAN_TYPES = /* @__PURE__ */ new Set(["bool", "boolean"]);
1569
+ var STRING_TYPES = /* @__PURE__ */ new Set([
1570
+ "int8",
1571
+ "bigint",
1572
+ "serial8",
1573
+ "bigserial",
1574
+ "numeric",
1575
+ "decimal",
1576
+ "money",
1577
+ "bytea"
1578
+ ]);
1579
+ function normalizeTypeLabel2(column) {
1580
+ const preferred = (column.udtName || column.dataType).toLowerCase().trim();
1581
+ if (column.arrayDimensions > 0 && preferred.startsWith("_")) {
1582
+ return preferred.slice(1);
1583
+ }
1584
+ return preferred;
1585
+ }
1586
+ function renderColumnBuilder(column) {
1587
+ const label = normalizeTypeLabel2(column);
1588
+ let helper;
1589
+ let expression;
1590
+ if (column.typeKind === "enum" && column.enumValues && column.enumValues.length > 0) {
1591
+ helper = "enumeration";
1592
+ expression = `enumeration([${column.enumValues.map((value) => escapeStringLiteral(value)).join(", ")}] as const)`;
1593
+ } else if (column.arrayDimensions > 0 || JSON_TYPES.has(label) || column.typeKind === "composite") {
1594
+ helper = "json";
1595
+ expression = `json<${resolvePostgresColumnType(column)}>()`;
1596
+ } else if (BOOLEAN_TYPES.has(label)) {
1597
+ helper = "boolean";
1598
+ expression = "boolean()";
1599
+ } else if (SAFE_NUMBER_TYPES.has(label)) {
1600
+ helper = "number";
1601
+ expression = "number()";
1602
+ } else if (STRING_TYPES.has(label)) {
1603
+ helper = "string";
1604
+ expression = "string()";
1605
+ } else {
1606
+ helper = "string";
1607
+ expression = "string()";
1608
+ }
1609
+ if (column.isNullable) {
1610
+ expression = `${expression}.optional()`;
1611
+ }
1612
+ if (column.hasDefault) {
1613
+ expression = `${expression}.defaulted()`;
1614
+ }
1615
+ if (column.isGenerated) {
1616
+ expression = `${expression}.generated()`;
1617
+ }
1618
+ return { helper, expression };
1619
+ }
1620
+ function renderModelArtifact(descriptor, config) {
1621
+ const helperImports = /* @__PURE__ */ new Set(["table"]);
1622
+ const columnLines = Object.entries(descriptor.table.columns).map(([columnName, column]) => {
1623
+ const propertyName = escapeTypePropertyName(columnName);
1624
+ const rendered = renderColumnBuilder(column);
1625
+ helperImports.add(rendered.helper);
1626
+ return ` ${propertyName}: ${rendered.expression}`;
1627
+ }).join(",\n");
1628
+ const helperImportLine = Array.from(helperImports).sort().join(", ");
1629
+ const rowSchemaConstName = `${descriptor.tableConstName}_row_schema`;
1630
+ const insertSchemaConstName = `${descriptor.tableConstName}_insert_schema`;
1631
+ const updateSchemaConstName = `${descriptor.tableConstName}_update_schema`;
1632
+ const formSchemaConstName = `${descriptor.tableConstName}_form_schema`;
1633
+ const relationEntries = Object.entries(descriptor.table.relations);
1634
+ const relationsAssignment = config.features.emitRelations && relationEntries.length > 0 ? `
1635
+ Object.assign(${descriptor.tableConstName}.meta, {
1636
+ relations: {
1637
+ ${relationEntries.map(([relationKey2, relationValue]) => ` ${renderObjectKey(relationKey2)}: ${renderRelationLiteral(relationValue)}`).join(",\n")}
1638
+ }
1639
+ })
1640
+ ` : "";
1641
+ const content = `import { ${helperImportLine} } from '@xylex-group/athena'
1642
+ import type { FormValuesOf, InsertOf, RowOf, UpdateOf } from '@xylex-group/athena'
1643
+
1644
+ export const ${descriptor.tableConstName} = table(${escapeStringLiteral(descriptor.tableName)})
1645
+ .schema(${escapeStringLiteral(descriptor.schemaName)})
1646
+ .columns({
1647
+ ${columnLines}
1648
+ })
1649
+ .primaryKey(${descriptor.table.primaryKey.map((value) => escapeStringLiteral(value)).join(", ")})
1650
+ ${relationsAssignment ? `${relationsAssignment}` : ""}
1651
+ export type ${descriptor.rowTypeName} = RowOf<typeof ${descriptor.tableConstName}>
1652
+ export type ${descriptor.insertTypeName} = InsertOf<typeof ${descriptor.tableConstName}>
1653
+ export type ${descriptor.updateTypeName} = UpdateOf<typeof ${descriptor.tableConstName}>
1654
+ export type ${descriptor.formValuesTypeName} = FormValuesOf<typeof ${descriptor.tableConstName}>
1655
+
1656
+ export const ${rowSchemaConstName} = ${descriptor.tableConstName}.schemas.row
1657
+ export const ${insertSchemaConstName} = ${descriptor.tableConstName}.schemas.insert
1658
+ export const ${updateSchemaConstName} = ${descriptor.tableConstName}.schemas.update
1659
+ export const ${formSchemaConstName} = ${descriptor.tableConstName}.schemas.form
1660
+ `;
1661
+ return {
1662
+ kind: "model",
1663
+ path: descriptor.filePath,
1664
+ content
1665
+ };
1666
+ }
1667
+ function generateTableBuilderArtifactsFromSnapshot(snapshot, config) {
1668
+ const normalizedConfig = "internal" in config ? config : normalizeGeneratorConfig(config);
1669
+ return composeGeneratorArtifacts({
1670
+ snapshot,
1671
+ config: normalizedConfig,
1672
+ createModelDescriptor({ providerName, databaseName, schemaName, tableName, table }) {
1673
+ const tableConstName = toSafeIdentifier(tableName, "preserve", "table");
1674
+ return {
1675
+ schemaName,
1676
+ tableName,
1677
+ filePath: resolveOutputPath(
1678
+ normalizedConfig.output.targets.model,
1679
+ {
1680
+ provider: providerName,
1681
+ kind: "model",
1682
+ database: databaseName,
1683
+ schema: schemaName,
1684
+ model: tableName
1685
+ },
1686
+ normalizedConfig
1687
+ ),
1688
+ rowTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}Row`,
1689
+ insertTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}Insert`,
1690
+ updateTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}Update`,
1691
+ formValuesTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}FormValues`,
1692
+ tableConstName,
1693
+ exportConstName: tableConstName,
1694
+ table
1695
+ };
1696
+ },
1697
+ renderModelArtifact: (descriptor) => renderModelArtifact(descriptor, normalizedConfig)
1698
+ });
1699
+ }
1700
+
1701
+ // src/generator/renderer.ts
1702
+ function renderModelArtifact2(databaseName, descriptor, config) {
1703
+ const columnLines = Object.values(descriptor.table.columns).map((column) => {
1704
+ const propertyName = escapeTypePropertyName(column.name);
1705
+ const baseType = resolvePostgresColumnType(column);
1706
+ const isOptional = column.isNullable;
1707
+ const typeWithNullability = column.isNullable ? `${baseType} | null` : baseType;
1708
+ return ` ${propertyName}${isOptional ? "?" : ""}: ${typeWithNullability}`;
1709
+ }).join("\n");
1710
+ const nullableLines = Object.values(descriptor.table.columns).map((column) => ` ${renderObjectKey(column.name)}: ${column.isNullable ? "true" : "false"}`).join(",\n");
1711
+ const relationEntries = Object.entries(descriptor.table.relations);
1712
+ const relationBlock = config.features.emitRelations && relationEntries.length > 0 ? `,
1713
+ relations: {
1714
+ ${relationEntries.map(([relationKey2, relationValue]) => ` ${renderObjectKey(relationKey2)}: ${renderRelationLiteral(relationValue)}`).join(",\n")}
1715
+ }` : "";
1716
+ const content = `import { defineModel } from '@xylex-group/athena'
1717
+
1718
+ export interface ${descriptor.rowTypeName} {
1719
+ ${columnLines}
1720
+ }
1721
+
1722
+ export type ${descriptor.insertTypeName} = Partial<${descriptor.rowTypeName}>
1723
+ export type ${descriptor.updateTypeName} = Partial<${descriptor.insertTypeName}>
1724
+
1725
+ export const ${descriptor.modelConstName} = defineModel<${descriptor.rowTypeName}, ${descriptor.insertTypeName}, ${descriptor.updateTypeName}>({
1726
+ meta: {
1727
+ database: ${escapeStringLiteral(databaseName)},
1728
+ schema: ${escapeStringLiteral(descriptor.schemaName)},
1729
+ model: ${escapeStringLiteral(descriptor.tableName)},
1730
+ tableName: ${escapeStringLiteral(`${descriptor.schemaName}.${descriptor.tableName}`)},
1731
+ primaryKey: [${descriptor.table.primaryKey.map((value) => escapeStringLiteral(value)).join(", ")}],
1732
+ nullable: {
1733
+ ${nullableLines}
1734
+ }${relationBlock}
1735
+ }
1736
+ })
1737
+ `;
1738
+ return {
1739
+ kind: "model",
1740
+ path: descriptor.filePath,
1741
+ content
1742
+ };
1743
+ }
1407
1744
  function generateArtifactsFromSnapshot(snapshot, config) {
1408
- const normalizedConfig = "naming" in config && "features" in config && "experimental" in config ? config : normalizeGeneratorConfig(config);
1409
- return new ArtifactComposer(snapshot, normalizedConfig).compose();
1745
+ const normalizedConfig = "internal" in config ? config : normalizeGeneratorConfig(config);
1746
+ if (normalizedConfig.output.format === "table-builder") {
1747
+ return generateTableBuilderArtifactsFromSnapshot(snapshot, normalizedConfig);
1748
+ }
1749
+ return composeGeneratorArtifacts({
1750
+ snapshot,
1751
+ config: normalizedConfig,
1752
+ createModelDescriptor({ providerName, databaseName, schemaName, tableName, table }) {
1753
+ const modelConstName = toSafeIdentifier(
1754
+ `${schemaName} ${tableName} model`,
1755
+ normalizedConfig.naming.modelConst,
1756
+ "model"
1757
+ );
1758
+ return {
1759
+ schemaName,
1760
+ tableName,
1761
+ filePath: resolveOutputPath(
1762
+ normalizedConfig.output.targets.model,
1763
+ {
1764
+ provider: providerName,
1765
+ kind: "model",
1766
+ database: databaseName,
1767
+ schema: schemaName,
1768
+ model: tableName
1769
+ },
1770
+ normalizedConfig
1771
+ ),
1772
+ rowTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}Row`,
1773
+ insertTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}Insert`,
1774
+ updateTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}Update`,
1775
+ modelConstName,
1776
+ exportConstName: modelConstName,
1777
+ table
1778
+ };
1779
+ },
1780
+ renderModelArtifact: (descriptor) => renderModelArtifact2(snapshot.database, descriptor, normalizedConfig)
1781
+ });
1410
1782
  }
1411
1783
 
1412
1784
  // src/gateway/url.ts
@@ -1495,16 +1867,23 @@ var getSessionCookie = (request, config) => {
1495
1867
  const { cookieName = "session_token", cookiePrefix = "athena-auth" } = {};
1496
1868
  const parsedCookie = parseCookies(cookies);
1497
1869
  const getCookie = (name) => parsedCookie.get(name) || parsedCookie.get(`${SECURE_COOKIE_PREFIX}${name}`);
1498
- const sessionToken = getCookie(`${cookiePrefix}.${cookieName}`) || getCookie(`${cookiePrefix}-${cookieName}`);
1499
- if (sessionToken) {
1500
- return sessionToken;
1870
+ const candidateCookieNames = Array.from(/* @__PURE__ */ new Set([
1871
+ cookieName,
1872
+ cookieName.replace(/_/g, "-"),
1873
+ cookieName.replace(/-/g, "_")
1874
+ ])).filter(Boolean);
1875
+ for (const candidateName of candidateCookieNames) {
1876
+ const sessionToken = getCookie(`${cookiePrefix}.${candidateName}`) || getCookie(`${cookiePrefix}-${candidateName}`);
1877
+ if (sessionToken) {
1878
+ return sessionToken;
1879
+ }
1501
1880
  }
1502
1881
  return null;
1503
1882
  };
1504
1883
 
1505
1884
  // package.json
1506
1885
  var package_default = {
1507
- version: "2.6.0"
1886
+ version: "2.8.0"
1508
1887
  };
1509
1888
 
1510
1889
  // src/sdk-version.ts
@@ -3451,11 +3830,12 @@ function createAuthClient(config = {}) {
3451
3830
  // src/db/module.ts
3452
3831
  function createDbModule(input) {
3453
3832
  const db = {
3454
- from(table, options) {
3455
- return input.from(table, options);
3456
- },
3457
- select(table, columns, options) {
3458
- return input.from(table).select(columns, options);
3833
+ from: input.from,
3834
+ select(table, first, second) {
3835
+ if (first && typeof first === "object" && !Array.isArray(first)) {
3836
+ return input.from(table).select(void 0, first);
3837
+ }
3838
+ return input.from(table).select(first, second);
3459
3839
  },
3460
3840
  insert(table, values, options) {
3461
3841
  return Array.isArray(values) ? input.from(table).insert(values, options) : input.from(table).insert(values, options);
@@ -3479,6 +3859,344 @@ function createDbModule(input) {
3479
3859
  return db;
3480
3860
  }
3481
3861
 
3862
+ // src/storage/file.ts
3863
+ function createStorageFileModule(base, config = {}) {
3864
+ const upload = async (input, options) => {
3865
+ const sources = normalizeUploadSources(input);
3866
+ validateUploadConstraints(sources, input);
3867
+ const uploadRequests = sources.map((source, index) => {
3868
+ const storageKey = resolveUploadStorageKey(input, source, index, options, config);
3869
+ return {
3870
+ source,
3871
+ uploadRequest: {
3872
+ s3_id: input.s3_id,
3873
+ bucket: input.bucket,
3874
+ storage_key: storageKey,
3875
+ name: input.name ?? source.fileName,
3876
+ original_name: input.original_name ?? source.fileName,
3877
+ resource_id: input.resource_id ?? input.resourceId,
3878
+ mime_type: input.mime_type ?? source.contentType,
3879
+ content_type: input.content_type ?? source.contentType,
3880
+ size_bytes: source.sizeBytes,
3881
+ public: input.public,
3882
+ metadata: input.metadata
3883
+ }
3884
+ };
3885
+ });
3886
+ input.onProgress?.(createProgressSnapshot("preparing", sources, 0, 0, 0));
3887
+ const uploadUrls = uploadRequests.length === 1 ? [await base.createStorageUploadUrl(uploadRequests[0].uploadRequest, options)] : (await base.createStorageUploadUrls({ files: uploadRequests.map((request) => request.uploadRequest) }, options)).files;
3888
+ const aggregateLoaded = new Array(uploadRequests.length).fill(0);
3889
+ const uploaded = [];
3890
+ for (let index = 0; index < uploadRequests.length; index += 1) {
3891
+ const request = uploadRequests[index];
3892
+ const uploadUrl = uploadUrls[index];
3893
+ const response = await putUploadBody(uploadUrl.upload.url, request.source, input, options, (progress) => {
3894
+ aggregateLoaded[index] = progress.loaded;
3895
+ input.onProgress?.(createProgressSnapshot("uploading", sources, index, progress.loaded, sum(aggregateLoaded)));
3896
+ });
3897
+ uploaded.push({
3898
+ file: uploadUrl.file,
3899
+ upload: uploadUrl.upload,
3900
+ source: request.source.source,
3901
+ fileName: request.source.fileName,
3902
+ storage_key: request.uploadRequest.storage_key,
3903
+ response
3904
+ });
3905
+ aggregateLoaded[index] = request.source.sizeBytes;
3906
+ input.onProgress?.(createProgressSnapshot("complete", sources, index, request.source.sizeBytes, sum(aggregateLoaded)));
3907
+ }
3908
+ return {
3909
+ files: uploaded,
3910
+ count: uploaded.length
3911
+ };
3912
+ };
3913
+ const download = ((input, queryOrOptions, maybeOptions) => {
3914
+ const { fileIds, query, options } = normalizeDownloadArgs(input, queryOrOptions, maybeOptions);
3915
+ const downloads = fileIds.map((fileId) => base.getStorageFileProxy(fileId, query, options));
3916
+ return Array.isArray(input) || isRecord5(input) && Array.isArray(input.fileIds) ? Promise.all(downloads) : downloads[0];
3917
+ });
3918
+ const deleteFile = ((input, options) => {
3919
+ if (Array.isArray(input)) {
3920
+ return Promise.all(input.map((fileId) => base.deleteStorageFile(fileId, options)));
3921
+ }
3922
+ return base.deleteStorageFile(input, options);
3923
+ });
3924
+ return {
3925
+ upload,
3926
+ download,
3927
+ list(input, options) {
3928
+ const prefix = resolveStoragePath(input.prefix ?? "", input, options, config);
3929
+ return base.listStorageFiles(
3930
+ {
3931
+ s3_id: input.s3_id,
3932
+ prefix
3933
+ },
3934
+ options
3935
+ );
3936
+ },
3937
+ delete: deleteFile
3938
+ };
3939
+ }
3940
+ function resolveStoragePath(path, input, options, config = {}) {
3941
+ const context = createPathContext(input, options, config);
3942
+ const prefixPath = input.prefixPath ?? config.prefixPath;
3943
+ const prefix = typeof prefixPath === "function" ? prefixPath(context) : prefixPath;
3944
+ return joinStoragePath(renderStorageTemplate(prefix ?? "", context), renderStorageTemplate(path, context));
3945
+ }
3946
+ function resolveUploadStorageKey(input, source, index, options, config) {
3947
+ const explicitKey = input.storage_key ?? input.storageKey;
3948
+ const keyTemplate = input.storageKeyTemplate;
3949
+ const fallbackName = source.fileName;
3950
+ const context = createPathContext(input, options, config);
3951
+ const key = keyTemplate ? renderStorageTemplate(keyTemplate, {
3952
+ ...context,
3953
+ vars: {
3954
+ ...context.vars,
3955
+ index,
3956
+ fileName: source.fileName,
3957
+ name: source.fileName
3958
+ }
3959
+ }) : explicitKey ?? fallbackName;
3960
+ return resolveStoragePath(key, input, options, config);
3961
+ }
3962
+ function normalizeUploadSources(input) {
3963
+ const files = toArray(input.files);
3964
+ if (files.length === 0) {
3965
+ throw new Error("athena.storage.file.upload requires at least one file");
3966
+ }
3967
+ return files.map((source, index) => {
3968
+ const fileName = input.fileName ?? sourceName(source) ?? `file-${index + 1}`;
3969
+ const sizeBytes = sourceSize(source);
3970
+ const contentType = input.content_type ?? input.mime_type ?? sourceContentType(source);
3971
+ return {
3972
+ source,
3973
+ fileName,
3974
+ sizeBytes,
3975
+ contentType
3976
+ };
3977
+ });
3978
+ }
3979
+ function validateUploadConstraints(sources, input) {
3980
+ const maxFiles = input.maxFiles ?? 1;
3981
+ if (sources.length > maxFiles) {
3982
+ throw new Error(`athena.storage.file.upload accepts at most ${maxFiles} file${maxFiles === 1 ? "" : "s"} for this call`);
3983
+ }
3984
+ const maxFileSizeBytes = input.maxFileSizeBytes ?? (input.maxFileSizeMb === void 0 ? void 0 : Math.floor(input.maxFileSizeMb * 1024 * 1024));
3985
+ if (maxFileSizeBytes !== void 0) {
3986
+ const tooLarge = sources.find((source) => source.sizeBytes > maxFileSizeBytes);
3987
+ if (tooLarge) {
3988
+ throw new Error(`athena.storage.file.upload rejected ${tooLarge.fileName}: file exceeds ${maxFileSizeBytes} bytes`);
3989
+ }
3990
+ }
3991
+ const allowedExtensions = normalizeExtensions(input.allowedExtensions ?? input.extensions);
3992
+ if (allowedExtensions.size > 0) {
3993
+ const invalid = sources.find((source) => !allowedExtensions.has(fileExtension(source.fileName)));
3994
+ if (invalid) {
3995
+ throw new Error(`athena.storage.file.upload rejected ${invalid.fileName}: extension is not allowed`);
3996
+ }
3997
+ }
3998
+ }
3999
+ async function putUploadBody(url, source, input, options, onProgress) {
4000
+ const headers = new Headers(input.uploadHeaders);
4001
+ if (source.contentType && !headers.has("Content-Type")) {
4002
+ headers.set("Content-Type", source.contentType);
4003
+ }
4004
+ if (typeof XMLHttpRequest !== "undefined") {
4005
+ return putUploadBodyWithXhr(url, source, headers, options, onProgress);
4006
+ }
4007
+ onProgress({ loaded: 0 });
4008
+ const response = await fetch(url, {
4009
+ method: "PUT",
4010
+ headers,
4011
+ body: source.source,
4012
+ signal: options?.signal
4013
+ });
4014
+ if (!response.ok) {
4015
+ throw new Error(`athena.storage.file.upload failed with status ${response.status}`);
4016
+ }
4017
+ onProgress({ loaded: source.sizeBytes });
4018
+ return response;
4019
+ }
4020
+ function putUploadBodyWithXhr(url, source, headers, options, onProgress) {
4021
+ const Xhr = XMLHttpRequest;
4022
+ if (Xhr === void 0) {
4023
+ return Promise.reject(new Error("athena.storage.file.upload requires XMLHttpRequest in this runtime"));
4024
+ }
4025
+ return new Promise((resolve3, reject) => {
4026
+ const xhr = new Xhr();
4027
+ const abort = () => xhr.abort();
4028
+ xhr.open("PUT", url);
4029
+ headers.forEach((value, key) => xhr.setRequestHeader(key, value));
4030
+ xhr.upload.onprogress = (event) => {
4031
+ onProgress({ loaded: event.loaded });
4032
+ };
4033
+ xhr.onload = () => {
4034
+ if (options?.signal) {
4035
+ options.signal.removeEventListener("abort", abort);
4036
+ }
4037
+ if (xhr.status < 200 || xhr.status >= 300) {
4038
+ reject(new Error(`athena.storage.file.upload failed with status ${xhr.status}`));
4039
+ return;
4040
+ }
4041
+ onProgress({ loaded: source.sizeBytes });
4042
+ resolve3(new Response(xhr.response, {
4043
+ status: xhr.status,
4044
+ statusText: xhr.statusText,
4045
+ headers: parseXhrHeaders(xhr.getAllResponseHeaders())
4046
+ }));
4047
+ };
4048
+ xhr.onerror = () => {
4049
+ if (options?.signal) {
4050
+ options.signal.removeEventListener("abort", abort);
4051
+ }
4052
+ reject(new Error("athena.storage.file.upload failed with a network error"));
4053
+ };
4054
+ xhr.onabort = () => {
4055
+ if (options?.signal) {
4056
+ options.signal.removeEventListener("abort", abort);
4057
+ }
4058
+ reject(new DOMException("Upload aborted", "AbortError"));
4059
+ };
4060
+ if (options?.signal) {
4061
+ if (options.signal.aborted) {
4062
+ abort();
4063
+ return;
4064
+ }
4065
+ options.signal.addEventListener("abort", abort, { once: true });
4066
+ }
4067
+ xhr.send(source.source);
4068
+ });
4069
+ }
4070
+ function normalizeDownloadArgs(input, queryOrOptions, maybeOptions) {
4071
+ if (typeof input === "string") {
4072
+ return { fileIds: [input], query: queryOrOptions, options: maybeOptions };
4073
+ }
4074
+ if (Array.isArray(input)) {
4075
+ return { fileIds: [...input], query: queryOrOptions, options: maybeOptions };
4076
+ }
4077
+ const downloadInput = input;
4078
+ const { fileId, fileIds, ...query } = downloadInput;
4079
+ return {
4080
+ fileIds: fileIds ? [...fileIds] : fileId ? [fileId] : [],
4081
+ query,
4082
+ options: queryOrOptions
4083
+ };
4084
+ }
4085
+ function createPathContext(input, options, config) {
4086
+ const organizationId = input.organizationId ?? input.organization_id ?? options?.organizationId ?? void 0;
4087
+ const userId = input.userId ?? input.user_id ?? options?.userId ?? void 0;
4088
+ const resourceId = input.resourceId ?? input.resource_id ?? void 0;
4089
+ const vars = {
4090
+ ...config.vars ?? {},
4091
+ ...input.vars ?? {}
4092
+ };
4093
+ if (organizationId !== void 0) {
4094
+ vars.organizationId = organizationId;
4095
+ vars.organization_id = organizationId;
4096
+ }
4097
+ if (userId !== void 0) {
4098
+ vars.userId = userId;
4099
+ vars.user_id = userId;
4100
+ }
4101
+ if (resourceId !== void 0) {
4102
+ vars.resourceId = resourceId;
4103
+ vars.resource_id = resourceId;
4104
+ }
4105
+ return {
4106
+ vars,
4107
+ env: {
4108
+ ...readProcessEnv(),
4109
+ ...config.env ?? {},
4110
+ ...input.env ?? {}
4111
+ },
4112
+ organizationId,
4113
+ organization_id: organizationId,
4114
+ userId,
4115
+ user_id: userId,
4116
+ resourceId,
4117
+ resource_id: resourceId
4118
+ };
4119
+ }
4120
+ function renderStorageTemplate(template, context) {
4121
+ return template.replace(/\$\{([^}]+)\}|\{([^}]+)\}/g, (_match, shellToken, braceToken) => {
4122
+ const token = (shellToken ?? braceToken ?? "").trim();
4123
+ if (!token) return "";
4124
+ const value = resolveTemplateToken(token, context);
4125
+ return value === void 0 || value === null ? "" : String(value);
4126
+ });
4127
+ }
4128
+ function resolveTemplateToken(token, context) {
4129
+ if (token.startsWith("env.")) {
4130
+ return context.env[token.slice(4)];
4131
+ }
4132
+ if (token in context.vars) {
4133
+ return context.vars[token];
4134
+ }
4135
+ return context.env[token];
4136
+ }
4137
+ function joinStoragePath(...parts) {
4138
+ return parts.map((part) => part.trim().replace(/^\/+|\/+$/g, "")).filter(Boolean).join("/");
4139
+ }
4140
+ function toArray(files) {
4141
+ if (isUploadSource(files)) return [files];
4142
+ return Array.from(files);
4143
+ }
4144
+ function isUploadSource(value) {
4145
+ return value instanceof Blob || value instanceof ArrayBuffer || value instanceof Uint8Array;
4146
+ }
4147
+ function sourceName(source) {
4148
+ return isRecord5(source) && typeof source.name === "string" && source.name.trim() ? source.name.trim() : void 0;
4149
+ }
4150
+ function sourceSize(source) {
4151
+ if (source instanceof Blob) return source.size;
4152
+ return source.byteLength;
4153
+ }
4154
+ function sourceContentType(source) {
4155
+ return source instanceof Blob && source.type.trim() ? source.type.trim() : void 0;
4156
+ }
4157
+ function normalizeExtensions(extensions) {
4158
+ return new Set((extensions ?? []).map((extension) => extension.replace(/^\./, "").toLowerCase()).filter(Boolean));
4159
+ }
4160
+ function fileExtension(fileName) {
4161
+ const lastDot = fileName.lastIndexOf(".");
4162
+ return lastDot === -1 ? "" : fileName.slice(lastDot + 1).toLowerCase();
4163
+ }
4164
+ function createProgressSnapshot(phase, sources, fileIndex, loaded, aggregateLoaded) {
4165
+ const total = sources[fileIndex]?.sizeBytes ?? 0;
4166
+ const aggregateTotal = sources.reduce((totalBytes, source) => totalBytes + source.sizeBytes, 0);
4167
+ return {
4168
+ phase,
4169
+ fileIndex,
4170
+ fileCount: sources.length,
4171
+ fileName: sources[fileIndex]?.fileName ?? "",
4172
+ loaded,
4173
+ total,
4174
+ percent: total > 0 ? Math.round(loaded / total * 100) : 100,
4175
+ aggregateLoaded,
4176
+ aggregateTotal,
4177
+ aggregatePercent: aggregateTotal > 0 ? Math.round(aggregateLoaded / aggregateTotal * 100) : 100
4178
+ };
4179
+ }
4180
+ function sum(values) {
4181
+ return values.reduce((total, value) => total + value, 0);
4182
+ }
4183
+ function parseXhrHeaders(raw) {
4184
+ const headers = new Headers();
4185
+ for (const line of raw.trim().split(/[\r\n]+/)) {
4186
+ const index = line.indexOf(":");
4187
+ if (index === -1) continue;
4188
+ headers.set(line.slice(0, index).trim(), line.slice(index + 1).trim());
4189
+ }
4190
+ return headers;
4191
+ }
4192
+ function readProcessEnv() {
4193
+ const processLike = globalThis.process;
4194
+ return processLike?.env ?? {};
4195
+ }
4196
+ function isRecord5(value) {
4197
+ return Boolean(value) && typeof value === "object";
4198
+ }
4199
+
3482
4200
  // src/storage/module.ts
3483
4201
  var storageSdkManifest = {
3484
4202
  methods: [
@@ -3673,7 +4391,7 @@ var AthenaStorageError = class extends Error {
3673
4391
  };
3674
4392
  }
3675
4393
  };
3676
- function isRecord5(value) {
4394
+ function isRecord6(value) {
3677
4395
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
3678
4396
  }
3679
4397
  function causeToString(cause) {
@@ -3784,11 +4502,20 @@ function appendQuery(path, query) {
3784
4502
  function storagePath(path) {
3785
4503
  return path;
3786
4504
  }
4505
+ function resolveStorageEndpointPath(endpoint, runtimeOptions) {
4506
+ if (!runtimeOptions?.stripBasePath) {
4507
+ return endpoint;
4508
+ }
4509
+ const [pathname, queryText] = String(endpoint).split("?", 2);
4510
+ const trimmedPathname = pathname.startsWith("/storage/") ? pathname.slice("/storage".length) : pathname === "/storage" ? "/" : pathname;
4511
+ const resolvedPath = trimmedPathname.startsWith("/") ? trimmedPathname : `/${trimmedPathname}`;
4512
+ return storagePath(queryText ? `${resolvedPath}?${queryText}` : resolvedPath);
4513
+ }
3787
4514
  function withPathParam(path, name, value) {
3788
4515
  return path.replace(`{${name}}`, encodeURIComponent(value));
3789
4516
  }
3790
4517
  function resolveErrorMessage3(payload, fallback) {
3791
- if (isRecord5(payload)) {
4518
+ if (isRecord6(payload)) {
3792
4519
  const message = payload.message ?? payload.error ?? payload.details;
3793
4520
  if (typeof message === "string" && message.trim()) {
3794
4521
  return message.trim();
@@ -3800,12 +4527,12 @@ function resolveErrorMessage3(payload, fallback) {
3800
4527
  return fallback;
3801
4528
  }
3802
4529
  function resolveErrorHint2(payload) {
3803
- if (!isRecord5(payload)) return void 0;
4530
+ if (!isRecord6(payload)) return void 0;
3804
4531
  const hint = payload.hint ?? payload.suggestion;
3805
4532
  return typeof hint === "string" && hint.trim() ? hint.trim() : void 0;
3806
4533
  }
3807
4534
  function resolveErrorCause(payload) {
3808
- if (!isRecord5(payload)) return void 0;
4535
+ if (!isRecord6(payload)) return void 0;
3809
4536
  const cause = payload.cause ?? payload.reason;
3810
4537
  return typeof cause === "string" && cause.trim() ? cause.trim() : void 0;
3811
4538
  }
@@ -3822,8 +4549,8 @@ async function callStorageEndpoint(gateway, endpoint, method, envelope, payload,
3822
4549
  let url;
3823
4550
  let headers;
3824
4551
  try {
3825
- const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : gateway.baseUrl;
3826
- url = buildAthenaGatewayUrl(baseUrl, endpoint);
4552
+ const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : runtimeOptions?.baseUrl ? normalizeAthenaGatewayBaseUrl(runtimeOptions.baseUrl) : gateway.baseUrl;
4553
+ url = buildAthenaGatewayUrl(baseUrl, resolveStorageEndpointPath(endpoint, runtimeOptions));
3827
4554
  headers = gateway.buildHeaders(options);
3828
4555
  } catch (error) {
3829
4556
  return rejectStorageError(
@@ -3924,7 +4651,7 @@ async function callStorageEndpoint(gateway, endpoint, method, envelope, payload,
3924
4651
  );
3925
4652
  }
3926
4653
  if (envelope === "athena") {
3927
- if (!isRecord5(parsedBody.parsed) || !("data" in parsedBody.parsed)) {
4654
+ if (!isRecord6(parsedBody.parsed) || !("data" in parsedBody.parsed)) {
3928
4655
  return rejectStorageError(
3929
4656
  {
3930
4657
  code: "INVALID_ATHENA_ENVELOPE",
@@ -3947,8 +4674,8 @@ async function callStorageBinaryEndpoint(gateway, endpoint, method, options, run
3947
4674
  let url;
3948
4675
  let headers;
3949
4676
  try {
3950
- const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : gateway.baseUrl;
3951
- url = buildAthenaGatewayUrl(baseUrl, endpoint);
4677
+ const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : runtimeOptions?.baseUrl ? normalizeAthenaGatewayBaseUrl(runtimeOptions.baseUrl) : gateway.baseUrl;
4678
+ url = buildAthenaGatewayUrl(baseUrl, resolveStorageEndpointPath(endpoint, runtimeOptions));
3952
4679
  headers = gateway.buildHeaders(options);
3953
4680
  } catch (error) {
3954
4681
  return rejectStorageError(
@@ -4032,129 +4759,515 @@ async function callStorageBinaryEndpoint(gateway, endpoint, method, options, run
4032
4759
  runtimeOptions
4033
4760
  );
4034
4761
  }
4035
- function createStorageModule(gateway, runtimeOptions) {
4762
+ function isBlobBody(body) {
4763
+ return typeof Blob !== "undefined" && body instanceof Blob;
4764
+ }
4765
+ function isReadableStreamBody(body) {
4766
+ return typeof ReadableStream !== "undefined" && body instanceof ReadableStream;
4767
+ }
4768
+ async function putPresignedUploadBody(uploadUrl, uploadHeaders, body, options) {
4769
+ const headers = new Headers(uploadHeaders);
4770
+ Object.entries(options?.headers ?? {}).forEach(([key, value]) => headers.set(key, value));
4771
+ if (!headers.has("Content-Type") && isBlobBody(body) && body.type) {
4772
+ headers.set("Content-Type", body.type);
4773
+ }
4774
+ const init = {
4775
+ method: "PUT",
4776
+ headers,
4777
+ body,
4778
+ signal: options?.signal
4779
+ };
4780
+ if (isReadableStreamBody(body)) {
4781
+ init.duplex = "half";
4782
+ }
4783
+ return fetch(uploadUrl, init);
4784
+ }
4785
+ function attachManagedUpload(upload) {
4786
+ const headers = {};
4036
4787
  return {
4037
- listStorageCatalogs(options) {
4038
- return callStorageEndpoint(gateway, storagePath("/storage/catalogs"), "GET", "raw", void 0, options, runtimeOptions);
4039
- },
4040
- createStorageCatalog(input, options) {
4041
- return callStorageEndpoint(gateway, storagePath("/storage/catalogs"), "POST", "raw", input, options, runtimeOptions);
4042
- },
4043
- updateStorageCatalog(id, input, options) {
4044
- return callStorageEndpoint(
4045
- gateway,
4046
- storagePath(withPathParam("/storage/catalogs/{id}", "id", id)),
4047
- "PATCH",
4048
- "raw",
4049
- input,
4050
- options,
4051
- runtimeOptions
4052
- );
4053
- },
4054
- deleteStorageCatalog(id, options) {
4055
- return callStorageEndpoint(
4056
- gateway,
4057
- storagePath(withPathParam("/storage/catalogs/{id}", "id", id)),
4058
- "DELETE",
4059
- "raw",
4060
- void 0,
4061
- options,
4062
- runtimeOptions
4063
- );
4788
+ ...upload,
4789
+ method: "PUT",
4790
+ headers,
4791
+ expiresAt: upload.expires_at,
4792
+ put(body, options) {
4793
+ return putPresignedUploadBody(upload.url, headers, body, options);
4794
+ }
4795
+ };
4796
+ }
4797
+ function attachUploadHelper(response) {
4798
+ return {
4799
+ ...response,
4800
+ upload: attachManagedUpload(response.upload)
4801
+ };
4802
+ }
4803
+ function attachUploadHelpers(response) {
4804
+ return {
4805
+ files: response.files.map(attachUploadHelper)
4806
+ };
4807
+ }
4808
+ function normalizeUploadUrlRequest(input) {
4809
+ const s3_id = input.s3_id ?? input.s3Id;
4810
+ const storage_key = input.storage_key ?? input.storageKey;
4811
+ if (!s3_id?.trim()) {
4812
+ throw new Error("athena.storage.file.upload requires s3_id or s3Id");
4813
+ }
4814
+ if (!storage_key?.trim()) {
4815
+ throw new Error("athena.storage.file.upload requires storage_key or storageKey");
4816
+ }
4817
+ const fileName = input.fileName?.trim();
4818
+ const originalName = input.originalName?.trim();
4819
+ return {
4820
+ s3_id,
4821
+ bucket: input.bucket,
4822
+ storage_key,
4823
+ name: input.name ?? fileName,
4824
+ original_name: input.original_name ?? originalName ?? fileName,
4825
+ resource_id: input.resource_id ?? input.resourceId,
4826
+ mime_type: input.mime_type ?? input.mimeType,
4827
+ content_type: input.content_type ?? input.contentType,
4828
+ size_bytes: input.size_bytes ?? input.sizeBytes,
4829
+ file_id: input.file_id ?? input.fileId,
4830
+ public: input.public,
4831
+ visibility: input.visibility,
4832
+ metadata: input.metadata
4833
+ };
4834
+ }
4835
+ async function callStorageUploadBinaryEndpoint(gateway, endpoint, body, options, runtimeOptions) {
4836
+ let url;
4837
+ let headers;
4838
+ try {
4839
+ const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : runtimeOptions?.baseUrl ? normalizeAthenaGatewayBaseUrl(runtimeOptions.baseUrl) : gateway.baseUrl;
4840
+ url = buildAthenaGatewayUrl(baseUrl, resolveStorageEndpointPath(endpoint, runtimeOptions));
4841
+ headers = gateway.buildHeaders(options);
4842
+ } catch (error) {
4843
+ return rejectStorageError(
4844
+ {
4845
+ code: storageCodeFromUnknown(error),
4846
+ message: error instanceof Error ? error.message : `Athena storage PUT ${endpoint} failed before sending the request`,
4847
+ status: isAthenaGatewayError(error) ? error.status : 0,
4848
+ endpoint,
4849
+ method: "PUT",
4850
+ raw: error,
4851
+ requestId: isAthenaGatewayError(error) ? error.requestId : void 0,
4852
+ hint: isAthenaGatewayError(error) ? error.hint : void 0,
4853
+ cause: error
4854
+ },
4855
+ options,
4856
+ runtimeOptions
4857
+ );
4858
+ }
4859
+ delete headers["Content-Type"];
4860
+ delete headers["content-type"];
4861
+ if (isBlobBody(body) && body.type) {
4862
+ headers["Content-Type"] = body.type;
4863
+ }
4864
+ const requestInit = {
4865
+ method: "PUT",
4866
+ headers,
4867
+ body,
4868
+ signal: options?.signal
4869
+ };
4870
+ if (isReadableStreamBody(body)) {
4871
+ requestInit.duplex = "half";
4872
+ }
4873
+ let response;
4874
+ try {
4875
+ response = await fetch(url, requestInit);
4876
+ } catch (error) {
4877
+ const message = error instanceof Error ? error.message : String(error);
4878
+ return rejectStorageError(
4879
+ {
4880
+ code: "NETWORK_ERROR",
4881
+ message: `Network error while calling Athena storage PUT ${endpoint}: ${message}`,
4882
+ status: 0,
4883
+ endpoint,
4884
+ method: "PUT",
4885
+ cause: error
4886
+ },
4887
+ options,
4888
+ runtimeOptions
4889
+ );
4890
+ }
4891
+ let rawText;
4892
+ try {
4893
+ rawText = await response.text();
4894
+ } catch (error) {
4895
+ return rejectStorageError(
4896
+ {
4897
+ code: "NETWORK_ERROR",
4898
+ message: `Athena storage PUT ${endpoint} response body could not be read`,
4899
+ status: response.status,
4900
+ endpoint,
4901
+ method: "PUT",
4902
+ requestId: headerValue(response.headers, ["x-athena-request-id", "x-request-id", "request-id"]),
4903
+ cause: error
4904
+ },
4905
+ options,
4906
+ runtimeOptions
4907
+ );
4908
+ }
4909
+ const parsedBody = parseResponseBody3(rawText ?? "", response.headers.get("content-type"));
4910
+ const requestId = headerValue(response.headers, ["x-athena-request-id", "x-request-id", "request-id"]);
4911
+ if (parsedBody.parseFailed) {
4912
+ return rejectStorageError(
4913
+ {
4914
+ code: "INVALID_JSON",
4915
+ message: `Athena storage PUT ${endpoint} returned malformed JSON`,
4916
+ status: response.status,
4917
+ endpoint,
4918
+ method: "PUT",
4919
+ requestId,
4920
+ raw: parsedBody.parsed
4921
+ },
4922
+ options,
4923
+ runtimeOptions
4924
+ );
4925
+ }
4926
+ if (!response.ok) {
4927
+ return rejectStorageError(
4928
+ {
4929
+ code: "HTTP_ERROR",
4930
+ message: resolveErrorMessage3(
4931
+ parsedBody.parsed,
4932
+ `Athena storage PUT ${endpoint} failed with status ${response.status}`
4933
+ ),
4934
+ status: response.status,
4935
+ endpoint,
4936
+ method: "PUT",
4937
+ requestId,
4938
+ hint: resolveErrorHint2(parsedBody.parsed),
4939
+ cause: resolveErrorCause(parsedBody.parsed),
4940
+ raw: parsedBody.parsed
4941
+ },
4942
+ options,
4943
+ runtimeOptions
4944
+ );
4945
+ }
4946
+ if (!isRecord6(parsedBody.parsed) || !("data" in parsedBody.parsed)) {
4947
+ return rejectStorageError(
4948
+ {
4949
+ code: "INVALID_ATHENA_ENVELOPE",
4950
+ message: `Athena storage PUT ${endpoint} returned an invalid Athena envelope`,
4951
+ status: response.status,
4952
+ endpoint,
4953
+ method: "PUT",
4954
+ requestId,
4955
+ raw: parsedBody.parsed
4956
+ },
4957
+ options,
4958
+ runtimeOptions
4959
+ );
4960
+ }
4961
+ return parsedBody.parsed.data;
4962
+ }
4963
+ function createStorageModule(gateway, runtimeOptions) {
4964
+ const resolvedRuntimeOptions = runtimeOptions;
4965
+ const callRaw = (path, method, payload, options) => callStorageEndpoint(
4966
+ gateway,
4967
+ storagePath(path),
4968
+ method,
4969
+ "raw",
4970
+ payload,
4971
+ options,
4972
+ resolvedRuntimeOptions
4973
+ );
4974
+ const callAthena2 = (path, method, payload, options) => callStorageEndpoint(
4975
+ gateway,
4976
+ storagePath(path),
4977
+ method,
4978
+ "athena",
4979
+ payload,
4980
+ options,
4981
+ resolvedRuntimeOptions
4982
+ );
4983
+ const base = {
4984
+ listStorageCatalogs(options) {
4985
+ return callRaw("/storage/catalogs", "GET", void 0, options);
4986
+ },
4987
+ createStorageCatalog(input, options) {
4988
+ return callRaw("/storage/catalogs", "POST", input, options);
4989
+ },
4990
+ updateStorageCatalog(id, input, options) {
4991
+ return callRaw(withPathParam("/storage/catalogs/{id}", "id", id), "PATCH", input, options);
4992
+ },
4993
+ deleteStorageCatalog(id, options) {
4994
+ return callRaw(withPathParam("/storage/catalogs/{id}", "id", id), "DELETE", void 0, options);
4064
4995
  },
4065
4996
  listStorageCredentials(options) {
4066
- return callStorageEndpoint(gateway, storagePath("/storage/credentials"), "GET", "raw", void 0, options, runtimeOptions);
4997
+ return callRaw("/storage/credentials", "GET", void 0, options);
4067
4998
  },
4068
4999
  createStorageUploadUrl(input, options) {
4069
- return callStorageEndpoint(
4070
- gateway,
4071
- storagePath("/storage/files/upload-url"),
4072
- "POST",
4073
- "athena",
4074
- input,
4075
- options,
4076
- runtimeOptions
4077
- );
5000
+ return callAthena2("/storage/files/upload-url", "POST", input, options);
4078
5001
  },
4079
5002
  createStorageUploadUrls(input, options) {
4080
- return callStorageEndpoint(
4081
- gateway,
4082
- storagePath("/storage/files/upload-urls"),
4083
- "POST",
4084
- "athena",
4085
- input,
4086
- options,
4087
- runtimeOptions
4088
- );
5003
+ return callAthena2("/storage/files/upload-urls", "POST", input, options);
4089
5004
  },
4090
5005
  listStorageFiles(input, options) {
4091
- return callStorageEndpoint(gateway, storagePath("/storage/files/list"), "POST", "athena", input, options, runtimeOptions);
5006
+ return callAthena2("/storage/files/list", "POST", input, options);
4092
5007
  },
4093
5008
  getStorageFile(fileId, options) {
4094
- return callStorageEndpoint(
4095
- gateway,
4096
- storagePath(withPathParam("/storage/files/{file_id}", "file_id", fileId)),
4097
- "GET",
4098
- "athena",
4099
- void 0,
4100
- options,
4101
- runtimeOptions
4102
- );
5009
+ return callAthena2(withPathParam("/storage/files/{file_id}", "file_id", fileId), "GET", void 0, options);
4103
5010
  },
4104
5011
  getStorageFileUrl(fileId, query, options) {
4105
5012
  const path = appendQuery(
4106
5013
  withPathParam("/storage/files/{file_id}/url", "file_id", fileId),
4107
5014
  query
4108
5015
  );
4109
- return callStorageEndpoint(gateway, storagePath(path), "GET", "athena", void 0, options, runtimeOptions);
5016
+ return callAthena2(path, "GET", void 0, options);
4110
5017
  },
4111
5018
  getStorageFileProxy(fileId, query, options) {
4112
5019
  const path = appendQuery(
4113
5020
  withPathParam("/storage/files/{file_id}/proxy", "file_id", fileId),
4114
5021
  query
4115
5022
  );
4116
- return callStorageBinaryEndpoint(gateway, storagePath(path), "GET", options, runtimeOptions);
5023
+ return callStorageBinaryEndpoint(gateway, storagePath(path), "GET", options, resolvedRuntimeOptions);
4117
5024
  },
4118
5025
  updateStorageFile(fileId, input, options) {
4119
- return callStorageEndpoint(
4120
- gateway,
4121
- storagePath(withPathParam("/storage/files/{file_id}", "file_id", fileId)),
4122
- "PATCH",
4123
- "athena",
4124
- input,
4125
- options,
4126
- runtimeOptions
4127
- );
5026
+ return callAthena2(withPathParam("/storage/files/{file_id}", "file_id", fileId), "PATCH", input, options);
4128
5027
  },
4129
5028
  deleteStorageFile(fileId, options) {
4130
- return callStorageEndpoint(
4131
- gateway,
4132
- storagePath(withPathParam("/storage/files/{file_id}", "file_id", fileId)),
4133
- "DELETE",
4134
- "athena",
4135
- void 0,
4136
- options,
4137
- runtimeOptions
4138
- );
5029
+ return callAthena2(withPathParam("/storage/files/{file_id}", "file_id", fileId), "DELETE", void 0, options);
4139
5030
  },
4140
5031
  setStorageFileVisibility(fileId, input, options) {
4141
- return callStorageEndpoint(
5032
+ return callAthena2(withPathParam("/storage/files/{file_id}/visibility", "file_id", fileId), "PATCH", input, options);
5033
+ },
5034
+ deleteStorageFolder(input, options) {
5035
+ return callAthena2("/storage/folders/delete", "POST", input, options);
5036
+ },
5037
+ moveStorageFolder(input, options) {
5038
+ return callAthena2("/storage/folders/move", "POST", input, options);
5039
+ }
5040
+ };
5041
+ const fileFacade = createStorageFileModule(base, runtimeOptions);
5042
+ const fileUpload = ((input, options) => {
5043
+ if (isRecord6(input) && "files" in input) {
5044
+ return fileFacade.upload(input, options);
5045
+ }
5046
+ return base.createStorageUploadUrl(
5047
+ normalizeUploadUrlRequest(input),
5048
+ options
5049
+ ).then(attachUploadHelper);
5050
+ });
5051
+ const fileDelete = ((input, options) => fileFacade.delete(input, options));
5052
+ const file = {
5053
+ ...fileFacade,
5054
+ upload: fileUpload,
5055
+ uploadMany(input, options) {
5056
+ return base.createStorageUploadUrls(
5057
+ { files: input.files.map(normalizeUploadUrlRequest) },
5058
+ options
5059
+ ).then(attachUploadHelpers);
5060
+ },
5061
+ confirmUpload(fileId, input, options) {
5062
+ return callAthena2(withPathParam("/storage/files/{file_id}/confirm-upload", "file_id", fileId), "POST", input ?? {}, options);
5063
+ },
5064
+ uploadBinary(fileId, body, options) {
5065
+ return callStorageUploadBinaryEndpoint(
4142
5066
  gateway,
4143
- storagePath(withPathParam("/storage/files/{file_id}/visibility", "file_id", fileId)),
4144
- "PATCH",
4145
- "athena",
4146
- input,
5067
+ storagePath(withPathParam("/storage/files/{file_id}/upload", "file_id", fileId)),
5068
+ body,
4147
5069
  options,
4148
- runtimeOptions
5070
+ resolvedRuntimeOptions
4149
5071
  );
4150
5072
  },
4151
- deleteStorageFolder(input, options) {
4152
- return callStorageEndpoint(gateway, storagePath("/storage/folders/delete"), "POST", "athena", input, options, runtimeOptions);
5073
+ search(input, options) {
5074
+ return callAthena2("/storage/files/search", "POST", input, options);
4153
5075
  },
4154
- moveStorageFolder(input, options) {
4155
- return callStorageEndpoint(gateway, storagePath("/storage/folders/move"), "POST", "athena", input, options, runtimeOptions);
5076
+ get(fileId, options) {
5077
+ return base.getStorageFile(fileId, options);
5078
+ },
5079
+ update(fileId, input, options) {
5080
+ return base.updateStorageFile(fileId, input, options);
5081
+ },
5082
+ delete: fileDelete,
5083
+ deleteMany(input, options) {
5084
+ return callAthena2("/storage/files/delete-many", "POST", input, options);
5085
+ },
5086
+ updateMany(input, options) {
5087
+ return callAthena2("/storage/files/update-many", "POST", input, options);
5088
+ },
5089
+ restore(fileId, options) {
5090
+ return callAthena2(withPathParam("/storage/files/{file_id}/restore", "file_id", fileId), "POST", {}, options);
5091
+ },
5092
+ purge(fileId, options) {
5093
+ return callAthena2(withPathParam("/storage/files/{file_id}/purge", "file_id", fileId), "DELETE", void 0, options);
5094
+ },
5095
+ copy(fileId, input, options) {
5096
+ return callAthena2(withPathParam("/storage/files/{file_id}/copy", "file_id", fileId), "POST", input, options);
5097
+ },
5098
+ url(fileId, query, options) {
5099
+ return base.getStorageFileUrl(fileId, query, options);
5100
+ },
5101
+ publicUrl(fileId, options) {
5102
+ return callAthena2(withPathParam("/storage/files/{file_id}/public-url", "file_id", fileId), "GET", void 0, options);
5103
+ },
5104
+ proxy(fileId, query, options) {
5105
+ return base.getStorageFileProxy(fileId, query, options);
5106
+ },
5107
+ visibility: {
5108
+ set(fileId, input, options) {
5109
+ return base.setStorageFileVisibility(fileId, input, options);
5110
+ },
5111
+ setMany(input, options) {
5112
+ return callAthena2("/storage/files/visibility-many", "POST", input, options);
5113
+ }
5114
+ }
5115
+ };
5116
+ const credentials = {
5117
+ list(options) {
5118
+ return base.listStorageCredentials(options);
5119
+ }
5120
+ };
5121
+ const catalog = {
5122
+ list(options) {
5123
+ return base.listStorageCatalogs(options);
5124
+ },
5125
+ create(input, options) {
5126
+ return base.createStorageCatalog(input, options);
5127
+ },
5128
+ update(id, input, options) {
5129
+ return base.updateStorageCatalog(id, input, options);
5130
+ },
5131
+ delete(id, options) {
5132
+ return base.deleteStorageCatalog(id, options);
5133
+ }
5134
+ };
5135
+ const folder = {
5136
+ list(input, options) {
5137
+ return callAthena2("/storage/folders/list", "POST", input, options);
5138
+ },
5139
+ tree(input, options) {
5140
+ return callAthena2("/storage/folders/tree", "POST", input, options);
5141
+ },
5142
+ delete(input, options) {
5143
+ return base.deleteStorageFolder(input, options);
5144
+ },
5145
+ move(input, options) {
5146
+ return base.moveStorageFolder(input, options);
5147
+ }
5148
+ };
5149
+ const permission = {
5150
+ list(input, options) {
5151
+ return callAthena2("/storage/permissions/list", "POST", input, options);
5152
+ },
5153
+ grant(input, options) {
5154
+ return callAthena2("/storage/permissions/grant", "POST", input, options);
5155
+ },
5156
+ revoke(input, options) {
5157
+ return callAthena2("/storage/permissions/revoke", "POST", input, options);
5158
+ },
5159
+ check(input, options) {
5160
+ return callAthena2("/storage/permissions/check", "POST", input, options);
5161
+ }
5162
+ };
5163
+ const objectFolder = {
5164
+ create(input, options) {
5165
+ return callAthena2("/storage/objects/folder", "POST", input, options);
5166
+ },
5167
+ delete(input, options) {
5168
+ return callAthena2("/storage/objects/folder/delete", "POST", input, options);
5169
+ },
5170
+ rename(input, options) {
5171
+ return callAthena2("/storage/objects/folder/rename", "POST", input, options);
4156
5172
  }
4157
5173
  };
5174
+ const object = {
5175
+ list(input, options) {
5176
+ return callAthena2("/storage/objects", "POST", input, options);
5177
+ },
5178
+ head(input, options) {
5179
+ return callAthena2("/storage/objects/head", "POST", input, options);
5180
+ },
5181
+ exists(input, options) {
5182
+ return callAthena2("/storage/objects/exists", "POST", input, options);
5183
+ },
5184
+ validate(input, options) {
5185
+ return callAthena2("/storage/objects/validate", "POST", input, options);
5186
+ },
5187
+ update(input, options) {
5188
+ return callAthena2("/storage/objects/update", "POST", input, options);
5189
+ },
5190
+ copy(input, options) {
5191
+ return callAthena2("/storage/objects/copy", "POST", input, options);
5192
+ },
5193
+ url(input, options) {
5194
+ return callAthena2("/storage/objects/url", "POST", input, options);
5195
+ },
5196
+ publicUrl(input, options) {
5197
+ return callAthena2("/storage/objects/public-url", "POST", input, options);
5198
+ },
5199
+ delete(input, options) {
5200
+ return callAthena2("/storage/objects/delete", "POST", input, options);
5201
+ },
5202
+ uploadUrl(input, options) {
5203
+ return callAthena2("/storage/objects/upload-url", "POST", input, options);
5204
+ },
5205
+ folder: objectFolder
5206
+ };
5207
+ const bucket = {
5208
+ list(input, options) {
5209
+ return callAthena2("/storage/buckets/list", "POST", input, options);
5210
+ },
5211
+ create(input, options) {
5212
+ return callAthena2("/storage/buckets/create", "POST", input, options);
5213
+ },
5214
+ delete(input, options) {
5215
+ return callAthena2("/storage/buckets/delete", "POST", input, options);
5216
+ },
5217
+ cors: {
5218
+ get(input, options) {
5219
+ return callAthena2("/storage/buckets/cors", "POST", input, options);
5220
+ },
5221
+ set(input, options) {
5222
+ return callAthena2("/storage/buckets/cors/set", "POST", input, options);
5223
+ },
5224
+ delete(input, options) {
5225
+ return callAthena2("/storage/buckets/cors/delete", "POST", input, options);
5226
+ }
5227
+ }
5228
+ };
5229
+ const multipart = {
5230
+ create(input, options) {
5231
+ return callAthena2("/storage/multipart/create", "POST", input, options);
5232
+ },
5233
+ signPart(input, options) {
5234
+ return callAthena2("/storage/multipart/sign-part", "POST", input, options);
5235
+ },
5236
+ complete(input, options) {
5237
+ return callAthena2("/storage/multipart/complete", "POST", input, options);
5238
+ },
5239
+ abort(input, options) {
5240
+ return callAthena2("/storage/multipart/abort", "POST", input, options);
5241
+ },
5242
+ listParts(input, options) {
5243
+ return callAthena2("/storage/multipart/list-parts", "POST", input, options);
5244
+ }
5245
+ };
5246
+ const audit = {
5247
+ list(input, options) {
5248
+ return callAthena2("/storage/audit/list", "POST", input, options);
5249
+ }
5250
+ };
5251
+ return {
5252
+ ...base,
5253
+ credentials,
5254
+ catalog,
5255
+ file,
5256
+ folder,
5257
+ permission,
5258
+ object,
5259
+ bucket,
5260
+ multipart,
5261
+ audit,
5262
+ delete: file.delete
5263
+ };
5264
+ }
5265
+
5266
+ // src/client-builder.ts
5267
+ var DEFAULT_BACKEND = { type: "athena" };
5268
+ function toBackendConfig(value) {
5269
+ if (!value) return DEFAULT_BACKEND;
5270
+ return typeof value === "string" ? { type: value } : value;
4158
5271
  }
4159
5272
 
4160
5273
  // src/query-ast.ts
@@ -4184,7 +5297,7 @@ var BOOLEAN_SAFE_OPERATORS = /* @__PURE__ */ new Set([
4184
5297
  "ilike",
4185
5298
  "is"
4186
5299
  ]);
4187
- function isRecord6(value) {
5300
+ function isRecord7(value) {
4188
5301
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
4189
5302
  }
4190
5303
  function isUuidString(value) {
@@ -4197,7 +5310,7 @@ function shouldUseUuidTextComparison(column, value) {
4197
5310
  return typeof value === "string" && isUuidString(value) && isUuidIdentifierColumn(column);
4198
5311
  }
4199
5312
  function isRelationSelectNode(value) {
4200
- return isRecord6(value) && isRecord6(value.select);
5313
+ return isRecord7(value) && isRecord7(value.select);
4201
5314
  }
4202
5315
  function normalizeIdentifier(value, label) {
4203
5316
  const normalized = value.trim();
@@ -4253,7 +5366,7 @@ function compileRelationToken(key, node) {
4253
5366
  return `${prefix}${relationToken}(${nested})`;
4254
5367
  }
4255
5368
  function compileSelectShape(select) {
4256
- if (!isRecord6(select)) {
5369
+ if (!isRecord7(select)) {
4257
5370
  throw new Error("findMany select must be an object");
4258
5371
  }
4259
5372
  const tokens = [];
@@ -4277,7 +5390,7 @@ function compileSelectShape(select) {
4277
5390
  return tokens.join(",");
4278
5391
  }
4279
5392
  function selectShapeUsesRelationSchema(select) {
4280
- if (!isRecord6(select)) {
5393
+ if (!isRecord7(select)) {
4281
5394
  return false;
4282
5395
  }
4283
5396
  for (const rawValue of Object.values(select)) {
@@ -4295,7 +5408,7 @@ function selectShapeUsesRelationSchema(select) {
4295
5408
  }
4296
5409
  function compileColumnWhere(column, input) {
4297
5410
  const normalizedColumn = normalizeIdentifier(column, "where column");
4298
- if (!isRecord6(input)) {
5411
+ if (!isRecord7(input)) {
4299
5412
  return [buildGatewayCondition("eq", normalizedColumn, input)];
4300
5413
  }
4301
5414
  const conditions = [];
@@ -4323,7 +5436,7 @@ function compileColumnWhere(column, input) {
4323
5436
  return conditions;
4324
5437
  }
4325
5438
  function compileBooleanExpressionTerms(clause, label) {
4326
- if (!isRecord6(clause)) {
5439
+ if (!isRecord7(clause)) {
4327
5440
  throw new Error(`findMany where.${label} clauses must be objects`);
4328
5441
  }
4329
5442
  const entries = Object.entries(clause).filter(([, value]) => value !== void 0);
@@ -4332,7 +5445,7 @@ function compileBooleanExpressionTerms(clause, label) {
4332
5445
  }
4333
5446
  const [rawColumn, rawValue] = entries[0];
4334
5447
  const column = normalizeIdentifier(rawColumn, `where.${label} column`);
4335
- if (!isRecord6(rawValue)) {
5448
+ if (!isRecord7(rawValue)) {
4336
5449
  return [`${column}.eq.${stringifyFilterValue(rawValue)}`];
4337
5450
  }
4338
5451
  const operatorEntries = Object.entries(rawValue).filter(([, value]) => value !== void 0);
@@ -4356,7 +5469,7 @@ function compileWhere(where) {
4356
5469
  if (where === void 0) {
4357
5470
  return void 0;
4358
5471
  }
4359
- if (!isRecord6(where)) {
5472
+ if (!isRecord7(where)) {
4360
5473
  throw new Error("findMany where must be an object");
4361
5474
  }
4362
5475
  const conditions = [];
@@ -4406,7 +5519,7 @@ function compileOrderBy(orderBy) {
4406
5519
  if (orderBy === void 0) {
4407
5520
  return void 0;
4408
5521
  }
4409
- if (!isRecord6(orderBy)) {
5522
+ if (!isRecord7(orderBy)) {
4410
5523
  throw new Error("findMany orderBy must be an object");
4411
5524
  }
4412
5525
  if ("column" in orderBy) {
@@ -4581,11 +5694,11 @@ function toFindManyAstOrder(order) {
4581
5694
  ascending: order.direction !== "descending"
4582
5695
  };
4583
5696
  }
4584
- function isRecord7(value) {
5697
+ function isRecord8(value) {
4585
5698
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
4586
5699
  }
4587
5700
  function normalizeFindManyAstColumnPredicate(value) {
4588
- if (!isRecord7(value)) {
5701
+ if (!isRecord8(value)) {
4589
5702
  return {
4590
5703
  eq: value
4591
5704
  };
@@ -4609,7 +5722,7 @@ function normalizeFindManyAstBooleanOperand(clause) {
4609
5722
  return normalized;
4610
5723
  }
4611
5724
  function normalizeFindManyAstWhere(where) {
4612
- if (!where || !isRecord7(where)) {
5725
+ if (!where || !isRecord8(where)) {
4613
5726
  return where;
4614
5727
  }
4615
5728
  const normalized = {};
@@ -4623,7 +5736,7 @@ function normalizeFindManyAstWhere(where) {
4623
5736
  );
4624
5737
  continue;
4625
5738
  }
4626
- if (key === "not" && isRecord7(value)) {
5739
+ if (key === "not" && isRecord8(value)) {
4627
5740
  normalized.not = normalizeFindManyAstBooleanOperand(
4628
5741
  value
4629
5742
  );
@@ -4634,7 +5747,7 @@ function normalizeFindManyAstWhere(where) {
4634
5747
  return normalized;
4635
5748
  }
4636
5749
  function predicateRequiresUuidQueryFallback(column, value) {
4637
- if (!isRecord7(value)) {
5750
+ if (!isRecord8(value)) {
4638
5751
  return shouldUseUuidTextComparison(column, value);
4639
5752
  }
4640
5753
  const eqValue = value.eq;
@@ -4652,7 +5765,7 @@ function booleanOperandRequiresUuidQueryFallback(clause) {
4652
5765
  return false;
4653
5766
  }
4654
5767
  function findManyAstWhereRequiresLegacyTransport(where) {
4655
- if (!where || !isRecord7(where)) {
5768
+ if (!where || !isRecord8(where)) {
4656
5769
  return false;
4657
5770
  }
4658
5771
  for (const [key, value] of Object.entries(where)) {
@@ -4667,7 +5780,7 @@ function findManyAstWhereRequiresLegacyTransport(where) {
4667
5780
  }
4668
5781
  continue;
4669
5782
  }
4670
- if (key === "not" && isRecord7(value)) {
5783
+ if (key === "not" && isRecord8(value)) {
4671
5784
  if (booleanOperandRequiresUuidQueryFallback(value)) {
4672
5785
  return true;
4673
5786
  }
@@ -4779,20 +5892,437 @@ function createSelectTransportPlan(input) {
4779
5892
  };
4780
5893
  }
4781
5894
 
5895
+ // src/query-debug-ast.ts
5896
+ var ATHENA_DEBUG_AST_KEY = "__athenaDebugAst";
5897
+ function cloneConditions(conditions) {
5898
+ return conditions.map((condition) => ({ ...condition }));
5899
+ }
5900
+ function cloneTableBuilderStateAst(state) {
5901
+ return {
5902
+ conditions: cloneConditions(state.conditions),
5903
+ limit: state.limit,
5904
+ offset: state.offset,
5905
+ order: state.order ? { ...state.order } : void 0,
5906
+ currentPage: state.currentPage,
5907
+ pageSize: state.pageSize,
5908
+ totalPages: state.totalPages
5909
+ };
5910
+ }
5911
+ function cloneRpcBuilderStateAst(state) {
5912
+ return {
5913
+ filters: state.filters.map((filter) => ({ ...filter })),
5914
+ limit: state.limit,
5915
+ offset: state.offset,
5916
+ order: state.order ? { ...state.order } : void 0
5917
+ };
5918
+ }
5919
+ function toSelectTransportAst(plan) {
5920
+ if (plan.kind === "query") {
5921
+ return {
5922
+ mode: "typed-query",
5923
+ endpoint: "/gateway/query",
5924
+ payload: plan.payload
5925
+ };
5926
+ }
5927
+ return {
5928
+ mode: plan.payload.select !== void 0 ? "structured-fetch" : "compiled-fetch",
5929
+ endpoint: "/gateway/fetch",
5930
+ payload: plan.payload
5931
+ };
5932
+ }
5933
+ function resolveDebugTableName(tableName) {
5934
+ return tableName ?? "__unknown_table__";
5935
+ }
5936
+ function buildSelectDebugAst(input) {
5937
+ return {
5938
+ version: 1,
5939
+ kind: "select",
5940
+ tableName: input.tableName,
5941
+ input: {
5942
+ columns: input.columns,
5943
+ state: cloneTableBuilderStateAst(input.state)
5944
+ },
5945
+ transport: toSelectTransportAst(input.plan)
5946
+ };
5947
+ }
5948
+ function buildFindManyCompiledDebugAst(input) {
5949
+ return {
5950
+ version: 1,
5951
+ kind: "findMany",
5952
+ tableName: input.tableName,
5953
+ input: {
5954
+ select: input.options.select,
5955
+ where: input.options.where,
5956
+ orderBy: input.options.orderBy,
5957
+ limit: input.options.limit
5958
+ },
5959
+ compiled: {
5960
+ columns: input.compiledColumns,
5961
+ baseState: cloneTableBuilderStateAst(input.baseState),
5962
+ executionState: cloneTableBuilderStateAst(input.executionState)
5963
+ },
5964
+ transport: planToFindManyTransport(input.plan)
5965
+ };
5966
+ }
5967
+ function buildFindManyDirectDebugAst(input) {
5968
+ return {
5969
+ version: 1,
5970
+ kind: "findMany",
5971
+ tableName: input.tableName,
5972
+ input: {
5973
+ select: input.options.select,
5974
+ where: input.options.where,
5975
+ orderBy: input.options.orderBy,
5976
+ limit: input.options.limit
5977
+ },
5978
+ compiled: {
5979
+ columns: input.compiledColumns,
5980
+ baseState: cloneTableBuilderStateAst(input.baseState),
5981
+ executionState: cloneTableBuilderStateAst(input.executionState)
5982
+ },
5983
+ transport: {
5984
+ mode: "direct-ast-fetch",
5985
+ endpoint: "/gateway/fetch",
5986
+ payload: input.payload
5987
+ }
5988
+ };
5989
+ }
5990
+ function planToFindManyTransport(plan) {
5991
+ if (plan.kind === "query") {
5992
+ return {
5993
+ mode: "compiled-query",
5994
+ endpoint: "/gateway/query",
5995
+ payload: plan.payload
5996
+ };
5997
+ }
5998
+ return {
5999
+ mode: plan.payload.select !== void 0 ? "structured-fetch" : "compiled-fetch",
6000
+ endpoint: "/gateway/fetch",
6001
+ payload: plan.payload
6002
+ };
6003
+ }
6004
+ function buildInsertDebugAst(payload) {
6005
+ return {
6006
+ version: 1,
6007
+ kind: "insert",
6008
+ tableName: payload.table_name,
6009
+ input: {
6010
+ values: payload.insert_body,
6011
+ returning: payload.columns,
6012
+ count: payload.count,
6013
+ head: payload.head,
6014
+ defaultToNull: payload.default_to_null
6015
+ },
6016
+ transport: {
6017
+ mode: "insert",
6018
+ endpoint: "/gateway/insert",
6019
+ payload
6020
+ }
6021
+ };
6022
+ }
6023
+ function buildUpsertDebugAst(payload) {
6024
+ return {
6025
+ version: 1,
6026
+ kind: "upsert",
6027
+ tableName: payload.table_name,
6028
+ input: {
6029
+ values: payload.insert_body,
6030
+ updateBody: payload.update_body,
6031
+ onConflict: payload.on_conflict,
6032
+ returning: payload.columns,
6033
+ count: payload.count,
6034
+ head: payload.head,
6035
+ defaultToNull: payload.default_to_null
6036
+ },
6037
+ transport: {
6038
+ mode: "upsert",
6039
+ endpoint: "/gateway/insert",
6040
+ payload
6041
+ }
6042
+ };
6043
+ }
6044
+ function buildUpdateDebugAst(input) {
6045
+ return {
6046
+ version: 1,
6047
+ kind: "update",
6048
+ tableName: resolveDebugTableName(input.payload.table_name),
6049
+ input: {
6050
+ values: input.payload.set,
6051
+ state: cloneTableBuilderStateAst(input.state),
6052
+ returning: input.payload.columns
6053
+ },
6054
+ transport: {
6055
+ mode: "update",
6056
+ endpoint: "/gateway/update",
6057
+ payload: input.payload
6058
+ }
6059
+ };
6060
+ }
6061
+ function buildDeleteDebugAst(input) {
6062
+ return {
6063
+ version: 1,
6064
+ kind: "delete",
6065
+ tableName: input.payload.table_name,
6066
+ input: {
6067
+ resourceId: input.payload.resource_id,
6068
+ state: cloneTableBuilderStateAst(input.state),
6069
+ returning: input.payload.columns
6070
+ },
6071
+ transport: {
6072
+ mode: "delete",
6073
+ endpoint: "/gateway/delete",
6074
+ payload: input.payload
6075
+ }
6076
+ };
6077
+ }
6078
+ function buildRpcDebugAst(input) {
6079
+ return {
6080
+ version: 1,
6081
+ kind: "rpc",
6082
+ functionName: input.functionName,
6083
+ input: {
6084
+ args: input.args,
6085
+ select: input.selectedColumns,
6086
+ state: cloneRpcBuilderStateAst(input.state)
6087
+ },
6088
+ transport: {
6089
+ mode: input.endpoint === "/gateway/rpc" ? "rpc-post" : "rpc-get",
6090
+ endpoint: input.endpoint,
6091
+ payload: input.payload
6092
+ }
6093
+ };
6094
+ }
6095
+ function buildRawQueryDebugAst(query) {
6096
+ return {
6097
+ version: 1,
6098
+ kind: "query",
6099
+ input: {
6100
+ query
6101
+ },
6102
+ transport: {
6103
+ mode: "raw-query",
6104
+ endpoint: "/gateway/query",
6105
+ payload: {
6106
+ query
6107
+ }
6108
+ }
6109
+ };
6110
+ }
6111
+ function attachAthenaDebugAst(target, ast) {
6112
+ if (!ast) {
6113
+ return;
6114
+ }
6115
+ if (!target || typeof target !== "object" && typeof target !== "function") {
6116
+ return;
6117
+ }
6118
+ Object.defineProperty(target, ATHENA_DEBUG_AST_KEY, {
6119
+ value: ast,
6120
+ enumerable: false,
6121
+ configurable: true,
6122
+ writable: false
6123
+ });
6124
+ }
6125
+
6126
+ // src/query-tracing.ts
6127
+ var QUERY_TRACE_STACK_SKIP_PATTERNS = [
6128
+ "src\\client.ts",
6129
+ "src/client.ts",
6130
+ "src\\query-tracing.ts",
6131
+ "src/query-tracing.ts",
6132
+ "dist\\client.",
6133
+ "dist/client.",
6134
+ "dist\\query-tracing.",
6135
+ "dist/query-tracing.",
6136
+ "node_modules\\@xylex-group\\athena",
6137
+ "node_modules/@xylex-group/athena",
6138
+ "node:internal",
6139
+ "internal/process"
6140
+ ];
6141
+ function parseQueryTraceCallsiteFrame(frame) {
6142
+ const trimmed = frame.trim();
6143
+ if (!trimmed) {
6144
+ return null;
6145
+ }
6146
+ let body = trimmed.replace(/^at\s+/, "");
6147
+ if (body.startsWith("async ")) {
6148
+ body = body.slice(6);
6149
+ }
6150
+ let functionName;
6151
+ let location = body;
6152
+ const wrappedMatch = body.match(/^(.*?)\s+\((.*)\)$/);
6153
+ if (wrappedMatch) {
6154
+ functionName = wrappedMatch[1].trim() || void 0;
6155
+ location = wrappedMatch[2].trim();
6156
+ }
6157
+ const locationMatch = location.match(/^(.*):(\d+):(\d+)$/);
6158
+ if (!locationMatch) {
6159
+ return null;
6160
+ }
6161
+ const filePath = locationMatch[1].replace(/^file:\/\//, "");
6162
+ const line = Number(locationMatch[2]);
6163
+ const column = Number(locationMatch[3]);
6164
+ if (!Number.isFinite(line) || !Number.isFinite(column)) {
6165
+ return null;
6166
+ }
6167
+ const normalizedPath = filePath.replace(/\\/g, "/");
6168
+ const fileName = normalizedPath.split("/").at(-1) ?? filePath;
6169
+ return {
6170
+ filePath,
6171
+ fileName,
6172
+ line,
6173
+ column,
6174
+ frame: trimmed,
6175
+ functionName
6176
+ };
6177
+ }
6178
+ function captureQueryTraceCallsite() {
6179
+ const stack = new Error().stack;
6180
+ if (!stack) return null;
6181
+ const frames = stack.split("\n").slice(2).map((frame) => frame.trim()).filter(Boolean);
6182
+ for (const frame of frames) {
6183
+ if (QUERY_TRACE_STACK_SKIP_PATTERNS.some((pattern) => frame.includes(pattern))) {
6184
+ continue;
6185
+ }
6186
+ const callsite = parseQueryTraceCallsiteFrame(frame);
6187
+ if (callsite) return callsite;
6188
+ }
6189
+ const fallback = frames.find((frame) => !frame.includes("captureQueryTraceCallsite"));
6190
+ return fallback ? parseQueryTraceCallsiteFrame(fallback) : null;
6191
+ }
6192
+ function defaultQueryTraceLogger(event) {
6193
+ const target = event.table ?? event.functionName ?? "gateway";
6194
+ const outcomeState = event.outcome?.error ? "error" : "ok";
6195
+ const banner = `[athena-js][trace] ${event.operation.toUpperCase()} ${event.endpoint} ${target} ${event.durationMs}ms ${outcomeState}`;
6196
+ console.info(banner, event);
6197
+ }
6198
+ function captureTraceCallsite(tracer) {
6199
+ return tracer?.captureCallsite() ?? null;
6200
+ }
6201
+ function createTraceCallsiteStore(tracer, initialCallsite) {
6202
+ let storedCallsite = initialCallsite ?? void 0;
6203
+ return {
6204
+ resolve(callsite) {
6205
+ if (callsite) {
6206
+ storedCallsite = callsite;
6207
+ return callsite;
6208
+ }
6209
+ if (storedCallsite !== void 0) {
6210
+ return storedCallsite;
6211
+ }
6212
+ const capturedCallsite = captureTraceCallsite(tracer);
6213
+ if (capturedCallsite) {
6214
+ storedCallsite = capturedCallsite;
6215
+ }
6216
+ return capturedCallsite;
6217
+ }
6218
+ };
6219
+ }
6220
+ function createQueryTracer(experimental) {
6221
+ const traceOption = experimental?.traceQueries;
6222
+ if (!traceOption) {
6223
+ return void 0;
6224
+ }
6225
+ const logger = typeof traceOption === "object" && traceOption.logger ? traceOption.logger : defaultQueryTraceLogger;
6226
+ const emit = (event) => {
6227
+ try {
6228
+ logger(event);
6229
+ } catch (error) {
6230
+ console.warn("[athena-js][trace] logger failed", error);
6231
+ }
6232
+ };
6233
+ return {
6234
+ captureCallsite: captureQueryTraceCallsite,
6235
+ publishSuccess(context, result, durationMs, callsite) {
6236
+ emit({
6237
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
6238
+ durationMs,
6239
+ operation: context.operation,
6240
+ endpoint: context.endpoint,
6241
+ table: context.table,
6242
+ functionName: context.functionName,
6243
+ sql: context.sql,
6244
+ payload: context.payload,
6245
+ ast: context.ast,
6246
+ options: context.options,
6247
+ callsite,
6248
+ outcome: {
6249
+ status: result.status,
6250
+ error: result.error,
6251
+ errorDetails: result.errorDetails ?? null,
6252
+ count: result.count ?? null,
6253
+ data: result.data,
6254
+ raw: result.raw
6255
+ }
6256
+ });
6257
+ },
6258
+ publishFailure(context, error, durationMs, callsite) {
6259
+ emit({
6260
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
6261
+ durationMs,
6262
+ operation: context.operation,
6263
+ endpoint: context.endpoint,
6264
+ table: context.table,
6265
+ functionName: context.functionName,
6266
+ sql: context.sql,
6267
+ payload: context.payload,
6268
+ ast: context.ast,
6269
+ options: context.options,
6270
+ callsite,
6271
+ thrownError: error
6272
+ });
6273
+ }
6274
+ };
6275
+ }
6276
+ async function executeWithQueryTrace(tracer, context, runner, callsiteOverride) {
6277
+ const callsite = tracer ? callsiteOverride ?? tracer.captureCallsite() : null;
6278
+ const startedAt = tracer ? Date.now() : 0;
6279
+ try {
6280
+ const result = await runner();
6281
+ attachAthenaDebugAst(result, context.ast);
6282
+ if (tracer) {
6283
+ tracer.publishSuccess(context, result, Date.now() - startedAt, callsite);
6284
+ }
6285
+ return result;
6286
+ } catch (error) {
6287
+ attachAthenaDebugAst(error, context.ast);
6288
+ if (tracer) {
6289
+ tracer.publishFailure(context, error, Date.now() - startedAt, callsite);
6290
+ }
6291
+ throw error;
6292
+ }
6293
+ }
6294
+
6295
+ // src/schema/model-target.ts
6296
+ function normalizeOptionalName(value) {
6297
+ const normalized = value?.trim();
6298
+ return normalized ? normalized : void 0;
6299
+ }
6300
+ function isAthenaModelTarget(value) {
6301
+ if (!value || typeof value !== "object") {
6302
+ return false;
6303
+ }
6304
+ const candidate = value;
6305
+ return Boolean(candidate.meta && Array.isArray(candidate.meta.primaryKey));
6306
+ }
6307
+ function resolveAthenaModelTargetTableName(target, options = {}) {
6308
+ const explicitTableName = normalizeOptionalName(target.meta.tableName);
6309
+ if (explicitTableName) {
6310
+ return explicitTableName;
6311
+ }
6312
+ const schemaName = normalizeOptionalName(target.meta.schema ?? options.fallbackSchema);
6313
+ const modelName = normalizeOptionalName(target.meta.model ?? options.fallbackModel);
6314
+ if (!modelName) {
6315
+ throw new Error(
6316
+ "Athena model target is missing meta.model or meta.tableName. Provide one of those before calling from(model)."
6317
+ );
6318
+ }
6319
+ return schemaName ? `${schemaName}.${modelName}` : modelName;
6320
+ }
6321
+
4782
6322
  // src/client.ts
4783
6323
  var DEFAULT_COLUMNS = "*";
4784
6324
  var SAFE_CAST_PATTERN = /^[a-z_][a-z0-9_]*(?:\[\])?$/i;
4785
6325
  var ATHENA_NORMALIZED_ERROR_KEY = "__athenaNormalizedError";
4786
- var QUERY_TRACE_STACK_SKIP_PATTERNS = [
4787
- "src\\client.ts",
4788
- "src/client.ts",
4789
- "dist\\client.",
4790
- "dist/client.",
4791
- "node_modules\\@xylex-group\\athena",
4792
- "node_modules/@xylex-group/athena",
4793
- "node:internal",
4794
- "internal/process"
4795
- ];
4796
6326
  function formatResult(response) {
4797
6327
  const result = {
4798
6328
  data: response.data ?? null,
@@ -4869,7 +6399,7 @@ async function executeExperimentalRead(experimental, runner) {
4869
6399
  throw error;
4870
6400
  }
4871
6401
  }
4872
- function isRecord8(value) {
6402
+ function isRecord9(value) {
4873
6403
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
4874
6404
  }
4875
6405
  function firstNonEmptyString2(...values) {
@@ -4881,8 +6411,8 @@ function firstNonEmptyString2(...values) {
4881
6411
  return void 0;
4882
6412
  }
4883
6413
  function resolveStructuredErrorPayload2(raw) {
4884
- if (!isRecord8(raw)) return null;
4885
- return isRecord8(raw.error) ? raw.error : raw;
6414
+ if (!isRecord9(raw)) return null;
6415
+ return isRecord9(raw.error) ? raw.error : raw;
4886
6416
  }
4887
6417
  function resolveStructuredErrorDetails(payload, message) {
4888
6418
  if (!payload || !("details" in payload)) {
@@ -4898,7 +6428,7 @@ function resolveStructuredErrorDetails(payload, message) {
4898
6428
  return details;
4899
6429
  }
4900
6430
  function createResultError(response, result, normalized) {
4901
- const rawRecord = isRecord8(response.raw) ? response.raw : null;
6431
+ const rawRecord = isRecord9(response.raw) ? response.raw : null;
4902
6432
  const payload = resolveStructuredErrorPayload2(response.raw);
4903
6433
  const message = firstNonEmptyString2(
4904
6434
  response.error,
@@ -4934,154 +6464,6 @@ function createResultError(response, result, normalized) {
4934
6464
  raw: result.raw
4935
6465
  };
4936
6466
  }
4937
- function parseQueryTraceCallsiteFrame(frame) {
4938
- const trimmed = frame.trim();
4939
- if (!trimmed) {
4940
- return null;
4941
- }
4942
- let body = trimmed.replace(/^at\s+/, "");
4943
- if (body.startsWith("async ")) {
4944
- body = body.slice(6);
4945
- }
4946
- let functionName;
4947
- let location = body;
4948
- const wrappedMatch = body.match(/^(.*?)\s+\((.*)\)$/);
4949
- if (wrappedMatch) {
4950
- functionName = wrappedMatch[1].trim() || void 0;
4951
- location = wrappedMatch[2].trim();
4952
- }
4953
- const locationMatch = location.match(/^(.*):(\d+):(\d+)$/);
4954
- if (!locationMatch) {
4955
- return null;
4956
- }
4957
- const filePath = locationMatch[1].replace(/^file:\/\//, "");
4958
- const line = Number(locationMatch[2]);
4959
- const column = Number(locationMatch[3]);
4960
- if (!Number.isFinite(line) || !Number.isFinite(column)) {
4961
- return null;
4962
- }
4963
- const normalizedPath = filePath.replace(/\\/g, "/");
4964
- const fileName = normalizedPath.split("/").at(-1) ?? filePath;
4965
- return {
4966
- filePath,
4967
- fileName,
4968
- line,
4969
- column,
4970
- frame: trimmed,
4971
- functionName
4972
- };
4973
- }
4974
- function captureQueryTraceCallsite() {
4975
- const stack = new Error().stack;
4976
- if (!stack) return null;
4977
- const frames = stack.split("\n").slice(2).map((frame) => frame.trim()).filter(Boolean);
4978
- for (const frame of frames) {
4979
- if (QUERY_TRACE_STACK_SKIP_PATTERNS.some((pattern) => frame.includes(pattern))) {
4980
- continue;
4981
- }
4982
- const callsite = parseQueryTraceCallsiteFrame(frame);
4983
- if (callsite) return callsite;
4984
- }
4985
- const fallback = frames.find((frame) => !frame.includes("captureQueryTraceCallsite"));
4986
- return fallback ? parseQueryTraceCallsiteFrame(fallback) : null;
4987
- }
4988
- function defaultQueryTraceLogger(event) {
4989
- const target = event.table ?? event.functionName ?? "gateway";
4990
- const outcomeState = event.outcome?.error ? "error" : "ok";
4991
- const banner = `[athena-js][trace] ${event.operation.toUpperCase()} ${event.endpoint} ${target} ${event.durationMs}ms ${outcomeState}`;
4992
- console.info(banner, event);
4993
- }
4994
- function captureTraceCallsite(tracer) {
4995
- return tracer?.captureCallsite() ?? null;
4996
- }
4997
- function createTraceCallsiteStore(tracer, initialCallsite) {
4998
- let storedCallsite = initialCallsite ?? void 0;
4999
- return {
5000
- resolve(callsite) {
5001
- if (callsite) {
5002
- storedCallsite = callsite;
5003
- return callsite;
5004
- }
5005
- if (storedCallsite !== void 0) {
5006
- return storedCallsite;
5007
- }
5008
- const capturedCallsite = captureTraceCallsite(tracer);
5009
- if (capturedCallsite) {
5010
- storedCallsite = capturedCallsite;
5011
- }
5012
- return capturedCallsite;
5013
- }
5014
- };
5015
- }
5016
- function createQueryTracer(experimental) {
5017
- const traceOption = experimental?.traceQueries;
5018
- if (!traceOption) {
5019
- return void 0;
5020
- }
5021
- const logger = typeof traceOption === "object" && traceOption.logger ? traceOption.logger : defaultQueryTraceLogger;
5022
- const emit = (event) => {
5023
- try {
5024
- logger(event);
5025
- } catch (error) {
5026
- console.warn("[athena-js][trace] logger failed", error);
5027
- }
5028
- };
5029
- return {
5030
- captureCallsite: captureQueryTraceCallsite,
5031
- publishSuccess(context, result, durationMs, callsite) {
5032
- emit({
5033
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
5034
- durationMs,
5035
- operation: context.operation,
5036
- endpoint: context.endpoint,
5037
- table: context.table,
5038
- functionName: context.functionName,
5039
- sql: context.sql,
5040
- payload: context.payload,
5041
- options: context.options,
5042
- callsite,
5043
- outcome: {
5044
- status: result.status,
5045
- error: result.error,
5046
- errorDetails: result.errorDetails ?? null,
5047
- count: result.count ?? null,
5048
- data: result.data,
5049
- raw: result.raw
5050
- }
5051
- });
5052
- },
5053
- publishFailure(context, error, durationMs, callsite) {
5054
- emit({
5055
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
5056
- durationMs,
5057
- operation: context.operation,
5058
- endpoint: context.endpoint,
5059
- table: context.table,
5060
- functionName: context.functionName,
5061
- sql: context.sql,
5062
- payload: context.payload,
5063
- options: context.options,
5064
- callsite,
5065
- thrownError: error
5066
- });
5067
- }
5068
- };
5069
- }
5070
- async function executeWithQueryTrace(tracer, context, runner, callsiteOverride) {
5071
- if (!tracer) {
5072
- return runner();
5073
- }
5074
- const callsite = callsiteOverride ?? tracer.captureCallsite();
5075
- const startedAt = Date.now();
5076
- try {
5077
- const result = await runner();
5078
- tracer.publishSuccess(context, result, Date.now() - startedAt, callsite);
5079
- return result;
5080
- } catch (error) {
5081
- tracer.publishFailure(context, error, Date.now() - startedAt, callsite);
5082
- throw error;
5083
- }
5084
- }
5085
6467
  function toSingleResult(response) {
5086
6468
  const payload = response.data;
5087
6469
  const singleData = Array.isArray(payload) ? payload.length ? payload[0] : null : payload ?? null;
@@ -5109,6 +6491,15 @@ function asAthenaJsonObject(value) {
5109
6491
  function asAthenaJsonObjectArray(values) {
5110
6492
  return values;
5111
6493
  }
6494
+ function normalizeSelectColumnsInput(columns) {
6495
+ if (columns === void 0) {
6496
+ return void 0;
6497
+ }
6498
+ if (typeof columns === "string") {
6499
+ return columns;
6500
+ }
6501
+ return [...columns];
6502
+ }
5112
6503
  function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS, tracer, initialCallsite) {
5113
6504
  let selectedColumns = defaultColumns === null ? void 0 : defaultColumns;
5114
6505
  let selectedOptions;
@@ -5118,25 +6509,29 @@ function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS, tracer,
5118
6509
  const payloadColumns = columns ?? selectedColumns;
5119
6510
  const payloadOptions = options ?? selectedOptions;
5120
6511
  if (!promise) {
5121
- promise = executor(payloadColumns, payloadOptions, callsiteStore.resolve(callsite));
6512
+ promise = executor(
6513
+ normalizeSelectColumnsInput(payloadColumns),
6514
+ payloadOptions,
6515
+ callsiteStore.resolve(callsite)
6516
+ );
5122
6517
  }
5123
6518
  return promise;
5124
6519
  };
5125
6520
  const mutationQuery = {
5126
- select(columns = selectedColumns, options) {
6521
+ select(columns, options) {
5127
6522
  selectedColumns = columns;
5128
6523
  selectedOptions = options ?? selectedOptions;
5129
6524
  return run(columns, options, captureTraceCallsite(tracer));
5130
6525
  },
5131
- returning(columns = selectedColumns, options) {
6526
+ returning(columns, options) {
5132
6527
  return mutationQuery.select(columns, options);
5133
6528
  },
5134
- single(columns = selectedColumns, options) {
6529
+ single(columns, options) {
5135
6530
  selectedColumns = columns;
5136
6531
  selectedOptions = options ?? selectedOptions;
5137
6532
  return run(columns, options, captureTraceCallsite(tracer)).then(toSingleResult);
5138
6533
  },
5139
- maybeSingle(columns = selectedColumns, options) {
6534
+ maybeSingle(columns, options) {
5140
6535
  return mutationQuery.single(columns, options);
5141
6536
  },
5142
6537
  then(onfulfilled, onrejected) {
@@ -5693,7 +7088,10 @@ function createFilterMethods(state, addCondition, self) {
5693
7088
  }
5694
7089
  function toRpcSelect(columns) {
5695
7090
  if (!columns) return void 0;
5696
- return Array.isArray(columns) ? columns.join(",") : columns;
7091
+ if (typeof columns === "string") {
7092
+ return columns;
7093
+ }
7094
+ return columns.join(",");
5697
7095
  }
5698
7096
  function createRpcFilterMethods(filters, self) {
5699
7097
  const addFilter = (operator, column, value) => {
@@ -5742,7 +7140,7 @@ function createRpcFilterMethods(filters, self) {
5742
7140
  }
5743
7141
  };
5744
7142
  }
5745
- function createRpcBuilder(functionName, args, baseOptions, client, formatGatewayResult, tracer, initialCallsite) {
7143
+ function createRpcBuilder(functionName, args, baseOptions, client, formatGatewayResult, tracer, initialCallsite, debugAstEnabled = false) {
5746
7144
  const state = {
5747
7145
  filters: []
5748
7146
  };
@@ -5752,6 +7150,7 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
5752
7150
  const callsiteStore = createTraceCallsiteStore(tracer, initialCallsite);
5753
7151
  const executeRpc = async (columns, options, callsite) => {
5754
7152
  const mergedOptions = mergeOptions(baseOptions, options);
7153
+ const normalizedSelectedColumns = normalizeSelectColumnsInput(columns);
5755
7154
  const payload = {
5756
7155
  function: functionName,
5757
7156
  args,
@@ -5766,6 +7165,14 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
5766
7165
  };
5767
7166
  const endpoint = mergedOptions?.get ? `/rpc/${functionName}` : "/gateway/rpc";
5768
7167
  const sql = buildRpcDebugSql(payload);
7168
+ const debugAst = debugAstEnabled ? buildRpcDebugAst({
7169
+ functionName,
7170
+ args,
7171
+ selectedColumns: normalizedSelectedColumns,
7172
+ state,
7173
+ payload,
7174
+ endpoint
7175
+ }) : void 0;
5769
7176
  return executeWithQueryTrace(
5770
7177
  tracer,
5771
7178
  {
@@ -5774,6 +7181,7 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
5774
7181
  functionName,
5775
7182
  sql,
5776
7183
  payload,
7184
+ ast: debugAst,
5777
7185
  options: mergedOptions
5778
7186
  },
5779
7187
  async () => {
@@ -5794,7 +7202,7 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
5794
7202
  const builder = {};
5795
7203
  const filterMethods = createRpcFilterMethods(state.filters, builder);
5796
7204
  Object.assign(builder, filterMethods, {
5797
- select(columns = selectedColumns, options) {
7205
+ select(columns, options) {
5798
7206
  selectedColumns = columns;
5799
7207
  selectedOptions = options ?? selectedOptions;
5800
7208
  return run(columns, options, captureTraceCallsite(tracer));
@@ -5839,6 +7247,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
5839
7247
  const state = {
5840
7248
  conditions: []
5841
7249
  };
7250
+ const debugAstEnabled = Boolean(experimental?.debugAst);
5842
7251
  const addCondition = (operator, column, value, hints) => {
5843
7252
  const condition = { operator };
5844
7253
  if (column) {
@@ -5882,15 +7291,27 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
5882
7291
  addCondition,
5883
7292
  builder
5884
7293
  );
5885
- const runSelect = async (columns = DEFAULT_COLUMNS, options, executionState = snapshotState(), callsite) => {
7294
+ const runSelect = async (columns = DEFAULT_COLUMNS, options, executionState = snapshotState(), callsite, debugAstFactory) => {
7295
+ const runtimeColumns = normalizeSelectColumnsInput(columns) ?? DEFAULT_COLUMNS;
5886
7296
  const resolvedTableName = resolveTableNameForCall(tableName, options?.schema);
5887
7297
  const plan = createSelectTransportPlan({
5888
7298
  tableName: resolvedTableName,
5889
- columns,
7299
+ columns: runtimeColumns,
5890
7300
  state: executionState,
5891
7301
  options,
5892
7302
  buildTypedSelectQuery
5893
7303
  });
7304
+ const debugAst = debugAstEnabled ? debugAstFactory?.({
7305
+ tableName: resolvedTableName,
7306
+ columns: runtimeColumns,
7307
+ executionState,
7308
+ plan
7309
+ }) ?? buildSelectDebugAst({
7310
+ tableName: resolvedTableName,
7311
+ columns: runtimeColumns,
7312
+ state: executionState,
7313
+ plan
7314
+ }) : void 0;
5894
7315
  if (plan.kind === "query") {
5895
7316
  return executeExperimentalRead(
5896
7317
  experimental,
@@ -5902,6 +7323,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
5902
7323
  table: resolvedTableName,
5903
7324
  sql: plan.query,
5904
7325
  payload: plan.payload,
7326
+ ast: debugAst,
5905
7327
  options
5906
7328
  },
5907
7329
  async () => {
@@ -5926,6 +7348,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
5926
7348
  table: resolvedTableName,
5927
7349
  sql,
5928
7350
  payload: plan.payload,
7351
+ ast: debugAst,
5929
7352
  options
5930
7353
  },
5931
7354
  async () => {
@@ -5939,7 +7362,11 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
5939
7362
  const createSelectChain = (columns, options, initialCallsite) => {
5940
7363
  const chain = {};
5941
7364
  const callsiteStore = createTraceCallsiteStore(tracer, initialCallsite);
5942
- const filterMethods2 = createFilterMethods(state, addCondition, chain);
7365
+ const filterMethods2 = createFilterMethods(
7366
+ state,
7367
+ addCondition,
7368
+ chain
7369
+ );
5943
7370
  Object.assign(chain, filterMethods2, {
5944
7371
  async single(cols, opts) {
5945
7372
  const r = await runSelect(
@@ -6026,6 +7453,14 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6026
7453
  limit: executionState.limit,
6027
7454
  order: executionState.order
6028
7455
  });
7456
+ const debugAst = debugAstEnabled ? buildFindManyDirectDebugAst({
7457
+ tableName: resolvedTableName,
7458
+ options,
7459
+ compiledColumns: columns,
7460
+ baseState,
7461
+ executionState,
7462
+ payload
7463
+ }) : void 0;
6029
7464
  return executeExperimentalRead(
6030
7465
  experimental,
6031
7466
  () => executeWithQueryTrace(
@@ -6035,7 +7470,8 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6035
7470
  endpoint: "/gateway/fetch",
6036
7471
  table: resolvedTableName,
6037
7472
  sql,
6038
- payload
7473
+ payload,
7474
+ ast: debugAst
6039
7475
  },
6040
7476
  async () => {
6041
7477
  const response = await client.fetchGateway(
@@ -6051,7 +7487,15 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6051
7487
  columns,
6052
7488
  void 0,
6053
7489
  executionState,
6054
- callsite
7490
+ callsite,
7491
+ debugAstEnabled ? ({ tableName: resolvedTableName, executionState: tracedState, plan }) => buildFindManyCompiledDebugAst({
7492
+ tableName: resolvedTableName,
7493
+ options,
7494
+ compiledColumns: columns,
7495
+ baseState,
7496
+ executionState: tracedState,
7497
+ plan
7498
+ }) : void 0
6055
7499
  );
6056
7500
  },
6057
7501
  insert(values, options) {
@@ -6071,6 +7515,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6071
7515
  payload.default_to_null = mergedOptions.defaultToNull;
6072
7516
  }
6073
7517
  const sql = buildInsertDebugSql(payload);
7518
+ const debugAst = debugAstEnabled ? buildInsertDebugAst(payload) : void 0;
6074
7519
  return executeWithQueryTrace(
6075
7520
  tracer,
6076
7521
  {
@@ -6079,6 +7524,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6079
7524
  table: resolvedTableName,
6080
7525
  sql,
6081
7526
  payload,
7527
+ ast: debugAst,
6082
7528
  options: mergedOptions
6083
7529
  },
6084
7530
  async () => {
@@ -6104,6 +7550,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6104
7550
  payload.default_to_null = mergedOptions.defaultToNull;
6105
7551
  }
6106
7552
  const sql = buildInsertDebugSql(payload);
7553
+ const debugAst = debugAstEnabled ? buildInsertDebugAst(payload) : void 0;
6107
7554
  return executeWithQueryTrace(
6108
7555
  tracer,
6109
7556
  {
@@ -6112,6 +7559,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6112
7559
  table: resolvedTableName,
6113
7560
  sql,
6114
7561
  payload,
7562
+ ast: debugAst,
6115
7563
  options: mergedOptions
6116
7564
  },
6117
7565
  async () => {
@@ -6142,6 +7590,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6142
7590
  payload.default_to_null = mergedOptions.defaultToNull;
6143
7591
  }
6144
7592
  const sql = buildInsertDebugSql(payload);
7593
+ const debugAst = debugAstEnabled ? buildUpsertDebugAst(payload) : void 0;
6145
7594
  return executeWithQueryTrace(
6146
7595
  tracer,
6147
7596
  {
@@ -6150,6 +7599,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6150
7599
  table: resolvedTableName,
6151
7600
  sql,
6152
7601
  payload,
7602
+ ast: debugAst,
6153
7603
  options: mergedOptions
6154
7604
  },
6155
7605
  async () => {
@@ -6177,6 +7627,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6177
7627
  payload.default_to_null = mergedOptions.defaultToNull;
6178
7628
  }
6179
7629
  const sql = buildInsertDebugSql(payload);
7630
+ const debugAst = debugAstEnabled ? buildUpsertDebugAst(payload) : void 0;
6180
7631
  return executeWithQueryTrace(
6181
7632
  tracer,
6182
7633
  {
@@ -6185,6 +7636,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6185
7636
  table: resolvedTableName,
6186
7637
  sql,
6187
7638
  payload,
7639
+ ast: debugAst,
6188
7640
  options: mergedOptions
6189
7641
  },
6190
7642
  async () => {
@@ -6199,7 +7651,8 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6199
7651
  update(values, options) {
6200
7652
  const mutationCallsite = captureTraceCallsite(tracer);
6201
7653
  const executeUpdate = async (columns, selectOptions, callsite) => {
6202
- const filters = state.conditions.length ? [...state.conditions] : void 0;
7654
+ const executionState = snapshotState();
7655
+ const filters = executionState.conditions.length ? [...executionState.conditions] : void 0;
6203
7656
  const mergedOptions = mergeOptions(options, selectOptions);
6204
7657
  const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
6205
7658
  const payload = {
@@ -6208,12 +7661,16 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6208
7661
  conditions: filters,
6209
7662
  strip_nulls: mergedOptions?.stripNulls ?? true
6210
7663
  };
6211
- if (state.order) payload.sort_by = state.order;
6212
- if (state.currentPage !== void 0) payload.current_page = state.currentPage;
6213
- if (state.pageSize !== void 0) payload.page_size = state.pageSize;
6214
- if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
7664
+ if (executionState.order) payload.sort_by = executionState.order;
7665
+ if (executionState.currentPage !== void 0) payload.current_page = executionState.currentPage;
7666
+ if (executionState.pageSize !== void 0) payload.page_size = executionState.pageSize;
7667
+ if (executionState.totalPages !== void 0) payload.total_pages = executionState.totalPages;
6215
7668
  if (columns) payload.columns = columns;
6216
7669
  const sql = buildUpdateDebugSql(payload);
7670
+ const debugAst = debugAstEnabled ? buildUpdateDebugAst({
7671
+ state: executionState,
7672
+ payload
7673
+ }) : void 0;
6217
7674
  return executeWithQueryTrace(
6218
7675
  tracer,
6219
7676
  {
@@ -6222,6 +7679,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6222
7679
  table: resolvedTableName,
6223
7680
  sql,
6224
7681
  payload,
7682
+ ast: debugAst,
6225
7683
  options: mergedOptions
6226
7684
  },
6227
7685
  async () => {
@@ -6245,6 +7703,11 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6245
7703
  }
6246
7704
  const mutationCallsite = captureTraceCallsite(tracer);
6247
7705
  const executeDelete = async (columns, selectOptions, callsite) => {
7706
+ const executionState = snapshotState();
7707
+ const debugState = {
7708
+ ...executionState,
7709
+ conditions: filters ? filters.map((condition) => ({ ...condition })) : []
7710
+ };
6248
7711
  const mergedOptions = mergeOptions(options, selectOptions);
6249
7712
  const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
6250
7713
  const payload = {
@@ -6252,12 +7715,16 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6252
7715
  resource_id: resourceId,
6253
7716
  conditions: filters
6254
7717
  };
6255
- if (state.order) payload.sort_by = state.order;
6256
- if (state.currentPage !== void 0) payload.current_page = state.currentPage;
6257
- if (state.pageSize !== void 0) payload.page_size = state.pageSize;
6258
- if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
7718
+ if (executionState.order) payload.sort_by = executionState.order;
7719
+ if (executionState.currentPage !== void 0) payload.current_page = executionState.currentPage;
7720
+ if (executionState.pageSize !== void 0) payload.page_size = executionState.pageSize;
7721
+ if (executionState.totalPages !== void 0) payload.total_pages = executionState.totalPages;
6259
7722
  if (columns) payload.columns = columns;
6260
7723
  const sql = buildDeleteDebugSql(payload);
7724
+ const debugAst = debugAstEnabled ? buildDeleteDebugAst({
7725
+ state: debugState,
7726
+ payload
7727
+ }) : void 0;
6261
7728
  return executeWithQueryTrace(
6262
7729
  tracer,
6263
7730
  {
@@ -6266,6 +7733,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6266
7733
  table: resolvedTableName,
6267
7734
  sql,
6268
7735
  payload,
7736
+ ast: debugAst,
6269
7737
  options: mergedOptions
6270
7738
  },
6271
7739
  async () => {
@@ -6293,6 +7761,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
6293
7761
  return builder;
6294
7762
  }
6295
7763
  function createQueryBuilder(client, formatGatewayResult, experimental, tracer) {
7764
+ const debugAstEnabled = Boolean(experimental?.debugAst);
6296
7765
  return async function query(query, options) {
6297
7766
  const normalizedQuery = query.trim();
6298
7767
  if (!normalizedQuery) {
@@ -6309,6 +7778,7 @@ function createQueryBuilder(client, formatGatewayResult, experimental, tracer) {
6309
7778
  endpoint: "/gateway/query",
6310
7779
  sql: normalizedQuery,
6311
7780
  payload,
7781
+ ast: debugAstEnabled ? buildRawQueryDebugAst(normalizedQuery) : void 0,
6312
7782
  options
6313
7783
  },
6314
7784
  async () => {
@@ -6320,6 +7790,63 @@ function createQueryBuilder(client, formatGatewayResult, experimental, tracer) {
6320
7790
  );
6321
7791
  };
6322
7792
  }
7793
+ function resolveClientServiceBaseUrl(value, label) {
7794
+ if (value === void 0 || value === null) {
7795
+ return void 0;
7796
+ }
7797
+ return normalizeAthenaGatewayBaseUrl(value, { label });
7798
+ }
7799
+ function appendServicePath(baseUrl, segment) {
7800
+ const normalizedBaseUrl = normalizeAthenaGatewayBaseUrl(baseUrl, { label: "Athena public base URL" });
7801
+ return `${normalizedBaseUrl}/${segment.replace(/^\/+/, "")}`;
7802
+ }
7803
+ function resolveServiceUrlOverride(value, label) {
7804
+ return resolveClientServiceBaseUrl(value, label);
7805
+ }
7806
+ function resolveServiceUrls(config) {
7807
+ const baseUrl = resolveClientServiceBaseUrl(config.url, "Athena public base URL");
7808
+ return {
7809
+ 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),
7810
+ 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),
7811
+ storageUrl: resolveServiceUrlOverride(config.storage?.url, "Athena storage base URL") ?? resolveServiceUrlOverride(config.storageUrl, "Athena storage base URL") ?? (baseUrl ? appendServicePath(baseUrl, "storage") : void 0)
7812
+ };
7813
+ }
7814
+ function normalizeAuthClientConfig(auth, defaultBaseUrl) {
7815
+ if (!auth && defaultBaseUrl === void 0) {
7816
+ return void 0;
7817
+ }
7818
+ const { url, ...rest } = auth ?? {};
7819
+ const normalized = {
7820
+ ...rest
7821
+ };
7822
+ const resolvedBaseUrl = resolveClientServiceBaseUrl(
7823
+ url ?? rest.baseUrl ?? defaultBaseUrl,
7824
+ "Athena auth base URL"
7825
+ );
7826
+ if (resolvedBaseUrl !== void 0) {
7827
+ normalized.baseUrl = resolvedBaseUrl;
7828
+ }
7829
+ return normalized;
7830
+ }
7831
+ function resolveCreateClientConfig(config) {
7832
+ const resolvedUrls = resolveServiceUrls(config);
7833
+ if (!resolvedUrls.dbUrl) {
7834
+ throw new Error(
7835
+ "Athena DB base URL is required. Pass createClient(url, key) for a unified root, or set db.url / gateway.url / gatewayUrl explicitly."
7836
+ );
7837
+ }
7838
+ return {
7839
+ baseUrl: resolvedUrls.dbUrl,
7840
+ apiKey: config.key,
7841
+ client: config.client,
7842
+ backend: toBackendConfig(config.backend),
7843
+ headers: config.headers,
7844
+ auth: config.auth,
7845
+ authUrl: resolvedUrls.authUrl,
7846
+ storageUrl: resolvedUrls.storageUrl,
7847
+ experimental: config.experimental
7848
+ };
7849
+ }
6323
7850
  function createClientFromConfig(config) {
6324
7851
  const gatewayHeaders = {
6325
7852
  ...config.headers ?? {}
@@ -6334,16 +7861,33 @@ function createClientFromConfig(config) {
6334
7861
  backend: config.backend,
6335
7862
  headers: gatewayHeaders
6336
7863
  });
6337
- const formatGatewayResult = createResultFormatter();
7864
+ const formatGatewayResult = createResultFormatter(config.experimental);
6338
7865
  const queryTracer = createQueryTracer(config.experimental);
6339
- const auth = createAuthClient(config.auth);
6340
- const from = (table, options) => createTableBuilder(
6341
- resolveTableNameForCall(table, options?.schema),
6342
- gateway,
6343
- formatGatewayResult,
6344
- queryTracer,
6345
- config.experimental
6346
- );
7866
+ const auth = createAuthClient(normalizeAuthClientConfig(config.auth, config.authUrl));
7867
+ function from(tableOrModel, options) {
7868
+ if (isAthenaModelTarget(tableOrModel)) {
7869
+ if (options?.schema !== void 0) {
7870
+ throw new Error(
7871
+ "from(model) does not accept a schema override because the model already defines its target."
7872
+ );
7873
+ }
7874
+ return createTableBuilder(
7875
+ resolveAthenaModelTargetTableName(tableOrModel),
7876
+ gateway,
7877
+ formatGatewayResult,
7878
+ queryTracer,
7879
+ config.experimental
7880
+ );
7881
+ }
7882
+ const resolvedTableName = resolveTableNameForCall(tableOrModel, options?.schema);
7883
+ return createTableBuilder(
7884
+ resolvedTableName,
7885
+ gateway,
7886
+ formatGatewayResult,
7887
+ queryTracer,
7888
+ config.experimental
7889
+ );
7890
+ }
6347
7891
  const rpc = (fn, args, options) => {
6348
7892
  const normalizedFn = fn.trim();
6349
7893
  if (!normalizedFn) {
@@ -6356,10 +7900,16 @@ function createClientFromConfig(config) {
6356
7900
  gateway,
6357
7901
  formatGatewayResult,
6358
7902
  queryTracer,
6359
- captureTraceCallsite(queryTracer)
7903
+ captureTraceCallsite(queryTracer),
7904
+ Boolean(config.experimental?.debugAst)
6360
7905
  );
6361
7906
  };
6362
- const query = createQueryBuilder(gateway, formatGatewayResult, config.experimental, queryTracer);
7907
+ const query = createQueryBuilder(
7908
+ gateway,
7909
+ formatGatewayResult,
7910
+ config.experimental,
7911
+ queryTracer
7912
+ );
6363
7913
  const db = createDbModule({ from, rpc, query });
6364
7914
  const sdkClient = {
6365
7915
  from,
@@ -6372,27 +7922,27 @@ function createClientFromConfig(config) {
6372
7922
  if (config.experimental?.athenaStorageBackend) {
6373
7923
  const storageClient = {
6374
7924
  ...sdkClient,
6375
- storage: createStorageModule(gateway, config.experimental.storage)
7925
+ storage: createStorageModule(gateway, {
7926
+ ...config.experimental.storage,
7927
+ ...config.storageUrl ? {
7928
+ baseUrl: config.storageUrl,
7929
+ stripBasePath: true
7930
+ } : {}
7931
+ })
6376
7932
  };
6377
7933
  return storageClient;
6378
7934
  }
6379
7935
  return sdkClient;
6380
7936
  }
6381
- var DEFAULT_BACKEND = { type: "athena" };
6382
- function toBackendConfig(b) {
6383
- if (!b) return DEFAULT_BACKEND;
6384
- return typeof b === "string" ? { type: b } : b;
6385
- }
6386
- function createClient(url, apiKey, options) {
6387
- return createClientFromConfig({
6388
- baseUrl: url,
6389
- apiKey,
6390
- client: options?.client,
6391
- backend: toBackendConfig(options?.backend),
6392
- headers: options?.headers,
6393
- auth: options?.auth,
6394
- experimental: options?.experimental
6395
- });
7937
+ function createClient(configOrUrl, apiKey, options) {
7938
+ if (typeof configOrUrl === "string") {
7939
+ return createClientFromConfig(resolveCreateClientConfig({
7940
+ url: configOrUrl,
7941
+ key: apiKey ?? "",
7942
+ ...options
7943
+ }));
7944
+ }
7945
+ return createClientFromConfig(resolveCreateClientConfig(configOrUrl));
6396
7946
  }
6397
7947
 
6398
7948
  // src/schema/postgres-introspection-core.ts
@@ -6989,6 +8539,7 @@ function rootUsage() {
6989
8539
  "",
6990
8540
  "Examples:",
6991
8541
  " athena-js generate",
8542
+ " DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/app_db athena-js generate --dry-run",
6992
8543
  " athena-js generate --config ./athena.config.ts --dry-run",
6993
8544
  " athena-js generate --help"
6994
8545
  ].join("\n");
@@ -7005,8 +8556,14 @@ function generateUsage() {
7005
8556
  " --dry-run Build generated files in memory without writing them to disk",
7006
8557
  " -h, --help Show help for generate",
7007
8558
  "",
8559
+ "Config resolution:",
8560
+ " - uses athena.config.* discovery first",
8561
+ " - falls back to env-only direct mode when DATABASE_URL/PG_URL is present",
8562
+ " - falls back to env-only gateway mode when ATHENA_URL + ATHENA_API_KEY are present",
8563
+ "",
7008
8564
  "Examples:",
7009
8565
  " athena-js generate",
8566
+ " DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/app_db athena-js generate --dry-run",
7010
8567
  " athena-js generate --config ./athena.config.ts --dry-run"
7011
8568
  ].join("\n");
7012
8569
  }