@fjell/lib-sequelize 4.4.69 → 4.4.71

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.
@@ -1 +1 @@
1
- {"version":3,"file":"RowProcessor.d.ts","sourceRoot":"","sources":["../src/RowProcessor.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAIlC,OAAO,EAAE,qBAAqB,EAAE,4BAA4B,EAAE,MAAM,WAAW,CAAC;AAChF,OAAO,KAAK,OAAO,MAAM,YAAY,CAAC;AACtC,OAAO,EAEL,cAAc,EACd,sBAAsB,EACtB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAQpB,YAAY,EAAE,gBAAgB,EAAE,CAAC;AACjC,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,CAAC;AAElD,eAAO,MAAM,UAAU,GAAU,CAAC,SAAS,MAAM,EAC/C,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACvB,KAAK,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,EACpB,UAAU,iBAAiB,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAClD,sBAAsB,4BAA4B,EAAE,EACpD,wBAAwB,qBAAqB,EAAE,EAC/C,UAAU,OAAO,CAAC,QAAQ,EAC1B,UAAU,gBAAgB,KACzB,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAyCvC,CAAC"}
1
+ {"version":3,"file":"RowProcessor.d.ts","sourceRoot":"","sources":["../src/RowProcessor.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAIlC,OAAO,EAAE,qBAAqB,EAAE,4BAA4B,EAAE,MAAM,WAAW,CAAC;AAChF,OAAO,KAAK,OAAO,MAAM,YAAY,CAAC;AACtC,OAAO,EAEL,cAAc,EACd,sBAAsB,EACtB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAUpB,YAAY,EAAE,gBAAgB,EAAE,CAAC;AACjC,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,CAAC;AAElD,eAAO,MAAM,UAAU,GAAU,CAAC,SAAS,MAAM,EAC/C,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACvB,KAAK,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,EACpB,UAAU,iBAAiB,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAClD,sBAAsB,4BAA4B,EAAE,EACpD,wBAAwB,qBAAqB,EAAE,EAC/C,UAAU,OAAO,CAAC,QAAQ,EAC1B,UAAU,gBAAgB,KACzB,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAqEvC,CAAC"}
package/dist/index.js CHANGED
@@ -580,11 +580,11 @@ var removeEvents = (item) => {
580
580
 
581
581
  // src/processing/ReferenceBuilder.ts
582
582
  var buildSequelizeReference = async (item, referenceDefinition, registry, context) => {
583
- const libLogger = logger_default.get("processing", "ReferenceBuilder");
583
+ const libLogger3 = logger_default.get("processing", "ReferenceBuilder");
584
584
  const isCompositeItem = referenceDefinition.kta.length > 1;
585
585
  const primaryKeyType = referenceDefinition.kta[0];
586
586
  if (isCompositeItem) {
587
- libLogger.debug(
587
+ libLogger3.debug(
588
588
  "Detected composite item reference - will use ComKey with empty loc array",
589
589
  {
590
590
  kta: referenceDefinition.kta,
@@ -619,18 +619,15 @@ var buildSequelizeReference = async (item, referenceDefinition, registry, contex
619
619
  } else if (referenceDefinition.locationColumns && referenceDefinition.locationColumns.length > 0) {
620
620
  const locationTypes = referenceDefinition.kta.slice(1);
621
621
  const loc = [];
622
+ let hasNullLocation = false;
622
623
  for (let i = 0; i < referenceDefinition.locationColumns.length; i++) {
623
624
  const columnName = referenceDefinition.locationColumns[i];
624
625
  const locValue = item[columnName];
625
626
  if (locValue == null) {
626
- libLogger.warning(
627
+ libLogger3.warning(
627
628
  `Location column '${columnName}' is null/undefined for reference '${referenceDefinition.property}'. Falling back to empty loc array search.`
628
629
  );
629
- itemKey = {
630
- kt: primaryKeyType,
631
- pk: columnValue,
632
- loc: []
633
- };
630
+ hasNullLocation = true;
634
631
  break;
635
632
  }
636
633
  loc.push({
@@ -638,13 +635,19 @@ var buildSequelizeReference = async (item, referenceDefinition, registry, contex
638
635
  lk: locValue
639
636
  });
640
637
  }
641
- if (!itemKey) {
638
+ if (hasNullLocation) {
639
+ itemKey = {
640
+ kt: primaryKeyType,
641
+ pk: columnValue,
642
+ loc: []
643
+ };
644
+ } else {
642
645
  itemKey = {
643
646
  kt: primaryKeyType,
644
647
  pk: columnValue,
645
648
  loc
646
649
  };
647
- libLogger.debug("Built full ComKey with location context", {
650
+ libLogger3.debug("Built full ComKey with location context", {
648
651
  itemKey,
649
652
  locationColumns: referenceDefinition.locationColumns,
650
653
  property: referenceDefinition.property
@@ -656,12 +659,12 @@ var buildSequelizeReference = async (item, referenceDefinition, registry, contex
656
659
  pk: columnValue,
657
660
  loc: []
658
661
  };
659
- libLogger.debug("Using empty loc array for composite item reference", {
662
+ libLogger3.debug("Using empty loc array for composite item reference", {
660
663
  kta: referenceDefinition.kta,
661
664
  property: referenceDefinition.property
662
665
  });
663
666
  }
664
- libLogger.debug("Created reference key", {
667
+ libLogger3.debug("Created reference key", {
665
668
  itemKey,
666
669
  isCompositeItem,
667
670
  hasLocationColumns: !!referenceDefinition.locationColumns,
@@ -670,10 +673,10 @@ var buildSequelizeReference = async (item, referenceDefinition, registry, contex
670
673
  let referencedItem;
671
674
  if (context) {
672
675
  if (context.isCached(itemKey)) {
673
- libLogger.debug("Using cached reference", { itemKey, property: referenceDefinition.property });
676
+ libLogger3.debug("Using cached reference", { itemKey, property: referenceDefinition.property });
674
677
  referencedItem = context.getCached(itemKey);
675
678
  } else if (context.isInProgress(itemKey)) {
676
- libLogger.debug("Circular dependency detected, creating reference placeholder", {
679
+ libLogger3.debug("Circular dependency detected, creating reference placeholder", {
677
680
  itemKey,
678
681
  property: referenceDefinition.property
679
682
  });
@@ -707,6 +710,173 @@ var stripSequelizeReferenceItems = (item, referenceDefinitions) => {
707
710
  return result;
708
711
  };
709
712
 
713
+ // src/processing/RefsAdapter.ts
714
+ import { isComKey as isComKey2, isPriKey as isPriKey2 } from "@fjell/core";
715
+ var libLogger = logger_default.get("sequelize", "processing", "RefsAdapter");
716
+ function buildKeyFromForeignKey(refDef, foreignKeyValue, item) {
717
+ const primaryKeyType = refDef.kta[0];
718
+ const isCompositeItem = refDef.kta.length > 1;
719
+ if (!isCompositeItem) {
720
+ return {
721
+ kt: primaryKeyType,
722
+ pk: foreignKeyValue
723
+ };
724
+ }
725
+ const loc = [];
726
+ if (refDef.locationColumns && refDef.locationColumns.length > 0) {
727
+ for (let i = 0; i < refDef.locationColumns.length; i++) {
728
+ const columnName = refDef.locationColumns[i];
729
+ const locValue = item[columnName];
730
+ if (locValue != null) {
731
+ const locationType = refDef.kta[i + 1];
732
+ loc.push({
733
+ kt: locationType,
734
+ lk: locValue
735
+ });
736
+ } else {
737
+ libLogger.debug(
738
+ `Location column '${columnName}' is null/undefined for reference '${refDef.property}'. Using empty loc array.`
739
+ );
740
+ break;
741
+ }
742
+ }
743
+ }
744
+ return {
745
+ kt: primaryKeyType,
746
+ pk: foreignKeyValue,
747
+ loc: loc.length > 0 ? loc : []
748
+ };
749
+ }
750
+ function addRefsToSequelizeItem(item, referenceDefinitions) {
751
+ const refs = {};
752
+ for (const refDef of referenceDefinitions) {
753
+ const foreignKeyValue = item[refDef.column];
754
+ const refName = refDef.property;
755
+ if (foreignKeyValue != null) {
756
+ const key = buildKeyFromForeignKey(refDef, foreignKeyValue, item);
757
+ const populatedItem = item[refDef.property];
758
+ if (populatedItem) {
759
+ const { key: _itemKey, ...itemProperties } = populatedItem;
760
+ refs[refName] = {
761
+ key,
762
+ ...itemProperties
763
+ };
764
+ } else {
765
+ refs[refName] = {
766
+ key
767
+ };
768
+ }
769
+ } else {
770
+ refs[refName] = {
771
+ key: {
772
+ kt: refDef.kta[0],
773
+ pk: null
774
+ // Will be handled as null reference
775
+ }
776
+ };
777
+ }
778
+ }
779
+ return {
780
+ ...item,
781
+ refs
782
+ };
783
+ }
784
+ function updateForeignKeysFromRefs(item, refs, referenceDefinitions) {
785
+ for (const refDef of referenceDefinitions) {
786
+ const refName = refDef.property;
787
+ const ref = refs[refName];
788
+ if (ref && ref.key) {
789
+ if (isPriKey2(ref.key)) {
790
+ item[refDef.column] = ref.key.pk;
791
+ } else if (isComKey2(ref.key)) {
792
+ const comKey = ref.key;
793
+ item[refDef.column] = comKey.pk;
794
+ if (refDef.locationColumns && comKey.loc) {
795
+ comKey.loc.forEach((locItem, index) => {
796
+ if (refDef.locationColumns && refDef.locationColumns[index]) {
797
+ item[refDef.locationColumns[index]] = locItem.lk;
798
+ }
799
+ });
800
+ }
801
+ }
802
+ const { key, ...itemProperties } = ref;
803
+ const hasItemProperties = Object.keys(itemProperties).length > 0;
804
+ if (hasItemProperties) {
805
+ item[refDef.property] = {
806
+ key,
807
+ ...itemProperties
808
+ };
809
+ } else {
810
+ delete item[refDef.property];
811
+ }
812
+ } else if (ref == null) {
813
+ if (refName in refs) {
814
+ item[refDef.column] = null;
815
+ delete item[refDef.property];
816
+ }
817
+ }
818
+ }
819
+ }
820
+ function removeRefsFromSequelizeItem(item, referenceDefinitions) {
821
+ const result = { ...item };
822
+ if (result.refs) {
823
+ updateForeignKeysFromRefs(result, result.refs, referenceDefinitions);
824
+ delete result.refs;
825
+ }
826
+ return result;
827
+ }
828
+
829
+ // src/processing/AggsAdapter.ts
830
+ var libLogger2 = logger_default.get("sequelize", "processing", "AggsAdapter");
831
+ function addAggsToItem(item, aggregationDefinitions) {
832
+ if (!aggregationDefinitions || aggregationDefinitions.length === 0) {
833
+ return item;
834
+ }
835
+ const aggs = {};
836
+ const result = { ...item };
837
+ for (const aggDef of aggregationDefinitions) {
838
+ const aggregationValue = item[aggDef.property];
839
+ if (typeof aggregationValue !== "undefined") {
840
+ aggs[aggDef.property] = aggregationValue;
841
+ delete result[aggDef.property];
842
+ libLogger2.debug(`Moved aggregation '${aggDef.property}' to aggs structure`, {
843
+ property: aggDef.property,
844
+ hasValue: typeof aggregationValue !== "undefined",
845
+ valueType: Array.isArray(aggregationValue) ? "array" : typeof aggregationValue
846
+ });
847
+ } else {
848
+ libLogger2.debug(`Aggregation '${aggDef.property}' is undefined, skipping`, {
849
+ property: aggDef.property
850
+ });
851
+ }
852
+ }
853
+ if (Object.keys(aggs).length > 0) {
854
+ return {
855
+ ...result,
856
+ aggs
857
+ };
858
+ }
859
+ return item;
860
+ }
861
+ function removeAggsFromItem(item, aggregationDefinitions) {
862
+ if (!aggregationDefinitions || aggregationDefinitions.length === 0) {
863
+ return item;
864
+ }
865
+ const result = { ...item };
866
+ if (result.aggs && typeof result.aggs === "object") {
867
+ for (const aggDef of aggregationDefinitions) {
868
+ if (typeof result.aggs[aggDef.property] !== "undefined") {
869
+ result[aggDef.property] = result.aggs[aggDef.property];
870
+ libLogger2.debug(`Moved aggregation '${aggDef.property}' from aggs to direct property`, {
871
+ property: aggDef.property
872
+ });
873
+ }
874
+ }
875
+ delete result.aggs;
876
+ }
877
+ return result;
878
+ }
879
+
710
880
  // src/RowProcessor.ts
711
881
  var logger6 = logger_default.get("sequelize", "RowProcessor");
712
882
  var processRow = async (row, keyTypes, referenceDefinitions, aggregationDefinitions, registry, context) => {
@@ -721,9 +891,15 @@ var processRow = async (row, keyTypes, referenceDefinitions, aggregationDefiniti
721
891
  operationContext.markInProgress(item.key);
722
892
  try {
723
893
  if (referenceDefinitions && referenceDefinitions.length > 0) {
724
- for (const referenceDefinition of referenceDefinitions) {
894
+ const referenceStartTime = typeof performance !== "undefined" ? performance.now() : Date.now();
895
+ const referencePromises = referenceDefinitions.map((referenceDefinition) => {
725
896
  logger6.default("Processing Reference for %s to %s", item.key.kt, stringifyJSON(referenceDefinition.kta));
726
- item = await buildSequelizeReference(item, referenceDefinition, registry, operationContext);
897
+ return buildSequelizeReference(item, referenceDefinition, registry, operationContext);
898
+ });
899
+ await Promise.all(referencePromises);
900
+ const referenceDuration = (typeof performance !== "undefined" ? performance.now() : Date.now()) - referenceStartTime;
901
+ if (referenceDuration > 100) {
902
+ logger6.debug(`\u23F1\uFE0F REFERENCE_BUILDER_PERF: Loaded ${referenceDefinitions.length} references in parallel for ${item.key.kt} - ${referenceDuration.toFixed(2)}ms`);
727
903
  }
728
904
  }
729
905
  if (aggregationDefinitions && aggregationDefinitions.length > 0) {
@@ -736,6 +912,14 @@ var processRow = async (row, keyTypes, referenceDefinitions, aggregationDefiniti
736
912
  } finally {
737
913
  operationContext.markComplete(item.key);
738
914
  }
915
+ if (referenceDefinitions && referenceDefinitions.length > 0) {
916
+ item = addRefsToSequelizeItem(item, referenceDefinitions);
917
+ logger6.debug("Added refs structure to item (transparent wrapper)", { key: item.key });
918
+ }
919
+ if (aggregationDefinitions && aggregationDefinitions.length > 0) {
920
+ item = addAggsToItem(item, aggregationDefinitions);
921
+ logger6.debug("Added aggs structure to item (transparent wrapper)", { key: item.key });
922
+ }
739
923
  logger6.default("Processed Row: %j", stringifyJSON(item));
740
924
  return item;
741
925
  });
@@ -958,7 +1142,7 @@ var getAllOperation = (models, definition, registry) => {
958
1142
  const { coordinate, options: { references, aggregations } } = definition;
959
1143
  return createAllWrapper(
960
1144
  coordinate,
961
- async (itemQuery, locations) => {
1145
+ async (itemQuery, locations, allOptions) => {
962
1146
  try {
963
1147
  const locs = locations ?? [];
964
1148
  logger7.debug(`ALL operation called on ${models[0].name} with ${locs.length} location filters: ${locs.map((loc2) => `${loc2.kt}=${loc2.lk}`).join(", ") || "none"}`);
@@ -1023,7 +1207,31 @@ var getAllOperation = (models, definition, registry) => {
1023
1207
  options.include = mergeIncludes(existingIncludes, additionalIncludes);
1024
1208
  }
1025
1209
  }
1026
- logger7.default(`All query configured for ${model.name} with where fields: ${options.where ? Object.keys(options.where).join(", ") : "none"}, includes: ${options.include?.length || 0}`);
1210
+ const effectiveLimit = allOptions?.limit ?? itemQuery?.limit;
1211
+ const effectiveOffset = allOptions?.offset ?? itemQuery?.offset ?? 0;
1212
+ const whereFields = options.where ? Object.keys(options.where).join(", ") : "none";
1213
+ const includeCount = options.include?.length || 0;
1214
+ logger7.default(
1215
+ `All query configured for ${model.name} with where fields: ${whereFields}, includes: ${includeCount}, limit: ${effectiveLimit}, offset: ${effectiveOffset}`
1216
+ );
1217
+ const countOptions = {
1218
+ where: options.where,
1219
+ distinct: true
1220
+ };
1221
+ if (options.include) {
1222
+ countOptions.include = options.include;
1223
+ }
1224
+ const countResult = await model.count(countOptions);
1225
+ const total = Array.isArray(countResult) ? countResult.length : countResult;
1226
+ logger7.debug(`[ALL] Total count for ${model.name}: ${total}`);
1227
+ delete options.limit;
1228
+ delete options.offset;
1229
+ if (effectiveLimit !== void 0) {
1230
+ options.limit = effectiveLimit;
1231
+ }
1232
+ if (effectiveOffset > 0) {
1233
+ options.offset = effectiveOffset;
1234
+ }
1027
1235
  try {
1028
1236
  logger7.trace(`[ALL] Executing ${model.name}.findAll() with options: ${JSON.stringify(options, null, 2)}`);
1029
1237
  } catch {
@@ -1031,12 +1239,21 @@ var getAllOperation = (models, definition, registry) => {
1031
1239
  }
1032
1240
  const matchingItems = await model.findAll(options);
1033
1241
  const currentContext = contextManager.getCurrentContext();
1034
- const results = await Promise.all(matchingItems.map(async (row) => {
1242
+ const items = await Promise.all(matchingItems.map(async (row) => {
1035
1243
  const processedRow = await processRow(row, coordinate.kta, references || [], aggregations || [], registry, currentContext);
1036
1244
  return validateKeys(processedRow, coordinate.kta);
1037
1245
  }));
1038
- logger7.debug(`[ALL] Returning ${results.length} ${model.name} records`);
1039
- return results;
1246
+ logger7.debug(`[ALL] Returning ${items.length} of ${total} ${model.name} records`);
1247
+ return {
1248
+ items,
1249
+ metadata: {
1250
+ total,
1251
+ returned: items.length,
1252
+ limit: effectiveLimit,
1253
+ offset: effectiveOffset,
1254
+ hasMore: effectiveOffset + items.length < total
1255
+ }
1256
+ };
1040
1257
  } catch (error) {
1041
1258
  throw transformSequelizeError(error, coordinate.kta[0]);
1042
1259
  }
@@ -1045,7 +1262,7 @@ var getAllOperation = (models, definition, registry) => {
1045
1262
  };
1046
1263
 
1047
1264
  // src/ops/create.ts
1048
- import { createCreateWrapper, isComKey as isComKey2, isPriKey as isPriKey2 } from "@fjell/core";
1265
+ import { createCreateWrapper, isComKey as isComKey3, isPriKey as isPriKey3 } from "@fjell/core";
1049
1266
  import { validateKeys as validateKeys2 } from "@fjell/core/validation";
1050
1267
  var logger8 = logger_default.get("sequelize", "ops", "create");
1051
1268
  async function validateHierarchicalChain(models, locKey, kta) {
@@ -1086,7 +1303,7 @@ var getCreateOperation = (models, definition, registry) => {
1086
1303
  return createCreateWrapper(
1087
1304
  coordinate,
1088
1305
  async (item, options) => {
1089
- const constraints = options?.key ? `key: pk=${options.key.pk}, loc=[${isComKey2(options.key) ? options.key.loc.map((l) => `${l.kt}=${l.lk}`).join(", ") : ""}]` : options?.locations ? `locations: ${options.locations.map((loc) => `${loc.kt}=${loc.lk}`).join(", ")}` : "no constraints";
1306
+ const constraints = options?.key ? `key: pk=${options.key.pk}, loc=[${isComKey3(options.key) ? options.key.loc.map((l) => `${l.kt}=${l.lk}`).join(", ") : ""}]` : options?.locations ? `locations: ${options.locations.map((loc) => `${loc.kt}=${loc.lk}`).join(", ")}` : "no constraints";
1090
1307
  logger8.debug(`CREATE operation called on ${models[0].name} with ${constraints}`);
1091
1308
  logger8.default(`Create configured for ${models[0].name} with ${Object.keys(item).length} item fields`);
1092
1309
  const model = models[0];
@@ -1094,6 +1311,12 @@ var getCreateOperation = (models, definition, registry) => {
1094
1311
  let itemData = { ...item };
1095
1312
  itemData = extractEvents(itemData);
1096
1313
  itemData = removeEvents(itemData);
1314
+ if (references && references.length > 0) {
1315
+ itemData = removeRefsFromSequelizeItem(itemData, references);
1316
+ }
1317
+ if (aggregations && aggregations.length > 0) {
1318
+ itemData = removeAggsFromItem(itemData, aggregations);
1319
+ }
1097
1320
  const invalidAttributes = [];
1098
1321
  for (const key of Object.keys(itemData)) {
1099
1322
  if (!modelAttributes[key]) {
@@ -1108,9 +1331,9 @@ var getCreateOperation = (models, definition, registry) => {
1108
1331
  }
1109
1332
  if (options?.key) {
1110
1333
  const key = options.key;
1111
- if (isPriKey2(key)) {
1334
+ if (isPriKey3(key)) {
1112
1335
  itemData.id = key.pk;
1113
- } else if (isComKey2(key)) {
1336
+ } else if (isComKey3(key)) {
1114
1337
  itemData.id = key.pk;
1115
1338
  const comKey = key;
1116
1339
  const directLocations = [];
@@ -1193,7 +1416,7 @@ var getFindOperation = (models, definition, registry) => {
1193
1416
  const { options: { finders, references, aggregations } } = definition;
1194
1417
  return createFindWrapper(
1195
1418
  definition.coordinate,
1196
- async (finder, finderParams, locations) => {
1419
+ async (finder, finderParams, locations, findOptions) => {
1197
1420
  try {
1198
1421
  const locs = locations ?? [];
1199
1422
  const params = finderParams ?? {};
@@ -1202,30 +1425,45 @@ var getFindOperation = (models, definition, registry) => {
1202
1425
  `FIND operation called on ${models[0].name} with finder '${finder}' and ${locs.length} location filters: ${locationFilters}`
1203
1426
  );
1204
1427
  logger9.default(`Find configured for ${models[0].name} using finder '${finder}' with ${Object.keys(params).length} params`);
1205
- if (finders && finders[finder]) {
1206
- const finderMethod = finders[finder];
1207
- if (finderMethod) {
1208
- logger9.trace(`[FIND] Executing finder '${finder}' on ${models[0].name} with params: ${stringifyJSON(params)}, locations: ${stringifyJSON(locs)}`);
1209
- const results = await finderMethod(params, locs);
1210
- if (results && results.length > 0) {
1211
- const processedResults = await Promise.all(results.map(async (row) => {
1212
- const processedRow = await processRow(row, definition.coordinate.kta, references || [], aggregations || [], registry);
1213
- return validateKeys3(processedRow, definition.coordinate.kta);
1214
- }));
1215
- logger9.debug(`[FIND] Found ${processedResults.length} ${models[0].name} records using finder '${finder}'`);
1216
- return processedResults;
1217
- } else {
1218
- logger9.debug(`[FIND] Found 0 ${models[0].name} records using finder '${finder}'`);
1219
- return [];
1220
- }
1221
- } else {
1222
- logger9.error(`Finder %s not found`, finder);
1223
- throw new Error(`Finder ${finder} not found`);
1224
- }
1225
- } else {
1428
+ if (!finders || !finders[finder]) {
1226
1429
  logger9.error(`No finders have been defined for this lib`);
1227
1430
  throw new Error(`No finders found`);
1228
1431
  }
1432
+ const finderMethod = finders[finder];
1433
+ if (!finderMethod) {
1434
+ logger9.error(`Finder %s not found`, finder);
1435
+ throw new Error(`Finder ${finder} not found`);
1436
+ }
1437
+ logger9.trace(`[FIND] Executing finder '${finder}' on ${models[0].name} with params: ${stringifyJSON(params)}, locations: ${stringifyJSON(locs)}, options: ${stringifyJSON(findOptions)}`);
1438
+ const finderResult = await finderMethod(params, locs, findOptions);
1439
+ const processItems = async (items) => {
1440
+ return await Promise.all(items.map(async (row) => {
1441
+ const processedRow = await processRow(row, definition.coordinate.kta, references || [], aggregations || [], registry);
1442
+ return validateKeys3(processedRow, definition.coordinate.kta);
1443
+ }));
1444
+ };
1445
+ const isOptInResult = finderResult && typeof finderResult === "object" && "items" in finderResult && "metadata" in finderResult;
1446
+ if (isOptInResult) {
1447
+ const optInResult = finderResult;
1448
+ const processedResults2 = optInResult.items && optInResult.items.length > 0 ? await processItems(optInResult.items) : [];
1449
+ logger9.debug(`[FIND] Finder opted-in, found ${processedResults2.length} ${models[0].name} records using finder '${finder}' (total: ${optInResult.metadata.total})`);
1450
+ return {
1451
+ items: processedResults2,
1452
+ metadata: optInResult.metadata
1453
+ };
1454
+ }
1455
+ const results = finderResult;
1456
+ const processedResults = results && results.length > 0 ? await processItems(results) : [];
1457
+ logger9.debug(`[FIND] Legacy finder, found ${processedResults.length} ${models[0].name} records using finder '${finder}'`);
1458
+ return {
1459
+ items: processedResults,
1460
+ metadata: {
1461
+ total: processedResults.length,
1462
+ returned: processedResults.length,
1463
+ offset: 0,
1464
+ hasMore: false
1465
+ }
1466
+ };
1229
1467
  } catch (error) {
1230
1468
  throw transformSequelizeError(error, definition.coordinate.kta[0]);
1231
1469
  }
@@ -1236,8 +1474,8 @@ var getFindOperation = (models, definition, registry) => {
1236
1474
  // src/ops/get.ts
1237
1475
  import {
1238
1476
  createGetWrapper,
1239
- isComKey as isComKey3,
1240
- isPriKey as isPriKey3,
1477
+ isComKey as isComKey4,
1478
+ isPriKey as isPriKey4,
1241
1479
  isValidItemKey,
1242
1480
  validateKeys as validateKeys4
1243
1481
  } from "@fjell/core";
@@ -1280,16 +1518,16 @@ var getGetOperation = (models, definition, registry) => {
1280
1518
  logger10.error("Key for Get is not a valid ItemKey: %j", key);
1281
1519
  throw new Error("Key for Get is not a valid ItemKey");
1282
1520
  }
1283
- const keyDescription = isPriKey3(key) ? `primary key: pk=${key.pk}` : `composite key: pk=${key.pk}, loc=[${key.loc.map((l) => `${l.kt}=${l.lk}`).join(", ")}]`;
1521
+ const keyDescription = isPriKey4(key) ? `primary key: pk=${key.pk}` : `composite key: pk=${key.pk}, loc=[${key.loc.map((l) => `${l.kt}=${l.lk}`).join(", ")}]`;
1284
1522
  logger10.debug(`GET operation called on ${models[0].name} with ${keyDescription}`);
1285
- logger10.default(`Get configured for ${models[0].name} with ${isPriKey3(key) ? "primary" : "composite"} key`);
1523
+ logger10.default(`Get configured for ${models[0].name} with ${isPriKey4(key) ? "primary" : "composite"} key`);
1286
1524
  const itemKey = key;
1287
1525
  const model = models[0];
1288
1526
  let item;
1289
- if (isPriKey3(itemKey)) {
1527
+ if (isPriKey4(itemKey)) {
1290
1528
  logger10.trace(`[GET] Executing ${model.name}.findByPk() with pk: ${itemKey.pk}`);
1291
1529
  item = await model.findByPk(itemKey.pk);
1292
- } else if (isComKey3(itemKey)) {
1530
+ } else if (isComKey4(itemKey)) {
1293
1531
  const comKey = itemKey;
1294
1532
  if (comKey.loc.length === 0) {
1295
1533
  logger10.debug(`[GET] Empty loc array detected - finding by primary key across all locations: ${comKey.pk}`);
@@ -1331,11 +1569,11 @@ var getOneOperation = (models, definition, registry) => {
1331
1569
  const locs = locations ?? [];
1332
1570
  logger11.debug(`ONE operation called on ${models[0].name} with ${locs.length} location filters: ${locs.map((loc) => `${loc.kt}=${loc.lk}`).join(", ") || "none"}`);
1333
1571
  logger11.default(`One configured for ${models[0].name} delegating to all operation`);
1334
- const items = await getAllOperation(models, definition, registry)(itemQuery ?? {}, locs);
1335
- if (items.length > 0) {
1336
- const result = items[0];
1337
- logger11.debug(`[ONE] Found ${models[0].name} record with key: ${result.key ? JSON.stringify(result.key) : "unknown"}`);
1338
- return result;
1572
+ const result = await getAllOperation(models, definition, registry)(itemQuery ?? {}, locs, { limit: 1 });
1573
+ if (result.items.length > 0) {
1574
+ const item = result.items[0];
1575
+ logger11.debug(`[ONE] Found ${models[0].name} record with key: ${item.key ? JSON.stringify(item.key) : "unknown"}`);
1576
+ return item;
1339
1577
  } else {
1340
1578
  logger11.debug(`[ONE] No ${models[0].name} record found`);
1341
1579
  return null;
@@ -1345,7 +1583,7 @@ var getOneOperation = (models, definition, registry) => {
1345
1583
  };
1346
1584
 
1347
1585
  // src/ops/remove.ts
1348
- import { abbrevIK, isComKey as isComKey4, isPriKey as isPriKey4, isValidItemKey as isValidItemKey2, createRemoveWrapper } from "@fjell/core";
1586
+ import { abbrevIK, isComKey as isComKey5, isPriKey as isPriKey5, isValidItemKey as isValidItemKey2, createRemoveWrapper } from "@fjell/core";
1349
1587
  import { NotFoundError as NotFoundError2 } from "@fjell/core";
1350
1588
  var logger12 = logger_default.get("sequelize", "ops", "remove");
1351
1589
  var processCompositeKey2 = (comKey, model, kta) => {
@@ -1385,17 +1623,17 @@ var getRemoveOperation = (models, definition, _registry) => {
1385
1623
  logger12.error("Key for Remove is not a valid ItemKey: %j", key);
1386
1624
  throw new Error("Key for Remove is not a valid ItemKey");
1387
1625
  }
1388
- const keyDescription = isPriKey4(key) ? `primary key: pk=${key.pk}` : `composite key: pk=${key.pk}, loc=[${key.loc.map((l) => `${l.kt}=${l.lk}`).join(", ")}]`;
1626
+ const keyDescription = isPriKey5(key) ? `primary key: pk=${key.pk}` : `composite key: pk=${key.pk}, loc=[${key.loc.map((l) => `${l.kt}=${l.lk}`).join(", ")}]`;
1389
1627
  logger12.debug(`REMOVE operation called on ${models[0].name} with ${keyDescription}`);
1390
- logger12.default(`Remove configured for ${models[0].name} with ${isPriKey4(key) ? "primary" : "composite"} key`);
1628
+ logger12.default(`Remove configured for ${models[0].name} with ${isPriKey5(key) ? "primary" : "composite"} key`);
1391
1629
  const model = models[0];
1392
1630
  let item;
1393
1631
  let returnItem;
1394
1632
  logger12.debug("remove: %s", abbrevIK(key));
1395
- if (isPriKey4(key)) {
1633
+ if (isPriKey5(key)) {
1396
1634
  logger12.debug(`[REMOVE] Executing ${model.name}.findByPk() with pk: ${key.pk}`);
1397
1635
  item = await model.findByPk(key.pk);
1398
- } else if (isComKey4(key)) {
1636
+ } else if (isComKey5(key)) {
1399
1637
  const comKey = key;
1400
1638
  const queryOptions = processCompositeKey2(comKey, model, kta);
1401
1639
  logger12.default(`Remove composite key query for ${model.name} with where fields: ${queryOptions.where ? Object.keys(queryOptions.where).join(", ") : "none"}`);
@@ -1433,6 +1671,10 @@ var getRemoveOperation = (models, definition, _registry) => {
1433
1671
  throw new Error("No deletedAt or isDeleted attribute found in model, and deleteOnRemove is not set");
1434
1672
  }
1435
1673
  logger12.debug(`[REMOVE] Removed ${model.name} with key: ${returnItem.key ? JSON.stringify(returnItem.key) : `id=${item.id}`}`);
1674
+ const { references } = options;
1675
+ if (references && references.length > 0) {
1676
+ returnItem = addRefsToSequelizeItem(returnItem, references);
1677
+ }
1436
1678
  return returnItem;
1437
1679
  } catch (error) {
1438
1680
  if (error instanceof NotFoundError2) throw error;
@@ -1446,8 +1688,8 @@ var getRemoveOperation = (models, definition, _registry) => {
1446
1688
  import {
1447
1689
  abbrevIK as abbrevIK2,
1448
1690
  createUpdateWrapper,
1449
- isComKey as isComKey5,
1450
- isPriKey as isPriKey5
1691
+ isComKey as isComKey6,
1692
+ isPriKey as isPriKey6
1451
1693
  } from "@fjell/core";
1452
1694
  import { validateKeys as validateKeys5 } from "@fjell/core/validation";
1453
1695
  import { NotFoundError as NotFoundError3 } from "@fjell/core";
@@ -1483,18 +1725,18 @@ var getUpdateOperation = (models, definition, registry) => {
1483
1725
  "UpdateOptions.replace is not supported for SQL databases. SQL UPDATE operations are always partial (they only update specified fields). To replace an entire record, use remove() followed by create(), or explicitly set all fields you want to change/clear."
1484
1726
  );
1485
1727
  }
1486
- const keyDescription = isPriKey5(key) ? `primary key: pk=${key.pk}` : `composite key: pk=${key.pk}, loc=[${key.loc.map((l) => `${l.kt}=${l.lk}`).join(", ")}]`;
1728
+ const keyDescription = isPriKey6(key) ? `primary key: pk=${key.pk}` : `composite key: pk=${key.pk}, loc=[${key.loc.map((l) => `${l.kt}=${l.lk}`).join(", ")}]`;
1487
1729
  logger13.debug(`UPDATE operation called on ${models[0].name} with ${keyDescription}`, { options });
1488
1730
  const { coordinate } = definition;
1489
1731
  const { kta } = coordinate;
1490
1732
  logger13.debug("update: %s, %j", abbrevIK2(key), item);
1491
1733
  const model = models[0];
1492
1734
  let response;
1493
- if (isPriKey5(key)) {
1735
+ if (isPriKey6(key)) {
1494
1736
  const priKey = key;
1495
1737
  logger13.trace(`[UPDATE] Executing ${model.name}.findByPk() with pk: ${priKey.pk}`);
1496
1738
  response = await model.findByPk(priKey.pk);
1497
- } else if (isComKey5(key)) {
1739
+ } else if (isComKey6(key)) {
1498
1740
  const comKey = key;
1499
1741
  const where = { id: comKey.pk };
1500
1742
  const additionalIncludes = [];
@@ -1535,6 +1777,12 @@ var getUpdateOperation = (models, definition, registry) => {
1535
1777
  let updateProps = removeKey(item);
1536
1778
  updateProps = extractEvents(updateProps);
1537
1779
  updateProps = removeEvents(updateProps);
1780
+ if (references && references.length > 0) {
1781
+ updateProps = removeRefsFromSequelizeItem(updateProps, references);
1782
+ }
1783
+ if (aggregations && aggregations.length > 0) {
1784
+ updateProps = removeAggsFromItem(updateProps, aggregations);
1785
+ }
1538
1786
  logger13.default(`Update found ${model.name} record to modify`);
1539
1787
  logger13.default(`Update properties configured: ${Object.keys(updateProps).join(", ")}`);
1540
1788
  logger13.trace(`[UPDATE] Executing ${model.name}.update() with properties: ${stringifyJSON(updateProps)}`);
@@ -1560,7 +1808,7 @@ var getUpsertOperation = (models, definition, registry) => {
1560
1808
  const create = getCreateOperation(models, definition, registry);
1561
1809
  return createUpsertWrapper(
1562
1810
  definition.coordinate,
1563
- async (key, item, options) => {
1811
+ async (key, item, locations, options) => {
1564
1812
  if (!isValidItemKey3(key)) {
1565
1813
  logger14.error("Key for Upsert is not a valid ItemKey: %j", key);
1566
1814
  throw new Error(`Key for Upsert is not a valid ItemKey: ${stringifyJSON(key)}`);
@@ -1574,7 +1822,8 @@ var getUpsertOperation = (models, definition, registry) => {
1574
1822
  const isNotFound = error instanceof NotFoundError4 || error?.name === "NotFoundError" || error?.errorInfo?.code === "NOT_FOUND";
1575
1823
  if (isNotFound) {
1576
1824
  logger14.debug(`[UPSERT] Item not found, creating new item with key: ${stringifyJSON(key)}, errorType: ${error?.name}, errorCode: ${error?.errorInfo?.code}`);
1577
- resultItem = await create(item, { key });
1825
+ const createOptions3 = locations ? { locations } : { key };
1826
+ resultItem = await create(item, createOptions3);
1578
1827
  } else {
1579
1828
  logger14.error(`[UPSERT] Unexpected error during get operation`, { error: error?.message, name: error?.name, code: error?.errorInfo?.code });
1580
1829
  throw error;
@@ -1608,7 +1857,7 @@ var createOperations = (models, coordinate, registry, options) => {
1608
1857
  };
1609
1858
  implOps.findOne = async (finder, params, locations) => {
1610
1859
  const results = await implOps.find(finder, params || {}, locations);
1611
- return results.length > 0 ? results[0] : null;
1860
+ return results.items.length > 0 ? results.items[0] : null;
1612
1861
  };
1613
1862
  return Library2.wrapImplementationOperations(implOps, options);
1614
1863
  };