@xylex-group/athena 2.7.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +210 -17
- package/dist/browser.cjs +1253 -401
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +8 -7
- package/dist/browser.d.ts +8 -7
- package/dist/browser.js +1247 -402
- package/dist/browser.js.map +1 -1
- package/dist/cli/index.cjs +1285 -451
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +3 -3
- package/dist/cli/index.d.ts +3 -3
- package/dist/cli/index.js +1285 -451
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +1921 -698
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -7
- package/dist/index.d.ts +8 -7
- package/dist/index.js +1915 -699
- package/dist/index.js.map +1 -1
- package/dist/{model-form-AKYrgede.d.ts → model-form-DMed05gE.d.cts} +347 -82
- package/dist/{model-form-ehfqLuG7.d.cts → model-form-DXPlOnlI.d.ts} +347 -82
- package/dist/{pipeline-BUsR9XlO.d.ts → pipeline-CkMnhwPI.d.ts} +1 -1
- package/dist/{pipeline-BfCWSRYl.d.cts → pipeline-D4sJRKqN.d.cts} +1 -1
- package/dist/{react-email-BQzmXBDE.d.cts → react-email-DZhDDlEl.d.cts} +121 -8
- package/dist/{react-email-BrVRp80B.d.ts → react-email-Lrz9A-BW.d.ts} +121 -8
- package/dist/react.cjs +1 -1
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +4 -4
- package/dist/react.d.ts +4 -4
- package/dist/react.js +1 -1
- package/dist/react.js.map +1 -1
- package/dist/{types-BSIsyss1.d.cts → types-BzY6fETM.d.ts} +47 -5
- package/dist/{types-t_TVqnmp.d.ts → types-CAtTGGoz.d.cts} +47 -5
- package/dist/{types-BsyRW49r.d.cts → types-vikz9YIO.d.cts} +23 -1
- package/dist/{types-BsyRW49r.d.ts → types-vikz9YIO.d.ts} +23 -1
- package/package.json +3 -2
package/dist/cli/index.cjs
CHANGED
|
@@ -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
|
|
974
|
+
...output?.targets ?? {}
|
|
958
975
|
},
|
|
959
976
|
placeholderMap: {
|
|
960
|
-
...output
|
|
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 =
|
|
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") &&
|
|
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/
|
|
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
|
-
|
|
1112
|
-
return escaped.startsWith("'") ? escaped : escaped;
|
|
1310
|
+
return escapeTypePropertyName(key);
|
|
1113
1311
|
}
|
|
1114
|
-
function
|
|
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.
|
|
1331
|
+
return `import { ${modelDescriptor.exportConstName} } from '${importPath}'`;
|
|
1176
1332
|
}).join("\n");
|
|
1177
|
-
const modelEntries = descriptor.models.map((modelDescriptor) => ` ${renderObjectKey(modelDescriptor.tableName)}: ${modelDescriptor.
|
|
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
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
const
|
|
1302
|
-
const
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
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,
|
|
1470
|
+
schemaName,
|
|
1471
|
+
tableName,
|
|
1472
|
+
table: schema.tables[tableName]
|
|
1473
|
+
})
|
|
1474
|
+
);
|
|
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
|
+
{
|
|
1483
|
+
provider: providerName,
|
|
1484
|
+
kind: "schema",
|
|
1485
|
+
database: databaseName,
|
|
1486
|
+
schema: schemaName,
|
|
1487
|
+
model: "index"
|
|
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));
|
|
1521
|
+
}
|
|
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
|
+
}
|
|
1746
|
+
function generateArtifactsFromSnapshot(snapshot, config) {
|
|
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
|
+
{
|
|
1314
1766
|
provider: providerName,
|
|
1315
1767
|
kind: "model",
|
|
1316
1768
|
database: databaseName,
|
|
1317
1769
|
schema: schemaName,
|
|
1318
1770
|
model: tableName
|
|
1319
|
-
},
|
|
1320
|
-
|
|
1321
|
-
modelDescriptors.push({
|
|
1322
|
-
schemaName,
|
|
1323
|
-
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)
|
|
1343
|
-
);
|
|
1344
|
-
return {
|
|
1345
|
-
schemaName,
|
|
1346
|
-
filePath: schemaPath,
|
|
1347
|
-
schemaConstName: toSafeIdentifier(
|
|
1348
|
-
`${schemaName} schema`,
|
|
1349
|
-
this.config.naming.schemaConst,
|
|
1350
|
-
"schema"
|
|
1771
|
+
},
|
|
1772
|
+
normalizedConfig
|
|
1351
1773
|
),
|
|
1352
|
-
|
|
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
|
|
1353
1780
|
};
|
|
1354
|
-
}
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
renderOutputPath(this.config.output.targets.database, {
|
|
1358
|
-
provider: providerName,
|
|
1359
|
-
kind: "database",
|
|
1360
|
-
database: databaseName,
|
|
1361
|
-
schema: "index",
|
|
1362
|
-
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
|
-
};
|
|
1407
|
-
}
|
|
1408
|
-
};
|
|
1409
|
-
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();
|
|
1781
|
+
},
|
|
1782
|
+
renderModelArtifact: (descriptor) => renderModelArtifact2(snapshot.database, descriptor, normalizedConfig)
|
|
1783
|
+
});
|
|
1412
1784
|
}
|
|
1413
1785
|
|
|
1414
1786
|
// src/gateway/url.ts
|
|
@@ -1513,7 +1885,7 @@ var getSessionCookie = (request, config) => {
|
|
|
1513
1885
|
|
|
1514
1886
|
// package.json
|
|
1515
1887
|
var package_default = {
|
|
1516
|
-
version: "2.
|
|
1888
|
+
version: "2.8.0"
|
|
1517
1889
|
};
|
|
1518
1890
|
|
|
1519
1891
|
// src/sdk-version.ts
|
|
@@ -3460,11 +3832,12 @@ function createAuthClient(config = {}) {
|
|
|
3460
3832
|
// src/db/module.ts
|
|
3461
3833
|
function createDbModule(input) {
|
|
3462
3834
|
const db = {
|
|
3463
|
-
from
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
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);
|
|
3468
3841
|
},
|
|
3469
3842
|
insert(table, values, options) {
|
|
3470
3843
|
return Array.isArray(values) ? input.from(table).insert(values, options) : input.from(table).insert(values, options);
|
|
@@ -4131,6 +4504,15 @@ function appendQuery(path, query) {
|
|
|
4131
4504
|
function storagePath(path) {
|
|
4132
4505
|
return path;
|
|
4133
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
|
+
}
|
|
4134
4516
|
function withPathParam(path, name, value) {
|
|
4135
4517
|
return path.replace(`{${name}}`, encodeURIComponent(value));
|
|
4136
4518
|
}
|
|
@@ -4169,8 +4551,8 @@ async function callStorageEndpoint(gateway, endpoint, method, envelope, payload,
|
|
|
4169
4551
|
let url;
|
|
4170
4552
|
let headers;
|
|
4171
4553
|
try {
|
|
4172
|
-
const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : gateway.baseUrl;
|
|
4173
|
-
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));
|
|
4174
4556
|
headers = gateway.buildHeaders(options);
|
|
4175
4557
|
} catch (error) {
|
|
4176
4558
|
return rejectStorageError(
|
|
@@ -4294,8 +4676,8 @@ async function callStorageBinaryEndpoint(gateway, endpoint, method, options, run
|
|
|
4294
4676
|
let url;
|
|
4295
4677
|
let headers;
|
|
4296
4678
|
try {
|
|
4297
|
-
const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : gateway.baseUrl;
|
|
4298
|
-
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));
|
|
4299
4681
|
headers = gateway.buildHeaders(options);
|
|
4300
4682
|
} catch (error) {
|
|
4301
4683
|
return rejectStorageError(
|
|
@@ -4456,8 +4838,8 @@ async function callStorageUploadBinaryEndpoint(gateway, endpoint, body, options,
|
|
|
4456
4838
|
let url;
|
|
4457
4839
|
let headers;
|
|
4458
4840
|
try {
|
|
4459
|
-
const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : gateway.baseUrl;
|
|
4460
|
-
url = buildAthenaGatewayUrl(baseUrl, endpoint);
|
|
4841
|
+
const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : runtimeOptions?.baseUrl ? normalizeAthenaGatewayBaseUrl(runtimeOptions.baseUrl) : gateway.baseUrl;
|
|
4842
|
+
url = buildAthenaGatewayUrl(baseUrl, resolveStorageEndpointPath(endpoint, runtimeOptions));
|
|
4461
4843
|
headers = gateway.buildHeaders(options);
|
|
4462
4844
|
} catch (error) {
|
|
4463
4845
|
return rejectStorageError(
|
|
@@ -4581,6 +4963,7 @@ async function callStorageUploadBinaryEndpoint(gateway, endpoint, body, options,
|
|
|
4581
4963
|
return parsedBody.parsed.data;
|
|
4582
4964
|
}
|
|
4583
4965
|
function createStorageModule(gateway, runtimeOptions) {
|
|
4966
|
+
const resolvedRuntimeOptions = runtimeOptions;
|
|
4584
4967
|
const callRaw = (path, method, payload, options) => callStorageEndpoint(
|
|
4585
4968
|
gateway,
|
|
4586
4969
|
storagePath(path),
|
|
@@ -4588,7 +4971,7 @@ function createStorageModule(gateway, runtimeOptions) {
|
|
|
4588
4971
|
"raw",
|
|
4589
4972
|
payload,
|
|
4590
4973
|
options,
|
|
4591
|
-
|
|
4974
|
+
resolvedRuntimeOptions
|
|
4592
4975
|
);
|
|
4593
4976
|
const callAthena2 = (path, method, payload, options) => callStorageEndpoint(
|
|
4594
4977
|
gateway,
|
|
@@ -4597,7 +4980,7 @@ function createStorageModule(gateway, runtimeOptions) {
|
|
|
4597
4980
|
"athena",
|
|
4598
4981
|
payload,
|
|
4599
4982
|
options,
|
|
4600
|
-
|
|
4983
|
+
resolvedRuntimeOptions
|
|
4601
4984
|
);
|
|
4602
4985
|
const base = {
|
|
4603
4986
|
listStorageCatalogs(options) {
|
|
@@ -4639,7 +5022,7 @@ function createStorageModule(gateway, runtimeOptions) {
|
|
|
4639
5022
|
withPathParam("/storage/files/{file_id}/proxy", "file_id", fileId),
|
|
4640
5023
|
query
|
|
4641
5024
|
);
|
|
4642
|
-
return callStorageBinaryEndpoint(gateway, storagePath(path), "GET", options,
|
|
5025
|
+
return callStorageBinaryEndpoint(gateway, storagePath(path), "GET", options, resolvedRuntimeOptions);
|
|
4643
5026
|
},
|
|
4644
5027
|
updateStorageFile(fileId, input, options) {
|
|
4645
5028
|
return callAthena2(withPathParam("/storage/files/{file_id}", "file_id", fileId), "PATCH", input, options);
|
|
@@ -4686,7 +5069,7 @@ function createStorageModule(gateway, runtimeOptions) {
|
|
|
4686
5069
|
storagePath(withPathParam("/storage/files/{file_id}/upload", "file_id", fileId)),
|
|
4687
5070
|
body,
|
|
4688
5071
|
options,
|
|
4689
|
-
|
|
5072
|
+
resolvedRuntimeOptions
|
|
4690
5073
|
);
|
|
4691
5074
|
},
|
|
4692
5075
|
search(input, options) {
|
|
@@ -4882,6 +5265,13 @@ function createStorageModule(gateway, runtimeOptions) {
|
|
|
4882
5265
|
};
|
|
4883
5266
|
}
|
|
4884
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;
|
|
5273
|
+
}
|
|
5274
|
+
|
|
4885
5275
|
// src/query-ast.ts
|
|
4886
5276
|
var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
4887
5277
|
var FILTER_OPERATORS = /* @__PURE__ */ new Set([
|
|
@@ -5504,20 +5894,437 @@ function createSelectTransportPlan(input) {
|
|
|
5504
5894
|
};
|
|
5505
5895
|
}
|
|
5506
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
|
+
|
|
5507
6324
|
// src/client.ts
|
|
5508
6325
|
var DEFAULT_COLUMNS = "*";
|
|
5509
6326
|
var SAFE_CAST_PATTERN = /^[a-z_][a-z0-9_]*(?:\[\])?$/i;
|
|
5510
6327
|
var ATHENA_NORMALIZED_ERROR_KEY = "__athenaNormalizedError";
|
|
5511
|
-
var QUERY_TRACE_STACK_SKIP_PATTERNS = [
|
|
5512
|
-
"src\\client.ts",
|
|
5513
|
-
"src/client.ts",
|
|
5514
|
-
"dist\\client.",
|
|
5515
|
-
"dist/client.",
|
|
5516
|
-
"node_modules\\@xylex-group\\athena",
|
|
5517
|
-
"node_modules/@xylex-group/athena",
|
|
5518
|
-
"node:internal",
|
|
5519
|
-
"internal/process"
|
|
5520
|
-
];
|
|
5521
6328
|
function formatResult(response) {
|
|
5522
6329
|
const result = {
|
|
5523
6330
|
data: response.data ?? null,
|
|
@@ -5659,154 +6466,6 @@ function createResultError(response, result, normalized) {
|
|
|
5659
6466
|
raw: result.raw
|
|
5660
6467
|
};
|
|
5661
6468
|
}
|
|
5662
|
-
function parseQueryTraceCallsiteFrame(frame) {
|
|
5663
|
-
const trimmed = frame.trim();
|
|
5664
|
-
if (!trimmed) {
|
|
5665
|
-
return null;
|
|
5666
|
-
}
|
|
5667
|
-
let body = trimmed.replace(/^at\s+/, "");
|
|
5668
|
-
if (body.startsWith("async ")) {
|
|
5669
|
-
body = body.slice(6);
|
|
5670
|
-
}
|
|
5671
|
-
let functionName;
|
|
5672
|
-
let location = body;
|
|
5673
|
-
const wrappedMatch = body.match(/^(.*?)\s+\((.*)\)$/);
|
|
5674
|
-
if (wrappedMatch) {
|
|
5675
|
-
functionName = wrappedMatch[1].trim() || void 0;
|
|
5676
|
-
location = wrappedMatch[2].trim();
|
|
5677
|
-
}
|
|
5678
|
-
const locationMatch = location.match(/^(.*):(\d+):(\d+)$/);
|
|
5679
|
-
if (!locationMatch) {
|
|
5680
|
-
return null;
|
|
5681
|
-
}
|
|
5682
|
-
const filePath = locationMatch[1].replace(/^file:\/\//, "");
|
|
5683
|
-
const line = Number(locationMatch[2]);
|
|
5684
|
-
const column = Number(locationMatch[3]);
|
|
5685
|
-
if (!Number.isFinite(line) || !Number.isFinite(column)) {
|
|
5686
|
-
return null;
|
|
5687
|
-
}
|
|
5688
|
-
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
5689
|
-
const fileName = normalizedPath.split("/").at(-1) ?? filePath;
|
|
5690
|
-
return {
|
|
5691
|
-
filePath,
|
|
5692
|
-
fileName,
|
|
5693
|
-
line,
|
|
5694
|
-
column,
|
|
5695
|
-
frame: trimmed,
|
|
5696
|
-
functionName
|
|
5697
|
-
};
|
|
5698
|
-
}
|
|
5699
|
-
function captureQueryTraceCallsite() {
|
|
5700
|
-
const stack = new Error().stack;
|
|
5701
|
-
if (!stack) return null;
|
|
5702
|
-
const frames = stack.split("\n").slice(2).map((frame) => frame.trim()).filter(Boolean);
|
|
5703
|
-
for (const frame of frames) {
|
|
5704
|
-
if (QUERY_TRACE_STACK_SKIP_PATTERNS.some((pattern) => frame.includes(pattern))) {
|
|
5705
|
-
continue;
|
|
5706
|
-
}
|
|
5707
|
-
const callsite = parseQueryTraceCallsiteFrame(frame);
|
|
5708
|
-
if (callsite) return callsite;
|
|
5709
|
-
}
|
|
5710
|
-
const fallback = frames.find((frame) => !frame.includes("captureQueryTraceCallsite"));
|
|
5711
|
-
return fallback ? parseQueryTraceCallsiteFrame(fallback) : null;
|
|
5712
|
-
}
|
|
5713
|
-
function defaultQueryTraceLogger(event) {
|
|
5714
|
-
const target = event.table ?? event.functionName ?? "gateway";
|
|
5715
|
-
const outcomeState = event.outcome?.error ? "error" : "ok";
|
|
5716
|
-
const banner = `[athena-js][trace] ${event.operation.toUpperCase()} ${event.endpoint} ${target} ${event.durationMs}ms ${outcomeState}`;
|
|
5717
|
-
console.info(banner, event);
|
|
5718
|
-
}
|
|
5719
|
-
function captureTraceCallsite(tracer) {
|
|
5720
|
-
return tracer?.captureCallsite() ?? null;
|
|
5721
|
-
}
|
|
5722
|
-
function createTraceCallsiteStore(tracer, initialCallsite) {
|
|
5723
|
-
let storedCallsite = initialCallsite ?? void 0;
|
|
5724
|
-
return {
|
|
5725
|
-
resolve(callsite) {
|
|
5726
|
-
if (callsite) {
|
|
5727
|
-
storedCallsite = callsite;
|
|
5728
|
-
return callsite;
|
|
5729
|
-
}
|
|
5730
|
-
if (storedCallsite !== void 0) {
|
|
5731
|
-
return storedCallsite;
|
|
5732
|
-
}
|
|
5733
|
-
const capturedCallsite = captureTraceCallsite(tracer);
|
|
5734
|
-
if (capturedCallsite) {
|
|
5735
|
-
storedCallsite = capturedCallsite;
|
|
5736
|
-
}
|
|
5737
|
-
return capturedCallsite;
|
|
5738
|
-
}
|
|
5739
|
-
};
|
|
5740
|
-
}
|
|
5741
|
-
function createQueryTracer(experimental) {
|
|
5742
|
-
const traceOption = experimental?.traceQueries;
|
|
5743
|
-
if (!traceOption) {
|
|
5744
|
-
return void 0;
|
|
5745
|
-
}
|
|
5746
|
-
const logger = typeof traceOption === "object" && traceOption.logger ? traceOption.logger : defaultQueryTraceLogger;
|
|
5747
|
-
const emit = (event) => {
|
|
5748
|
-
try {
|
|
5749
|
-
logger(event);
|
|
5750
|
-
} catch (error) {
|
|
5751
|
-
console.warn("[athena-js][trace] logger failed", error);
|
|
5752
|
-
}
|
|
5753
|
-
};
|
|
5754
|
-
return {
|
|
5755
|
-
captureCallsite: captureQueryTraceCallsite,
|
|
5756
|
-
publishSuccess(context, result, durationMs, callsite) {
|
|
5757
|
-
emit({
|
|
5758
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5759
|
-
durationMs,
|
|
5760
|
-
operation: context.operation,
|
|
5761
|
-
endpoint: context.endpoint,
|
|
5762
|
-
table: context.table,
|
|
5763
|
-
functionName: context.functionName,
|
|
5764
|
-
sql: context.sql,
|
|
5765
|
-
payload: context.payload,
|
|
5766
|
-
options: context.options,
|
|
5767
|
-
callsite,
|
|
5768
|
-
outcome: {
|
|
5769
|
-
status: result.status,
|
|
5770
|
-
error: result.error,
|
|
5771
|
-
errorDetails: result.errorDetails ?? null,
|
|
5772
|
-
count: result.count ?? null,
|
|
5773
|
-
data: result.data,
|
|
5774
|
-
raw: result.raw
|
|
5775
|
-
}
|
|
5776
|
-
});
|
|
5777
|
-
},
|
|
5778
|
-
publishFailure(context, error, durationMs, callsite) {
|
|
5779
|
-
emit({
|
|
5780
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5781
|
-
durationMs,
|
|
5782
|
-
operation: context.operation,
|
|
5783
|
-
endpoint: context.endpoint,
|
|
5784
|
-
table: context.table,
|
|
5785
|
-
functionName: context.functionName,
|
|
5786
|
-
sql: context.sql,
|
|
5787
|
-
payload: context.payload,
|
|
5788
|
-
options: context.options,
|
|
5789
|
-
callsite,
|
|
5790
|
-
thrownError: error
|
|
5791
|
-
});
|
|
5792
|
-
}
|
|
5793
|
-
};
|
|
5794
|
-
}
|
|
5795
|
-
async function executeWithQueryTrace(tracer, context, runner, callsiteOverride) {
|
|
5796
|
-
if (!tracer) {
|
|
5797
|
-
return runner();
|
|
5798
|
-
}
|
|
5799
|
-
const callsite = callsiteOverride ?? tracer.captureCallsite();
|
|
5800
|
-
const startedAt = Date.now();
|
|
5801
|
-
try {
|
|
5802
|
-
const result = await runner();
|
|
5803
|
-
tracer.publishSuccess(context, result, Date.now() - startedAt, callsite);
|
|
5804
|
-
return result;
|
|
5805
|
-
} catch (error) {
|
|
5806
|
-
tracer.publishFailure(context, error, Date.now() - startedAt, callsite);
|
|
5807
|
-
throw error;
|
|
5808
|
-
}
|
|
5809
|
-
}
|
|
5810
6469
|
function toSingleResult(response) {
|
|
5811
6470
|
const payload = response.data;
|
|
5812
6471
|
const singleData = Array.isArray(payload) ? payload.length ? payload[0] : null : payload ?? null;
|
|
@@ -5834,6 +6493,15 @@ function asAthenaJsonObject(value) {
|
|
|
5834
6493
|
function asAthenaJsonObjectArray(values) {
|
|
5835
6494
|
return values;
|
|
5836
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
|
+
}
|
|
5837
6505
|
function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS, tracer, initialCallsite) {
|
|
5838
6506
|
let selectedColumns = defaultColumns === null ? void 0 : defaultColumns;
|
|
5839
6507
|
let selectedOptions;
|
|
@@ -5843,25 +6511,29 @@ function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS, tracer,
|
|
|
5843
6511
|
const payloadColumns = columns ?? selectedColumns;
|
|
5844
6512
|
const payloadOptions = options ?? selectedOptions;
|
|
5845
6513
|
if (!promise) {
|
|
5846
|
-
promise = executor(
|
|
6514
|
+
promise = executor(
|
|
6515
|
+
normalizeSelectColumnsInput(payloadColumns),
|
|
6516
|
+
payloadOptions,
|
|
6517
|
+
callsiteStore.resolve(callsite)
|
|
6518
|
+
);
|
|
5847
6519
|
}
|
|
5848
6520
|
return promise;
|
|
5849
6521
|
};
|
|
5850
6522
|
const mutationQuery = {
|
|
5851
|
-
select(columns
|
|
6523
|
+
select(columns, options) {
|
|
5852
6524
|
selectedColumns = columns;
|
|
5853
6525
|
selectedOptions = options ?? selectedOptions;
|
|
5854
6526
|
return run(columns, options, captureTraceCallsite(tracer));
|
|
5855
6527
|
},
|
|
5856
|
-
returning(columns
|
|
6528
|
+
returning(columns, options) {
|
|
5857
6529
|
return mutationQuery.select(columns, options);
|
|
5858
6530
|
},
|
|
5859
|
-
single(columns
|
|
6531
|
+
single(columns, options) {
|
|
5860
6532
|
selectedColumns = columns;
|
|
5861
6533
|
selectedOptions = options ?? selectedOptions;
|
|
5862
6534
|
return run(columns, options, captureTraceCallsite(tracer)).then(toSingleResult);
|
|
5863
6535
|
},
|
|
5864
|
-
maybeSingle(columns
|
|
6536
|
+
maybeSingle(columns, options) {
|
|
5865
6537
|
return mutationQuery.single(columns, options);
|
|
5866
6538
|
},
|
|
5867
6539
|
then(onfulfilled, onrejected) {
|
|
@@ -6418,7 +7090,10 @@ function createFilterMethods(state, addCondition, self) {
|
|
|
6418
7090
|
}
|
|
6419
7091
|
function toRpcSelect(columns) {
|
|
6420
7092
|
if (!columns) return void 0;
|
|
6421
|
-
|
|
7093
|
+
if (typeof columns === "string") {
|
|
7094
|
+
return columns;
|
|
7095
|
+
}
|
|
7096
|
+
return columns.join(",");
|
|
6422
7097
|
}
|
|
6423
7098
|
function createRpcFilterMethods(filters, self) {
|
|
6424
7099
|
const addFilter = (operator, column, value) => {
|
|
@@ -6467,7 +7142,7 @@ function createRpcFilterMethods(filters, self) {
|
|
|
6467
7142
|
}
|
|
6468
7143
|
};
|
|
6469
7144
|
}
|
|
6470
|
-
function createRpcBuilder(functionName, args, baseOptions, client, formatGatewayResult, tracer, initialCallsite) {
|
|
7145
|
+
function createRpcBuilder(functionName, args, baseOptions, client, formatGatewayResult, tracer, initialCallsite, debugAstEnabled = false) {
|
|
6471
7146
|
const state = {
|
|
6472
7147
|
filters: []
|
|
6473
7148
|
};
|
|
@@ -6477,6 +7152,7 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
|
|
|
6477
7152
|
const callsiteStore = createTraceCallsiteStore(tracer, initialCallsite);
|
|
6478
7153
|
const executeRpc = async (columns, options, callsite) => {
|
|
6479
7154
|
const mergedOptions = mergeOptions(baseOptions, options);
|
|
7155
|
+
const normalizedSelectedColumns = normalizeSelectColumnsInput(columns);
|
|
6480
7156
|
const payload = {
|
|
6481
7157
|
function: functionName,
|
|
6482
7158
|
args,
|
|
@@ -6491,6 +7167,14 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
|
|
|
6491
7167
|
};
|
|
6492
7168
|
const endpoint = mergedOptions?.get ? `/rpc/${functionName}` : "/gateway/rpc";
|
|
6493
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;
|
|
6494
7178
|
return executeWithQueryTrace(
|
|
6495
7179
|
tracer,
|
|
6496
7180
|
{
|
|
@@ -6499,6 +7183,7 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
|
|
|
6499
7183
|
functionName,
|
|
6500
7184
|
sql,
|
|
6501
7185
|
payload,
|
|
7186
|
+
ast: debugAst,
|
|
6502
7187
|
options: mergedOptions
|
|
6503
7188
|
},
|
|
6504
7189
|
async () => {
|
|
@@ -6519,7 +7204,7 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
|
|
|
6519
7204
|
const builder = {};
|
|
6520
7205
|
const filterMethods = createRpcFilterMethods(state.filters, builder);
|
|
6521
7206
|
Object.assign(builder, filterMethods, {
|
|
6522
|
-
select(columns
|
|
7207
|
+
select(columns, options) {
|
|
6523
7208
|
selectedColumns = columns;
|
|
6524
7209
|
selectedOptions = options ?? selectedOptions;
|
|
6525
7210
|
return run(columns, options, captureTraceCallsite(tracer));
|
|
@@ -6564,6 +7249,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6564
7249
|
const state = {
|
|
6565
7250
|
conditions: []
|
|
6566
7251
|
};
|
|
7252
|
+
const debugAstEnabled = Boolean(experimental?.debugAst);
|
|
6567
7253
|
const addCondition = (operator, column, value, hints) => {
|
|
6568
7254
|
const condition = { operator };
|
|
6569
7255
|
if (column) {
|
|
@@ -6607,15 +7293,27 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6607
7293
|
addCondition,
|
|
6608
7294
|
builder
|
|
6609
7295
|
);
|
|
6610
|
-
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;
|
|
6611
7298
|
const resolvedTableName = resolveTableNameForCall(tableName, options?.schema);
|
|
6612
7299
|
const plan = createSelectTransportPlan({
|
|
6613
7300
|
tableName: resolvedTableName,
|
|
6614
|
-
columns,
|
|
7301
|
+
columns: runtimeColumns,
|
|
6615
7302
|
state: executionState,
|
|
6616
7303
|
options,
|
|
6617
7304
|
buildTypedSelectQuery
|
|
6618
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;
|
|
6619
7317
|
if (plan.kind === "query") {
|
|
6620
7318
|
return executeExperimentalRead(
|
|
6621
7319
|
experimental,
|
|
@@ -6627,6 +7325,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6627
7325
|
table: resolvedTableName,
|
|
6628
7326
|
sql: plan.query,
|
|
6629
7327
|
payload: plan.payload,
|
|
7328
|
+
ast: debugAst,
|
|
6630
7329
|
options
|
|
6631
7330
|
},
|
|
6632
7331
|
async () => {
|
|
@@ -6651,6 +7350,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6651
7350
|
table: resolvedTableName,
|
|
6652
7351
|
sql,
|
|
6653
7352
|
payload: plan.payload,
|
|
7353
|
+
ast: debugAst,
|
|
6654
7354
|
options
|
|
6655
7355
|
},
|
|
6656
7356
|
async () => {
|
|
@@ -6664,7 +7364,11 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6664
7364
|
const createSelectChain = (columns, options, initialCallsite) => {
|
|
6665
7365
|
const chain = {};
|
|
6666
7366
|
const callsiteStore = createTraceCallsiteStore(tracer, initialCallsite);
|
|
6667
|
-
const filterMethods2 = createFilterMethods(
|
|
7367
|
+
const filterMethods2 = createFilterMethods(
|
|
7368
|
+
state,
|
|
7369
|
+
addCondition,
|
|
7370
|
+
chain
|
|
7371
|
+
);
|
|
6668
7372
|
Object.assign(chain, filterMethods2, {
|
|
6669
7373
|
async single(cols, opts) {
|
|
6670
7374
|
const r = await runSelect(
|
|
@@ -6751,6 +7455,14 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6751
7455
|
limit: executionState.limit,
|
|
6752
7456
|
order: executionState.order
|
|
6753
7457
|
});
|
|
7458
|
+
const debugAst = debugAstEnabled ? buildFindManyDirectDebugAst({
|
|
7459
|
+
tableName: resolvedTableName,
|
|
7460
|
+
options,
|
|
7461
|
+
compiledColumns: columns,
|
|
7462
|
+
baseState,
|
|
7463
|
+
executionState,
|
|
7464
|
+
payload
|
|
7465
|
+
}) : void 0;
|
|
6754
7466
|
return executeExperimentalRead(
|
|
6755
7467
|
experimental,
|
|
6756
7468
|
() => executeWithQueryTrace(
|
|
@@ -6760,7 +7472,8 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6760
7472
|
endpoint: "/gateway/fetch",
|
|
6761
7473
|
table: resolvedTableName,
|
|
6762
7474
|
sql,
|
|
6763
|
-
payload
|
|
7475
|
+
payload,
|
|
7476
|
+
ast: debugAst
|
|
6764
7477
|
},
|
|
6765
7478
|
async () => {
|
|
6766
7479
|
const response = await client.fetchGateway(
|
|
@@ -6776,7 +7489,15 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6776
7489
|
columns,
|
|
6777
7490
|
void 0,
|
|
6778
7491
|
executionState,
|
|
6779
|
-
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
|
|
6780
7501
|
);
|
|
6781
7502
|
},
|
|
6782
7503
|
insert(values, options) {
|
|
@@ -6796,6 +7517,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6796
7517
|
payload.default_to_null = mergedOptions.defaultToNull;
|
|
6797
7518
|
}
|
|
6798
7519
|
const sql = buildInsertDebugSql(payload);
|
|
7520
|
+
const debugAst = debugAstEnabled ? buildInsertDebugAst(payload) : void 0;
|
|
6799
7521
|
return executeWithQueryTrace(
|
|
6800
7522
|
tracer,
|
|
6801
7523
|
{
|
|
@@ -6804,6 +7526,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6804
7526
|
table: resolvedTableName,
|
|
6805
7527
|
sql,
|
|
6806
7528
|
payload,
|
|
7529
|
+
ast: debugAst,
|
|
6807
7530
|
options: mergedOptions
|
|
6808
7531
|
},
|
|
6809
7532
|
async () => {
|
|
@@ -6829,6 +7552,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6829
7552
|
payload.default_to_null = mergedOptions.defaultToNull;
|
|
6830
7553
|
}
|
|
6831
7554
|
const sql = buildInsertDebugSql(payload);
|
|
7555
|
+
const debugAst = debugAstEnabled ? buildInsertDebugAst(payload) : void 0;
|
|
6832
7556
|
return executeWithQueryTrace(
|
|
6833
7557
|
tracer,
|
|
6834
7558
|
{
|
|
@@ -6837,6 +7561,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6837
7561
|
table: resolvedTableName,
|
|
6838
7562
|
sql,
|
|
6839
7563
|
payload,
|
|
7564
|
+
ast: debugAst,
|
|
6840
7565
|
options: mergedOptions
|
|
6841
7566
|
},
|
|
6842
7567
|
async () => {
|
|
@@ -6867,6 +7592,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6867
7592
|
payload.default_to_null = mergedOptions.defaultToNull;
|
|
6868
7593
|
}
|
|
6869
7594
|
const sql = buildInsertDebugSql(payload);
|
|
7595
|
+
const debugAst = debugAstEnabled ? buildUpsertDebugAst(payload) : void 0;
|
|
6870
7596
|
return executeWithQueryTrace(
|
|
6871
7597
|
tracer,
|
|
6872
7598
|
{
|
|
@@ -6875,6 +7601,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6875
7601
|
table: resolvedTableName,
|
|
6876
7602
|
sql,
|
|
6877
7603
|
payload,
|
|
7604
|
+
ast: debugAst,
|
|
6878
7605
|
options: mergedOptions
|
|
6879
7606
|
},
|
|
6880
7607
|
async () => {
|
|
@@ -6902,6 +7629,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6902
7629
|
payload.default_to_null = mergedOptions.defaultToNull;
|
|
6903
7630
|
}
|
|
6904
7631
|
const sql = buildInsertDebugSql(payload);
|
|
7632
|
+
const debugAst = debugAstEnabled ? buildUpsertDebugAst(payload) : void 0;
|
|
6905
7633
|
return executeWithQueryTrace(
|
|
6906
7634
|
tracer,
|
|
6907
7635
|
{
|
|
@@ -6910,6 +7638,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6910
7638
|
table: resolvedTableName,
|
|
6911
7639
|
sql,
|
|
6912
7640
|
payload,
|
|
7641
|
+
ast: debugAst,
|
|
6913
7642
|
options: mergedOptions
|
|
6914
7643
|
},
|
|
6915
7644
|
async () => {
|
|
@@ -6924,7 +7653,8 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6924
7653
|
update(values, options) {
|
|
6925
7654
|
const mutationCallsite = captureTraceCallsite(tracer);
|
|
6926
7655
|
const executeUpdate = async (columns, selectOptions, callsite) => {
|
|
6927
|
-
const
|
|
7656
|
+
const executionState = snapshotState();
|
|
7657
|
+
const filters = executionState.conditions.length ? [...executionState.conditions] : void 0;
|
|
6928
7658
|
const mergedOptions = mergeOptions(options, selectOptions);
|
|
6929
7659
|
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
6930
7660
|
const payload = {
|
|
@@ -6933,12 +7663,16 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6933
7663
|
conditions: filters,
|
|
6934
7664
|
strip_nulls: mergedOptions?.stripNulls ?? true
|
|
6935
7665
|
};
|
|
6936
|
-
if (
|
|
6937
|
-
if (
|
|
6938
|
-
if (
|
|
6939
|
-
if (
|
|
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;
|
|
6940
7670
|
if (columns) payload.columns = columns;
|
|
6941
7671
|
const sql = buildUpdateDebugSql(payload);
|
|
7672
|
+
const debugAst = debugAstEnabled ? buildUpdateDebugAst({
|
|
7673
|
+
state: executionState,
|
|
7674
|
+
payload
|
|
7675
|
+
}) : void 0;
|
|
6942
7676
|
return executeWithQueryTrace(
|
|
6943
7677
|
tracer,
|
|
6944
7678
|
{
|
|
@@ -6947,6 +7681,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6947
7681
|
table: resolvedTableName,
|
|
6948
7682
|
sql,
|
|
6949
7683
|
payload,
|
|
7684
|
+
ast: debugAst,
|
|
6950
7685
|
options: mergedOptions
|
|
6951
7686
|
},
|
|
6952
7687
|
async () => {
|
|
@@ -6970,6 +7705,11 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6970
7705
|
}
|
|
6971
7706
|
const mutationCallsite = captureTraceCallsite(tracer);
|
|
6972
7707
|
const executeDelete = async (columns, selectOptions, callsite) => {
|
|
7708
|
+
const executionState = snapshotState();
|
|
7709
|
+
const debugState = {
|
|
7710
|
+
...executionState,
|
|
7711
|
+
conditions: filters ? filters.map((condition) => ({ ...condition })) : []
|
|
7712
|
+
};
|
|
6973
7713
|
const mergedOptions = mergeOptions(options, selectOptions);
|
|
6974
7714
|
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
6975
7715
|
const payload = {
|
|
@@ -6977,12 +7717,16 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6977
7717
|
resource_id: resourceId,
|
|
6978
7718
|
conditions: filters
|
|
6979
7719
|
};
|
|
6980
|
-
if (
|
|
6981
|
-
if (
|
|
6982
|
-
if (
|
|
6983
|
-
if (
|
|
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;
|
|
6984
7724
|
if (columns) payload.columns = columns;
|
|
6985
7725
|
const sql = buildDeleteDebugSql(payload);
|
|
7726
|
+
const debugAst = debugAstEnabled ? buildDeleteDebugAst({
|
|
7727
|
+
state: debugState,
|
|
7728
|
+
payload
|
|
7729
|
+
}) : void 0;
|
|
6986
7730
|
return executeWithQueryTrace(
|
|
6987
7731
|
tracer,
|
|
6988
7732
|
{
|
|
@@ -6991,6 +7735,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6991
7735
|
table: resolvedTableName,
|
|
6992
7736
|
sql,
|
|
6993
7737
|
payload,
|
|
7738
|
+
ast: debugAst,
|
|
6994
7739
|
options: mergedOptions
|
|
6995
7740
|
},
|
|
6996
7741
|
async () => {
|
|
@@ -7018,6 +7763,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
7018
7763
|
return builder;
|
|
7019
7764
|
}
|
|
7020
7765
|
function createQueryBuilder(client, formatGatewayResult, experimental, tracer) {
|
|
7766
|
+
const debugAstEnabled = Boolean(experimental?.debugAst);
|
|
7021
7767
|
return async function query(query, options) {
|
|
7022
7768
|
const normalizedQuery = query.trim();
|
|
7023
7769
|
if (!normalizedQuery) {
|
|
@@ -7034,6 +7780,7 @@ function createQueryBuilder(client, formatGatewayResult, experimental, tracer) {
|
|
|
7034
7780
|
endpoint: "/gateway/query",
|
|
7035
7781
|
sql: normalizedQuery,
|
|
7036
7782
|
payload,
|
|
7783
|
+
ast: debugAstEnabled ? buildRawQueryDebugAst(normalizedQuery) : void 0,
|
|
7037
7784
|
options
|
|
7038
7785
|
},
|
|
7039
7786
|
async () => {
|
|
@@ -7045,6 +7792,63 @@ function createQueryBuilder(client, formatGatewayResult, experimental, tracer) {
|
|
|
7045
7792
|
);
|
|
7046
7793
|
};
|
|
7047
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
|
+
}
|
|
7048
7852
|
function createClientFromConfig(config) {
|
|
7049
7853
|
const gatewayHeaders = {
|
|
7050
7854
|
...config.headers ?? {}
|
|
@@ -7059,16 +7863,33 @@ function createClientFromConfig(config) {
|
|
|
7059
7863
|
backend: config.backend,
|
|
7060
7864
|
headers: gatewayHeaders
|
|
7061
7865
|
});
|
|
7062
|
-
const formatGatewayResult = createResultFormatter();
|
|
7866
|
+
const formatGatewayResult = createResultFormatter(config.experimental);
|
|
7063
7867
|
const queryTracer = createQueryTracer(config.experimental);
|
|
7064
|
-
const auth = createAuthClient(config.auth);
|
|
7065
|
-
|
|
7066
|
-
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
7070
|
-
|
|
7071
|
-
|
|
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
|
+
}
|
|
7072
7893
|
const rpc = (fn, args, options) => {
|
|
7073
7894
|
const normalizedFn = fn.trim();
|
|
7074
7895
|
if (!normalizedFn) {
|
|
@@ -7081,10 +7902,16 @@ function createClientFromConfig(config) {
|
|
|
7081
7902
|
gateway,
|
|
7082
7903
|
formatGatewayResult,
|
|
7083
7904
|
queryTracer,
|
|
7084
|
-
captureTraceCallsite(queryTracer)
|
|
7905
|
+
captureTraceCallsite(queryTracer),
|
|
7906
|
+
Boolean(config.experimental?.debugAst)
|
|
7085
7907
|
);
|
|
7086
7908
|
};
|
|
7087
|
-
const query = createQueryBuilder(
|
|
7909
|
+
const query = createQueryBuilder(
|
|
7910
|
+
gateway,
|
|
7911
|
+
formatGatewayResult,
|
|
7912
|
+
config.experimental,
|
|
7913
|
+
queryTracer
|
|
7914
|
+
);
|
|
7088
7915
|
const db = createDbModule({ from, rpc, query });
|
|
7089
7916
|
const sdkClient = {
|
|
7090
7917
|
from,
|
|
@@ -7097,27 +7924,27 @@ function createClientFromConfig(config) {
|
|
|
7097
7924
|
if (config.experimental?.athenaStorageBackend) {
|
|
7098
7925
|
const storageClient = {
|
|
7099
7926
|
...sdkClient,
|
|
7100
|
-
storage: createStorageModule(gateway,
|
|
7927
|
+
storage: createStorageModule(gateway, {
|
|
7928
|
+
...config.experimental.storage,
|
|
7929
|
+
...config.storageUrl ? {
|
|
7930
|
+
baseUrl: config.storageUrl,
|
|
7931
|
+
stripBasePath: true
|
|
7932
|
+
} : {}
|
|
7933
|
+
})
|
|
7101
7934
|
};
|
|
7102
7935
|
return storageClient;
|
|
7103
7936
|
}
|
|
7104
7937
|
return sdkClient;
|
|
7105
7938
|
}
|
|
7106
|
-
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7111
|
-
|
|
7112
|
-
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
client: options?.client,
|
|
7116
|
-
backend: toBackendConfig(options?.backend),
|
|
7117
|
-
headers: options?.headers,
|
|
7118
|
-
auth: options?.auth,
|
|
7119
|
-
experimental: options?.experimental
|
|
7120
|
-
});
|
|
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));
|
|
7121
7948
|
}
|
|
7122
7949
|
|
|
7123
7950
|
// src/schema/postgres-introspection-core.ts
|
|
@@ -7714,6 +8541,7 @@ function rootUsage() {
|
|
|
7714
8541
|
"",
|
|
7715
8542
|
"Examples:",
|
|
7716
8543
|
" athena-js generate",
|
|
8544
|
+
" DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/app_db athena-js generate --dry-run",
|
|
7717
8545
|
" athena-js generate --config ./athena.config.ts --dry-run",
|
|
7718
8546
|
" athena-js generate --help"
|
|
7719
8547
|
].join("\n");
|
|
@@ -7730,8 +8558,14 @@ function generateUsage() {
|
|
|
7730
8558
|
" --dry-run Build generated files in memory without writing them to disk",
|
|
7731
8559
|
" -h, --help Show help for generate",
|
|
7732
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
|
+
"",
|
|
7733
8566
|
"Examples:",
|
|
7734
8567
|
" athena-js generate",
|
|
8568
|
+
" DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/app_db athena-js generate --dry-run",
|
|
7735
8569
|
" athena-js generate --config ./athena.config.ts --dry-run"
|
|
7736
8570
|
].join("\n");
|
|
7737
8571
|
}
|