@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.js
CHANGED
|
@@ -129,59 +129,6 @@ function escapeStringLiteral(value) {
|
|
|
129
129
|
return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
// src/generator/placeholders.ts
|
|
133
|
-
function createStyleTokens(prefix, value) {
|
|
134
|
-
return {
|
|
135
|
-
[prefix]: value,
|
|
136
|
-
[`${prefix}_camel`]: applyNamingStyle(value, "camel"),
|
|
137
|
-
[`${prefix}_pascal`]: applyNamingStyle(value, "pascal"),
|
|
138
|
-
[`${prefix}_snake`]: applyNamingStyle(value, "snake"),
|
|
139
|
-
[`${prefix}_kebab`]: applyNamingStyle(value, "kebab")
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
function renderTemplate(template, tokenMap) {
|
|
143
|
-
return template.replace(/\{([A-Za-z0-9_]+)\}/g, (_match, token) => {
|
|
144
|
-
if (!(token in tokenMap)) {
|
|
145
|
-
throw new Error(`Unknown placeholder token "${token}" in template "${template}"`);
|
|
146
|
-
}
|
|
147
|
-
return tokenMap[token];
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
function resolvePlaceholderMap(baseTokens, outputConfig) {
|
|
151
|
-
const resolved = {
|
|
152
|
-
...baseTokens
|
|
153
|
-
};
|
|
154
|
-
const reservedTokenKeys = new Set(Object.keys(baseTokens));
|
|
155
|
-
const entries = Object.entries(outputConfig.placeholderMap ?? {});
|
|
156
|
-
for (let index = 0; index < entries.length; index += 1) {
|
|
157
|
-
const [key, value] = entries[index];
|
|
158
|
-
if (reservedTokenKeys.has(key)) {
|
|
159
|
-
continue;
|
|
160
|
-
}
|
|
161
|
-
let current = value;
|
|
162
|
-
for (let depth = 0; depth < 8; depth += 1) {
|
|
163
|
-
const next = renderTemplate(current, resolved);
|
|
164
|
-
if (next === current) {
|
|
165
|
-
break;
|
|
166
|
-
}
|
|
167
|
-
current = next;
|
|
168
|
-
}
|
|
169
|
-
resolved[key] = current;
|
|
170
|
-
}
|
|
171
|
-
return resolved;
|
|
172
|
-
}
|
|
173
|
-
function renderOutputPath(template, context, outputConfig) {
|
|
174
|
-
const baseTokens = {
|
|
175
|
-
provider: context.provider,
|
|
176
|
-
kind: context.kind,
|
|
177
|
-
...createStyleTokens("database", context.database),
|
|
178
|
-
...createStyleTokens("schema", context.schema),
|
|
179
|
-
...createStyleTokens("model", context.model)
|
|
180
|
-
};
|
|
181
|
-
const tokens = resolvePlaceholderMap(baseTokens, outputConfig);
|
|
182
|
-
return renderTemplate(template, tokens);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
132
|
// src/generator/postgres-type-mapping.ts
|
|
186
133
|
var NUMBER_TYPES = /* @__PURE__ */ new Set([
|
|
187
134
|
"int2",
|
|
@@ -755,6 +702,7 @@ var DEFAULT_TARGETS = {
|
|
|
755
702
|
database: "athena/relations.ts",
|
|
756
703
|
registry: "athena/config.ts"
|
|
757
704
|
};
|
|
705
|
+
var DEFAULT_OUTPUT_FORMAT = "define-model";
|
|
758
706
|
var DEFAULT_NAMING = {
|
|
759
707
|
modelType: "pascal",
|
|
760
708
|
modelConst: "camel",
|
|
@@ -770,6 +718,9 @@ var DEFAULT_EXPERIMENTAL_FLAGS = {
|
|
|
770
718
|
postgresGatewayIntrospection: false,
|
|
771
719
|
scyllaProviderContracts: true
|
|
772
720
|
};
|
|
721
|
+
var DEFAULT_INTERNAL_CONFIG = {
|
|
722
|
+
schemaVersion: 1
|
|
723
|
+
};
|
|
773
724
|
var PROJECT_ENV_FILENAMES = [".env", ".env.local"];
|
|
774
725
|
var DIRECT_CONNECTION_STRING_ENV_KEYS = [
|
|
775
726
|
"ATHENA_GENERATOR_PG_URL",
|
|
@@ -786,6 +737,27 @@ var GATEWAY_API_KEY_ENV_KEYS = [
|
|
|
786
737
|
"ATHENA_GATEWAY_API_KEY",
|
|
787
738
|
"ATHENA_GENERATOR_API_KEY"
|
|
788
739
|
];
|
|
740
|
+
var GENERATOR_SCHEMA_ENV_KEYS = ["ATHENA_GENERATOR_SCHEMAS"];
|
|
741
|
+
var OUTPUT_FORMAT_ENV_KEYS = ["ATHENA_GENERATOR_OUTPUT_FORMAT"];
|
|
742
|
+
var MODEL_TARGET_ENV_KEYS = ["ATHENA_GENERATOR_MODEL_TARGET"];
|
|
743
|
+
var SCHEMA_TARGET_ENV_KEYS = ["ATHENA_GENERATOR_SCHEMA_TARGET"];
|
|
744
|
+
var DATABASE_TARGET_ENV_KEYS = ["ATHENA_GENERATOR_DATABASE_TARGET"];
|
|
745
|
+
var REGISTRY_TARGET_ENV_KEYS = ["ATHENA_GENERATOR_REGISTRY_TARGET"];
|
|
746
|
+
var PLACEHOLDER_MAP_ENV_KEYS = ["ATHENA_GENERATOR_PLACEHOLDER_MAP"];
|
|
747
|
+
var MODEL_TYPE_ENV_KEYS = ["ATHENA_GENERATOR_MODEL_TYPE", "ATHENA_GENERATOR_MODEL_STYLE"];
|
|
748
|
+
var MODEL_CONST_ENV_KEYS = ["ATHENA_GENERATOR_MODEL_CONST"];
|
|
749
|
+
var SCHEMA_CONST_ENV_KEYS = ["ATHENA_GENERATOR_SCHEMA_CONST"];
|
|
750
|
+
var DATABASE_CONST_ENV_KEYS = ["ATHENA_GENERATOR_DATABASE_CONST"];
|
|
751
|
+
var REGISTRY_CONST_ENV_KEYS = ["ATHENA_GENERATOR_REGISTRY_CONST"];
|
|
752
|
+
var EMIT_RELATIONS_ENV_KEYS = ["ATHENA_GENERATOR_EMIT_RELATIONS"];
|
|
753
|
+
var EMIT_REGISTRY_ENV_KEYS = ["ATHENA_GENERATOR_EMIT_REGISTRY"];
|
|
754
|
+
var GATEWAY_BACKEND_ENV_KEYS = ["ATHENA_GENERATOR_BACKEND"];
|
|
755
|
+
var GATEWAY_EXPERIMENTAL_ENV_KEYS = ["ATHENA_GENERATOR_GATEWAY_EXPERIMENTAL"];
|
|
756
|
+
var SCYLLA_PROVIDER_CONTRACTS_ENV_KEYS = ["ATHENA_GENERATOR_SCYLLA_PROVIDER_CONTRACTS"];
|
|
757
|
+
var ENV_ONLY_CONFIG_PATH = "[environment defaults]";
|
|
758
|
+
var NAMING_STYLE_VALUES = ["preserve", "camel", "pascal", "snake", "kebab"];
|
|
759
|
+
var OUTPUT_FORMAT_VALUES = ["define-model", "table-builder"];
|
|
760
|
+
var BACKEND_TYPE_VALUES = ["athena", "postgrest", "postgresql", "scylladb"];
|
|
789
761
|
function normalizeRawEnvValue(rawValue) {
|
|
790
762
|
if (rawValue.startsWith('"') && rawValue.endsWith('"') && rawValue.length >= 2) {
|
|
791
763
|
const inner = rawValue.slice(1, -1);
|
|
@@ -877,6 +849,50 @@ function resolveFallbackValue(fallbackKeys) {
|
|
|
877
849
|
}
|
|
878
850
|
return void 0;
|
|
879
851
|
}
|
|
852
|
+
function normalizeOneOfValue(rawValue, allowedValues, envKeys) {
|
|
853
|
+
if (!rawValue) {
|
|
854
|
+
return void 0;
|
|
855
|
+
}
|
|
856
|
+
if (allowedValues.includes(rawValue)) {
|
|
857
|
+
return rawValue;
|
|
858
|
+
}
|
|
859
|
+
throw new Error(
|
|
860
|
+
`Generator config env vars ${envKeys.join(", ")} must resolve to one of: ${allowedValues.join(", ")}. Received: ${rawValue}.`
|
|
861
|
+
);
|
|
862
|
+
}
|
|
863
|
+
function resolveOptionalOneOf(envKeys, allowedValues) {
|
|
864
|
+
return normalizeOneOfValue(resolveFallbackValue(envKeys), allowedValues, envKeys);
|
|
865
|
+
}
|
|
866
|
+
function resolveOptionalBoolean(envKeys) {
|
|
867
|
+
const rawValue = resolveFallbackValue(envKeys);
|
|
868
|
+
return rawValue === void 0 ? void 0 : parseBooleanFlag2(rawValue, false);
|
|
869
|
+
}
|
|
870
|
+
function resolveOptionalJson(envKeys) {
|
|
871
|
+
const rawValue = resolveFallbackValue(envKeys);
|
|
872
|
+
if (rawValue === void 0) {
|
|
873
|
+
return void 0;
|
|
874
|
+
}
|
|
875
|
+
try {
|
|
876
|
+
return JSON.parse(rawValue);
|
|
877
|
+
} catch (error) {
|
|
878
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
879
|
+
throw new Error(
|
|
880
|
+
`Generator config env vars ${envKeys.join(", ")} must contain valid JSON. ${message}`
|
|
881
|
+
);
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
function deriveDatabaseNameFromConnectionString(connectionString) {
|
|
885
|
+
try {
|
|
886
|
+
const parsedUrl = new URL(connectionString);
|
|
887
|
+
if (!POSTGRES_PROTOCOLS.has(parsedUrl.protocol)) {
|
|
888
|
+
return void 0;
|
|
889
|
+
}
|
|
890
|
+
const pathname = parsedUrl.pathname.replace(/^\/+/, "").trim();
|
|
891
|
+
return pathname.length > 0 ? decodeURIComponent(pathname) : void 0;
|
|
892
|
+
} catch {
|
|
893
|
+
return void 0;
|
|
894
|
+
}
|
|
895
|
+
}
|
|
880
896
|
function normalizeOptionalString(value, fallbackKeys) {
|
|
881
897
|
if (typeof value === "string") {
|
|
882
898
|
const trimmed = value.trim();
|
|
@@ -950,12 +966,13 @@ function normalizeExperimentalFlags(input) {
|
|
|
950
966
|
}
|
|
951
967
|
function normalizeOutputConfig(output) {
|
|
952
968
|
return {
|
|
969
|
+
format: output?.format ?? DEFAULT_OUTPUT_FORMAT,
|
|
953
970
|
targets: {
|
|
954
971
|
...DEFAULT_TARGETS,
|
|
955
|
-
...output
|
|
972
|
+
...output?.targets ?? {}
|
|
956
973
|
},
|
|
957
974
|
placeholderMap: {
|
|
958
|
-
...output
|
|
975
|
+
...output?.placeholderMap ?? {}
|
|
959
976
|
}
|
|
960
977
|
};
|
|
961
978
|
}
|
|
@@ -966,7 +983,7 @@ function normalizeProviderConfig(provider) {
|
|
|
966
983
|
"provider.connectionString",
|
|
967
984
|
DIRECT_CONNECTION_STRING_ENV_KEYS
|
|
968
985
|
);
|
|
969
|
-
const database = normalizeOptionalString(provider.database, POSTGRES_DATABASE_ENV_KEYS);
|
|
986
|
+
const database = normalizeOptionalString(provider.database, POSTGRES_DATABASE_ENV_KEYS) ?? deriveDatabaseNameFromConnectionString(connectionString);
|
|
970
987
|
return {
|
|
971
988
|
...provider,
|
|
972
989
|
connectionString: applyPostgresPasswordFallback(connectionString),
|
|
@@ -985,11 +1002,7 @@ function normalizeProviderConfig(provider) {
|
|
|
985
1002
|
"provider.apiKey",
|
|
986
1003
|
GATEWAY_API_KEY_ENV_KEYS
|
|
987
1004
|
);
|
|
988
|
-
const database =
|
|
989
|
-
provider.database,
|
|
990
|
-
"provider.database",
|
|
991
|
-
POSTGRES_DATABASE_ENV_KEYS
|
|
992
|
-
);
|
|
1005
|
+
const database = normalizeOptionalString(provider.database, POSTGRES_DATABASE_ENV_KEYS) ?? "postgres";
|
|
993
1006
|
return {
|
|
994
1007
|
...provider,
|
|
995
1008
|
gatewayUrl,
|
|
@@ -998,6 +1011,26 @@ function normalizeProviderConfig(provider) {
|
|
|
998
1011
|
schemas: normalizeSchemaSelection(provider.schemas)
|
|
999
1012
|
};
|
|
1000
1013
|
}
|
|
1014
|
+
if (provider.kind === "scylla" && provider.mode === "direct") {
|
|
1015
|
+
if (!provider.contactPoints?.length) {
|
|
1016
|
+
throw new Error(
|
|
1017
|
+
"Generator config is missing provider.contactPoints for scylla direct mode."
|
|
1018
|
+
);
|
|
1019
|
+
}
|
|
1020
|
+
const keyspace = normalizeOptionalString(provider.keyspace, []);
|
|
1021
|
+
if (!keyspace) {
|
|
1022
|
+
throw new Error(
|
|
1023
|
+
"Generator config is missing provider.keyspace for scylla direct mode."
|
|
1024
|
+
);
|
|
1025
|
+
}
|
|
1026
|
+
return {
|
|
1027
|
+
kind: "scylla",
|
|
1028
|
+
mode: "direct",
|
|
1029
|
+
contactPoints: provider.contactPoints.slice(),
|
|
1030
|
+
keyspace,
|
|
1031
|
+
datacenter: normalizeOptionalString(provider.datacenter, [])
|
|
1032
|
+
};
|
|
1033
|
+
}
|
|
1001
1034
|
return provider;
|
|
1002
1035
|
}
|
|
1003
1036
|
function isAthenaGeneratorConfig(value) {
|
|
@@ -1005,7 +1038,7 @@ function isAthenaGeneratorConfig(value) {
|
|
|
1005
1038
|
return false;
|
|
1006
1039
|
}
|
|
1007
1040
|
const record = value;
|
|
1008
|
-
return Boolean(record.provider && typeof record.provider === "object") &&
|
|
1041
|
+
return Boolean(record.provider && typeof record.provider === "object") && (record.output === void 0 || typeof record.output === "object");
|
|
1009
1042
|
}
|
|
1010
1043
|
function normalizeGeneratorConfig(input) {
|
|
1011
1044
|
return {
|
|
@@ -1016,7 +1049,10 @@ function normalizeGeneratorConfig(input) {
|
|
|
1016
1049
|
...input.naming ?? {}
|
|
1017
1050
|
},
|
|
1018
1051
|
features: normalizeFeatureFlags(input.features),
|
|
1019
|
-
experimental: normalizeExperimentalFlags(input.experimental)
|
|
1052
|
+
experimental: normalizeExperimentalFlags(input.experimental),
|
|
1053
|
+
internal: {
|
|
1054
|
+
...DEFAULT_INTERNAL_CONFIG
|
|
1055
|
+
}
|
|
1020
1056
|
};
|
|
1021
1057
|
}
|
|
1022
1058
|
function findGeneratorConfigPath(cwd = process.cwd()) {
|
|
@@ -1070,16 +1106,123 @@ function importConfigModule(moduleSpecifier) {
|
|
|
1070
1106
|
);
|
|
1071
1107
|
return runtimeImport(moduleSpecifier);
|
|
1072
1108
|
}
|
|
1109
|
+
function buildEnvironmentOutputConfig() {
|
|
1110
|
+
const format = resolveOptionalOneOf(OUTPUT_FORMAT_ENV_KEYS, OUTPUT_FORMAT_VALUES);
|
|
1111
|
+
const modelTarget = resolveFallbackValue(MODEL_TARGET_ENV_KEYS);
|
|
1112
|
+
const schemaTarget = resolveFallbackValue(SCHEMA_TARGET_ENV_KEYS);
|
|
1113
|
+
const databaseTarget = resolveFallbackValue(DATABASE_TARGET_ENV_KEYS);
|
|
1114
|
+
const registryTarget = resolveFallbackValue(REGISTRY_TARGET_ENV_KEYS);
|
|
1115
|
+
const placeholderMap = resolveOptionalJson(PLACEHOLDER_MAP_ENV_KEYS);
|
|
1116
|
+
if (format === void 0 && modelTarget === void 0 && schemaTarget === void 0 && databaseTarget === void 0 && registryTarget === void 0 && placeholderMap === void 0) {
|
|
1117
|
+
return void 0;
|
|
1118
|
+
}
|
|
1119
|
+
return {
|
|
1120
|
+
format,
|
|
1121
|
+
targets: {
|
|
1122
|
+
...modelTarget ? { model: modelTarget } : {},
|
|
1123
|
+
...schemaTarget ? { schema: schemaTarget } : {},
|
|
1124
|
+
...databaseTarget ? { database: databaseTarget } : {},
|
|
1125
|
+
...registryTarget ? { registry: registryTarget } : {}
|
|
1126
|
+
},
|
|
1127
|
+
placeholderMap
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1130
|
+
function buildEnvironmentNamingConfig() {
|
|
1131
|
+
const modelType = resolveOptionalOneOf(MODEL_TYPE_ENV_KEYS, NAMING_STYLE_VALUES);
|
|
1132
|
+
const modelConst = resolveOptionalOneOf(MODEL_CONST_ENV_KEYS, NAMING_STYLE_VALUES);
|
|
1133
|
+
const schemaConst = resolveOptionalOneOf(SCHEMA_CONST_ENV_KEYS, NAMING_STYLE_VALUES);
|
|
1134
|
+
const databaseConst = resolveOptionalOneOf(DATABASE_CONST_ENV_KEYS, NAMING_STYLE_VALUES);
|
|
1135
|
+
const registryConst = resolveOptionalOneOf(REGISTRY_CONST_ENV_KEYS, NAMING_STYLE_VALUES);
|
|
1136
|
+
if (modelType === void 0 && modelConst === void 0 && schemaConst === void 0 && databaseConst === void 0 && registryConst === void 0) {
|
|
1137
|
+
return void 0;
|
|
1138
|
+
}
|
|
1139
|
+
return {
|
|
1140
|
+
...modelType ? { modelType } : {},
|
|
1141
|
+
...modelConst ? { modelConst } : {},
|
|
1142
|
+
...schemaConst ? { schemaConst } : {},
|
|
1143
|
+
...databaseConst ? { databaseConst } : {},
|
|
1144
|
+
...registryConst ? { registryConst } : {}
|
|
1145
|
+
};
|
|
1146
|
+
}
|
|
1147
|
+
function buildEnvironmentFeatureFlags() {
|
|
1148
|
+
const emitRelations = resolveOptionalBoolean(EMIT_RELATIONS_ENV_KEYS);
|
|
1149
|
+
const emitRegistry = resolveOptionalBoolean(EMIT_REGISTRY_ENV_KEYS);
|
|
1150
|
+
if (emitRelations === void 0 && emitRegistry === void 0) {
|
|
1151
|
+
return void 0;
|
|
1152
|
+
}
|
|
1153
|
+
return {
|
|
1154
|
+
...emitRelations !== void 0 ? { emitRelations } : {},
|
|
1155
|
+
...emitRegistry !== void 0 ? { emitRegistry } : {}
|
|
1156
|
+
};
|
|
1157
|
+
}
|
|
1158
|
+
function buildEnvironmentExperimentalFlags() {
|
|
1159
|
+
const postgresGatewayIntrospection = resolveOptionalBoolean(GATEWAY_EXPERIMENTAL_ENV_KEYS);
|
|
1160
|
+
const scyllaProviderContracts = resolveOptionalBoolean(SCYLLA_PROVIDER_CONTRACTS_ENV_KEYS);
|
|
1161
|
+
if (postgresGatewayIntrospection === void 0 && scyllaProviderContracts === void 0) {
|
|
1162
|
+
return void 0;
|
|
1163
|
+
}
|
|
1164
|
+
return {
|
|
1165
|
+
...postgresGatewayIntrospection !== void 0 ? { postgresGatewayIntrospection } : {},
|
|
1166
|
+
...scyllaProviderContracts !== void 0 ? { scyllaProviderContracts } : {}
|
|
1167
|
+
};
|
|
1168
|
+
}
|
|
1169
|
+
function buildEnvironmentProviderConfig() {
|
|
1170
|
+
const directConnectionString = resolveFallbackValue(DIRECT_CONNECTION_STRING_ENV_KEYS);
|
|
1171
|
+
if (directConnectionString) {
|
|
1172
|
+
return {
|
|
1173
|
+
kind: "postgres",
|
|
1174
|
+
mode: "direct",
|
|
1175
|
+
connectionString: directConnectionString,
|
|
1176
|
+
database: normalizeOptionalString(void 0, POSTGRES_DATABASE_ENV_KEYS),
|
|
1177
|
+
schemas: normalizeSchemaSelection(resolveFallbackValue(GENERATOR_SCHEMA_ENV_KEYS))
|
|
1178
|
+
};
|
|
1179
|
+
}
|
|
1180
|
+
const gatewayUrl = resolveFallbackValue(GATEWAY_URL_ENV_KEYS);
|
|
1181
|
+
const apiKey = resolveFallbackValue(GATEWAY_API_KEY_ENV_KEYS);
|
|
1182
|
+
if (gatewayUrl && apiKey) {
|
|
1183
|
+
const backend = resolveOptionalOneOf(GATEWAY_BACKEND_ENV_KEYS, BACKEND_TYPE_VALUES);
|
|
1184
|
+
return {
|
|
1185
|
+
kind: "postgres",
|
|
1186
|
+
mode: "gateway",
|
|
1187
|
+
gatewayUrl,
|
|
1188
|
+
apiKey,
|
|
1189
|
+
database: normalizeOptionalString(void 0, POSTGRES_DATABASE_ENV_KEYS),
|
|
1190
|
+
schemas: normalizeSchemaSelection(resolveFallbackValue(GENERATOR_SCHEMA_ENV_KEYS)),
|
|
1191
|
+
backend
|
|
1192
|
+
};
|
|
1193
|
+
}
|
|
1194
|
+
return void 0;
|
|
1195
|
+
}
|
|
1196
|
+
function createEnvironmentGeneratorConfig() {
|
|
1197
|
+
const provider = buildEnvironmentProviderConfig();
|
|
1198
|
+
if (!provider) {
|
|
1199
|
+
return void 0;
|
|
1200
|
+
}
|
|
1201
|
+
return {
|
|
1202
|
+
provider,
|
|
1203
|
+
output: buildEnvironmentOutputConfig(),
|
|
1204
|
+
naming: buildEnvironmentNamingConfig(),
|
|
1205
|
+
features: buildEnvironmentFeatureFlags(),
|
|
1206
|
+
experimental: buildEnvironmentExperimentalFlags()
|
|
1207
|
+
};
|
|
1208
|
+
}
|
|
1073
1209
|
async function loadGeneratorConfig(options = {}) {
|
|
1074
1210
|
const cwd = options.cwd ?? process.cwd();
|
|
1075
1211
|
const restoreProjectEnv = applyProjectEnv(cwd);
|
|
1076
|
-
const resolvedPath = options.configPath ? resolve(cwd, options.configPath) : findGeneratorConfigPath(cwd);
|
|
1077
|
-
if (!resolvedPath) {
|
|
1078
|
-
throw new Error(
|
|
1079
|
-
`No generator config found in ${cwd}. Expected one of: ${DEFAULT_CONFIG_CANDIDATES.join(", ")}`
|
|
1080
|
-
);
|
|
1081
|
-
}
|
|
1082
1212
|
try {
|
|
1213
|
+
const resolvedPath = options.configPath ? resolve(cwd, options.configPath) : findGeneratorConfigPath(cwd);
|
|
1214
|
+
if (!resolvedPath) {
|
|
1215
|
+
const environmentConfig = createEnvironmentGeneratorConfig();
|
|
1216
|
+
if (environmentConfig) {
|
|
1217
|
+
return {
|
|
1218
|
+
configPath: ENV_ONLY_CONFIG_PATH,
|
|
1219
|
+
config: normalizeGeneratorConfig(environmentConfig)
|
|
1220
|
+
};
|
|
1221
|
+
}
|
|
1222
|
+
throw new Error(
|
|
1223
|
+
`No generator config found in ${cwd}. Expected one of: ${DEFAULT_CONFIG_CANDIDATES.join(", ")}. To run without a config file, set DATABASE_URL (direct mode) or ATHENA_URL + ATHENA_API_KEY (gateway mode).`
|
|
1224
|
+
);
|
|
1225
|
+
}
|
|
1083
1226
|
const moduleUrl = pathToFileURL(resolvedPath);
|
|
1084
1227
|
const module = await importConfigModule(`${moduleUrl.href}?cacheBust=${Date.now()}`);
|
|
1085
1228
|
const rawConfig = extractConfigExport(module);
|
|
@@ -1092,7 +1235,60 @@ async function loadGeneratorConfig(options = {}) {
|
|
|
1092
1235
|
}
|
|
1093
1236
|
}
|
|
1094
1237
|
|
|
1095
|
-
// src/generator/
|
|
1238
|
+
// src/generator/placeholders.ts
|
|
1239
|
+
function createStyleTokens(prefix, value) {
|
|
1240
|
+
return {
|
|
1241
|
+
[prefix]: value,
|
|
1242
|
+
[`${prefix}_camel`]: applyNamingStyle(value, "camel"),
|
|
1243
|
+
[`${prefix}_pascal`]: applyNamingStyle(value, "pascal"),
|
|
1244
|
+
[`${prefix}_snake`]: applyNamingStyle(value, "snake"),
|
|
1245
|
+
[`${prefix}_kebab`]: applyNamingStyle(value, "kebab")
|
|
1246
|
+
};
|
|
1247
|
+
}
|
|
1248
|
+
function renderTemplate(template, tokenMap) {
|
|
1249
|
+
return template.replace(/\{([A-Za-z0-9_]+)\}/g, (_match, token) => {
|
|
1250
|
+
if (!(token in tokenMap)) {
|
|
1251
|
+
throw new Error(`Unknown placeholder token "${token}" in template "${template}"`);
|
|
1252
|
+
}
|
|
1253
|
+
return tokenMap[token];
|
|
1254
|
+
});
|
|
1255
|
+
}
|
|
1256
|
+
function resolvePlaceholderMap(baseTokens, outputConfig) {
|
|
1257
|
+
const resolved = {
|
|
1258
|
+
...baseTokens
|
|
1259
|
+
};
|
|
1260
|
+
const reservedTokenKeys = new Set(Object.keys(baseTokens));
|
|
1261
|
+
const entries = Object.entries(outputConfig.placeholderMap ?? {});
|
|
1262
|
+
for (let index = 0; index < entries.length; index += 1) {
|
|
1263
|
+
const [key, value] = entries[index];
|
|
1264
|
+
if (reservedTokenKeys.has(key)) {
|
|
1265
|
+
continue;
|
|
1266
|
+
}
|
|
1267
|
+
let current = value;
|
|
1268
|
+
for (let depth = 0; depth < 8; depth += 1) {
|
|
1269
|
+
const next = renderTemplate(current, resolved);
|
|
1270
|
+
if (next === current) {
|
|
1271
|
+
break;
|
|
1272
|
+
}
|
|
1273
|
+
current = next;
|
|
1274
|
+
}
|
|
1275
|
+
resolved[key] = current;
|
|
1276
|
+
}
|
|
1277
|
+
return resolved;
|
|
1278
|
+
}
|
|
1279
|
+
function renderOutputPath(template, context, outputConfig) {
|
|
1280
|
+
const baseTokens = {
|
|
1281
|
+
provider: context.provider,
|
|
1282
|
+
kind: context.kind,
|
|
1283
|
+
...createStyleTokens("database", context.database),
|
|
1284
|
+
...createStyleTokens("schema", context.schema),
|
|
1285
|
+
...createStyleTokens("model", context.model)
|
|
1286
|
+
};
|
|
1287
|
+
const tokens = resolvePlaceholderMap(baseTokens, outputConfig);
|
|
1288
|
+
return renderTemplate(template, tokens);
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
// src/generator/render-shared.ts
|
|
1096
1292
|
function normalizePath(pathValue) {
|
|
1097
1293
|
return pathValue.replace(/\\/g, "/");
|
|
1098
1294
|
}
|
|
@@ -1105,11 +1301,13 @@ function toModuleImportPath(fromFile, targetFile) {
|
|
|
1105
1301
|
);
|
|
1106
1302
|
return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
1107
1303
|
}
|
|
1304
|
+
function resolveOutputPath(target, tokens, config) {
|
|
1305
|
+
return normalizePath(renderOutputPath(target, tokens, config.output));
|
|
1306
|
+
}
|
|
1108
1307
|
function renderObjectKey(key) {
|
|
1109
|
-
|
|
1110
|
-
return escaped.startsWith("'") ? escaped : escaped;
|
|
1308
|
+
return escapeTypePropertyName(key);
|
|
1111
1309
|
}
|
|
1112
|
-
function
|
|
1310
|
+
function renderRelationLiteral(relation) {
|
|
1113
1311
|
const through = relation.through ? `,
|
|
1114
1312
|
through: {
|
|
1115
1313
|
schema: ${escapeStringLiteral(relation.through.schema)},
|
|
@@ -1125,54 +1323,12 @@ function renderRelation(relation) {
|
|
|
1125
1323
|
targetColumns: [${relation.targetColumns.map((value) => escapeStringLiteral(value)).join(", ")}]${through}
|
|
1126
1324
|
}`;
|
|
1127
1325
|
}
|
|
1128
|
-
function renderModelArtifact(snapshot, descriptor, config) {
|
|
1129
|
-
const columnLines = Object.values(descriptor.table.columns).map((column) => {
|
|
1130
|
-
const propertyName = escapeTypePropertyName(column.name);
|
|
1131
|
-
const baseType = resolvePostgresColumnType(column);
|
|
1132
|
-
const isOptional = column.isNullable;
|
|
1133
|
-
const typeWithNullability = column.isNullable ? `${baseType} | null` : baseType;
|
|
1134
|
-
return ` ${propertyName}${isOptional ? "?" : ""}: ${typeWithNullability}`;
|
|
1135
|
-
}).join("\n");
|
|
1136
|
-
const nullableLines = Object.values(descriptor.table.columns).map((column) => ` ${renderObjectKey(column.name)}: ${column.isNullable ? "true" : "false"}`).join(",\n");
|
|
1137
|
-
const relationEntries = Object.entries(descriptor.table.relations);
|
|
1138
|
-
const relationBlock = config.features.emitRelations && relationEntries.length > 0 ? `,
|
|
1139
|
-
relations: {
|
|
1140
|
-
${relationEntries.map(([relationKey2, relationValue]) => ` ${renderObjectKey(relationKey2)}: ${renderRelation(relationValue)}`).join(",\n")}
|
|
1141
|
-
}` : "";
|
|
1142
|
-
const content = `import { defineModel } from '@xylex-group/athena'
|
|
1143
|
-
|
|
1144
|
-
export interface ${descriptor.rowTypeName} {
|
|
1145
|
-
${columnLines}
|
|
1146
|
-
}
|
|
1147
|
-
|
|
1148
|
-
export type ${descriptor.insertTypeName} = Partial<${descriptor.rowTypeName}>
|
|
1149
|
-
export type ${descriptor.updateTypeName} = Partial<${descriptor.insertTypeName}>
|
|
1150
|
-
|
|
1151
|
-
export const ${descriptor.modelConstName} = defineModel<${descriptor.rowTypeName}, ${descriptor.insertTypeName}, ${descriptor.updateTypeName}>({
|
|
1152
|
-
meta: {
|
|
1153
|
-
database: ${escapeStringLiteral(snapshot.database)},
|
|
1154
|
-
schema: ${escapeStringLiteral(descriptor.schemaName)},
|
|
1155
|
-
model: ${escapeStringLiteral(descriptor.tableName)},
|
|
1156
|
-
tableName: ${escapeStringLiteral(`${descriptor.schemaName}.${descriptor.tableName}`)},
|
|
1157
|
-
primaryKey: [${descriptor.table.primaryKey.map((value) => escapeStringLiteral(value)).join(", ")}],
|
|
1158
|
-
nullable: {
|
|
1159
|
-
${nullableLines}
|
|
1160
|
-
}${relationBlock}
|
|
1161
|
-
}
|
|
1162
|
-
})
|
|
1163
|
-
`;
|
|
1164
|
-
return {
|
|
1165
|
-
kind: "model",
|
|
1166
|
-
path: descriptor.filePath,
|
|
1167
|
-
content
|
|
1168
|
-
};
|
|
1169
|
-
}
|
|
1170
1326
|
function renderSchemaArtifact(descriptor) {
|
|
1171
1327
|
const importLines = descriptor.models.map((modelDescriptor) => {
|
|
1172
1328
|
const importPath = toModuleImportPath(descriptor.filePath, modelDescriptor.filePath);
|
|
1173
|
-
return `import { ${modelDescriptor.
|
|
1329
|
+
return `import { ${modelDescriptor.exportConstName} } from '${importPath}'`;
|
|
1174
1330
|
}).join("\n");
|
|
1175
|
-
const modelEntries = descriptor.models.map((modelDescriptor) => ` ${renderObjectKey(modelDescriptor.tableName)}: ${modelDescriptor.
|
|
1331
|
+
const modelEntries = descriptor.models.map((modelDescriptor) => ` ${renderObjectKey(modelDescriptor.tableName)}: ${modelDescriptor.exportConstName}`).join(",\n");
|
|
1176
1332
|
const content = `import { defineSchema } from '@xylex-group/athena'
|
|
1177
1333
|
${importLines ? `
|
|
1178
1334
|
${importLines}
|
|
@@ -1207,11 +1363,18 @@ ${schemaEntries}
|
|
|
1207
1363
|
content
|
|
1208
1364
|
};
|
|
1209
1365
|
}
|
|
1210
|
-
function renderRegistryArtifact(registryPath, databasePath, databaseConstName, registryConstName, databaseName) {
|
|
1366
|
+
function renderRegistryArtifact(registryPath, databasePath, databaseConstName, registryConstName, databaseName, generatedAt, outputFormat, schemaVersion) {
|
|
1211
1367
|
const databaseImportPath = toModuleImportPath(registryPath, databasePath);
|
|
1212
1368
|
const content = `import { defineRegistry } from '@xylex-group/athena'
|
|
1213
1369
|
import { ${databaseConstName} } from '${databaseImportPath}'
|
|
1214
1370
|
|
|
1371
|
+
export const __athena_schema_meta = {
|
|
1372
|
+
schemaVersion: ${schemaVersion},
|
|
1373
|
+
generatedAt: ${escapeStringLiteral(generatedAt)},
|
|
1374
|
+
database: ${escapeStringLiteral(databaseName)},
|
|
1375
|
+
outputFormat: ${escapeStringLiteral(outputFormat)},
|
|
1376
|
+
} as const
|
|
1377
|
+
|
|
1215
1378
|
export const ${registryConstName} = defineRegistry({
|
|
1216
1379
|
${renderObjectKey(databaseName)}: ${databaseConstName}
|
|
1217
1380
|
})
|
|
@@ -1290,123 +1453,332 @@ function scopeDuplicateDescriptorPathsBySchema(descriptors) {
|
|
|
1290
1453
|
}
|
|
1291
1454
|
return nextDescriptors;
|
|
1292
1455
|
}
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
const
|
|
1300
|
-
const
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1456
|
+
function composeGeneratorArtifacts(input) {
|
|
1457
|
+
const { snapshot, config, createModelDescriptor, renderModelArtifact: renderModelArtifact3 } = input;
|
|
1458
|
+
const providerName = snapshot.backend;
|
|
1459
|
+
const databaseName = snapshot.database;
|
|
1460
|
+
const modelDescriptors = [];
|
|
1461
|
+
for (const schemaName of Object.keys(snapshot.schemas).sort()) {
|
|
1462
|
+
const schema = snapshot.schemas[schemaName];
|
|
1463
|
+
for (const tableName of Object.keys(schema.tables).sort()) {
|
|
1464
|
+
modelDescriptors.push(
|
|
1465
|
+
createModelDescriptor({
|
|
1466
|
+
providerName,
|
|
1467
|
+
databaseName,
|
|
1468
|
+
schemaName,
|
|
1469
|
+
tableName,
|
|
1470
|
+
table: schema.tables[tableName]
|
|
1471
|
+
})
|
|
1472
|
+
);
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
const scopedModelDescriptors = scopeDuplicateDescriptorPathsBySchema(modelDescriptors);
|
|
1476
|
+
let schemaDescriptors = Object.keys(snapshot.schemas).sort().map((schemaName) => ({
|
|
1477
|
+
schemaName,
|
|
1478
|
+
filePath: resolveOutputPath(
|
|
1479
|
+
config.output.targets.schema,
|
|
1480
|
+
{
|
|
1481
|
+
provider: providerName,
|
|
1482
|
+
kind: "schema",
|
|
1483
|
+
database: databaseName,
|
|
1484
|
+
schema: schemaName,
|
|
1485
|
+
model: "index"
|
|
1486
|
+
},
|
|
1487
|
+
config
|
|
1488
|
+
),
|
|
1489
|
+
schemaConstName: toSafeIdentifier(
|
|
1490
|
+
`${schemaName} schema`,
|
|
1491
|
+
config.naming.schemaConst,
|
|
1492
|
+
"schema"
|
|
1493
|
+
),
|
|
1494
|
+
models: scopedModelDescriptors.filter((model) => model.schemaName === schemaName)
|
|
1495
|
+
}));
|
|
1496
|
+
schemaDescriptors = scopeDuplicateDescriptorPathsBySchema(schemaDescriptors);
|
|
1497
|
+
const databaseDescriptor = {
|
|
1498
|
+
filePath: resolveOutputPath(
|
|
1499
|
+
config.output.targets.database,
|
|
1500
|
+
{
|
|
1501
|
+
provider: providerName,
|
|
1502
|
+
kind: "database",
|
|
1503
|
+
database: databaseName,
|
|
1504
|
+
schema: "index",
|
|
1505
|
+
model: "index"
|
|
1506
|
+
},
|
|
1507
|
+
config
|
|
1508
|
+
),
|
|
1509
|
+
databaseConstName: toSafeIdentifier(
|
|
1510
|
+
`${databaseName} database`,
|
|
1511
|
+
config.naming.databaseConst,
|
|
1512
|
+
"database"
|
|
1513
|
+
),
|
|
1514
|
+
schemas: schemaDescriptors
|
|
1515
|
+
};
|
|
1516
|
+
const files = [];
|
|
1517
|
+
for (const modelDescriptor of scopedModelDescriptors) {
|
|
1518
|
+
files.push(renderModelArtifact3(modelDescriptor));
|
|
1519
|
+
}
|
|
1520
|
+
for (const schemaDescriptor of schemaDescriptors) {
|
|
1521
|
+
files.push(renderSchemaArtifact(schemaDescriptor));
|
|
1522
|
+
}
|
|
1523
|
+
files.push(renderDatabaseArtifact(databaseDescriptor));
|
|
1524
|
+
if (config.features.emitRegistry) {
|
|
1525
|
+
const registryPath = resolveOutputPath(
|
|
1526
|
+
config.output.targets.registry,
|
|
1527
|
+
{
|
|
1528
|
+
provider: providerName,
|
|
1529
|
+
kind: "registry",
|
|
1530
|
+
database: databaseName,
|
|
1531
|
+
schema: "index",
|
|
1532
|
+
model: "index"
|
|
1533
|
+
},
|
|
1534
|
+
config
|
|
1535
|
+
);
|
|
1536
|
+
files.push(
|
|
1537
|
+
renderRegistryArtifact(
|
|
1538
|
+
registryPath,
|
|
1539
|
+
databaseDescriptor.filePath,
|
|
1540
|
+
databaseDescriptor.databaseConstName,
|
|
1541
|
+
toSafeIdentifier("registry", config.naming.registryConst, "registry"),
|
|
1542
|
+
databaseName,
|
|
1543
|
+
snapshot.generatedAt,
|
|
1544
|
+
config.output.format,
|
|
1545
|
+
config.internal.schemaVersion
|
|
1546
|
+
)
|
|
1547
|
+
);
|
|
1548
|
+
}
|
|
1549
|
+
assertNoDuplicatePaths(files);
|
|
1550
|
+
return {
|
|
1551
|
+
snapshot,
|
|
1552
|
+
files
|
|
1553
|
+
};
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
// src/generator/table-builder-renderer.ts
|
|
1557
|
+
var SAFE_NUMBER_TYPES = /* @__PURE__ */ new Set([
|
|
1558
|
+
"int2",
|
|
1559
|
+
"int4",
|
|
1560
|
+
"float4",
|
|
1561
|
+
"float8",
|
|
1562
|
+
"smallint",
|
|
1563
|
+
"integer",
|
|
1564
|
+
"real",
|
|
1565
|
+
"double precision"
|
|
1566
|
+
]);
|
|
1567
|
+
var JSON_TYPES = /* @__PURE__ */ new Set(["json", "jsonb"]);
|
|
1568
|
+
var BOOLEAN_TYPES = /* @__PURE__ */ new Set(["bool", "boolean"]);
|
|
1569
|
+
var STRING_TYPES = /* @__PURE__ */ new Set([
|
|
1570
|
+
"int8",
|
|
1571
|
+
"bigint",
|
|
1572
|
+
"serial8",
|
|
1573
|
+
"bigserial",
|
|
1574
|
+
"numeric",
|
|
1575
|
+
"decimal",
|
|
1576
|
+
"money",
|
|
1577
|
+
"bytea"
|
|
1578
|
+
]);
|
|
1579
|
+
function normalizeTypeLabel2(column) {
|
|
1580
|
+
const preferred = (column.udtName || column.dataType).toLowerCase().trim();
|
|
1581
|
+
if (column.arrayDimensions > 0 && preferred.startsWith("_")) {
|
|
1582
|
+
return preferred.slice(1);
|
|
1583
|
+
}
|
|
1584
|
+
return preferred;
|
|
1585
|
+
}
|
|
1586
|
+
function renderColumnBuilder(column) {
|
|
1587
|
+
const label = normalizeTypeLabel2(column);
|
|
1588
|
+
let helper;
|
|
1589
|
+
let expression;
|
|
1590
|
+
if (column.typeKind === "enum" && column.enumValues && column.enumValues.length > 0) {
|
|
1591
|
+
helper = "enumeration";
|
|
1592
|
+
expression = `enumeration([${column.enumValues.map((value) => escapeStringLiteral(value)).join(", ")}] as const)`;
|
|
1593
|
+
} else if (column.arrayDimensions > 0 || JSON_TYPES.has(label) || column.typeKind === "composite") {
|
|
1594
|
+
helper = "json";
|
|
1595
|
+
expression = `json<${resolvePostgresColumnType(column)}>()`;
|
|
1596
|
+
} else if (BOOLEAN_TYPES.has(label)) {
|
|
1597
|
+
helper = "boolean";
|
|
1598
|
+
expression = "boolean()";
|
|
1599
|
+
} else if (SAFE_NUMBER_TYPES.has(label)) {
|
|
1600
|
+
helper = "number";
|
|
1601
|
+
expression = "number()";
|
|
1602
|
+
} else if (STRING_TYPES.has(label)) {
|
|
1603
|
+
helper = "string";
|
|
1604
|
+
expression = "string()";
|
|
1605
|
+
} else {
|
|
1606
|
+
helper = "string";
|
|
1607
|
+
expression = "string()";
|
|
1608
|
+
}
|
|
1609
|
+
if (column.isNullable) {
|
|
1610
|
+
expression = `${expression}.optional()`;
|
|
1611
|
+
}
|
|
1612
|
+
if (column.hasDefault) {
|
|
1613
|
+
expression = `${expression}.defaulted()`;
|
|
1614
|
+
}
|
|
1615
|
+
if (column.isGenerated) {
|
|
1616
|
+
expression = `${expression}.generated()`;
|
|
1617
|
+
}
|
|
1618
|
+
return { helper, expression };
|
|
1619
|
+
}
|
|
1620
|
+
function renderModelArtifact(descriptor, config) {
|
|
1621
|
+
const helperImports = /* @__PURE__ */ new Set(["table"]);
|
|
1622
|
+
const columnLines = Object.entries(descriptor.table.columns).map(([columnName, column]) => {
|
|
1623
|
+
const propertyName = escapeTypePropertyName(columnName);
|
|
1624
|
+
const rendered = renderColumnBuilder(column);
|
|
1625
|
+
helperImports.add(rendered.helper);
|
|
1626
|
+
return ` ${propertyName}: ${rendered.expression}`;
|
|
1627
|
+
}).join(",\n");
|
|
1628
|
+
const helperImportLine = Array.from(helperImports).sort().join(", ");
|
|
1629
|
+
const rowSchemaConstName = `${descriptor.tableConstName}_row_schema`;
|
|
1630
|
+
const insertSchemaConstName = `${descriptor.tableConstName}_insert_schema`;
|
|
1631
|
+
const updateSchemaConstName = `${descriptor.tableConstName}_update_schema`;
|
|
1632
|
+
const formSchemaConstName = `${descriptor.tableConstName}_form_schema`;
|
|
1633
|
+
const relationEntries = Object.entries(descriptor.table.relations);
|
|
1634
|
+
const relationsAssignment = config.features.emitRelations && relationEntries.length > 0 ? `
|
|
1635
|
+
Object.assign(${descriptor.tableConstName}.meta, {
|
|
1636
|
+
relations: {
|
|
1637
|
+
${relationEntries.map(([relationKey2, relationValue]) => ` ${renderObjectKey(relationKey2)}: ${renderRelationLiteral(relationValue)}`).join(",\n")}
|
|
1638
|
+
}
|
|
1639
|
+
})
|
|
1640
|
+
` : "";
|
|
1641
|
+
const content = `import { ${helperImportLine} } from '@xylex-group/athena'
|
|
1642
|
+
import type { FormValuesOf, InsertOf, RowOf, UpdateOf } from '@xylex-group/athena'
|
|
1643
|
+
|
|
1644
|
+
export const ${descriptor.tableConstName} = table(${escapeStringLiteral(descriptor.tableName)})
|
|
1645
|
+
.schema(${escapeStringLiteral(descriptor.schemaName)})
|
|
1646
|
+
.columns({
|
|
1647
|
+
${columnLines}
|
|
1648
|
+
})
|
|
1649
|
+
.primaryKey(${descriptor.table.primaryKey.map((value) => escapeStringLiteral(value)).join(", ")})
|
|
1650
|
+
${relationsAssignment ? `${relationsAssignment}` : ""}
|
|
1651
|
+
export type ${descriptor.rowTypeName} = RowOf<typeof ${descriptor.tableConstName}>
|
|
1652
|
+
export type ${descriptor.insertTypeName} = InsertOf<typeof ${descriptor.tableConstName}>
|
|
1653
|
+
export type ${descriptor.updateTypeName} = UpdateOf<typeof ${descriptor.tableConstName}>
|
|
1654
|
+
export type ${descriptor.formValuesTypeName} = FormValuesOf<typeof ${descriptor.tableConstName}>
|
|
1655
|
+
|
|
1656
|
+
export const ${rowSchemaConstName} = ${descriptor.tableConstName}.schemas.row
|
|
1657
|
+
export const ${insertSchemaConstName} = ${descriptor.tableConstName}.schemas.insert
|
|
1658
|
+
export const ${updateSchemaConstName} = ${descriptor.tableConstName}.schemas.update
|
|
1659
|
+
export const ${formSchemaConstName} = ${descriptor.tableConstName}.schemas.form
|
|
1660
|
+
`;
|
|
1661
|
+
return {
|
|
1662
|
+
kind: "model",
|
|
1663
|
+
path: descriptor.filePath,
|
|
1664
|
+
content
|
|
1665
|
+
};
|
|
1666
|
+
}
|
|
1667
|
+
function generateTableBuilderArtifactsFromSnapshot(snapshot, config) {
|
|
1668
|
+
const normalizedConfig = "internal" in config ? config : normalizeGeneratorConfig(config);
|
|
1669
|
+
return composeGeneratorArtifacts({
|
|
1670
|
+
snapshot,
|
|
1671
|
+
config: normalizedConfig,
|
|
1672
|
+
createModelDescriptor({ providerName, databaseName, schemaName, tableName, table }) {
|
|
1673
|
+
const tableConstName = toSafeIdentifier(tableName, "preserve", "table");
|
|
1674
|
+
return {
|
|
1675
|
+
schemaName,
|
|
1676
|
+
tableName,
|
|
1677
|
+
filePath: resolveOutputPath(
|
|
1678
|
+
normalizedConfig.output.targets.model,
|
|
1679
|
+
{
|
|
1680
|
+
provider: providerName,
|
|
1681
|
+
kind: "model",
|
|
1682
|
+
database: databaseName,
|
|
1683
|
+
schema: schemaName,
|
|
1684
|
+
model: tableName
|
|
1685
|
+
},
|
|
1686
|
+
normalizedConfig
|
|
1687
|
+
),
|
|
1688
|
+
rowTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}Row`,
|
|
1689
|
+
insertTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}Insert`,
|
|
1690
|
+
updateTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}Update`,
|
|
1691
|
+
formValuesTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}FormValues`,
|
|
1692
|
+
tableConstName,
|
|
1693
|
+
exportConstName: tableConstName,
|
|
1694
|
+
table
|
|
1695
|
+
};
|
|
1696
|
+
},
|
|
1697
|
+
renderModelArtifact: (descriptor) => renderModelArtifact(descriptor, normalizedConfig)
|
|
1698
|
+
});
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1701
|
+
// src/generator/renderer.ts
|
|
1702
|
+
function renderModelArtifact2(databaseName, descriptor, config) {
|
|
1703
|
+
const columnLines = Object.values(descriptor.table.columns).map((column) => {
|
|
1704
|
+
const propertyName = escapeTypePropertyName(column.name);
|
|
1705
|
+
const baseType = resolvePostgresColumnType(column);
|
|
1706
|
+
const isOptional = column.isNullable;
|
|
1707
|
+
const typeWithNullability = column.isNullable ? `${baseType} | null` : baseType;
|
|
1708
|
+
return ` ${propertyName}${isOptional ? "?" : ""}: ${typeWithNullability}`;
|
|
1709
|
+
}).join("\n");
|
|
1710
|
+
const nullableLines = Object.values(descriptor.table.columns).map((column) => ` ${renderObjectKey(column.name)}: ${column.isNullable ? "true" : "false"}`).join(",\n");
|
|
1711
|
+
const relationEntries = Object.entries(descriptor.table.relations);
|
|
1712
|
+
const relationBlock = config.features.emitRelations && relationEntries.length > 0 ? `,
|
|
1713
|
+
relations: {
|
|
1714
|
+
${relationEntries.map(([relationKey2, relationValue]) => ` ${renderObjectKey(relationKey2)}: ${renderRelationLiteral(relationValue)}`).join(",\n")}
|
|
1715
|
+
}` : "";
|
|
1716
|
+
const content = `import { defineModel } from '@xylex-group/athena'
|
|
1717
|
+
|
|
1718
|
+
export interface ${descriptor.rowTypeName} {
|
|
1719
|
+
${columnLines}
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
export type ${descriptor.insertTypeName} = Partial<${descriptor.rowTypeName}>
|
|
1723
|
+
export type ${descriptor.updateTypeName} = Partial<${descriptor.insertTypeName}>
|
|
1724
|
+
|
|
1725
|
+
export const ${descriptor.modelConstName} = defineModel<${descriptor.rowTypeName}, ${descriptor.insertTypeName}, ${descriptor.updateTypeName}>({
|
|
1726
|
+
meta: {
|
|
1727
|
+
database: ${escapeStringLiteral(databaseName)},
|
|
1728
|
+
schema: ${escapeStringLiteral(descriptor.schemaName)},
|
|
1729
|
+
model: ${escapeStringLiteral(descriptor.tableName)},
|
|
1730
|
+
tableName: ${escapeStringLiteral(`${descriptor.schemaName}.${descriptor.tableName}`)},
|
|
1731
|
+
primaryKey: [${descriptor.table.primaryKey.map((value) => escapeStringLiteral(value)).join(", ")}],
|
|
1732
|
+
nullable: {
|
|
1733
|
+
${nullableLines}
|
|
1734
|
+
}${relationBlock}
|
|
1735
|
+
}
|
|
1736
|
+
})
|
|
1737
|
+
`;
|
|
1738
|
+
return {
|
|
1739
|
+
kind: "model",
|
|
1740
|
+
path: descriptor.filePath,
|
|
1741
|
+
content
|
|
1742
|
+
};
|
|
1743
|
+
}
|
|
1744
|
+
function generateArtifactsFromSnapshot(snapshot, config) {
|
|
1745
|
+
const normalizedConfig = "internal" in config ? config : normalizeGeneratorConfig(config);
|
|
1746
|
+
if (normalizedConfig.output.format === "table-builder") {
|
|
1747
|
+
return generateTableBuilderArtifactsFromSnapshot(snapshot, normalizedConfig);
|
|
1748
|
+
}
|
|
1749
|
+
return composeGeneratorArtifacts({
|
|
1750
|
+
snapshot,
|
|
1751
|
+
config: normalizedConfig,
|
|
1752
|
+
createModelDescriptor({ providerName, databaseName, schemaName, tableName, table }) {
|
|
1753
|
+
const modelConstName = toSafeIdentifier(
|
|
1754
|
+
`${schemaName} ${tableName} model`,
|
|
1755
|
+
normalizedConfig.naming.modelConst,
|
|
1756
|
+
"model"
|
|
1757
|
+
);
|
|
1758
|
+
return {
|
|
1759
|
+
schemaName,
|
|
1760
|
+
tableName,
|
|
1761
|
+
filePath: resolveOutputPath(
|
|
1762
|
+
normalizedConfig.output.targets.model,
|
|
1763
|
+
{
|
|
1312
1764
|
provider: providerName,
|
|
1313
1765
|
kind: "model",
|
|
1314
1766
|
database: databaseName,
|
|
1315
1767
|
schema: schemaName,
|
|
1316
1768
|
model: tableName
|
|
1317
|
-
},
|
|
1318
|
-
|
|
1319
|
-
modelDescriptors.push({
|
|
1320
|
-
schemaName,
|
|
1321
|
-
tableName,
|
|
1322
|
-
filePath: modelPath,
|
|
1323
|
-
rowTypeName,
|
|
1324
|
-
insertTypeName,
|
|
1325
|
-
updateTypeName,
|
|
1326
|
-
modelConstName,
|
|
1327
|
-
table
|
|
1328
|
-
});
|
|
1329
|
-
}
|
|
1330
|
-
}
|
|
1331
|
-
const scopedModelDescriptors = scopeDuplicateDescriptorPathsBySchema(modelDescriptors);
|
|
1332
|
-
let schemaDescriptors = Object.keys(this.snapshot.schemas).sort().map((schemaName) => {
|
|
1333
|
-
const schemaPath = normalizePath(
|
|
1334
|
-
renderOutputPath(this.config.output.targets.schema, {
|
|
1335
|
-
provider: providerName,
|
|
1336
|
-
kind: "schema",
|
|
1337
|
-
database: databaseName,
|
|
1338
|
-
schema: schemaName,
|
|
1339
|
-
model: "index"
|
|
1340
|
-
}, this.config.output)
|
|
1341
|
-
);
|
|
1342
|
-
return {
|
|
1343
|
-
schemaName,
|
|
1344
|
-
filePath: schemaPath,
|
|
1345
|
-
schemaConstName: toSafeIdentifier(
|
|
1346
|
-
`${schemaName} schema`,
|
|
1347
|
-
this.config.naming.schemaConst,
|
|
1348
|
-
"schema"
|
|
1769
|
+
},
|
|
1770
|
+
normalizedConfig
|
|
1349
1771
|
),
|
|
1350
|
-
|
|
1772
|
+
rowTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}Row`,
|
|
1773
|
+
insertTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}Insert`,
|
|
1774
|
+
updateTypeName: `${toSafeIdentifier(`${schemaName} ${tableName}`, normalizedConfig.naming.modelType, "Model")}Update`,
|
|
1775
|
+
modelConstName,
|
|
1776
|
+
exportConstName: modelConstName,
|
|
1777
|
+
table
|
|
1351
1778
|
};
|
|
1352
|
-
}
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
renderOutputPath(this.config.output.targets.database, {
|
|
1356
|
-
provider: providerName,
|
|
1357
|
-
kind: "database",
|
|
1358
|
-
database: databaseName,
|
|
1359
|
-
schema: "index",
|
|
1360
|
-
model: "index"
|
|
1361
|
-
}, this.config.output)
|
|
1362
|
-
);
|
|
1363
|
-
const databaseDescriptor = {
|
|
1364
|
-
filePath: databasePath,
|
|
1365
|
-
databaseConstName: toSafeIdentifier(
|
|
1366
|
-
`${databaseName} database`,
|
|
1367
|
-
this.config.naming.databaseConst,
|
|
1368
|
-
"database"
|
|
1369
|
-
),
|
|
1370
|
-
schemas: schemaDescriptors
|
|
1371
|
-
};
|
|
1372
|
-
const files = [];
|
|
1373
|
-
for (const modelDescriptor of scopedModelDescriptors) {
|
|
1374
|
-
files.push(renderModelArtifact(this.snapshot, modelDescriptor, this.config));
|
|
1375
|
-
}
|
|
1376
|
-
for (const schemaDescriptor of schemaDescriptors) {
|
|
1377
|
-
files.push(renderSchemaArtifact(schemaDescriptor));
|
|
1378
|
-
}
|
|
1379
|
-
files.push(renderDatabaseArtifact(databaseDescriptor));
|
|
1380
|
-
if (this.config.features.emitRegistry) {
|
|
1381
|
-
const registryPath = normalizePath(
|
|
1382
|
-
renderOutputPath(this.config.output.targets.registry, {
|
|
1383
|
-
provider: providerName,
|
|
1384
|
-
kind: "registry",
|
|
1385
|
-
database: databaseName,
|
|
1386
|
-
schema: "index",
|
|
1387
|
-
model: "index"
|
|
1388
|
-
}, this.config.output)
|
|
1389
|
-
);
|
|
1390
|
-
files.push(
|
|
1391
|
-
renderRegistryArtifact(
|
|
1392
|
-
registryPath,
|
|
1393
|
-
databaseDescriptor.filePath,
|
|
1394
|
-
databaseDescriptor.databaseConstName,
|
|
1395
|
-
toSafeIdentifier("registry", this.config.naming.registryConst, "registry"),
|
|
1396
|
-
databaseName
|
|
1397
|
-
)
|
|
1398
|
-
);
|
|
1399
|
-
}
|
|
1400
|
-
assertNoDuplicatePaths(files);
|
|
1401
|
-
return {
|
|
1402
|
-
snapshot: this.snapshot,
|
|
1403
|
-
files
|
|
1404
|
-
};
|
|
1405
|
-
}
|
|
1406
|
-
};
|
|
1407
|
-
function generateArtifactsFromSnapshot(snapshot, config) {
|
|
1408
|
-
const normalizedConfig = "naming" in config && "features" in config && "experimental" in config ? config : normalizeGeneratorConfig(config);
|
|
1409
|
-
return new ArtifactComposer(snapshot, normalizedConfig).compose();
|
|
1779
|
+
},
|
|
1780
|
+
renderModelArtifact: (descriptor) => renderModelArtifact2(snapshot.database, descriptor, normalizedConfig)
|
|
1781
|
+
});
|
|
1410
1782
|
}
|
|
1411
1783
|
|
|
1412
1784
|
// src/gateway/url.ts
|
|
@@ -1511,7 +1883,7 @@ var getSessionCookie = (request, config) => {
|
|
|
1511
1883
|
|
|
1512
1884
|
// package.json
|
|
1513
1885
|
var package_default = {
|
|
1514
|
-
version: "2.
|
|
1886
|
+
version: "2.8.0"
|
|
1515
1887
|
};
|
|
1516
1888
|
|
|
1517
1889
|
// src/sdk-version.ts
|
|
@@ -3458,11 +3830,12 @@ function createAuthClient(config = {}) {
|
|
|
3458
3830
|
// src/db/module.ts
|
|
3459
3831
|
function createDbModule(input) {
|
|
3460
3832
|
const db = {
|
|
3461
|
-
from
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3833
|
+
from: input.from,
|
|
3834
|
+
select(table, first, second) {
|
|
3835
|
+
if (first && typeof first === "object" && !Array.isArray(first)) {
|
|
3836
|
+
return input.from(table).select(void 0, first);
|
|
3837
|
+
}
|
|
3838
|
+
return input.from(table).select(first, second);
|
|
3466
3839
|
},
|
|
3467
3840
|
insert(table, values, options) {
|
|
3468
3841
|
return Array.isArray(values) ? input.from(table).insert(values, options) : input.from(table).insert(values, options);
|
|
@@ -4129,6 +4502,15 @@ function appendQuery(path, query) {
|
|
|
4129
4502
|
function storagePath(path) {
|
|
4130
4503
|
return path;
|
|
4131
4504
|
}
|
|
4505
|
+
function resolveStorageEndpointPath(endpoint, runtimeOptions) {
|
|
4506
|
+
if (!runtimeOptions?.stripBasePath) {
|
|
4507
|
+
return endpoint;
|
|
4508
|
+
}
|
|
4509
|
+
const [pathname, queryText] = String(endpoint).split("?", 2);
|
|
4510
|
+
const trimmedPathname = pathname.startsWith("/storage/") ? pathname.slice("/storage".length) : pathname === "/storage" ? "/" : pathname;
|
|
4511
|
+
const resolvedPath = trimmedPathname.startsWith("/") ? trimmedPathname : `/${trimmedPathname}`;
|
|
4512
|
+
return storagePath(queryText ? `${resolvedPath}?${queryText}` : resolvedPath);
|
|
4513
|
+
}
|
|
4132
4514
|
function withPathParam(path, name, value) {
|
|
4133
4515
|
return path.replace(`{${name}}`, encodeURIComponent(value));
|
|
4134
4516
|
}
|
|
@@ -4167,8 +4549,8 @@ async function callStorageEndpoint(gateway, endpoint, method, envelope, payload,
|
|
|
4167
4549
|
let url;
|
|
4168
4550
|
let headers;
|
|
4169
4551
|
try {
|
|
4170
|
-
const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : gateway.baseUrl;
|
|
4171
|
-
url = buildAthenaGatewayUrl(baseUrl, endpoint);
|
|
4552
|
+
const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : runtimeOptions?.baseUrl ? normalizeAthenaGatewayBaseUrl(runtimeOptions.baseUrl) : gateway.baseUrl;
|
|
4553
|
+
url = buildAthenaGatewayUrl(baseUrl, resolveStorageEndpointPath(endpoint, runtimeOptions));
|
|
4172
4554
|
headers = gateway.buildHeaders(options);
|
|
4173
4555
|
} catch (error) {
|
|
4174
4556
|
return rejectStorageError(
|
|
@@ -4292,8 +4674,8 @@ async function callStorageBinaryEndpoint(gateway, endpoint, method, options, run
|
|
|
4292
4674
|
let url;
|
|
4293
4675
|
let headers;
|
|
4294
4676
|
try {
|
|
4295
|
-
const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : gateway.baseUrl;
|
|
4296
|
-
url = buildAthenaGatewayUrl(baseUrl, endpoint);
|
|
4677
|
+
const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : runtimeOptions?.baseUrl ? normalizeAthenaGatewayBaseUrl(runtimeOptions.baseUrl) : gateway.baseUrl;
|
|
4678
|
+
url = buildAthenaGatewayUrl(baseUrl, resolveStorageEndpointPath(endpoint, runtimeOptions));
|
|
4297
4679
|
headers = gateway.buildHeaders(options);
|
|
4298
4680
|
} catch (error) {
|
|
4299
4681
|
return rejectStorageError(
|
|
@@ -4454,8 +4836,8 @@ async function callStorageUploadBinaryEndpoint(gateway, endpoint, body, options,
|
|
|
4454
4836
|
let url;
|
|
4455
4837
|
let headers;
|
|
4456
4838
|
try {
|
|
4457
|
-
const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : gateway.baseUrl;
|
|
4458
|
-
url = buildAthenaGatewayUrl(baseUrl, endpoint);
|
|
4839
|
+
const baseUrl = options?.baseUrl ? normalizeAthenaGatewayBaseUrl(options.baseUrl) : runtimeOptions?.baseUrl ? normalizeAthenaGatewayBaseUrl(runtimeOptions.baseUrl) : gateway.baseUrl;
|
|
4840
|
+
url = buildAthenaGatewayUrl(baseUrl, resolveStorageEndpointPath(endpoint, runtimeOptions));
|
|
4459
4841
|
headers = gateway.buildHeaders(options);
|
|
4460
4842
|
} catch (error) {
|
|
4461
4843
|
return rejectStorageError(
|
|
@@ -4579,6 +4961,7 @@ async function callStorageUploadBinaryEndpoint(gateway, endpoint, body, options,
|
|
|
4579
4961
|
return parsedBody.parsed.data;
|
|
4580
4962
|
}
|
|
4581
4963
|
function createStorageModule(gateway, runtimeOptions) {
|
|
4964
|
+
const resolvedRuntimeOptions = runtimeOptions;
|
|
4582
4965
|
const callRaw = (path, method, payload, options) => callStorageEndpoint(
|
|
4583
4966
|
gateway,
|
|
4584
4967
|
storagePath(path),
|
|
@@ -4586,7 +4969,7 @@ function createStorageModule(gateway, runtimeOptions) {
|
|
|
4586
4969
|
"raw",
|
|
4587
4970
|
payload,
|
|
4588
4971
|
options,
|
|
4589
|
-
|
|
4972
|
+
resolvedRuntimeOptions
|
|
4590
4973
|
);
|
|
4591
4974
|
const callAthena2 = (path, method, payload, options) => callStorageEndpoint(
|
|
4592
4975
|
gateway,
|
|
@@ -4595,7 +4978,7 @@ function createStorageModule(gateway, runtimeOptions) {
|
|
|
4595
4978
|
"athena",
|
|
4596
4979
|
payload,
|
|
4597
4980
|
options,
|
|
4598
|
-
|
|
4981
|
+
resolvedRuntimeOptions
|
|
4599
4982
|
);
|
|
4600
4983
|
const base = {
|
|
4601
4984
|
listStorageCatalogs(options) {
|
|
@@ -4637,7 +5020,7 @@ function createStorageModule(gateway, runtimeOptions) {
|
|
|
4637
5020
|
withPathParam("/storage/files/{file_id}/proxy", "file_id", fileId),
|
|
4638
5021
|
query
|
|
4639
5022
|
);
|
|
4640
|
-
return callStorageBinaryEndpoint(gateway, storagePath(path), "GET", options,
|
|
5023
|
+
return callStorageBinaryEndpoint(gateway, storagePath(path), "GET", options, resolvedRuntimeOptions);
|
|
4641
5024
|
},
|
|
4642
5025
|
updateStorageFile(fileId, input, options) {
|
|
4643
5026
|
return callAthena2(withPathParam("/storage/files/{file_id}", "file_id", fileId), "PATCH", input, options);
|
|
@@ -4684,7 +5067,7 @@ function createStorageModule(gateway, runtimeOptions) {
|
|
|
4684
5067
|
storagePath(withPathParam("/storage/files/{file_id}/upload", "file_id", fileId)),
|
|
4685
5068
|
body,
|
|
4686
5069
|
options,
|
|
4687
|
-
|
|
5070
|
+
resolvedRuntimeOptions
|
|
4688
5071
|
);
|
|
4689
5072
|
},
|
|
4690
5073
|
search(input, options) {
|
|
@@ -4880,6 +5263,13 @@ function createStorageModule(gateway, runtimeOptions) {
|
|
|
4880
5263
|
};
|
|
4881
5264
|
}
|
|
4882
5265
|
|
|
5266
|
+
// src/client-builder.ts
|
|
5267
|
+
var DEFAULT_BACKEND = { type: "athena" };
|
|
5268
|
+
function toBackendConfig(value) {
|
|
5269
|
+
if (!value) return DEFAULT_BACKEND;
|
|
5270
|
+
return typeof value === "string" ? { type: value } : value;
|
|
5271
|
+
}
|
|
5272
|
+
|
|
4883
5273
|
// src/query-ast.ts
|
|
4884
5274
|
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;
|
|
4885
5275
|
var FILTER_OPERATORS = /* @__PURE__ */ new Set([
|
|
@@ -5502,20 +5892,437 @@ function createSelectTransportPlan(input) {
|
|
|
5502
5892
|
};
|
|
5503
5893
|
}
|
|
5504
5894
|
|
|
5895
|
+
// src/query-debug-ast.ts
|
|
5896
|
+
var ATHENA_DEBUG_AST_KEY = "__athenaDebugAst";
|
|
5897
|
+
function cloneConditions(conditions) {
|
|
5898
|
+
return conditions.map((condition) => ({ ...condition }));
|
|
5899
|
+
}
|
|
5900
|
+
function cloneTableBuilderStateAst(state) {
|
|
5901
|
+
return {
|
|
5902
|
+
conditions: cloneConditions(state.conditions),
|
|
5903
|
+
limit: state.limit,
|
|
5904
|
+
offset: state.offset,
|
|
5905
|
+
order: state.order ? { ...state.order } : void 0,
|
|
5906
|
+
currentPage: state.currentPage,
|
|
5907
|
+
pageSize: state.pageSize,
|
|
5908
|
+
totalPages: state.totalPages
|
|
5909
|
+
};
|
|
5910
|
+
}
|
|
5911
|
+
function cloneRpcBuilderStateAst(state) {
|
|
5912
|
+
return {
|
|
5913
|
+
filters: state.filters.map((filter) => ({ ...filter })),
|
|
5914
|
+
limit: state.limit,
|
|
5915
|
+
offset: state.offset,
|
|
5916
|
+
order: state.order ? { ...state.order } : void 0
|
|
5917
|
+
};
|
|
5918
|
+
}
|
|
5919
|
+
function toSelectTransportAst(plan) {
|
|
5920
|
+
if (plan.kind === "query") {
|
|
5921
|
+
return {
|
|
5922
|
+
mode: "typed-query",
|
|
5923
|
+
endpoint: "/gateway/query",
|
|
5924
|
+
payload: plan.payload
|
|
5925
|
+
};
|
|
5926
|
+
}
|
|
5927
|
+
return {
|
|
5928
|
+
mode: plan.payload.select !== void 0 ? "structured-fetch" : "compiled-fetch",
|
|
5929
|
+
endpoint: "/gateway/fetch",
|
|
5930
|
+
payload: plan.payload
|
|
5931
|
+
};
|
|
5932
|
+
}
|
|
5933
|
+
function resolveDebugTableName(tableName) {
|
|
5934
|
+
return tableName ?? "__unknown_table__";
|
|
5935
|
+
}
|
|
5936
|
+
function buildSelectDebugAst(input) {
|
|
5937
|
+
return {
|
|
5938
|
+
version: 1,
|
|
5939
|
+
kind: "select",
|
|
5940
|
+
tableName: input.tableName,
|
|
5941
|
+
input: {
|
|
5942
|
+
columns: input.columns,
|
|
5943
|
+
state: cloneTableBuilderStateAst(input.state)
|
|
5944
|
+
},
|
|
5945
|
+
transport: toSelectTransportAst(input.plan)
|
|
5946
|
+
};
|
|
5947
|
+
}
|
|
5948
|
+
function buildFindManyCompiledDebugAst(input) {
|
|
5949
|
+
return {
|
|
5950
|
+
version: 1,
|
|
5951
|
+
kind: "findMany",
|
|
5952
|
+
tableName: input.tableName,
|
|
5953
|
+
input: {
|
|
5954
|
+
select: input.options.select,
|
|
5955
|
+
where: input.options.where,
|
|
5956
|
+
orderBy: input.options.orderBy,
|
|
5957
|
+
limit: input.options.limit
|
|
5958
|
+
},
|
|
5959
|
+
compiled: {
|
|
5960
|
+
columns: input.compiledColumns,
|
|
5961
|
+
baseState: cloneTableBuilderStateAst(input.baseState),
|
|
5962
|
+
executionState: cloneTableBuilderStateAst(input.executionState)
|
|
5963
|
+
},
|
|
5964
|
+
transport: planToFindManyTransport(input.plan)
|
|
5965
|
+
};
|
|
5966
|
+
}
|
|
5967
|
+
function buildFindManyDirectDebugAst(input) {
|
|
5968
|
+
return {
|
|
5969
|
+
version: 1,
|
|
5970
|
+
kind: "findMany",
|
|
5971
|
+
tableName: input.tableName,
|
|
5972
|
+
input: {
|
|
5973
|
+
select: input.options.select,
|
|
5974
|
+
where: input.options.where,
|
|
5975
|
+
orderBy: input.options.orderBy,
|
|
5976
|
+
limit: input.options.limit
|
|
5977
|
+
},
|
|
5978
|
+
compiled: {
|
|
5979
|
+
columns: input.compiledColumns,
|
|
5980
|
+
baseState: cloneTableBuilderStateAst(input.baseState),
|
|
5981
|
+
executionState: cloneTableBuilderStateAst(input.executionState)
|
|
5982
|
+
},
|
|
5983
|
+
transport: {
|
|
5984
|
+
mode: "direct-ast-fetch",
|
|
5985
|
+
endpoint: "/gateway/fetch",
|
|
5986
|
+
payload: input.payload
|
|
5987
|
+
}
|
|
5988
|
+
};
|
|
5989
|
+
}
|
|
5990
|
+
function planToFindManyTransport(plan) {
|
|
5991
|
+
if (plan.kind === "query") {
|
|
5992
|
+
return {
|
|
5993
|
+
mode: "compiled-query",
|
|
5994
|
+
endpoint: "/gateway/query",
|
|
5995
|
+
payload: plan.payload
|
|
5996
|
+
};
|
|
5997
|
+
}
|
|
5998
|
+
return {
|
|
5999
|
+
mode: plan.payload.select !== void 0 ? "structured-fetch" : "compiled-fetch",
|
|
6000
|
+
endpoint: "/gateway/fetch",
|
|
6001
|
+
payload: plan.payload
|
|
6002
|
+
};
|
|
6003
|
+
}
|
|
6004
|
+
function buildInsertDebugAst(payload) {
|
|
6005
|
+
return {
|
|
6006
|
+
version: 1,
|
|
6007
|
+
kind: "insert",
|
|
6008
|
+
tableName: payload.table_name,
|
|
6009
|
+
input: {
|
|
6010
|
+
values: payload.insert_body,
|
|
6011
|
+
returning: payload.columns,
|
|
6012
|
+
count: payload.count,
|
|
6013
|
+
head: payload.head,
|
|
6014
|
+
defaultToNull: payload.default_to_null
|
|
6015
|
+
},
|
|
6016
|
+
transport: {
|
|
6017
|
+
mode: "insert",
|
|
6018
|
+
endpoint: "/gateway/insert",
|
|
6019
|
+
payload
|
|
6020
|
+
}
|
|
6021
|
+
};
|
|
6022
|
+
}
|
|
6023
|
+
function buildUpsertDebugAst(payload) {
|
|
6024
|
+
return {
|
|
6025
|
+
version: 1,
|
|
6026
|
+
kind: "upsert",
|
|
6027
|
+
tableName: payload.table_name,
|
|
6028
|
+
input: {
|
|
6029
|
+
values: payload.insert_body,
|
|
6030
|
+
updateBody: payload.update_body,
|
|
6031
|
+
onConflict: payload.on_conflict,
|
|
6032
|
+
returning: payload.columns,
|
|
6033
|
+
count: payload.count,
|
|
6034
|
+
head: payload.head,
|
|
6035
|
+
defaultToNull: payload.default_to_null
|
|
6036
|
+
},
|
|
6037
|
+
transport: {
|
|
6038
|
+
mode: "upsert",
|
|
6039
|
+
endpoint: "/gateway/insert",
|
|
6040
|
+
payload
|
|
6041
|
+
}
|
|
6042
|
+
};
|
|
6043
|
+
}
|
|
6044
|
+
function buildUpdateDebugAst(input) {
|
|
6045
|
+
return {
|
|
6046
|
+
version: 1,
|
|
6047
|
+
kind: "update",
|
|
6048
|
+
tableName: resolveDebugTableName(input.payload.table_name),
|
|
6049
|
+
input: {
|
|
6050
|
+
values: input.payload.set,
|
|
6051
|
+
state: cloneTableBuilderStateAst(input.state),
|
|
6052
|
+
returning: input.payload.columns
|
|
6053
|
+
},
|
|
6054
|
+
transport: {
|
|
6055
|
+
mode: "update",
|
|
6056
|
+
endpoint: "/gateway/update",
|
|
6057
|
+
payload: input.payload
|
|
6058
|
+
}
|
|
6059
|
+
};
|
|
6060
|
+
}
|
|
6061
|
+
function buildDeleteDebugAst(input) {
|
|
6062
|
+
return {
|
|
6063
|
+
version: 1,
|
|
6064
|
+
kind: "delete",
|
|
6065
|
+
tableName: input.payload.table_name,
|
|
6066
|
+
input: {
|
|
6067
|
+
resourceId: input.payload.resource_id,
|
|
6068
|
+
state: cloneTableBuilderStateAst(input.state),
|
|
6069
|
+
returning: input.payload.columns
|
|
6070
|
+
},
|
|
6071
|
+
transport: {
|
|
6072
|
+
mode: "delete",
|
|
6073
|
+
endpoint: "/gateway/delete",
|
|
6074
|
+
payload: input.payload
|
|
6075
|
+
}
|
|
6076
|
+
};
|
|
6077
|
+
}
|
|
6078
|
+
function buildRpcDebugAst(input) {
|
|
6079
|
+
return {
|
|
6080
|
+
version: 1,
|
|
6081
|
+
kind: "rpc",
|
|
6082
|
+
functionName: input.functionName,
|
|
6083
|
+
input: {
|
|
6084
|
+
args: input.args,
|
|
6085
|
+
select: input.selectedColumns,
|
|
6086
|
+
state: cloneRpcBuilderStateAst(input.state)
|
|
6087
|
+
},
|
|
6088
|
+
transport: {
|
|
6089
|
+
mode: input.endpoint === "/gateway/rpc" ? "rpc-post" : "rpc-get",
|
|
6090
|
+
endpoint: input.endpoint,
|
|
6091
|
+
payload: input.payload
|
|
6092
|
+
}
|
|
6093
|
+
};
|
|
6094
|
+
}
|
|
6095
|
+
function buildRawQueryDebugAst(query) {
|
|
6096
|
+
return {
|
|
6097
|
+
version: 1,
|
|
6098
|
+
kind: "query",
|
|
6099
|
+
input: {
|
|
6100
|
+
query
|
|
6101
|
+
},
|
|
6102
|
+
transport: {
|
|
6103
|
+
mode: "raw-query",
|
|
6104
|
+
endpoint: "/gateway/query",
|
|
6105
|
+
payload: {
|
|
6106
|
+
query
|
|
6107
|
+
}
|
|
6108
|
+
}
|
|
6109
|
+
};
|
|
6110
|
+
}
|
|
6111
|
+
function attachAthenaDebugAst(target, ast) {
|
|
6112
|
+
if (!ast) {
|
|
6113
|
+
return;
|
|
6114
|
+
}
|
|
6115
|
+
if (!target || typeof target !== "object" && typeof target !== "function") {
|
|
6116
|
+
return;
|
|
6117
|
+
}
|
|
6118
|
+
Object.defineProperty(target, ATHENA_DEBUG_AST_KEY, {
|
|
6119
|
+
value: ast,
|
|
6120
|
+
enumerable: false,
|
|
6121
|
+
configurable: true,
|
|
6122
|
+
writable: false
|
|
6123
|
+
});
|
|
6124
|
+
}
|
|
6125
|
+
|
|
6126
|
+
// src/query-tracing.ts
|
|
6127
|
+
var QUERY_TRACE_STACK_SKIP_PATTERNS = [
|
|
6128
|
+
"src\\client.ts",
|
|
6129
|
+
"src/client.ts",
|
|
6130
|
+
"src\\query-tracing.ts",
|
|
6131
|
+
"src/query-tracing.ts",
|
|
6132
|
+
"dist\\client.",
|
|
6133
|
+
"dist/client.",
|
|
6134
|
+
"dist\\query-tracing.",
|
|
6135
|
+
"dist/query-tracing.",
|
|
6136
|
+
"node_modules\\@xylex-group\\athena",
|
|
6137
|
+
"node_modules/@xylex-group/athena",
|
|
6138
|
+
"node:internal",
|
|
6139
|
+
"internal/process"
|
|
6140
|
+
];
|
|
6141
|
+
function parseQueryTraceCallsiteFrame(frame) {
|
|
6142
|
+
const trimmed = frame.trim();
|
|
6143
|
+
if (!trimmed) {
|
|
6144
|
+
return null;
|
|
6145
|
+
}
|
|
6146
|
+
let body = trimmed.replace(/^at\s+/, "");
|
|
6147
|
+
if (body.startsWith("async ")) {
|
|
6148
|
+
body = body.slice(6);
|
|
6149
|
+
}
|
|
6150
|
+
let functionName;
|
|
6151
|
+
let location = body;
|
|
6152
|
+
const wrappedMatch = body.match(/^(.*?)\s+\((.*)\)$/);
|
|
6153
|
+
if (wrappedMatch) {
|
|
6154
|
+
functionName = wrappedMatch[1].trim() || void 0;
|
|
6155
|
+
location = wrappedMatch[2].trim();
|
|
6156
|
+
}
|
|
6157
|
+
const locationMatch = location.match(/^(.*):(\d+):(\d+)$/);
|
|
6158
|
+
if (!locationMatch) {
|
|
6159
|
+
return null;
|
|
6160
|
+
}
|
|
6161
|
+
const filePath = locationMatch[1].replace(/^file:\/\//, "");
|
|
6162
|
+
const line = Number(locationMatch[2]);
|
|
6163
|
+
const column = Number(locationMatch[3]);
|
|
6164
|
+
if (!Number.isFinite(line) || !Number.isFinite(column)) {
|
|
6165
|
+
return null;
|
|
6166
|
+
}
|
|
6167
|
+
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
6168
|
+
const fileName = normalizedPath.split("/").at(-1) ?? filePath;
|
|
6169
|
+
return {
|
|
6170
|
+
filePath,
|
|
6171
|
+
fileName,
|
|
6172
|
+
line,
|
|
6173
|
+
column,
|
|
6174
|
+
frame: trimmed,
|
|
6175
|
+
functionName
|
|
6176
|
+
};
|
|
6177
|
+
}
|
|
6178
|
+
function captureQueryTraceCallsite() {
|
|
6179
|
+
const stack = new Error().stack;
|
|
6180
|
+
if (!stack) return null;
|
|
6181
|
+
const frames = stack.split("\n").slice(2).map((frame) => frame.trim()).filter(Boolean);
|
|
6182
|
+
for (const frame of frames) {
|
|
6183
|
+
if (QUERY_TRACE_STACK_SKIP_PATTERNS.some((pattern) => frame.includes(pattern))) {
|
|
6184
|
+
continue;
|
|
6185
|
+
}
|
|
6186
|
+
const callsite = parseQueryTraceCallsiteFrame(frame);
|
|
6187
|
+
if (callsite) return callsite;
|
|
6188
|
+
}
|
|
6189
|
+
const fallback = frames.find((frame) => !frame.includes("captureQueryTraceCallsite"));
|
|
6190
|
+
return fallback ? parseQueryTraceCallsiteFrame(fallback) : null;
|
|
6191
|
+
}
|
|
6192
|
+
function defaultQueryTraceLogger(event) {
|
|
6193
|
+
const target = event.table ?? event.functionName ?? "gateway";
|
|
6194
|
+
const outcomeState = event.outcome?.error ? "error" : "ok";
|
|
6195
|
+
const banner = `[athena-js][trace] ${event.operation.toUpperCase()} ${event.endpoint} ${target} ${event.durationMs}ms ${outcomeState}`;
|
|
6196
|
+
console.info(banner, event);
|
|
6197
|
+
}
|
|
6198
|
+
function captureTraceCallsite(tracer) {
|
|
6199
|
+
return tracer?.captureCallsite() ?? null;
|
|
6200
|
+
}
|
|
6201
|
+
function createTraceCallsiteStore(tracer, initialCallsite) {
|
|
6202
|
+
let storedCallsite = initialCallsite ?? void 0;
|
|
6203
|
+
return {
|
|
6204
|
+
resolve(callsite) {
|
|
6205
|
+
if (callsite) {
|
|
6206
|
+
storedCallsite = callsite;
|
|
6207
|
+
return callsite;
|
|
6208
|
+
}
|
|
6209
|
+
if (storedCallsite !== void 0) {
|
|
6210
|
+
return storedCallsite;
|
|
6211
|
+
}
|
|
6212
|
+
const capturedCallsite = captureTraceCallsite(tracer);
|
|
6213
|
+
if (capturedCallsite) {
|
|
6214
|
+
storedCallsite = capturedCallsite;
|
|
6215
|
+
}
|
|
6216
|
+
return capturedCallsite;
|
|
6217
|
+
}
|
|
6218
|
+
};
|
|
6219
|
+
}
|
|
6220
|
+
function createQueryTracer(experimental) {
|
|
6221
|
+
const traceOption = experimental?.traceQueries;
|
|
6222
|
+
if (!traceOption) {
|
|
6223
|
+
return void 0;
|
|
6224
|
+
}
|
|
6225
|
+
const logger = typeof traceOption === "object" && traceOption.logger ? traceOption.logger : defaultQueryTraceLogger;
|
|
6226
|
+
const emit = (event) => {
|
|
6227
|
+
try {
|
|
6228
|
+
logger(event);
|
|
6229
|
+
} catch (error) {
|
|
6230
|
+
console.warn("[athena-js][trace] logger failed", error);
|
|
6231
|
+
}
|
|
6232
|
+
};
|
|
6233
|
+
return {
|
|
6234
|
+
captureCallsite: captureQueryTraceCallsite,
|
|
6235
|
+
publishSuccess(context, result, durationMs, callsite) {
|
|
6236
|
+
emit({
|
|
6237
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6238
|
+
durationMs,
|
|
6239
|
+
operation: context.operation,
|
|
6240
|
+
endpoint: context.endpoint,
|
|
6241
|
+
table: context.table,
|
|
6242
|
+
functionName: context.functionName,
|
|
6243
|
+
sql: context.sql,
|
|
6244
|
+
payload: context.payload,
|
|
6245
|
+
ast: context.ast,
|
|
6246
|
+
options: context.options,
|
|
6247
|
+
callsite,
|
|
6248
|
+
outcome: {
|
|
6249
|
+
status: result.status,
|
|
6250
|
+
error: result.error,
|
|
6251
|
+
errorDetails: result.errorDetails ?? null,
|
|
6252
|
+
count: result.count ?? null,
|
|
6253
|
+
data: result.data,
|
|
6254
|
+
raw: result.raw
|
|
6255
|
+
}
|
|
6256
|
+
});
|
|
6257
|
+
},
|
|
6258
|
+
publishFailure(context, error, durationMs, callsite) {
|
|
6259
|
+
emit({
|
|
6260
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6261
|
+
durationMs,
|
|
6262
|
+
operation: context.operation,
|
|
6263
|
+
endpoint: context.endpoint,
|
|
6264
|
+
table: context.table,
|
|
6265
|
+
functionName: context.functionName,
|
|
6266
|
+
sql: context.sql,
|
|
6267
|
+
payload: context.payload,
|
|
6268
|
+
ast: context.ast,
|
|
6269
|
+
options: context.options,
|
|
6270
|
+
callsite,
|
|
6271
|
+
thrownError: error
|
|
6272
|
+
});
|
|
6273
|
+
}
|
|
6274
|
+
};
|
|
6275
|
+
}
|
|
6276
|
+
async function executeWithQueryTrace(tracer, context, runner, callsiteOverride) {
|
|
6277
|
+
const callsite = tracer ? callsiteOverride ?? tracer.captureCallsite() : null;
|
|
6278
|
+
const startedAt = tracer ? Date.now() : 0;
|
|
6279
|
+
try {
|
|
6280
|
+
const result = await runner();
|
|
6281
|
+
attachAthenaDebugAst(result, context.ast);
|
|
6282
|
+
if (tracer) {
|
|
6283
|
+
tracer.publishSuccess(context, result, Date.now() - startedAt, callsite);
|
|
6284
|
+
}
|
|
6285
|
+
return result;
|
|
6286
|
+
} catch (error) {
|
|
6287
|
+
attachAthenaDebugAst(error, context.ast);
|
|
6288
|
+
if (tracer) {
|
|
6289
|
+
tracer.publishFailure(context, error, Date.now() - startedAt, callsite);
|
|
6290
|
+
}
|
|
6291
|
+
throw error;
|
|
6292
|
+
}
|
|
6293
|
+
}
|
|
6294
|
+
|
|
6295
|
+
// src/schema/model-target.ts
|
|
6296
|
+
function normalizeOptionalName(value) {
|
|
6297
|
+
const normalized = value?.trim();
|
|
6298
|
+
return normalized ? normalized : void 0;
|
|
6299
|
+
}
|
|
6300
|
+
function isAthenaModelTarget(value) {
|
|
6301
|
+
if (!value || typeof value !== "object") {
|
|
6302
|
+
return false;
|
|
6303
|
+
}
|
|
6304
|
+
const candidate = value;
|
|
6305
|
+
return Boolean(candidate.meta && Array.isArray(candidate.meta.primaryKey));
|
|
6306
|
+
}
|
|
6307
|
+
function resolveAthenaModelTargetTableName(target, options = {}) {
|
|
6308
|
+
const explicitTableName = normalizeOptionalName(target.meta.tableName);
|
|
6309
|
+
if (explicitTableName) {
|
|
6310
|
+
return explicitTableName;
|
|
6311
|
+
}
|
|
6312
|
+
const schemaName = normalizeOptionalName(target.meta.schema ?? options.fallbackSchema);
|
|
6313
|
+
const modelName = normalizeOptionalName(target.meta.model ?? options.fallbackModel);
|
|
6314
|
+
if (!modelName) {
|
|
6315
|
+
throw new Error(
|
|
6316
|
+
"Athena model target is missing meta.model or meta.tableName. Provide one of those before calling from(model)."
|
|
6317
|
+
);
|
|
6318
|
+
}
|
|
6319
|
+
return schemaName ? `${schemaName}.${modelName}` : modelName;
|
|
6320
|
+
}
|
|
6321
|
+
|
|
5505
6322
|
// src/client.ts
|
|
5506
6323
|
var DEFAULT_COLUMNS = "*";
|
|
5507
6324
|
var SAFE_CAST_PATTERN = /^[a-z_][a-z0-9_]*(?:\[\])?$/i;
|
|
5508
6325
|
var ATHENA_NORMALIZED_ERROR_KEY = "__athenaNormalizedError";
|
|
5509
|
-
var QUERY_TRACE_STACK_SKIP_PATTERNS = [
|
|
5510
|
-
"src\\client.ts",
|
|
5511
|
-
"src/client.ts",
|
|
5512
|
-
"dist\\client.",
|
|
5513
|
-
"dist/client.",
|
|
5514
|
-
"node_modules\\@xylex-group\\athena",
|
|
5515
|
-
"node_modules/@xylex-group/athena",
|
|
5516
|
-
"node:internal",
|
|
5517
|
-
"internal/process"
|
|
5518
|
-
];
|
|
5519
6326
|
function formatResult(response) {
|
|
5520
6327
|
const result = {
|
|
5521
6328
|
data: response.data ?? null,
|
|
@@ -5657,154 +6464,6 @@ function createResultError(response, result, normalized) {
|
|
|
5657
6464
|
raw: result.raw
|
|
5658
6465
|
};
|
|
5659
6466
|
}
|
|
5660
|
-
function parseQueryTraceCallsiteFrame(frame) {
|
|
5661
|
-
const trimmed = frame.trim();
|
|
5662
|
-
if (!trimmed) {
|
|
5663
|
-
return null;
|
|
5664
|
-
}
|
|
5665
|
-
let body = trimmed.replace(/^at\s+/, "");
|
|
5666
|
-
if (body.startsWith("async ")) {
|
|
5667
|
-
body = body.slice(6);
|
|
5668
|
-
}
|
|
5669
|
-
let functionName;
|
|
5670
|
-
let location = body;
|
|
5671
|
-
const wrappedMatch = body.match(/^(.*?)\s+\((.*)\)$/);
|
|
5672
|
-
if (wrappedMatch) {
|
|
5673
|
-
functionName = wrappedMatch[1].trim() || void 0;
|
|
5674
|
-
location = wrappedMatch[2].trim();
|
|
5675
|
-
}
|
|
5676
|
-
const locationMatch = location.match(/^(.*):(\d+):(\d+)$/);
|
|
5677
|
-
if (!locationMatch) {
|
|
5678
|
-
return null;
|
|
5679
|
-
}
|
|
5680
|
-
const filePath = locationMatch[1].replace(/^file:\/\//, "");
|
|
5681
|
-
const line = Number(locationMatch[2]);
|
|
5682
|
-
const column = Number(locationMatch[3]);
|
|
5683
|
-
if (!Number.isFinite(line) || !Number.isFinite(column)) {
|
|
5684
|
-
return null;
|
|
5685
|
-
}
|
|
5686
|
-
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
5687
|
-
const fileName = normalizedPath.split("/").at(-1) ?? filePath;
|
|
5688
|
-
return {
|
|
5689
|
-
filePath,
|
|
5690
|
-
fileName,
|
|
5691
|
-
line,
|
|
5692
|
-
column,
|
|
5693
|
-
frame: trimmed,
|
|
5694
|
-
functionName
|
|
5695
|
-
};
|
|
5696
|
-
}
|
|
5697
|
-
function captureQueryTraceCallsite() {
|
|
5698
|
-
const stack = new Error().stack;
|
|
5699
|
-
if (!stack) return null;
|
|
5700
|
-
const frames = stack.split("\n").slice(2).map((frame) => frame.trim()).filter(Boolean);
|
|
5701
|
-
for (const frame of frames) {
|
|
5702
|
-
if (QUERY_TRACE_STACK_SKIP_PATTERNS.some((pattern) => frame.includes(pattern))) {
|
|
5703
|
-
continue;
|
|
5704
|
-
}
|
|
5705
|
-
const callsite = parseQueryTraceCallsiteFrame(frame);
|
|
5706
|
-
if (callsite) return callsite;
|
|
5707
|
-
}
|
|
5708
|
-
const fallback = frames.find((frame) => !frame.includes("captureQueryTraceCallsite"));
|
|
5709
|
-
return fallback ? parseQueryTraceCallsiteFrame(fallback) : null;
|
|
5710
|
-
}
|
|
5711
|
-
function defaultQueryTraceLogger(event) {
|
|
5712
|
-
const target = event.table ?? event.functionName ?? "gateway";
|
|
5713
|
-
const outcomeState = event.outcome?.error ? "error" : "ok";
|
|
5714
|
-
const banner = `[athena-js][trace] ${event.operation.toUpperCase()} ${event.endpoint} ${target} ${event.durationMs}ms ${outcomeState}`;
|
|
5715
|
-
console.info(banner, event);
|
|
5716
|
-
}
|
|
5717
|
-
function captureTraceCallsite(tracer) {
|
|
5718
|
-
return tracer?.captureCallsite() ?? null;
|
|
5719
|
-
}
|
|
5720
|
-
function createTraceCallsiteStore(tracer, initialCallsite) {
|
|
5721
|
-
let storedCallsite = initialCallsite ?? void 0;
|
|
5722
|
-
return {
|
|
5723
|
-
resolve(callsite) {
|
|
5724
|
-
if (callsite) {
|
|
5725
|
-
storedCallsite = callsite;
|
|
5726
|
-
return callsite;
|
|
5727
|
-
}
|
|
5728
|
-
if (storedCallsite !== void 0) {
|
|
5729
|
-
return storedCallsite;
|
|
5730
|
-
}
|
|
5731
|
-
const capturedCallsite = captureTraceCallsite(tracer);
|
|
5732
|
-
if (capturedCallsite) {
|
|
5733
|
-
storedCallsite = capturedCallsite;
|
|
5734
|
-
}
|
|
5735
|
-
return capturedCallsite;
|
|
5736
|
-
}
|
|
5737
|
-
};
|
|
5738
|
-
}
|
|
5739
|
-
function createQueryTracer(experimental) {
|
|
5740
|
-
const traceOption = experimental?.traceQueries;
|
|
5741
|
-
if (!traceOption) {
|
|
5742
|
-
return void 0;
|
|
5743
|
-
}
|
|
5744
|
-
const logger = typeof traceOption === "object" && traceOption.logger ? traceOption.logger : defaultQueryTraceLogger;
|
|
5745
|
-
const emit = (event) => {
|
|
5746
|
-
try {
|
|
5747
|
-
logger(event);
|
|
5748
|
-
} catch (error) {
|
|
5749
|
-
console.warn("[athena-js][trace] logger failed", error);
|
|
5750
|
-
}
|
|
5751
|
-
};
|
|
5752
|
-
return {
|
|
5753
|
-
captureCallsite: captureQueryTraceCallsite,
|
|
5754
|
-
publishSuccess(context, result, durationMs, callsite) {
|
|
5755
|
-
emit({
|
|
5756
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5757
|
-
durationMs,
|
|
5758
|
-
operation: context.operation,
|
|
5759
|
-
endpoint: context.endpoint,
|
|
5760
|
-
table: context.table,
|
|
5761
|
-
functionName: context.functionName,
|
|
5762
|
-
sql: context.sql,
|
|
5763
|
-
payload: context.payload,
|
|
5764
|
-
options: context.options,
|
|
5765
|
-
callsite,
|
|
5766
|
-
outcome: {
|
|
5767
|
-
status: result.status,
|
|
5768
|
-
error: result.error,
|
|
5769
|
-
errorDetails: result.errorDetails ?? null,
|
|
5770
|
-
count: result.count ?? null,
|
|
5771
|
-
data: result.data,
|
|
5772
|
-
raw: result.raw
|
|
5773
|
-
}
|
|
5774
|
-
});
|
|
5775
|
-
},
|
|
5776
|
-
publishFailure(context, error, durationMs, callsite) {
|
|
5777
|
-
emit({
|
|
5778
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5779
|
-
durationMs,
|
|
5780
|
-
operation: context.operation,
|
|
5781
|
-
endpoint: context.endpoint,
|
|
5782
|
-
table: context.table,
|
|
5783
|
-
functionName: context.functionName,
|
|
5784
|
-
sql: context.sql,
|
|
5785
|
-
payload: context.payload,
|
|
5786
|
-
options: context.options,
|
|
5787
|
-
callsite,
|
|
5788
|
-
thrownError: error
|
|
5789
|
-
});
|
|
5790
|
-
}
|
|
5791
|
-
};
|
|
5792
|
-
}
|
|
5793
|
-
async function executeWithQueryTrace(tracer, context, runner, callsiteOverride) {
|
|
5794
|
-
if (!tracer) {
|
|
5795
|
-
return runner();
|
|
5796
|
-
}
|
|
5797
|
-
const callsite = callsiteOverride ?? tracer.captureCallsite();
|
|
5798
|
-
const startedAt = Date.now();
|
|
5799
|
-
try {
|
|
5800
|
-
const result = await runner();
|
|
5801
|
-
tracer.publishSuccess(context, result, Date.now() - startedAt, callsite);
|
|
5802
|
-
return result;
|
|
5803
|
-
} catch (error) {
|
|
5804
|
-
tracer.publishFailure(context, error, Date.now() - startedAt, callsite);
|
|
5805
|
-
throw error;
|
|
5806
|
-
}
|
|
5807
|
-
}
|
|
5808
6467
|
function toSingleResult(response) {
|
|
5809
6468
|
const payload = response.data;
|
|
5810
6469
|
const singleData = Array.isArray(payload) ? payload.length ? payload[0] : null : payload ?? null;
|
|
@@ -5832,6 +6491,15 @@ function asAthenaJsonObject(value) {
|
|
|
5832
6491
|
function asAthenaJsonObjectArray(values) {
|
|
5833
6492
|
return values;
|
|
5834
6493
|
}
|
|
6494
|
+
function normalizeSelectColumnsInput(columns) {
|
|
6495
|
+
if (columns === void 0) {
|
|
6496
|
+
return void 0;
|
|
6497
|
+
}
|
|
6498
|
+
if (typeof columns === "string") {
|
|
6499
|
+
return columns;
|
|
6500
|
+
}
|
|
6501
|
+
return [...columns];
|
|
6502
|
+
}
|
|
5835
6503
|
function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS, tracer, initialCallsite) {
|
|
5836
6504
|
let selectedColumns = defaultColumns === null ? void 0 : defaultColumns;
|
|
5837
6505
|
let selectedOptions;
|
|
@@ -5841,25 +6509,29 @@ function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS, tracer,
|
|
|
5841
6509
|
const payloadColumns = columns ?? selectedColumns;
|
|
5842
6510
|
const payloadOptions = options ?? selectedOptions;
|
|
5843
6511
|
if (!promise) {
|
|
5844
|
-
promise = executor(
|
|
6512
|
+
promise = executor(
|
|
6513
|
+
normalizeSelectColumnsInput(payloadColumns),
|
|
6514
|
+
payloadOptions,
|
|
6515
|
+
callsiteStore.resolve(callsite)
|
|
6516
|
+
);
|
|
5845
6517
|
}
|
|
5846
6518
|
return promise;
|
|
5847
6519
|
};
|
|
5848
6520
|
const mutationQuery = {
|
|
5849
|
-
select(columns
|
|
6521
|
+
select(columns, options) {
|
|
5850
6522
|
selectedColumns = columns;
|
|
5851
6523
|
selectedOptions = options ?? selectedOptions;
|
|
5852
6524
|
return run(columns, options, captureTraceCallsite(tracer));
|
|
5853
6525
|
},
|
|
5854
|
-
returning(columns
|
|
6526
|
+
returning(columns, options) {
|
|
5855
6527
|
return mutationQuery.select(columns, options);
|
|
5856
6528
|
},
|
|
5857
|
-
single(columns
|
|
6529
|
+
single(columns, options) {
|
|
5858
6530
|
selectedColumns = columns;
|
|
5859
6531
|
selectedOptions = options ?? selectedOptions;
|
|
5860
6532
|
return run(columns, options, captureTraceCallsite(tracer)).then(toSingleResult);
|
|
5861
6533
|
},
|
|
5862
|
-
maybeSingle(columns
|
|
6534
|
+
maybeSingle(columns, options) {
|
|
5863
6535
|
return mutationQuery.single(columns, options);
|
|
5864
6536
|
},
|
|
5865
6537
|
then(onfulfilled, onrejected) {
|
|
@@ -6416,7 +7088,10 @@ function createFilterMethods(state, addCondition, self) {
|
|
|
6416
7088
|
}
|
|
6417
7089
|
function toRpcSelect(columns) {
|
|
6418
7090
|
if (!columns) return void 0;
|
|
6419
|
-
|
|
7091
|
+
if (typeof columns === "string") {
|
|
7092
|
+
return columns;
|
|
7093
|
+
}
|
|
7094
|
+
return columns.join(",");
|
|
6420
7095
|
}
|
|
6421
7096
|
function createRpcFilterMethods(filters, self) {
|
|
6422
7097
|
const addFilter = (operator, column, value) => {
|
|
@@ -6465,7 +7140,7 @@ function createRpcFilterMethods(filters, self) {
|
|
|
6465
7140
|
}
|
|
6466
7141
|
};
|
|
6467
7142
|
}
|
|
6468
|
-
function createRpcBuilder(functionName, args, baseOptions, client, formatGatewayResult, tracer, initialCallsite) {
|
|
7143
|
+
function createRpcBuilder(functionName, args, baseOptions, client, formatGatewayResult, tracer, initialCallsite, debugAstEnabled = false) {
|
|
6469
7144
|
const state = {
|
|
6470
7145
|
filters: []
|
|
6471
7146
|
};
|
|
@@ -6475,6 +7150,7 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
|
|
|
6475
7150
|
const callsiteStore = createTraceCallsiteStore(tracer, initialCallsite);
|
|
6476
7151
|
const executeRpc = async (columns, options, callsite) => {
|
|
6477
7152
|
const mergedOptions = mergeOptions(baseOptions, options);
|
|
7153
|
+
const normalizedSelectedColumns = normalizeSelectColumnsInput(columns);
|
|
6478
7154
|
const payload = {
|
|
6479
7155
|
function: functionName,
|
|
6480
7156
|
args,
|
|
@@ -6489,6 +7165,14 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
|
|
|
6489
7165
|
};
|
|
6490
7166
|
const endpoint = mergedOptions?.get ? `/rpc/${functionName}` : "/gateway/rpc";
|
|
6491
7167
|
const sql = buildRpcDebugSql(payload);
|
|
7168
|
+
const debugAst = debugAstEnabled ? buildRpcDebugAst({
|
|
7169
|
+
functionName,
|
|
7170
|
+
args,
|
|
7171
|
+
selectedColumns: normalizedSelectedColumns,
|
|
7172
|
+
state,
|
|
7173
|
+
payload,
|
|
7174
|
+
endpoint
|
|
7175
|
+
}) : void 0;
|
|
6492
7176
|
return executeWithQueryTrace(
|
|
6493
7177
|
tracer,
|
|
6494
7178
|
{
|
|
@@ -6497,6 +7181,7 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
|
|
|
6497
7181
|
functionName,
|
|
6498
7182
|
sql,
|
|
6499
7183
|
payload,
|
|
7184
|
+
ast: debugAst,
|
|
6500
7185
|
options: mergedOptions
|
|
6501
7186
|
},
|
|
6502
7187
|
async () => {
|
|
@@ -6517,7 +7202,7 @@ function createRpcBuilder(functionName, args, baseOptions, client, formatGateway
|
|
|
6517
7202
|
const builder = {};
|
|
6518
7203
|
const filterMethods = createRpcFilterMethods(state.filters, builder);
|
|
6519
7204
|
Object.assign(builder, filterMethods, {
|
|
6520
|
-
select(columns
|
|
7205
|
+
select(columns, options) {
|
|
6521
7206
|
selectedColumns = columns;
|
|
6522
7207
|
selectedOptions = options ?? selectedOptions;
|
|
6523
7208
|
return run(columns, options, captureTraceCallsite(tracer));
|
|
@@ -6562,6 +7247,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6562
7247
|
const state = {
|
|
6563
7248
|
conditions: []
|
|
6564
7249
|
};
|
|
7250
|
+
const debugAstEnabled = Boolean(experimental?.debugAst);
|
|
6565
7251
|
const addCondition = (operator, column, value, hints) => {
|
|
6566
7252
|
const condition = { operator };
|
|
6567
7253
|
if (column) {
|
|
@@ -6605,15 +7291,27 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6605
7291
|
addCondition,
|
|
6606
7292
|
builder
|
|
6607
7293
|
);
|
|
6608
|
-
const runSelect = async (columns = DEFAULT_COLUMNS, options, executionState = snapshotState(), callsite) => {
|
|
7294
|
+
const runSelect = async (columns = DEFAULT_COLUMNS, options, executionState = snapshotState(), callsite, debugAstFactory) => {
|
|
7295
|
+
const runtimeColumns = normalizeSelectColumnsInput(columns) ?? DEFAULT_COLUMNS;
|
|
6609
7296
|
const resolvedTableName = resolveTableNameForCall(tableName, options?.schema);
|
|
6610
7297
|
const plan = createSelectTransportPlan({
|
|
6611
7298
|
tableName: resolvedTableName,
|
|
6612
|
-
columns,
|
|
7299
|
+
columns: runtimeColumns,
|
|
6613
7300
|
state: executionState,
|
|
6614
7301
|
options,
|
|
6615
7302
|
buildTypedSelectQuery
|
|
6616
7303
|
});
|
|
7304
|
+
const debugAst = debugAstEnabled ? debugAstFactory?.({
|
|
7305
|
+
tableName: resolvedTableName,
|
|
7306
|
+
columns: runtimeColumns,
|
|
7307
|
+
executionState,
|
|
7308
|
+
plan
|
|
7309
|
+
}) ?? buildSelectDebugAst({
|
|
7310
|
+
tableName: resolvedTableName,
|
|
7311
|
+
columns: runtimeColumns,
|
|
7312
|
+
state: executionState,
|
|
7313
|
+
plan
|
|
7314
|
+
}) : void 0;
|
|
6617
7315
|
if (plan.kind === "query") {
|
|
6618
7316
|
return executeExperimentalRead(
|
|
6619
7317
|
experimental,
|
|
@@ -6625,6 +7323,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6625
7323
|
table: resolvedTableName,
|
|
6626
7324
|
sql: plan.query,
|
|
6627
7325
|
payload: plan.payload,
|
|
7326
|
+
ast: debugAst,
|
|
6628
7327
|
options
|
|
6629
7328
|
},
|
|
6630
7329
|
async () => {
|
|
@@ -6649,6 +7348,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6649
7348
|
table: resolvedTableName,
|
|
6650
7349
|
sql,
|
|
6651
7350
|
payload: plan.payload,
|
|
7351
|
+
ast: debugAst,
|
|
6652
7352
|
options
|
|
6653
7353
|
},
|
|
6654
7354
|
async () => {
|
|
@@ -6662,7 +7362,11 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6662
7362
|
const createSelectChain = (columns, options, initialCallsite) => {
|
|
6663
7363
|
const chain = {};
|
|
6664
7364
|
const callsiteStore = createTraceCallsiteStore(tracer, initialCallsite);
|
|
6665
|
-
const filterMethods2 = createFilterMethods(
|
|
7365
|
+
const filterMethods2 = createFilterMethods(
|
|
7366
|
+
state,
|
|
7367
|
+
addCondition,
|
|
7368
|
+
chain
|
|
7369
|
+
);
|
|
6666
7370
|
Object.assign(chain, filterMethods2, {
|
|
6667
7371
|
async single(cols, opts) {
|
|
6668
7372
|
const r = await runSelect(
|
|
@@ -6749,6 +7453,14 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6749
7453
|
limit: executionState.limit,
|
|
6750
7454
|
order: executionState.order
|
|
6751
7455
|
});
|
|
7456
|
+
const debugAst = debugAstEnabled ? buildFindManyDirectDebugAst({
|
|
7457
|
+
tableName: resolvedTableName,
|
|
7458
|
+
options,
|
|
7459
|
+
compiledColumns: columns,
|
|
7460
|
+
baseState,
|
|
7461
|
+
executionState,
|
|
7462
|
+
payload
|
|
7463
|
+
}) : void 0;
|
|
6752
7464
|
return executeExperimentalRead(
|
|
6753
7465
|
experimental,
|
|
6754
7466
|
() => executeWithQueryTrace(
|
|
@@ -6758,7 +7470,8 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6758
7470
|
endpoint: "/gateway/fetch",
|
|
6759
7471
|
table: resolvedTableName,
|
|
6760
7472
|
sql,
|
|
6761
|
-
payload
|
|
7473
|
+
payload,
|
|
7474
|
+
ast: debugAst
|
|
6762
7475
|
},
|
|
6763
7476
|
async () => {
|
|
6764
7477
|
const response = await client.fetchGateway(
|
|
@@ -6774,7 +7487,15 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6774
7487
|
columns,
|
|
6775
7488
|
void 0,
|
|
6776
7489
|
executionState,
|
|
6777
|
-
callsite
|
|
7490
|
+
callsite,
|
|
7491
|
+
debugAstEnabled ? ({ tableName: resolvedTableName, executionState: tracedState, plan }) => buildFindManyCompiledDebugAst({
|
|
7492
|
+
tableName: resolvedTableName,
|
|
7493
|
+
options,
|
|
7494
|
+
compiledColumns: columns,
|
|
7495
|
+
baseState,
|
|
7496
|
+
executionState: tracedState,
|
|
7497
|
+
plan
|
|
7498
|
+
}) : void 0
|
|
6778
7499
|
);
|
|
6779
7500
|
},
|
|
6780
7501
|
insert(values, options) {
|
|
@@ -6794,6 +7515,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6794
7515
|
payload.default_to_null = mergedOptions.defaultToNull;
|
|
6795
7516
|
}
|
|
6796
7517
|
const sql = buildInsertDebugSql(payload);
|
|
7518
|
+
const debugAst = debugAstEnabled ? buildInsertDebugAst(payload) : void 0;
|
|
6797
7519
|
return executeWithQueryTrace(
|
|
6798
7520
|
tracer,
|
|
6799
7521
|
{
|
|
@@ -6802,6 +7524,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6802
7524
|
table: resolvedTableName,
|
|
6803
7525
|
sql,
|
|
6804
7526
|
payload,
|
|
7527
|
+
ast: debugAst,
|
|
6805
7528
|
options: mergedOptions
|
|
6806
7529
|
},
|
|
6807
7530
|
async () => {
|
|
@@ -6827,6 +7550,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6827
7550
|
payload.default_to_null = mergedOptions.defaultToNull;
|
|
6828
7551
|
}
|
|
6829
7552
|
const sql = buildInsertDebugSql(payload);
|
|
7553
|
+
const debugAst = debugAstEnabled ? buildInsertDebugAst(payload) : void 0;
|
|
6830
7554
|
return executeWithQueryTrace(
|
|
6831
7555
|
tracer,
|
|
6832
7556
|
{
|
|
@@ -6835,6 +7559,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6835
7559
|
table: resolvedTableName,
|
|
6836
7560
|
sql,
|
|
6837
7561
|
payload,
|
|
7562
|
+
ast: debugAst,
|
|
6838
7563
|
options: mergedOptions
|
|
6839
7564
|
},
|
|
6840
7565
|
async () => {
|
|
@@ -6865,6 +7590,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6865
7590
|
payload.default_to_null = mergedOptions.defaultToNull;
|
|
6866
7591
|
}
|
|
6867
7592
|
const sql = buildInsertDebugSql(payload);
|
|
7593
|
+
const debugAst = debugAstEnabled ? buildUpsertDebugAst(payload) : void 0;
|
|
6868
7594
|
return executeWithQueryTrace(
|
|
6869
7595
|
tracer,
|
|
6870
7596
|
{
|
|
@@ -6873,6 +7599,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6873
7599
|
table: resolvedTableName,
|
|
6874
7600
|
sql,
|
|
6875
7601
|
payload,
|
|
7602
|
+
ast: debugAst,
|
|
6876
7603
|
options: mergedOptions
|
|
6877
7604
|
},
|
|
6878
7605
|
async () => {
|
|
@@ -6900,6 +7627,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6900
7627
|
payload.default_to_null = mergedOptions.defaultToNull;
|
|
6901
7628
|
}
|
|
6902
7629
|
const sql = buildInsertDebugSql(payload);
|
|
7630
|
+
const debugAst = debugAstEnabled ? buildUpsertDebugAst(payload) : void 0;
|
|
6903
7631
|
return executeWithQueryTrace(
|
|
6904
7632
|
tracer,
|
|
6905
7633
|
{
|
|
@@ -6908,6 +7636,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6908
7636
|
table: resolvedTableName,
|
|
6909
7637
|
sql,
|
|
6910
7638
|
payload,
|
|
7639
|
+
ast: debugAst,
|
|
6911
7640
|
options: mergedOptions
|
|
6912
7641
|
},
|
|
6913
7642
|
async () => {
|
|
@@ -6922,7 +7651,8 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6922
7651
|
update(values, options) {
|
|
6923
7652
|
const mutationCallsite = captureTraceCallsite(tracer);
|
|
6924
7653
|
const executeUpdate = async (columns, selectOptions, callsite) => {
|
|
6925
|
-
const
|
|
7654
|
+
const executionState = snapshotState();
|
|
7655
|
+
const filters = executionState.conditions.length ? [...executionState.conditions] : void 0;
|
|
6926
7656
|
const mergedOptions = mergeOptions(options, selectOptions);
|
|
6927
7657
|
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
6928
7658
|
const payload = {
|
|
@@ -6931,12 +7661,16 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6931
7661
|
conditions: filters,
|
|
6932
7662
|
strip_nulls: mergedOptions?.stripNulls ?? true
|
|
6933
7663
|
};
|
|
6934
|
-
if (
|
|
6935
|
-
if (
|
|
6936
|
-
if (
|
|
6937
|
-
if (
|
|
7664
|
+
if (executionState.order) payload.sort_by = executionState.order;
|
|
7665
|
+
if (executionState.currentPage !== void 0) payload.current_page = executionState.currentPage;
|
|
7666
|
+
if (executionState.pageSize !== void 0) payload.page_size = executionState.pageSize;
|
|
7667
|
+
if (executionState.totalPages !== void 0) payload.total_pages = executionState.totalPages;
|
|
6938
7668
|
if (columns) payload.columns = columns;
|
|
6939
7669
|
const sql = buildUpdateDebugSql(payload);
|
|
7670
|
+
const debugAst = debugAstEnabled ? buildUpdateDebugAst({
|
|
7671
|
+
state: executionState,
|
|
7672
|
+
payload
|
|
7673
|
+
}) : void 0;
|
|
6940
7674
|
return executeWithQueryTrace(
|
|
6941
7675
|
tracer,
|
|
6942
7676
|
{
|
|
@@ -6945,6 +7679,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6945
7679
|
table: resolvedTableName,
|
|
6946
7680
|
sql,
|
|
6947
7681
|
payload,
|
|
7682
|
+
ast: debugAst,
|
|
6948
7683
|
options: mergedOptions
|
|
6949
7684
|
},
|
|
6950
7685
|
async () => {
|
|
@@ -6968,6 +7703,11 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6968
7703
|
}
|
|
6969
7704
|
const mutationCallsite = captureTraceCallsite(tracer);
|
|
6970
7705
|
const executeDelete = async (columns, selectOptions, callsite) => {
|
|
7706
|
+
const executionState = snapshotState();
|
|
7707
|
+
const debugState = {
|
|
7708
|
+
...executionState,
|
|
7709
|
+
conditions: filters ? filters.map((condition) => ({ ...condition })) : []
|
|
7710
|
+
};
|
|
6971
7711
|
const mergedOptions = mergeOptions(options, selectOptions);
|
|
6972
7712
|
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
6973
7713
|
const payload = {
|
|
@@ -6975,12 +7715,16 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6975
7715
|
resource_id: resourceId,
|
|
6976
7716
|
conditions: filters
|
|
6977
7717
|
};
|
|
6978
|
-
if (
|
|
6979
|
-
if (
|
|
6980
|
-
if (
|
|
6981
|
-
if (
|
|
7718
|
+
if (executionState.order) payload.sort_by = executionState.order;
|
|
7719
|
+
if (executionState.currentPage !== void 0) payload.current_page = executionState.currentPage;
|
|
7720
|
+
if (executionState.pageSize !== void 0) payload.page_size = executionState.pageSize;
|
|
7721
|
+
if (executionState.totalPages !== void 0) payload.total_pages = executionState.totalPages;
|
|
6982
7722
|
if (columns) payload.columns = columns;
|
|
6983
7723
|
const sql = buildDeleteDebugSql(payload);
|
|
7724
|
+
const debugAst = debugAstEnabled ? buildDeleteDebugAst({
|
|
7725
|
+
state: debugState,
|
|
7726
|
+
payload
|
|
7727
|
+
}) : void 0;
|
|
6984
7728
|
return executeWithQueryTrace(
|
|
6985
7729
|
tracer,
|
|
6986
7730
|
{
|
|
@@ -6989,6 +7733,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
6989
7733
|
table: resolvedTableName,
|
|
6990
7734
|
sql,
|
|
6991
7735
|
payload,
|
|
7736
|
+
ast: debugAst,
|
|
6992
7737
|
options: mergedOptions
|
|
6993
7738
|
},
|
|
6994
7739
|
async () => {
|
|
@@ -7016,6 +7761,7 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, expe
|
|
|
7016
7761
|
return builder;
|
|
7017
7762
|
}
|
|
7018
7763
|
function createQueryBuilder(client, formatGatewayResult, experimental, tracer) {
|
|
7764
|
+
const debugAstEnabled = Boolean(experimental?.debugAst);
|
|
7019
7765
|
return async function query(query, options) {
|
|
7020
7766
|
const normalizedQuery = query.trim();
|
|
7021
7767
|
if (!normalizedQuery) {
|
|
@@ -7032,6 +7778,7 @@ function createQueryBuilder(client, formatGatewayResult, experimental, tracer) {
|
|
|
7032
7778
|
endpoint: "/gateway/query",
|
|
7033
7779
|
sql: normalizedQuery,
|
|
7034
7780
|
payload,
|
|
7781
|
+
ast: debugAstEnabled ? buildRawQueryDebugAst(normalizedQuery) : void 0,
|
|
7035
7782
|
options
|
|
7036
7783
|
},
|
|
7037
7784
|
async () => {
|
|
@@ -7043,6 +7790,63 @@ function createQueryBuilder(client, formatGatewayResult, experimental, tracer) {
|
|
|
7043
7790
|
);
|
|
7044
7791
|
};
|
|
7045
7792
|
}
|
|
7793
|
+
function resolveClientServiceBaseUrl(value, label) {
|
|
7794
|
+
if (value === void 0 || value === null) {
|
|
7795
|
+
return void 0;
|
|
7796
|
+
}
|
|
7797
|
+
return normalizeAthenaGatewayBaseUrl(value, { label });
|
|
7798
|
+
}
|
|
7799
|
+
function appendServicePath(baseUrl, segment) {
|
|
7800
|
+
const normalizedBaseUrl = normalizeAthenaGatewayBaseUrl(baseUrl, { label: "Athena public base URL" });
|
|
7801
|
+
return `${normalizedBaseUrl}/${segment.replace(/^\/+/, "")}`;
|
|
7802
|
+
}
|
|
7803
|
+
function resolveServiceUrlOverride(value, label) {
|
|
7804
|
+
return resolveClientServiceBaseUrl(value, label);
|
|
7805
|
+
}
|
|
7806
|
+
function resolveServiceUrls(config) {
|
|
7807
|
+
const baseUrl = resolveClientServiceBaseUrl(config.url, "Athena public base URL");
|
|
7808
|
+
return {
|
|
7809
|
+
dbUrl: resolveServiceUrlOverride(config.db?.url, "Athena DB base URL") ?? resolveServiceUrlOverride(config.gateway?.url, "Athena gateway base URL") ?? resolveServiceUrlOverride(config.dbUrl, "Athena DB base URL") ?? resolveServiceUrlOverride(config.gatewayUrl, "Athena gateway base URL") ?? (baseUrl ? appendServicePath(baseUrl, "db") : void 0),
|
|
7810
|
+
authUrl: resolveServiceUrlOverride(config.auth?.url, "Athena auth base URL") ?? resolveServiceUrlOverride(config.auth?.baseUrl, "Athena auth base URL") ?? resolveServiceUrlOverride(config.authUrl, "Athena auth base URL") ?? (baseUrl ? appendServicePath(baseUrl, "auth") : void 0),
|
|
7811
|
+
storageUrl: resolveServiceUrlOverride(config.storage?.url, "Athena storage base URL") ?? resolveServiceUrlOverride(config.storageUrl, "Athena storage base URL") ?? (baseUrl ? appendServicePath(baseUrl, "storage") : void 0)
|
|
7812
|
+
};
|
|
7813
|
+
}
|
|
7814
|
+
function normalizeAuthClientConfig(auth, defaultBaseUrl) {
|
|
7815
|
+
if (!auth && defaultBaseUrl === void 0) {
|
|
7816
|
+
return void 0;
|
|
7817
|
+
}
|
|
7818
|
+
const { url, ...rest } = auth ?? {};
|
|
7819
|
+
const normalized = {
|
|
7820
|
+
...rest
|
|
7821
|
+
};
|
|
7822
|
+
const resolvedBaseUrl = resolveClientServiceBaseUrl(
|
|
7823
|
+
url ?? rest.baseUrl ?? defaultBaseUrl,
|
|
7824
|
+
"Athena auth base URL"
|
|
7825
|
+
);
|
|
7826
|
+
if (resolvedBaseUrl !== void 0) {
|
|
7827
|
+
normalized.baseUrl = resolvedBaseUrl;
|
|
7828
|
+
}
|
|
7829
|
+
return normalized;
|
|
7830
|
+
}
|
|
7831
|
+
function resolveCreateClientConfig(config) {
|
|
7832
|
+
const resolvedUrls = resolveServiceUrls(config);
|
|
7833
|
+
if (!resolvedUrls.dbUrl) {
|
|
7834
|
+
throw new Error(
|
|
7835
|
+
"Athena DB base URL is required. Pass createClient(url, key) for a unified root, or set db.url / gateway.url / gatewayUrl explicitly."
|
|
7836
|
+
);
|
|
7837
|
+
}
|
|
7838
|
+
return {
|
|
7839
|
+
baseUrl: resolvedUrls.dbUrl,
|
|
7840
|
+
apiKey: config.key,
|
|
7841
|
+
client: config.client,
|
|
7842
|
+
backend: toBackendConfig(config.backend),
|
|
7843
|
+
headers: config.headers,
|
|
7844
|
+
auth: config.auth,
|
|
7845
|
+
authUrl: resolvedUrls.authUrl,
|
|
7846
|
+
storageUrl: resolvedUrls.storageUrl,
|
|
7847
|
+
experimental: config.experimental
|
|
7848
|
+
};
|
|
7849
|
+
}
|
|
7046
7850
|
function createClientFromConfig(config) {
|
|
7047
7851
|
const gatewayHeaders = {
|
|
7048
7852
|
...config.headers ?? {}
|
|
@@ -7057,16 +7861,33 @@ function createClientFromConfig(config) {
|
|
|
7057
7861
|
backend: config.backend,
|
|
7058
7862
|
headers: gatewayHeaders
|
|
7059
7863
|
});
|
|
7060
|
-
const formatGatewayResult = createResultFormatter();
|
|
7864
|
+
const formatGatewayResult = createResultFormatter(config.experimental);
|
|
7061
7865
|
const queryTracer = createQueryTracer(config.experimental);
|
|
7062
|
-
const auth = createAuthClient(config.auth);
|
|
7063
|
-
|
|
7064
|
-
|
|
7065
|
-
|
|
7066
|
-
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
7866
|
+
const auth = createAuthClient(normalizeAuthClientConfig(config.auth, config.authUrl));
|
|
7867
|
+
function from(tableOrModel, options) {
|
|
7868
|
+
if (isAthenaModelTarget(tableOrModel)) {
|
|
7869
|
+
if (options?.schema !== void 0) {
|
|
7870
|
+
throw new Error(
|
|
7871
|
+
"from(model) does not accept a schema override because the model already defines its target."
|
|
7872
|
+
);
|
|
7873
|
+
}
|
|
7874
|
+
return createTableBuilder(
|
|
7875
|
+
resolveAthenaModelTargetTableName(tableOrModel),
|
|
7876
|
+
gateway,
|
|
7877
|
+
formatGatewayResult,
|
|
7878
|
+
queryTracer,
|
|
7879
|
+
config.experimental
|
|
7880
|
+
);
|
|
7881
|
+
}
|
|
7882
|
+
const resolvedTableName = resolveTableNameForCall(tableOrModel, options?.schema);
|
|
7883
|
+
return createTableBuilder(
|
|
7884
|
+
resolvedTableName,
|
|
7885
|
+
gateway,
|
|
7886
|
+
formatGatewayResult,
|
|
7887
|
+
queryTracer,
|
|
7888
|
+
config.experimental
|
|
7889
|
+
);
|
|
7890
|
+
}
|
|
7070
7891
|
const rpc = (fn, args, options) => {
|
|
7071
7892
|
const normalizedFn = fn.trim();
|
|
7072
7893
|
if (!normalizedFn) {
|
|
@@ -7079,10 +7900,16 @@ function createClientFromConfig(config) {
|
|
|
7079
7900
|
gateway,
|
|
7080
7901
|
formatGatewayResult,
|
|
7081
7902
|
queryTracer,
|
|
7082
|
-
captureTraceCallsite(queryTracer)
|
|
7903
|
+
captureTraceCallsite(queryTracer),
|
|
7904
|
+
Boolean(config.experimental?.debugAst)
|
|
7083
7905
|
);
|
|
7084
7906
|
};
|
|
7085
|
-
const query = createQueryBuilder(
|
|
7907
|
+
const query = createQueryBuilder(
|
|
7908
|
+
gateway,
|
|
7909
|
+
formatGatewayResult,
|
|
7910
|
+
config.experimental,
|
|
7911
|
+
queryTracer
|
|
7912
|
+
);
|
|
7086
7913
|
const db = createDbModule({ from, rpc, query });
|
|
7087
7914
|
const sdkClient = {
|
|
7088
7915
|
from,
|
|
@@ -7095,27 +7922,27 @@ function createClientFromConfig(config) {
|
|
|
7095
7922
|
if (config.experimental?.athenaStorageBackend) {
|
|
7096
7923
|
const storageClient = {
|
|
7097
7924
|
...sdkClient,
|
|
7098
|
-
storage: createStorageModule(gateway,
|
|
7925
|
+
storage: createStorageModule(gateway, {
|
|
7926
|
+
...config.experimental.storage,
|
|
7927
|
+
...config.storageUrl ? {
|
|
7928
|
+
baseUrl: config.storageUrl,
|
|
7929
|
+
stripBasePath: true
|
|
7930
|
+
} : {}
|
|
7931
|
+
})
|
|
7099
7932
|
};
|
|
7100
7933
|
return storageClient;
|
|
7101
7934
|
}
|
|
7102
7935
|
return sdkClient;
|
|
7103
7936
|
}
|
|
7104
|
-
|
|
7105
|
-
|
|
7106
|
-
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7111
|
-
|
|
7112
|
-
|
|
7113
|
-
client: options?.client,
|
|
7114
|
-
backend: toBackendConfig(options?.backend),
|
|
7115
|
-
headers: options?.headers,
|
|
7116
|
-
auth: options?.auth,
|
|
7117
|
-
experimental: options?.experimental
|
|
7118
|
-
});
|
|
7937
|
+
function createClient(configOrUrl, apiKey, options) {
|
|
7938
|
+
if (typeof configOrUrl === "string") {
|
|
7939
|
+
return createClientFromConfig(resolveCreateClientConfig({
|
|
7940
|
+
url: configOrUrl,
|
|
7941
|
+
key: apiKey ?? "",
|
|
7942
|
+
...options
|
|
7943
|
+
}));
|
|
7944
|
+
}
|
|
7945
|
+
return createClientFromConfig(resolveCreateClientConfig(configOrUrl));
|
|
7119
7946
|
}
|
|
7120
7947
|
|
|
7121
7948
|
// src/schema/postgres-introspection-core.ts
|
|
@@ -7712,6 +8539,7 @@ function rootUsage() {
|
|
|
7712
8539
|
"",
|
|
7713
8540
|
"Examples:",
|
|
7714
8541
|
" athena-js generate",
|
|
8542
|
+
" DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/app_db athena-js generate --dry-run",
|
|
7715
8543
|
" athena-js generate --config ./athena.config.ts --dry-run",
|
|
7716
8544
|
" athena-js generate --help"
|
|
7717
8545
|
].join("\n");
|
|
@@ -7728,8 +8556,14 @@ function generateUsage() {
|
|
|
7728
8556
|
" --dry-run Build generated files in memory without writing them to disk",
|
|
7729
8557
|
" -h, --help Show help for generate",
|
|
7730
8558
|
"",
|
|
8559
|
+
"Config resolution:",
|
|
8560
|
+
" - uses athena.config.* discovery first",
|
|
8561
|
+
" - falls back to env-only direct mode when DATABASE_URL/PG_URL is present",
|
|
8562
|
+
" - falls back to env-only gateway mode when ATHENA_URL + ATHENA_API_KEY are present",
|
|
8563
|
+
"",
|
|
7731
8564
|
"Examples:",
|
|
7732
8565
|
" athena-js generate",
|
|
8566
|
+
" DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/app_db athena-js generate --dry-run",
|
|
7733
8567
|
" athena-js generate --config ./athena.config.ts --dry-run"
|
|
7734
8568
|
].join("\n");
|
|
7735
8569
|
}
|