@xylex-group/athena 2.8.2 → 2.9.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 (52) hide show
  1. package/README.md +154 -64
  2. package/dist/browser.cjs +636 -21
  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 +630 -22
  7. package/dist/browser.js.map +1 -1
  8. package/dist/cli/index.cjs +591 -29
  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 +591 -29
  13. package/dist/cli/index.js.map +1 -1
  14. package/dist/{model-form-Cx3wtvi8.d.ts → client-CfAE_QOj.d.cts} +101 -97
  15. package/dist/{model-form-_ugfOXao.d.cts → client-D6EIJdQS.d.ts} +101 -97
  16. package/dist/index.cjs +714 -41
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +8 -7
  19. package/dist/index.d.ts +8 -7
  20. package/dist/index.js +708 -42
  21. package/dist/index.js.map +1 -1
  22. package/dist/model-form-ByvyyvxB.d.ts +96 -0
  23. package/dist/model-form-DACdBLYG.d.cts +96 -0
  24. package/dist/next/client.cjs +7875 -0
  25. package/dist/next/client.cjs.map +1 -0
  26. package/dist/next/client.d.cts +25 -0
  27. package/dist/next/client.d.ts +25 -0
  28. package/dist/next/client.js +7873 -0
  29. package/dist/next/client.js.map +1 -0
  30. package/dist/next/server.cjs +7993 -0
  31. package/dist/next/server.cjs.map +1 -0
  32. package/dist/next/server.d.cts +52 -0
  33. package/dist/next/server.d.ts +52 -0
  34. package/dist/next/server.js +7990 -0
  35. package/dist/next/server.js.map +1 -0
  36. package/dist/{pipeline-BtD-Uo5X.d.cts → pipeline-CmUZsXsi.d.cts} +1 -1
  37. package/dist/{pipeline-yCIZNJHE.d.ts → pipeline-DZMsPxUg.d.ts} +1 -1
  38. package/dist/{react-email-CiiSVa9F.d.cts → react-email-BvJ3fj_F.d.cts} +35 -5
  39. package/dist/{react-email-WN8UU3AL.d.ts → react-email-PLAJuZuO.d.ts} +35 -5
  40. package/dist/react.cjs +30 -1
  41. package/dist/react.cjs.map +1 -1
  42. package/dist/react.d.cts +39 -10
  43. package/dist/react.d.ts +39 -10
  44. package/dist/react.js +30 -2
  45. package/dist/react.js.map +1 -1
  46. package/dist/shared-BW6hoLBY.d.cts +33 -0
  47. package/dist/shared-BiJvoURI.d.ts +33 -0
  48. package/dist/{types-g8G6J0xE.d.cts → types-BeZIHduP.d.cts} +2 -1
  49. package/dist/{types-g8G6J0xE.d.ts → types-BeZIHduP.d.ts} +2 -1
  50. package/dist/{types-C2kiTt6-.d.ts → types-C-YvfgYh.d.cts} +26 -2
  51. package/dist/{types-89EfjLjV.d.cts → types-CRjDwmtJ.d.ts} +26 -2
  52. package/package.json +32 -14
package/dist/cli/index.js CHANGED
@@ -686,6 +686,77 @@ function resolveProviderSchemas(providerConfig) {
686
686
  return [...DEFAULT_POSTGRES_SCHEMAS];
687
687
  }
688
688
 
689
+ // src/generator/table-selection.ts
690
+ function normalizeTableSelector(value) {
691
+ const trimmed = value.trim();
692
+ return trimmed.length > 0 ? trimmed : void 0;
693
+ }
694
+ function normalizeTableSelection(value) {
695
+ if (typeof value === "string") {
696
+ return Array.from(
697
+ new Set(
698
+ value.split(",").map(normalizeTableSelector).filter((entry) => Boolean(entry))
699
+ )
700
+ );
701
+ }
702
+ if (Array.isArray(value)) {
703
+ return Array.from(
704
+ new Set(
705
+ value.map((entry) => typeof entry === "string" ? normalizeTableSelector(entry) : void 0).filter((entry) => Boolean(entry))
706
+ )
707
+ );
708
+ }
709
+ return [];
710
+ }
711
+ function matchesTableSelector(schemaName, tableName, selector) {
712
+ const separatorIndex = selector.indexOf(".");
713
+ if (separatorIndex < 0) {
714
+ return tableName === selector;
715
+ }
716
+ const selectorSchema = selector.slice(0, separatorIndex).trim();
717
+ const selectorTable = selector.slice(separatorIndex + 1).trim();
718
+ return selectorSchema === schemaName && selectorTable === tableName;
719
+ }
720
+ function shouldKeepTable(schemaName, tableName, filter) {
721
+ const included = filter.includeTables.length === 0 || filter.includeTables.some((selector) => matchesTableSelector(schemaName, tableName, selector));
722
+ if (!included) {
723
+ return false;
724
+ }
725
+ return !filter.excludeTables.some((selector) => matchesTableSelector(schemaName, tableName, selector));
726
+ }
727
+ function hasTableFilters(filter) {
728
+ return filter.includeTables.length > 0 || filter.excludeTables.length > 0;
729
+ }
730
+ function filterIntrospectionSnapshot(snapshot, filter) {
731
+ if (!hasTableFilters(filter)) {
732
+ return snapshot;
733
+ }
734
+ const schemas = {};
735
+ for (const [schemaName, schema] of Object.entries(snapshot.schemas)) {
736
+ const tables = Object.fromEntries(
737
+ Object.entries(schema.tables).filter(([tableName]) => shouldKeepTable(schemaName, tableName, filter))
738
+ );
739
+ if (Object.keys(tables).length === 0) {
740
+ continue;
741
+ }
742
+ schemas[schemaName] = {
743
+ ...schema,
744
+ tables
745
+ };
746
+ }
747
+ if (Object.keys(schemas).length === 0) {
748
+ const includeLabel = filter.includeTables.length > 0 ? ` includeTables=${filter.includeTables.join(", ")}` : "";
749
+ const excludeLabel = filter.excludeTables.length > 0 ? ` excludeTables=${filter.excludeTables.join(", ")}` : "";
750
+ throw new Error(
751
+ `Generator table filters matched no tables after schema selection.${includeLabel}${excludeLabel}`
752
+ );
753
+ }
754
+ return {
755
+ ...snapshot,
756
+ schemas
757
+ };
758
+ }
759
+
689
760
  // src/generator/config.ts
690
761
  var POSTGRES_PROTOCOLS = /* @__PURE__ */ new Set(["postgres:", "postgresql:"]);
691
762
  var DEFAULT_CONFIG_CANDIDATES = [
@@ -696,13 +767,20 @@ var DEFAULT_CONFIG_CANDIDATES = [
696
767
  ".athena.config.ts",
697
768
  ".athena.config.js"
698
769
  ];
699
- var DEFAULT_TARGETS = {
770
+ var LEGACY_DEFAULT_TARGETS = {
700
771
  model: "athena/models/{schema_kebab}/{model_kebab}.ts",
701
772
  schema: "athena/schemas/{schema_kebab}.ts",
702
773
  database: "athena/relations.ts",
703
774
  registry: "athena/config.ts"
704
775
  };
705
- var DEFAULT_OUTPUT_FORMAT = "define-model";
776
+ var ATHENA_DIRECT_TARGETS = {
777
+ model: "athena/models/{schema_kebab}/{model_kebab}.ts",
778
+ schema: "athena/schemas/{schema_kebab}.ts",
779
+ database: "athena/relations.ts",
780
+ registry: "athena/registry.generated.ts"
781
+ };
782
+ var DEFAULT_OUTPUT_FORMAT = "table-builder";
783
+ var DEFAULT_OUTPUT_PRESET = "athena-direct";
706
784
  var DEFAULT_NAMING = {
707
785
  modelType: "pascal",
708
786
  modelConst: "camel",
@@ -721,6 +799,10 @@ var DEFAULT_EXPERIMENTAL_FLAGS = {
721
799
  var DEFAULT_INTERNAL_CONFIG = {
722
800
  schemaVersion: 1
723
801
  };
802
+ var DEFAULT_FILTER_CONFIG = {
803
+ includeTables: [],
804
+ excludeTables: []
805
+ };
724
806
  var PROJECT_ENV_FILENAMES = [".env", ".env.local"];
725
807
  var DIRECT_CONNECTION_STRING_ENV_KEYS = [
726
808
  "ATHENA_GENERATOR_PG_URL",
@@ -739,10 +821,13 @@ var GATEWAY_API_KEY_ENV_KEYS = [
739
821
  ];
740
822
  var GENERATOR_SCHEMA_ENV_KEYS = ["ATHENA_GENERATOR_SCHEMAS"];
741
823
  var OUTPUT_FORMAT_ENV_KEYS = ["ATHENA_GENERATOR_OUTPUT_FORMAT"];
824
+ var OUTPUT_PRESET_ENV_KEYS = ["ATHENA_GENERATOR_OUTPUT_PRESET"];
742
825
  var MODEL_TARGET_ENV_KEYS = ["ATHENA_GENERATOR_MODEL_TARGET"];
743
826
  var SCHEMA_TARGET_ENV_KEYS = ["ATHENA_GENERATOR_SCHEMA_TARGET"];
744
827
  var DATABASE_TARGET_ENV_KEYS = ["ATHENA_GENERATOR_DATABASE_TARGET"];
745
828
  var REGISTRY_TARGET_ENV_KEYS = ["ATHENA_GENERATOR_REGISTRY_TARGET"];
829
+ var TABLES_ENV_KEYS = ["ATHENA_GENERATOR_TABLES"];
830
+ var EXCLUDE_TABLES_ENV_KEYS = ["ATHENA_GENERATOR_EXCLUDE_TABLES"];
746
831
  var PLACEHOLDER_MAP_ENV_KEYS = ["ATHENA_GENERATOR_PLACEHOLDER_MAP"];
747
832
  var MODEL_TYPE_ENV_KEYS = ["ATHENA_GENERATOR_MODEL_TYPE", "ATHENA_GENERATOR_MODEL_STYLE"];
748
833
  var MODEL_CONST_ENV_KEYS = ["ATHENA_GENERATOR_MODEL_CONST"];
@@ -757,7 +842,12 @@ var SCYLLA_PROVIDER_CONTRACTS_ENV_KEYS = ["ATHENA_GENERATOR_SCYLLA_PROVIDER_CONT
757
842
  var ENV_ONLY_CONFIG_PATH = "[environment defaults]";
758
843
  var NAMING_STYLE_VALUES = ["preserve", "camel", "pascal", "snake", "kebab"];
759
844
  var OUTPUT_FORMAT_VALUES = ["define-model", "table-builder"];
845
+ var OUTPUT_PRESET_VALUES = ["legacy", "athena-direct"];
760
846
  var BACKEND_TYPE_VALUES = ["athena", "postgrest", "postgresql", "scylladb"];
847
+ var OUTPUT_PRESET_TARGETS = {
848
+ legacy: LEGACY_DEFAULT_TARGETS,
849
+ "athena-direct": ATHENA_DIRECT_TARGETS
850
+ };
761
851
  function normalizeRawEnvValue(rawValue) {
762
852
  if (rawValue.startsWith('"') && rawValue.endsWith('"') && rawValue.length >= 2) {
763
853
  const inner = rawValue.slice(1, -1);
@@ -964,11 +1054,19 @@ function normalizeExperimentalFlags(input) {
964
1054
  )
965
1055
  };
966
1056
  }
1057
+ function normalizeFilterConfig(input) {
1058
+ return {
1059
+ includeTables: normalizeTableSelection(input?.includeTables),
1060
+ excludeTables: normalizeTableSelection(input?.excludeTables)
1061
+ };
1062
+ }
967
1063
  function normalizeOutputConfig(output) {
1064
+ const preset = output?.preset ?? DEFAULT_OUTPUT_PRESET;
968
1065
  return {
969
1066
  format: output?.format ?? DEFAULT_OUTPUT_FORMAT,
1067
+ preset,
970
1068
  targets: {
971
- ...DEFAULT_TARGETS,
1069
+ ...OUTPUT_PRESET_TARGETS[preset],
972
1070
  ...output?.targets ?? {}
973
1071
  },
974
1072
  placeholderMap: {
@@ -1048,6 +1146,10 @@ function normalizeGeneratorConfig(input) {
1048
1146
  ...DEFAULT_NAMING,
1049
1147
  ...input.naming ?? {}
1050
1148
  },
1149
+ filter: {
1150
+ ...DEFAULT_FILTER_CONFIG,
1151
+ ...normalizeFilterConfig(input.filter)
1152
+ },
1051
1153
  features: normalizeFeatureFlags(input.features),
1052
1154
  experimental: normalizeExperimentalFlags(input.experimental),
1053
1155
  internal: {
@@ -1108,16 +1210,18 @@ function importConfigModule(moduleSpecifier) {
1108
1210
  }
1109
1211
  function buildEnvironmentOutputConfig() {
1110
1212
  const format = resolveOptionalOneOf(OUTPUT_FORMAT_ENV_KEYS, OUTPUT_FORMAT_VALUES);
1213
+ const preset = resolveOptionalOneOf(OUTPUT_PRESET_ENV_KEYS, OUTPUT_PRESET_VALUES);
1111
1214
  const modelTarget = resolveFallbackValue(MODEL_TARGET_ENV_KEYS);
1112
1215
  const schemaTarget = resolveFallbackValue(SCHEMA_TARGET_ENV_KEYS);
1113
1216
  const databaseTarget = resolveFallbackValue(DATABASE_TARGET_ENV_KEYS);
1114
1217
  const registryTarget = resolveFallbackValue(REGISTRY_TARGET_ENV_KEYS);
1115
1218
  const placeholderMap = resolveOptionalJson(PLACEHOLDER_MAP_ENV_KEYS);
1116
- if (format === void 0 && modelTarget === void 0 && schemaTarget === void 0 && databaseTarget === void 0 && registryTarget === void 0 && placeholderMap === void 0) {
1219
+ if (format === void 0 && preset === void 0 && modelTarget === void 0 && schemaTarget === void 0 && databaseTarget === void 0 && registryTarget === void 0 && placeholderMap === void 0) {
1117
1220
  return void 0;
1118
1221
  }
1119
1222
  return {
1120
1223
  format,
1224
+ preset,
1121
1225
  targets: {
1122
1226
  ...modelTarget ? { model: modelTarget } : {},
1123
1227
  ...schemaTarget ? { schema: schemaTarget } : {},
@@ -1127,6 +1231,17 @@ function buildEnvironmentOutputConfig() {
1127
1231
  placeholderMap
1128
1232
  };
1129
1233
  }
1234
+ function buildEnvironmentFilterConfig() {
1235
+ const includeTables = resolveFallbackValue(TABLES_ENV_KEYS);
1236
+ const excludeTables = resolveFallbackValue(EXCLUDE_TABLES_ENV_KEYS);
1237
+ if (includeTables === void 0 && excludeTables === void 0) {
1238
+ return void 0;
1239
+ }
1240
+ return {
1241
+ ...includeTables !== void 0 ? { includeTables } : {},
1242
+ ...excludeTables !== void 0 ? { excludeTables } : {}
1243
+ };
1244
+ }
1130
1245
  function buildEnvironmentNamingConfig() {
1131
1246
  const modelType = resolveOptionalOneOf(MODEL_TYPE_ENV_KEYS, NAMING_STYLE_VALUES);
1132
1247
  const modelConst = resolveOptionalOneOf(MODEL_CONST_ENV_KEYS, NAMING_STYLE_VALUES);
@@ -1202,6 +1317,7 @@ function createEnvironmentGeneratorConfig() {
1202
1317
  provider,
1203
1318
  output: buildEnvironmentOutputConfig(),
1204
1319
  naming: buildEnvironmentNamingConfig(),
1320
+ filter: buildEnvironmentFilterConfig(),
1205
1321
  features: buildEnvironmentFeatureFlags(),
1206
1322
  experimental: buildEnvironmentExperimentalFlags()
1207
1323
  };
@@ -1363,7 +1479,7 @@ ${schemaEntries}
1363
1479
  content
1364
1480
  };
1365
1481
  }
1366
- function renderRegistryArtifact(registryPath, databasePath, databaseConstName, registryConstName, databaseName, generatedAt, outputFormat, schemaVersion) {
1482
+ function renderRegistryArtifact(registryPath, databasePath, databaseConstName, registryConstName, databaseName, generatedAt, outputPreset, outputFormat, schemaVersion) {
1367
1483
  const databaseImportPath = toModuleImportPath(registryPath, databasePath);
1368
1484
  const content = `import { defineRegistry } from '@xylex-group/athena'
1369
1485
  import { ${databaseConstName} } from '${databaseImportPath}'
@@ -1372,6 +1488,7 @@ export const __athena_schema_meta = {
1372
1488
  schemaVersion: ${schemaVersion},
1373
1489
  generatedAt: ${escapeStringLiteral(generatedAt)},
1374
1490
  database: ${escapeStringLiteral(databaseName)},
1491
+ outputPreset: ${escapeStringLiteral(outputPreset)},
1375
1492
  outputFormat: ${escapeStringLiteral(outputFormat)},
1376
1493
  } as const
1377
1494
 
@@ -1541,6 +1658,7 @@ function composeGeneratorArtifacts(input) {
1541
1658
  toSafeIdentifier("registry", config.naming.registryConst, "registry"),
1542
1659
  databaseName,
1543
1660
  snapshot.generatedAt,
1661
+ config.output.preset,
1544
1662
  config.output.format,
1545
1663
  config.internal.schemaVersion
1546
1664
  )
@@ -1646,7 +1764,7 @@ export const ${descriptor.tableConstName} = table(${escapeStringLiteral(descript
1646
1764
  .columns({
1647
1765
  ${columnLines}
1648
1766
  })
1649
- .primaryKey(${descriptor.table.primaryKey.map((value) => escapeStringLiteral(value)).join(", ")})
1767
+ ${descriptor.table.primaryKey.length > 0 ? `.primaryKey(${descriptor.table.primaryKey.map((value) => escapeStringLiteral(value)).join(", ")})` : ".withoutPrimaryKey()"}
1650
1768
  ${relationsAssignment ? `${relationsAssignment}` : ""}
1651
1769
  export type ${descriptor.rowTypeName} = RowOf<typeof ${descriptor.tableConstName}>
1652
1770
  export type ${descriptor.insertTypeName} = InsertOf<typeof ${descriptor.tableConstName}>
@@ -1743,11 +1861,12 @@ ${nullableLines}
1743
1861
  }
1744
1862
  function generateArtifactsFromSnapshot(snapshot, config) {
1745
1863
  const normalizedConfig = "internal" in config ? config : normalizeGeneratorConfig(config);
1864
+ const filteredSnapshot = filterIntrospectionSnapshot(snapshot, normalizedConfig.filter);
1746
1865
  if (normalizedConfig.output.format === "table-builder") {
1747
- return generateTableBuilderArtifactsFromSnapshot(snapshot, normalizedConfig);
1866
+ return generateTableBuilderArtifactsFromSnapshot(filteredSnapshot, normalizedConfig);
1748
1867
  }
1749
1868
  return composeGeneratorArtifacts({
1750
- snapshot,
1869
+ snapshot: filteredSnapshot,
1751
1870
  config: normalizedConfig,
1752
1871
  createModelDescriptor({ providerName, databaseName, schemaName, tableName, table }) {
1753
1872
  const modelConstName = toSafeIdentifier(
@@ -1777,7 +1896,7 @@ function generateArtifactsFromSnapshot(snapshot, config) {
1777
1896
  table
1778
1897
  };
1779
1898
  },
1780
- renderModelArtifact: (descriptor) => renderModelArtifact2(snapshot.database, descriptor, normalizedConfig)
1899
+ renderModelArtifact: (descriptor) => renderModelArtifact2(filteredSnapshot.database, descriptor, normalizedConfig)
1781
1900
  });
1782
1901
  }
1783
1902
 
@@ -1883,7 +2002,7 @@ var getSessionCookie = (request, config) => {
1883
2002
 
1884
2003
  // package.json
1885
2004
  var package_default = {
1886
- version: "2.8.2"
2005
+ version: "2.9.0"
1887
2006
  };
1888
2007
 
1889
2008
  // src/sdk-version.ts
@@ -1896,6 +2015,7 @@ function buildSdkHeaderValue(sdkName) {
1896
2015
  var DEFAULT_CLIENT = "railway_direct";
1897
2016
  var SDK_NAME = "xylex-group/athena";
1898
2017
  var SDK_HEADER_VALUE = buildSdkHeaderValue(SDK_NAME);
2018
+ var NO_CACHE_HEADER_VALUE = "no-cache";
1899
2019
  function parseResponseBody(rawText, contentType) {
1900
2020
  if (!rawText) {
1901
2021
  return { parsed: null, parseFailed: false };
@@ -1914,6 +2034,9 @@ function parseResponseBody(rawText, contentType) {
1914
2034
  function normalizeHeaderValue(value) {
1915
2035
  return value ? value : void 0;
1916
2036
  }
2037
+ function isCacheControlHeaderName(name) {
2038
+ return name.toLowerCase() === "cache-control";
2039
+ }
1917
2040
  function resolveHeaderValue(headers, candidates) {
1918
2041
  for (const candidate of candidates) {
1919
2042
  const direct = normalizeHeaderValue(headers[candidate]);
@@ -2072,6 +2195,7 @@ function buildRpcGetEndpoint(payload) {
2072
2195
  }
2073
2196
  function buildHeaders(config, options) {
2074
2197
  const mergedStripNulls = options?.stripNulls ?? true;
2198
+ const forceNoCache = Boolean(config.forceNoCache || options?.forceNoCache);
2075
2199
  const extraHeaders = {
2076
2200
  ...config.headers ?? {},
2077
2201
  ...options?.headers ?? {}
@@ -2125,11 +2249,15 @@ function buildHeaders(config, options) {
2125
2249
  const athenaClientKeys = ["x-athena-client", "X-Athena-Client"];
2126
2250
  Object.entries(extraHeaders).forEach(([key, value]) => {
2127
2251
  if (athenaClientKeys.includes(key)) return;
2252
+ if (forceNoCache && isCacheControlHeaderName(key)) return;
2128
2253
  const normalized = normalizeHeaderValue(value);
2129
2254
  if (normalized) {
2130
2255
  headers[key] = normalized;
2131
2256
  }
2132
2257
  });
2258
+ if (forceNoCache) {
2259
+ headers["Cache-Control"] = NO_CACHE_HEADER_VALUE;
2260
+ }
2133
2261
  return headers;
2134
2262
  }
2135
2263
  function toInvalidUrlResponse(error, endpoint, method) {
@@ -2569,6 +2697,35 @@ function quoteSelectColumnsExpression(columns) {
2569
2697
  }
2570
2698
  return tokens.map(quoteSelectToken).join(", ");
2571
2699
  }
2700
+ var ATHENA_AUTH_MAX_TEMPLATE_VARIABLES = 64;
2701
+ var ATHENA_AUTH_MAX_TEMPLATE_VARIABLE_LENGTH = 128;
2702
+ function describeTemplateVariableTarget(target) {
2703
+ const normalized = target?.trim();
2704
+ return normalized && normalized.length > 0 ? normalized : "Athena auth admin email template variables";
2705
+ }
2706
+ function assertAthenaAuthTemplateVariables(variables, target) {
2707
+ const label = describeTemplateVariableTarget(target);
2708
+ if (!Array.isArray(variables)) {
2709
+ throw new Error(`${label} must be an array of strings.`);
2710
+ }
2711
+ if (variables.length > ATHENA_AUTH_MAX_TEMPLATE_VARIABLES) {
2712
+ throw new Error(
2713
+ `${label} cannot contain more than ${ATHENA_AUTH_MAX_TEMPLATE_VARIABLES} entries.`
2714
+ );
2715
+ }
2716
+ variables.forEach((variable, index) => {
2717
+ if (typeof variable !== "string") {
2718
+ throw new Error(
2719
+ `${label} must contain only strings. Received ${typeof variable} at index ${index}.`
2720
+ );
2721
+ }
2722
+ if (variable.length > ATHENA_AUTH_MAX_TEMPLATE_VARIABLE_LENGTH) {
2723
+ throw new Error(
2724
+ `${label} cannot contain entries longer than ${ATHENA_AUTH_MAX_TEMPLATE_VARIABLE_LENGTH} characters. Received ${variable.length} characters at index ${index}.`
2725
+ );
2726
+ }
2727
+ });
2728
+ }
2572
2729
 
2573
2730
  // src/auth/react-email.ts
2574
2731
  var reactEmailRenderModulePromise;
@@ -2758,6 +2915,7 @@ async function resolveReactEmailPayloadFields(input, fields, options) {
2758
2915
  var DEFAULT_AUTH_BASE_URL = "http://localhost:3001/api/auth";
2759
2916
  var SDK_NAME2 = "xylex-group/athena-auth";
2760
2917
  var SDK_HEADER_VALUE2 = buildSdkHeaderValue(SDK_NAME2);
2918
+ var NO_CACHE_HEADER_VALUE2 = "no-cache";
2761
2919
  function normalizeBaseUrl(baseUrl) {
2762
2920
  return (baseUrl ?? DEFAULT_AUTH_BASE_URL).replace(/\/$/, "");
2763
2921
  }
@@ -2767,6 +2925,9 @@ function isRecord4(value) {
2767
2925
  function normalizeHeaderValue2(value) {
2768
2926
  return value ? value : void 0;
2769
2927
  }
2928
+ function isCacheControlHeaderName2(name) {
2929
+ return name.toLowerCase() === "cache-control";
2930
+ }
2770
2931
  function parseResponseBody2(rawText, contentType) {
2771
2932
  if (!rawText) {
2772
2933
  return { parsed: null, parseFailed: false };
@@ -2822,6 +2983,54 @@ function mergeCallOptions(base, override) {
2822
2983
  }
2823
2984
  };
2824
2985
  }
2986
+ function toSessionGuardFailure(sessionResult) {
2987
+ if (sessionResult.status === 401 || sessionResult.data == null) {
2988
+ return {
2989
+ ok: false,
2990
+ reason: "unauthorized",
2991
+ status: 401,
2992
+ error: sessionResult.error ?? "Unauthorized",
2993
+ sessionResult
2994
+ };
2995
+ }
2996
+ return {
2997
+ ok: false,
2998
+ reason: "upstream_error",
2999
+ status: sessionResult.status,
3000
+ error: sessionResult.error ?? "Failed to resolve current session",
3001
+ sessionResult
3002
+ };
3003
+ }
3004
+ function toPermissionGuardFailure(permissionResult, sessionResult) {
3005
+ if (permissionResult.status === 401) {
3006
+ return {
3007
+ ok: false,
3008
+ reason: "unauthorized",
3009
+ status: 401,
3010
+ error: permissionResult.error ?? "Unauthorized",
3011
+ sessionResult,
3012
+ permissionResult
3013
+ };
3014
+ }
3015
+ if (permissionResult.status === 403) {
3016
+ return {
3017
+ ok: false,
3018
+ reason: "forbidden",
3019
+ status: 403,
3020
+ error: permissionResult.error ?? "Forbidden",
3021
+ sessionResult,
3022
+ permissionResult
3023
+ };
3024
+ }
3025
+ return {
3026
+ ok: false,
3027
+ reason: "upstream_error",
3028
+ status: permissionResult.status,
3029
+ error: permissionResult.error ?? "Failed to resolve permission check",
3030
+ sessionResult,
3031
+ permissionResult
3032
+ };
3033
+ }
2825
3034
  function extractFetchOptions(input) {
2826
3035
  if (!input) {
2827
3036
  return {
@@ -2837,6 +3046,7 @@ function extractFetchOptions(input) {
2837
3046
  };
2838
3047
  }
2839
3048
  function buildHeaders2(config, options) {
3049
+ const forceNoCache = Boolean(config.forceNoCache || options?.forceNoCache);
2840
3050
  const headers = {
2841
3051
  "Content-Type": "application/json",
2842
3052
  "X-Athena-Sdk": SDK_HEADER_VALUE2
@@ -2850,16 +3060,30 @@ function buildHeaders2(config, options) {
2850
3060
  if (bearerToken) {
2851
3061
  headers.Authorization = `Bearer ${bearerToken}`;
2852
3062
  }
3063
+ const cookie = options?.cookie ?? config.cookie;
3064
+ if (cookie) {
3065
+ headers.Cookie = cookie;
3066
+ }
3067
+ const sessionToken = options?.sessionToken ?? config.sessionToken;
3068
+ if (sessionToken) {
3069
+ headers["X-Athena-Auth-Session-Token"] = sessionToken;
3070
+ }
2853
3071
  const mergedExtraHeaders = {
2854
3072
  ...config.headers ?? {},
2855
3073
  ...options?.headers ?? {}
2856
3074
  };
2857
3075
  Object.entries(mergedExtraHeaders).forEach(([key, value]) => {
3076
+ if (forceNoCache && isCacheControlHeaderName2(key)) {
3077
+ return;
3078
+ }
2858
3079
  const normalized = normalizeHeaderValue2(value);
2859
3080
  if (normalized) {
2860
3081
  headers[key] = normalized;
2861
3082
  }
2862
3083
  });
3084
+ if (forceNoCache) {
3085
+ headers["Cache-Control"] = NO_CACHE_HEADER_VALUE2;
3086
+ }
2863
3087
  return headers;
2864
3088
  }
2865
3089
  function appendQueryParam(searchParams, key, value) {
@@ -3124,7 +3348,91 @@ function createAuthClient(config = {}) {
3124
3348
  htmlField: "htmlTemplate",
3125
3349
  textField: "textTemplate",
3126
3350
  variablesField: "variables"
3127
- }, withReactEmailRoute(route));
3351
+ }, withReactEmailRoute(route)).then((payload) => {
3352
+ if ("variables" in payload && payload.variables !== void 0 && payload.variables !== null) {
3353
+ assertAthenaAuthTemplateVariables(
3354
+ payload.variables,
3355
+ `${route} variables`
3356
+ );
3357
+ }
3358
+ return payload;
3359
+ });
3360
+ const requireSession = async (input, options) => {
3361
+ const sessionInput = input?.fetchOptions ? { fetchOptions: input.fetchOptions } : void 0;
3362
+ const sessionResult = await getGeneric(
3363
+ "/get-session",
3364
+ sessionInput,
3365
+ options
3366
+ );
3367
+ if (!sessionResult.ok || sessionResult.data == null) {
3368
+ return toSessionGuardFailure(sessionResult);
3369
+ }
3370
+ return {
3371
+ ok: true,
3372
+ session: sessionResult.data
3373
+ };
3374
+ };
3375
+ const getUser = async (input, options) => {
3376
+ const sessionResult = await getGeneric(
3377
+ "/get-session",
3378
+ input,
3379
+ options
3380
+ );
3381
+ if (!sessionResult.ok) {
3382
+ return {
3383
+ ...sessionResult,
3384
+ data: null
3385
+ };
3386
+ }
3387
+ return {
3388
+ ...sessionResult,
3389
+ data: {
3390
+ user: sessionResult.data?.user ?? null
3391
+ }
3392
+ };
3393
+ };
3394
+ const requirePermission = async (endpoint, input, options) => {
3395
+ const sessionGuard = await requireSession(
3396
+ input?.fetchOptions ? { fetchOptions: input.fetchOptions } : void 0,
3397
+ options
3398
+ );
3399
+ if (!sessionGuard.ok) {
3400
+ return sessionGuard;
3401
+ }
3402
+ const permissionResult = await postGeneric(
3403
+ endpoint,
3404
+ input,
3405
+ options
3406
+ );
3407
+ if (!permissionResult.ok) {
3408
+ return toPermissionGuardFailure(permissionResult, {
3409
+ ok: true,
3410
+ status: 200,
3411
+ data: sessionGuard.session,
3412
+ error: null,
3413
+ errorDetails: null,
3414
+ raw: sessionGuard.session
3415
+ });
3416
+ }
3417
+ if (!permissionResult.data?.success) {
3418
+ return {
3419
+ ok: false,
3420
+ reason: "forbidden",
3421
+ status: 403,
3422
+ error: permissionResult.data?.error ?? "Forbidden",
3423
+ sessionResult: {
3424
+ ok: true,
3425
+ status: 200,
3426
+ data: sessionGuard.session,
3427
+ error: null,
3428
+ errorDetails: null,
3429
+ raw: sessionGuard.session
3430
+ },
3431
+ permissionResult
3432
+ };
3433
+ }
3434
+ return sessionGuard;
3435
+ };
3128
3436
  const listUserEmailsWithFallback = async (input, options) => {
3129
3437
  const primary = await getWithQuery(
3130
3438
  "/email/list",
@@ -3286,6 +3594,7 @@ function createAuthClient(config = {}) {
3286
3594
  input,
3287
3595
  options
3288
3596
  ),
3597
+ requirePermission: (input, options) => requirePermission("/organization/has-permission", input, options),
3289
3598
  invitation: {
3290
3599
  cancel: (input, options) => executePostWithCompatibleInput(
3291
3600
  resolvedConfig,
@@ -3481,6 +3790,8 @@ function createAuthClient(config = {}) {
3481
3790
  };
3482
3791
  const auth = {
3483
3792
  getSession: (input, options) => getGeneric("/get-session", input, options),
3793
+ getUser,
3794
+ requireSession,
3484
3795
  signOut,
3485
3796
  forgetPassword: (input, options) => postGeneric("/forget-password", input, options),
3486
3797
  resetPassword: authResetPassword,
@@ -3575,6 +3886,7 @@ function createAuthClient(config = {}) {
3575
3886
  }
3576
3887
  },
3577
3888
  hasPermission: (input, options) => postGeneric("/admin/has-permission", input, options),
3889
+ requirePermission: (input, options) => requirePermission("/admin/has-permission", input, options),
3578
3890
  apiKey: {
3579
3891
  create: (input, options) => postGeneric("/admin/api-key/create", input, options)
3580
3892
  },
@@ -3726,6 +4038,8 @@ function createAuthClient(config = {}) {
3726
4038
  input,
3727
4039
  options
3728
4040
  ),
4041
+ getUser,
4042
+ requireSession,
3729
4043
  listSessions: (input, options) => executeGetWithCompatibleInput(
3730
4044
  resolvedConfig,
3731
4045
  { endpoint: "/list-sessions", method: "GET" },
@@ -8403,6 +8717,59 @@ function createQueryBuilder(client, formatGatewayResult, experimental, tracer) {
8403
8717
  );
8404
8718
  };
8405
8719
  }
8720
+ function normalizeOptionalString2(value) {
8721
+ if (typeof value !== "string") {
8722
+ return void 0;
8723
+ }
8724
+ const normalizedValue = value.trim();
8725
+ return normalizedValue ? normalizedValue : void 0;
8726
+ }
8727
+ function readHeaderBagValue(headers, targetKey) {
8728
+ if (!headers) {
8729
+ return void 0;
8730
+ }
8731
+ if (typeof headers.get === "function") {
8732
+ return normalizeOptionalString2(headers.get(targetKey));
8733
+ }
8734
+ const normalizedTargetKey = targetKey.toLowerCase();
8735
+ for (const [key, value] of Object.entries(headers)) {
8736
+ if (key.toLowerCase() !== normalizedTargetKey) {
8737
+ continue;
8738
+ }
8739
+ if (typeof value === "string") {
8740
+ return normalizeOptionalString2(value);
8741
+ }
8742
+ return void 0;
8743
+ }
8744
+ return void 0;
8745
+ }
8746
+ function resolveSessionContextOptions(session, options) {
8747
+ const sessionToken = normalizeOptionalString2(session?.session?.token);
8748
+ const requestCookie = readHeaderBagValue(options?.requestHeaders, "cookie") ?? readHeaderBagValue(options?.headers, "cookie");
8749
+ const authInput = options?.auth;
8750
+ const resolvedUserId = options?.userId !== void 0 ? options.userId : session?.user?.id;
8751
+ const resolvedOrganizationId = options?.organizationId !== void 0 ? options.organizationId : session?.session?.activeOrganizationId;
8752
+ const resolvedBearerToken = authInput?.bearerToken !== void 0 ? authInput.bearerToken : sessionToken;
8753
+ const resolvedSessionToken = authInput?.sessionToken !== void 0 ? authInput.sessionToken : sessionToken;
8754
+ const resolvedCookie = authInput?.cookie !== void 0 ? authInput.cookie : requestCookie;
8755
+ const auth = authInput !== void 0 || resolvedBearerToken !== void 0 || resolvedSessionToken !== void 0 || resolvedCookie !== void 0 ? {
8756
+ ...authInput ?? {},
8757
+ ...resolvedBearerToken !== void 0 ? { bearerToken: resolvedBearerToken } : {},
8758
+ ...resolvedSessionToken !== void 0 ? { sessionToken: resolvedSessionToken } : {},
8759
+ ...resolvedCookie !== void 0 ? { cookie: resolvedCookie } : {},
8760
+ headers: authInput?.headers ? { ...authInput.headers } : void 0
8761
+ } : void 0;
8762
+ if (resolvedUserId === void 0 && resolvedOrganizationId === void 0 && options?.forceNoCache === void 0 && !options?.headers && !auth) {
8763
+ return void 0;
8764
+ }
8765
+ return {
8766
+ userId: resolvedUserId,
8767
+ organizationId: resolvedOrganizationId,
8768
+ forceNoCache: options?.forceNoCache,
8769
+ headers: options?.headers ? { ...options.headers } : void 0,
8770
+ auth
8771
+ };
8772
+ }
8406
8773
  function resolveClientServiceBaseUrl(value, label) {
8407
8774
  if (value === void 0 || value === null) {
8408
8775
  return void 0;
@@ -8445,6 +8812,87 @@ function resolveRequiredClientApiKey(value) {
8445
8812
  }
8446
8813
  return normalizedValue;
8447
8814
  }
8815
+ function hasHeaderIgnoreCase(headers, targetKey) {
8816
+ const normalizedTargetKey = targetKey.toLowerCase();
8817
+ return Object.keys(headers).some((key) => key.toLowerCase() === normalizedTargetKey);
8818
+ }
8819
+ function mergeClientHeaders(current, next) {
8820
+ if (!current && !next) {
8821
+ return void 0;
8822
+ }
8823
+ return {
8824
+ ...current ?? {},
8825
+ ...next ?? {}
8826
+ };
8827
+ }
8828
+ function mergeDefinedObject(current, next) {
8829
+ if (!current && !next) {
8830
+ return void 0;
8831
+ }
8832
+ const merged = {
8833
+ ...current ?? {}
8834
+ };
8835
+ const mutableMerged = merged;
8836
+ for (const [key, value] of Object.entries(next ?? {})) {
8837
+ if (value !== void 0) {
8838
+ mutableMerged[key] = value;
8839
+ }
8840
+ }
8841
+ return merged;
8842
+ }
8843
+ function mergeAuthClientOptions(current, next) {
8844
+ const merged = mergeDefinedObject(current, next);
8845
+ if (!merged) {
8846
+ return void 0;
8847
+ }
8848
+ const mergedHeaders = mergeClientHeaders(current?.headers, next?.headers);
8849
+ if (mergedHeaders) {
8850
+ merged.headers = mergedHeaders;
8851
+ }
8852
+ return merged;
8853
+ }
8854
+ function mergeServiceUrlOverrides(current, next) {
8855
+ return mergeDefinedObject(current, next);
8856
+ }
8857
+ function toClientContextOverrides(context) {
8858
+ if (!context) {
8859
+ return void 0;
8860
+ }
8861
+ return {
8862
+ userId: context.userId,
8863
+ organizationId: context.organizationId,
8864
+ forceNoCache: context.forceNoCache,
8865
+ headers: context.headers,
8866
+ auth: context.auth ? {
8867
+ ...context.auth,
8868
+ headers: context.auth.headers ? { ...context.auth.headers } : void 0
8869
+ } : void 0
8870
+ };
8871
+ }
8872
+ function mergeClientOverrideOptions(base, overrides) {
8873
+ if (!overrides) {
8874
+ return {
8875
+ ...base,
8876
+ headers: base.headers ? { ...base.headers } : void 0,
8877
+ auth: base.auth ? {
8878
+ ...base.auth,
8879
+ headers: base.auth.headers ? { ...base.auth.headers } : void 0
8880
+ } : void 0,
8881
+ db: base.db ? { ...base.db } : void 0,
8882
+ gateway: base.gateway ? { ...base.gateway } : void 0,
8883
+ storage: base.storage ? { ...base.storage } : void 0
8884
+ };
8885
+ }
8886
+ const merged = mergeDefinedObject(base, overrides) ?? { ...base };
8887
+ return {
8888
+ ...merged,
8889
+ headers: mergeClientHeaders(base.headers, overrides.headers),
8890
+ auth: mergeAuthClientOptions(base.auth, overrides.auth),
8891
+ db: mergeServiceUrlOverrides(base.db, overrides.db),
8892
+ gateway: mergeServiceUrlOverrides(base.gateway, overrides.gateway),
8893
+ storage: mergeServiceUrlOverrides(base.storage, overrides.storage)
8894
+ };
8895
+ }
8448
8896
  function normalizeAuthClientConfig(auth, defaultBaseUrl) {
8449
8897
  if (!auth && defaultBaseUrl === void 0) {
8450
8898
  return void 0;
@@ -8454,6 +8902,8 @@ function normalizeAuthClientConfig(auth, defaultBaseUrl) {
8454
8902
  baseUrl,
8455
8903
  apiKey,
8456
8904
  bearerToken,
8905
+ cookie,
8906
+ sessionToken,
8457
8907
  ...rest
8458
8908
  } = auth ?? {};
8459
8909
  const normalized = {
@@ -8472,6 +8922,12 @@ function normalizeAuthClientConfig(auth, defaultBaseUrl) {
8472
8922
  if (typeof bearerToken === "string") {
8473
8923
  normalized.bearerToken = bearerToken;
8474
8924
  }
8925
+ if (typeof cookie === "string") {
8926
+ normalized.cookie = cookie;
8927
+ }
8928
+ if (typeof sessionToken === "string") {
8929
+ normalized.sessionToken = sessionToken;
8930
+ }
8475
8931
  return normalized;
8476
8932
  }
8477
8933
  function resolveCreateClientConfig(config) {
@@ -8485,6 +8941,9 @@ function resolveCreateClientConfig(config) {
8485
8941
  baseUrl: resolvedUrls.dbUrl,
8486
8942
  apiKey: resolveRequiredClientApiKey(config.key),
8487
8943
  client: resolveOptionalClientName(config.client),
8944
+ userId: config.userId,
8945
+ organizationId: config.organizationId,
8946
+ forceNoCache: config.forceNoCache,
8488
8947
  backend: toBackendConfig(config.backend),
8489
8948
  headers: config.headers,
8490
8949
  auth: config.auth,
@@ -8493,23 +8952,39 @@ function resolveCreateClientConfig(config) {
8493
8952
  experimental: config.experimental
8494
8953
  };
8495
8954
  }
8496
- function createClientFromConfig(config) {
8955
+ function createClientFromInput(sourceConfig) {
8956
+ return createClientFromConfig(resolveCreateClientConfig(sourceConfig), sourceConfig);
8957
+ }
8958
+ function createClientFromConfig(config, sourceConfig) {
8959
+ const normalizedAuthConfig = normalizeAuthClientConfig(config.auth, config.authUrl);
8497
8960
  const gatewayHeaders = {
8498
8961
  ...config.headers ?? {}
8499
8962
  };
8500
- if (config.auth?.bearerToken && gatewayHeaders["X-Athena-Auth-Bearer-Token"] === void 0 && gatewayHeaders["x-athena-auth-bearer-token"] === void 0) {
8501
- gatewayHeaders["X-Athena-Auth-Bearer-Token"] = config.auth.bearerToken;
8963
+ if (normalizedAuthConfig?.bearerToken && !hasHeaderIgnoreCase(gatewayHeaders, "X-Athena-Auth-Bearer-Token")) {
8964
+ gatewayHeaders["X-Athena-Auth-Bearer-Token"] = normalizedAuthConfig.bearerToken;
8965
+ }
8966
+ if (normalizedAuthConfig?.cookie && !hasHeaderIgnoreCase(gatewayHeaders, "Cookie")) {
8967
+ gatewayHeaders.Cookie = normalizedAuthConfig.cookie;
8968
+ }
8969
+ if (normalizedAuthConfig?.sessionToken && !hasHeaderIgnoreCase(gatewayHeaders, "X-Athena-Auth-Session-Token")) {
8970
+ gatewayHeaders["X-Athena-Auth-Session-Token"] = normalizedAuthConfig.sessionToken;
8502
8971
  }
8503
8972
  const gateway = createAthenaGatewayClient({
8504
8973
  baseUrl: config.baseUrl,
8505
8974
  apiKey: config.apiKey,
8506
8975
  client: config.client,
8976
+ userId: config.userId,
8977
+ organizationId: config.organizationId,
8978
+ forceNoCache: config.forceNoCache,
8507
8979
  backend: config.backend,
8508
8980
  headers: gatewayHeaders
8509
8981
  });
8510
8982
  const formatGatewayResult = createResultFormatter(config.experimental);
8511
8983
  const queryTracer = createQueryTracer(config.experimental);
8512
- const auth = createAuthClient(normalizeAuthClientConfig(config.auth, config.authUrl));
8984
+ const auth = createAuthClient({
8985
+ ...normalizedAuthConfig ?? {},
8986
+ ...config.forceNoCache ? { forceNoCache: true } : {}
8987
+ });
8513
8988
  function from(tableOrModel, options) {
8514
8989
  if (isAthenaModelTarget(tableOrModel)) {
8515
8990
  if (options?.schema !== void 0) {
@@ -8557,17 +9032,45 @@ function createClientFromConfig(config) {
8557
9032
  queryTracer
8558
9033
  );
8559
9034
  const db = createDbModule({ from, rpc, query });
9035
+ const withContext = (context) => createClientFromInput(
9036
+ mergeClientOverrideOptions(sourceConfig, toClientContextOverrides(context))
9037
+ );
9038
+ const withSession = (session, options) => createClientFromInput(
9039
+ mergeClientOverrideOptions(
9040
+ sourceConfig,
9041
+ toClientContextOverrides(resolveSessionContextOptions(session, options))
9042
+ )
9043
+ );
9044
+ const authWithOptions = (options) => createClientFromInput(mergeClientOverrideOptions(sourceConfig, options));
8560
9045
  const sdkClient = {
8561
9046
  from,
8562
9047
  db,
8563
9048
  rpc,
8564
9049
  query,
8565
9050
  verifyConnection: gateway.verifyConnection,
8566
- auth: auth.auth
9051
+ auth: auth.auth,
9052
+ withContext,
9053
+ withSession,
9054
+ withOptions: authWithOptions
8567
9055
  };
8568
9056
  if (config.experimental?.athenaStorageBackend) {
9057
+ const storageWithContext = (context) => createClientFromInput(
9058
+ mergeClientOverrideOptions(sourceConfig, toClientContextOverrides(context))
9059
+ );
9060
+ const storageWithSession = (session, options) => createClientFromInput(
9061
+ mergeClientOverrideOptions(
9062
+ sourceConfig,
9063
+ toClientContextOverrides(resolveSessionContextOptions(session, options))
9064
+ )
9065
+ );
9066
+ const storageWithOptions = (options) => createClientFromInput(
9067
+ mergeClientOverrideOptions(sourceConfig, options)
9068
+ );
8569
9069
  const storageClient = {
8570
9070
  ...sdkClient,
9071
+ withContext: storageWithContext,
9072
+ withSession: storageWithSession,
9073
+ withOptions: storageWithOptions,
8571
9074
  storage: createStorageModule(gateway, {
8572
9075
  ...config.experimental.storage,
8573
9076
  ...config.storageUrl ? {
@@ -8582,13 +9085,13 @@ function createClientFromConfig(config) {
8582
9085
  }
8583
9086
  function createClient(configOrUrl, apiKey, options) {
8584
9087
  if (typeof configOrUrl === "string" || configOrUrl === null || configOrUrl === void 0) {
8585
- return createClientFromConfig(resolveCreateClientConfig({
9088
+ return createClientFromInput({
8586
9089
  url: configOrUrl,
8587
9090
  key: apiKey ?? "",
8588
9091
  ...options
8589
- }));
9092
+ });
8590
9093
  }
8591
- return createClientFromConfig(resolveCreateClientConfig(configOrUrl));
9094
+ return createClientFromInput(configOrUrl);
8592
9095
  }
8593
9096
 
8594
9097
  // src/schema/postgres-introspection-core.ts
@@ -9144,16 +9647,25 @@ async function fileExists(path) {
9144
9647
  }
9145
9648
  async function writeArtifacts(files, cwd) {
9146
9649
  const writtenFiles = [];
9650
+ const skippedFiles = [];
9147
9651
  for (const file of files) {
9148
9652
  const absolutePath = resolve(cwd, file.path);
9149
9653
  if (!canOverwriteArtifact(file) && await fileExists(absolutePath)) {
9654
+ skippedFiles.push({
9655
+ kind: file.kind,
9656
+ path: file.path,
9657
+ reason: "protected-existing-file"
9658
+ });
9150
9659
  continue;
9151
9660
  }
9152
9661
  await mkdir(dirname(absolutePath), { recursive: true });
9153
9662
  await writeFile(absolutePath, file.content, "utf8");
9154
9663
  writtenFiles.push(file.path);
9155
9664
  }
9156
- return writtenFiles;
9665
+ return {
9666
+ writtenFiles,
9667
+ skippedFiles
9668
+ };
9157
9669
  }
9158
9670
  async function runSchemaGenerator(options = {}) {
9159
9671
  const cwd = options.cwd ?? process.cwd();
@@ -9167,12 +9679,13 @@ async function runSchemaGenerator(options = {}) {
9167
9679
  schemas: resolveProviderSchemas(config.provider)
9168
9680
  });
9169
9681
  const generated = generateArtifactsFromSnapshot(snapshot, config);
9170
- const writtenFiles = options.dryRun ? [] : await writeArtifacts(generated.files, cwd);
9682
+ const writeResult = options.dryRun ? { writtenFiles: [], skippedFiles: [] } : await writeArtifacts(generated.files, cwd);
9171
9683
  return {
9172
9684
  ...generated,
9173
9685
  configPath,
9174
9686
  config,
9175
- writtenFiles
9687
+ writtenFiles: writeResult.writtenFiles,
9688
+ skippedFiles: writeResult.skippedFiles
9176
9689
  };
9177
9690
  }
9178
9691
 
@@ -9214,24 +9727,64 @@ function generateUsage() {
9214
9727
  " athena-js generate --config ./athena.config.ts --dry-run"
9215
9728
  ].join("\n");
9216
9729
  }
9217
- function usesSchemaScopedModelTarget(target) {
9218
- return /\{schema(?:_[a-z]+)?\}/.test(target);
9730
+ function normalizePath2(pathValue) {
9731
+ return pathValue.replace(/\\/g, "/");
9732
+ }
9733
+ function isLegacyConfigRegistryTarget(target) {
9734
+ return normalizePath2(target) === "athena/config.ts";
9735
+ }
9736
+ function isFlatSchemaTarget(target) {
9737
+ return normalizePath2(target) === "athena/schema.ts";
9738
+ }
9739
+ function formatProviderLine(result) {
9740
+ const { provider } = result.config;
9741
+ if (provider.kind === "postgres") {
9742
+ const schemaList = Array.isArray(provider.schemas) ? provider.schemas.join(",") : typeof provider.schemas === "string" ? provider.schemas : "public";
9743
+ const database = provider.database ? ` database=${provider.database}` : "";
9744
+ const backend = provider.mode === "gateway" && provider.backend ? ` backend=${provider.backend}` : "";
9745
+ return `[provider] kind=${provider.kind} mode=${provider.mode}${database}${backend} schemas=${schemaList}`;
9746
+ }
9747
+ const datacenter = provider.datacenter ? ` datacenter=${provider.datacenter}` : "";
9748
+ return `[provider] kind=${provider.kind} mode=${provider.mode} keyspace=${provider.keyspace} contactPoints=${provider.contactPoints.join(",")}${datacenter}`;
9749
+ }
9750
+ function formatFilterLine(result) {
9751
+ const { includeTables, excludeTables } = result.config.filter;
9752
+ if (includeTables.length === 0 && excludeTables.length === 0) {
9753
+ return void 0;
9754
+ }
9755
+ return `[filter] include=${includeTables.length > 0 ? includeTables.join(",") : "-"} exclude=${excludeTables.length > 0 ? excludeTables.join(",") : "-"}`;
9219
9756
  }
9220
9757
  function formatGeneratorModeLines(result) {
9221
9758
  const lines = [
9222
- `[mode] format=${result.config.output.format} modelTarget=${result.config.output.targets.model}`
9759
+ `[mode] preset=${result.config.output.preset} format=${result.config.output.format} modelTarget=${result.config.output.targets.model}`,
9760
+ formatProviderLine(result),
9761
+ `[targets] schema=${result.config.output.targets.schema} database=${result.config.output.targets.database} registry=${result.config.output.targets.registry}`
9223
9762
  ];
9763
+ const filterLine = formatFilterLine(result);
9764
+ if (filterLine) {
9765
+ lines.push(filterLine);
9766
+ }
9224
9767
  if (result.config.output.format === "define-model") {
9225
9768
  lines.push(
9226
- '[note] Zero-style table-builder files are not active. Set output.format="table-builder" or ATHENA_GENERATOR_OUTPUT_FORMAT=table-builder to emit table(...).schema(...).columns(...).primaryKey(...).'
9769
+ '[note] Legacy define-model compatibility output is active. Set output.format="table-builder" or ATHENA_GENERATOR_OUTPUT_FORMAT=table-builder to emit table(...).schema(...).columns(...).primaryKey(...).'
9770
+ );
9771
+ }
9772
+ if (result.config.output.preset === "legacy") {
9773
+ lines.push(
9774
+ '[note] Legacy preset is active. It keeps registry output on athena/config.ts for compatibility; prefer output.preset="athena-direct" for the default safe direct layout.'
9227
9775
  );
9228
9776
  }
9229
9777
  lines.push(
9230
- "[note] Table-builder generation is stable. experimental.findManyAst only affects runtime findMany(...) transport and does not enable generator table output."
9778
+ "[note] Default generator mode is preset=athena-direct + format=table-builder. experimental.findManyAst only affects runtime findMany(...) transport and does not enable generator table output."
9231
9779
  );
9232
- if (usesSchemaScopedModelTarget(result.config.output.targets.model)) {
9780
+ if (isLegacyConfigRegistryTarget(result.config.output.targets.registry)) {
9233
9781
  lines.push(
9234
- '[note] Flat athena/models/*.ts output is opt-in. Set output.targets.model="athena/models/{model_kebab}.ts" or ATHENA_GENERATOR_MODEL_TARGET=athena/models/{model_kebab}.ts; multi-schema collisions are still auto-scoped by schema when needed.'
9782
+ '[warn] Registry target points at athena/config.ts. That file is often a handwritten runtime seam; prefer output.preset="athena-direct" or output.targets.registry="athena/registry.generated.ts" unless you intentionally need legacy compatibility.'
9783
+ );
9784
+ }
9785
+ if (isFlatSchemaTarget(result.config.output.targets.schema)) {
9786
+ lines.push(
9787
+ "[warn] Schema target points at athena/schema.ts. Prefer schema-scoped output such as athena/schemas/{schema_kebab}.ts."
9235
9788
  );
9236
9789
  }
9237
9790
  return lines;
@@ -9318,6 +9871,12 @@ function formatGeneratorError(error, configPath) {
9318
9871
  }
9319
9872
  return new Error(normalizeErrorMessage(error));
9320
9873
  }
9874
+ function formatSkippedArtifactLine(artifact) {
9875
+ if (artifact.reason === "protected-existing-file") {
9876
+ return ` [skip] ${artifact.path} (existing ${artifact.kind} artifacts are protected from overwrite; delete or retarget the file to regenerate it)`;
9877
+ }
9878
+ return ` [skip] ${artifact.path}`;
9879
+ }
9321
9880
  async function runCLI(argv, runtime = {}) {
9322
9881
  const log = runtime.log ?? console.log;
9323
9882
  const runGenerator = runtime.runGenerator ?? runSchemaGenerator;
@@ -9352,6 +9911,9 @@ async function runCLI(argv, runtime = {}) {
9352
9911
  for (const filePath of result.writtenFiles) {
9353
9912
  log(` - ${filePath}`);
9354
9913
  }
9914
+ for (const artifact of result.skippedFiles) {
9915
+ log(formatSkippedArtifactLine(artifact));
9916
+ }
9355
9917
  }
9356
9918
 
9357
9919
  export { parseCommand, runCLI, usage };