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