@xylex-group/athena 1.7.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -534,6 +534,12 @@ function mergeOptions(...options) {
534
534
  return { ...acc, ...next };
535
535
  }, void 0);
536
536
  }
537
+ function asAthenaJsonObject(value) {
538
+ return value;
539
+ }
540
+ function asAthenaJsonObjectArray(values) {
541
+ return values;
542
+ }
537
543
  function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS) {
538
544
  let selectedColumns = defaultColumns === null ? void 0 : defaultColumns;
539
545
  let selectedOptions;
@@ -622,6 +628,22 @@ function buildSelectColumnsClause(columns) {
622
628
  }
623
629
  return quoteSelectColumnsExpression(columns);
624
630
  }
631
+ function resolveTableNameForCall(tableName, schema) {
632
+ if (!schema) return tableName;
633
+ const normalizedSchema = schema.trim();
634
+ if (!normalizedSchema) {
635
+ throw new Error("schema option must be a non-empty string");
636
+ }
637
+ if (tableName.includes(".")) {
638
+ if (tableName.startsWith(`${normalizedSchema}.`)) {
639
+ return tableName;
640
+ }
641
+ throw new Error(
642
+ `schema option "${normalizedSchema}" conflicts with schema-qualified table "${tableName}"`
643
+ );
644
+ }
645
+ return `${normalizedSchema}.${tableName}`;
646
+ }
625
647
  function conditionToSqlClause(condition) {
626
648
  if (!condition.column) return null;
627
649
  const column = withCast(quoteQualifiedIdentifier(condition.column), condition.column_cast);
@@ -701,23 +723,27 @@ function buildTypedSelectQuery(input) {
701
723
  function createFilterMethods(state, addCondition, self) {
702
724
  return {
703
725
  eq(column, value) {
704
- if (shouldUseUuidTextComparison(column, value)) {
705
- addCondition("eq", column, value, { columnCast: "text" });
726
+ const columnName = String(column);
727
+ if (shouldUseUuidTextComparison(columnName, value)) {
728
+ addCondition("eq", columnName, value, { columnCast: "text" });
706
729
  } else {
707
- addCondition("eq", column, value);
730
+ addCondition("eq", columnName, value);
708
731
  }
709
732
  return self;
710
733
  },
711
734
  eqCast(column, value, cast) {
712
- addCondition("eq", column, value, { valueCast: cast });
735
+ addCondition("eq", String(column), value, { valueCast: cast });
713
736
  return self;
714
737
  },
715
738
  eqUuid(column, value) {
716
- addCondition("eq", column, value, { valueCast: "uuid" });
739
+ addCondition("eq", String(column), value, { valueCast: "uuid" });
717
740
  return self;
718
741
  },
719
742
  match(filters) {
720
743
  Object.entries(filters).forEach(([column, value]) => {
744
+ if (value === void 0) {
745
+ return;
746
+ }
721
747
  if (shouldUseUuidTextComparison(column, value)) {
722
748
  addCondition("eq", column, value, { columnCast: "text" });
723
749
  } else {
@@ -753,60 +779,61 @@ function createFilterMethods(state, addCondition, self) {
753
779
  },
754
780
  order(column, options) {
755
781
  state.order = {
756
- field: column,
782
+ field: String(column),
757
783
  direction: options?.ascending === false ? "descending" : "ascending"
758
784
  };
759
785
  return self;
760
786
  },
761
787
  gt(column, value) {
762
- addCondition("gt", column, value);
788
+ addCondition("gt", String(column), value);
763
789
  return self;
764
790
  },
765
791
  gte(column, value) {
766
- addCondition("gte", column, value);
792
+ addCondition("gte", String(column), value);
767
793
  return self;
768
794
  },
769
795
  lt(column, value) {
770
- addCondition("lt", column, value);
796
+ addCondition("lt", String(column), value);
771
797
  return self;
772
798
  },
773
799
  lte(column, value) {
774
- addCondition("lte", column, value);
800
+ addCondition("lte", String(column), value);
775
801
  return self;
776
802
  },
777
803
  neq(column, value) {
778
- addCondition("neq", column, value);
804
+ addCondition("neq", String(column), value);
779
805
  return self;
780
806
  },
781
807
  like(column, value) {
782
- addCondition("like", column, value);
808
+ addCondition("like", String(column), value);
783
809
  return self;
784
810
  },
785
811
  ilike(column, value) {
786
- addCondition("ilike", column, value);
812
+ addCondition("ilike", String(column), value);
787
813
  return self;
788
814
  },
789
815
  is(column, value) {
790
- addCondition("is", column, value);
816
+ addCondition("is", String(column), value);
791
817
  return self;
792
818
  },
793
819
  in(column, values) {
794
- addCondition("in", column, values);
820
+ addCondition("in", String(column), values);
795
821
  return self;
796
822
  },
797
823
  contains(column, values) {
798
- addCondition("contains", column, values);
824
+ addCondition("contains", String(column), values);
799
825
  return self;
800
826
  },
801
827
  containedBy(column, values) {
802
- addCondition("containedBy", column, values);
828
+ addCondition("containedBy", String(column), values);
803
829
  return self;
804
830
  },
805
831
  not(columnOrExpression, operator, value) {
832
+ const expression = String(columnOrExpression);
806
833
  if (operator != null && value !== void 0) {
807
- addCondition("not", void 0, `${columnOrExpression}.${operator}.${stringifyFilterValue(value)}`);
834
+ addCondition("not", void 0, `${expression}.${operator}.${stringifyFilterValue(value)}`);
808
835
  } else {
809
- addCondition("not", void 0, columnOrExpression);
836
+ addCondition("not", void 0, expression);
810
837
  }
811
838
  return self;
812
839
  },
@@ -976,15 +1003,20 @@ function createTableBuilder(tableName, client) {
976
1003
  state.conditions.push(condition);
977
1004
  };
978
1005
  const builder = {};
979
- const filterMethods = createFilterMethods(state, addCondition, builder);
1006
+ const filterMethods = createFilterMethods(
1007
+ state,
1008
+ addCondition,
1009
+ builder
1010
+ );
980
1011
  const runSelect = async (columns = DEFAULT_COLUMNS, options) => {
1012
+ const resolvedTableName = resolveTableNameForCall(tableName, options?.schema);
981
1013
  const conditions = state.conditions.length ? state.conditions.map((condition) => ({ ...condition })) : void 0;
982
1014
  const hasTypedEqualityComparison = conditions?.some(
983
1015
  (condition) => condition.operator === "eq" && (condition.value_cast !== void 0 || condition.column_cast !== void 0)
984
1016
  ) ?? false;
985
1017
  if (hasTypedEqualityComparison && !options?.head && !options?.count && conditions) {
986
1018
  const query = buildTypedSelectQuery({
987
- tableName,
1019
+ tableName: resolvedTableName,
988
1020
  columns,
989
1021
  conditions,
990
1022
  limit: state.limit,
@@ -999,7 +1031,7 @@ function createTableBuilder(tableName, client) {
999
1031
  }
1000
1032
  }
1001
1033
  const payload = {
1002
- table_name: tableName,
1034
+ table_name: resolvedTableName,
1003
1035
  columns,
1004
1036
  conditions,
1005
1037
  limit: state.limit,
@@ -1056,9 +1088,10 @@ function createTableBuilder(tableName, client) {
1056
1088
  if (Array.isArray(values)) {
1057
1089
  const executeInsertMany = async (columns, selectOptions) => {
1058
1090
  const mergedOptions = mergeOptions(options, selectOptions);
1091
+ const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
1059
1092
  const payload = {
1060
- table_name: tableName,
1061
- insert_body: values
1093
+ table_name: resolvedTableName,
1094
+ insert_body: asAthenaJsonObjectArray(values)
1062
1095
  };
1063
1096
  if (columns) payload.columns = columns;
1064
1097
  if (mergedOptions?.count) payload.count = mergedOptions.count;
@@ -1073,9 +1106,10 @@ function createTableBuilder(tableName, client) {
1073
1106
  }
1074
1107
  const executeInsertOne = async (columns, selectOptions) => {
1075
1108
  const mergedOptions = mergeOptions(options, selectOptions);
1109
+ const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
1076
1110
  const payload = {
1077
- table_name: tableName,
1078
- insert_body: values
1111
+ table_name: resolvedTableName,
1112
+ insert_body: asAthenaJsonObject(values)
1079
1113
  };
1080
1114
  if (columns) payload.columns = columns;
1081
1115
  if (mergedOptions?.count) payload.count = mergedOptions.count;
@@ -1092,10 +1126,11 @@ function createTableBuilder(tableName, client) {
1092
1126
  if (Array.isArray(values)) {
1093
1127
  const executeUpsertMany = async (columns, selectOptions) => {
1094
1128
  const mergedOptions = mergeOptions(options, selectOptions);
1129
+ const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
1095
1130
  const payload = {
1096
- table_name: tableName,
1097
- insert_body: values,
1098
- update_body: options?.updateBody ? options.updateBody : void 0
1131
+ table_name: resolvedTableName,
1132
+ insert_body: asAthenaJsonObjectArray(values),
1133
+ update_body: options?.updateBody ? asAthenaJsonObject(options.updateBody) : void 0
1099
1134
  };
1100
1135
  if (columns) payload.columns = columns;
1101
1136
  if (options?.onConflict) payload.on_conflict = options.onConflict;
@@ -1111,10 +1146,11 @@ function createTableBuilder(tableName, client) {
1111
1146
  }
1112
1147
  const executeUpsertOne = async (columns, selectOptions) => {
1113
1148
  const mergedOptions = mergeOptions(options, selectOptions);
1149
+ const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
1114
1150
  const payload = {
1115
- table_name: tableName,
1116
- insert_body: values,
1117
- update_body: options?.updateBody ? options.updateBody : void 0
1151
+ table_name: resolvedTableName,
1152
+ insert_body: asAthenaJsonObject(values),
1153
+ update_body: options?.updateBody ? asAthenaJsonObject(options.updateBody) : void 0
1118
1154
  };
1119
1155
  if (columns) payload.columns = columns;
1120
1156
  if (options?.onConflict) payload.on_conflict = options.onConflict;
@@ -1132,9 +1168,10 @@ function createTableBuilder(tableName, client) {
1132
1168
  const executeUpdate = async (columns, selectOptions) => {
1133
1169
  const filters = state.conditions.length ? [...state.conditions] : void 0;
1134
1170
  const mergedOptions = mergeOptions(options, selectOptions);
1171
+ const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
1135
1172
  const payload = {
1136
- table_name: tableName,
1137
- set: values,
1173
+ table_name: resolvedTableName,
1174
+ set: asAthenaJsonObject(values),
1138
1175
  conditions: filters,
1139
1176
  strip_nulls: mergedOptions?.stripNulls ?? true
1140
1177
  };
@@ -1160,8 +1197,9 @@ function createTableBuilder(tableName, client) {
1160
1197
  }
1161
1198
  const executeDelete = async (columns, selectOptions) => {
1162
1199
  const mergedOptions = mergeOptions(options, selectOptions);
1200
+ const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
1163
1201
  const payload = {
1164
- table_name: tableName,
1202
+ table_name: resolvedTableName,
1165
1203
  resource_id: resourceId,
1166
1204
  conditions: filters
1167
1205
  };
@@ -2274,6 +2312,67 @@ function createPostgresIntrospectionProvider(options) {
2274
2312
  return new PostgresIntrospectionProvider(options);
2275
2313
  }
2276
2314
 
2315
+ // src/schema/model-form.ts
2316
+ function resolveNullishValue(mode) {
2317
+ if (mode === "undefined") return void 0;
2318
+ if (mode === "null") return null;
2319
+ return "";
2320
+ }
2321
+ function isRecord3(value) {
2322
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
2323
+ }
2324
+ function isNullableColumn(model, key) {
2325
+ const nullable = model.meta.nullable;
2326
+ return nullable?.[key] === true;
2327
+ }
2328
+ function toModelFormDefaults(model, values, options) {
2329
+ const source = values;
2330
+ if (!isRecord3(source)) {
2331
+ return {};
2332
+ }
2333
+ const mode = options?.nullishMode ?? "empty-string";
2334
+ const nullishValue = resolveNullishValue(mode);
2335
+ const result = {};
2336
+ for (const [key, value] of Object.entries(source)) {
2337
+ if (value === null && isNullableColumn(model, key)) {
2338
+ result[key] = nullishValue;
2339
+ continue;
2340
+ }
2341
+ result[key] = value;
2342
+ }
2343
+ return result;
2344
+ }
2345
+ function toModelPayload(model, formValues, options) {
2346
+ const emptyStringAsNull = options?.emptyStringAsNull ?? true;
2347
+ const stripUndefined = options?.stripUndefined ?? true;
2348
+ const result = {};
2349
+ for (const [key, rawValue] of Object.entries(formValues)) {
2350
+ if (rawValue === void 0 && stripUndefined) {
2351
+ continue;
2352
+ }
2353
+ if (emptyStringAsNull && rawValue === "" && isNullableColumn(model, key)) {
2354
+ result[key] = null;
2355
+ continue;
2356
+ }
2357
+ result[key] = rawValue;
2358
+ }
2359
+ return result;
2360
+ }
2361
+ function createModelFormAdapter(model) {
2362
+ return {
2363
+ model,
2364
+ toDefaults(values, options) {
2365
+ return toModelFormDefaults(model, values, options);
2366
+ },
2367
+ toInsert(values, options) {
2368
+ return toModelPayload(model, values, options);
2369
+ },
2370
+ toUpdate(values, options) {
2371
+ return toModelPayload(model, values, options);
2372
+ }
2373
+ };
2374
+ }
2375
+
2277
2376
  // src/generator/schema-selection.ts
2278
2377
  var DEFAULT_POSTGRES_SCHEMAS = ["public"];
2279
2378
  function collectSchemaNames(input) {
@@ -3133,7 +3232,7 @@ var SDK_HEADER_VALUE2 = `${SDK_NAME2} ${SDK_VERSION2}`;
3133
3232
  function normalizeBaseUrl(baseUrl) {
3134
3233
  return (baseUrl ?? DEFAULT_AUTH_BASE_URL).replace(/\/$/, "");
3135
3234
  }
3136
- function isRecord3(value) {
3235
+ function isRecord4(value) {
3137
3236
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
3138
3237
  }
3139
3238
  function normalizeHeaderValue2(value) {
@@ -3158,7 +3257,7 @@ function resolveRequestId2(headers) {
3158
3257
  return headers.get("x-request-id") ?? headers.get("x-correlation-id") ?? headers.get("x-athena-request-id") ?? void 0;
3159
3258
  }
3160
3259
  function resolveErrorMessage2(payload, fallback) {
3161
- if (isRecord3(payload)) {
3260
+ if (isRecord4(payload)) {
3162
3261
  const messageCandidates = [payload.error, payload.message, payload.details];
3163
3262
  for (const candidate of messageCandidates) {
3164
3263
  if (typeof candidate === "string" && candidate.trim().length > 0) {
@@ -3627,6 +3726,7 @@ exports.assertInt = assertInt;
3627
3726
  exports.coerceInt = coerceInt;
3628
3727
  exports.createAuthClient = createAuthClient;
3629
3728
  exports.createClient = createClient;
3729
+ exports.createModelFormAdapter = createModelFormAdapter;
3630
3730
  exports.createPostgresIntrospectionProvider = createPostgresIntrospectionProvider;
3631
3731
  exports.createTypedClient = createTypedClient;
3632
3732
  exports.defineDatabase = defineDatabase;
@@ -3649,6 +3749,8 @@ exports.resolveGeneratorProvider = resolveGeneratorProvider;
3649
3749
  exports.resolvePostgresColumnType = resolvePostgresColumnType;
3650
3750
  exports.resolveProviderSchemas = resolveProviderSchemas;
3651
3751
  exports.runSchemaGenerator = runSchemaGenerator;
3752
+ exports.toModelFormDefaults = toModelFormDefaults;
3753
+ exports.toModelPayload = toModelPayload;
3652
3754
  exports.unwrap = unwrap;
3653
3755
  exports.unwrapOne = unwrapOne;
3654
3756
  exports.unwrapRows = unwrapRows;