@exabugs/dynamodb-client 1.25.0 → 1.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/integrations/react-admin/dataProvider.d.ts +9 -0
  3. package/dist/integrations/react-admin/dataProvider.d.ts.map +1 -1
  4. package/dist/integrations/react-admin/dataProvider.js +24 -3
  5. package/dist/integrations/react-admin/dataProvider.js.map +1 -1
  6. package/dist/server/handler.cjs +367 -295
  7. package/dist/server/handler.cjs.map +4 -4
  8. package/dist/server/media-handler.cjs +2 -2
  9. package/dist/server/media-process-handler-dlq.cjs +2 -2
  10. package/dist/server/media-process-handler.cjs +2 -2
  11. package/dist/server/operations/deleteMany.d.ts.map +1 -1
  12. package/dist/server/operations/deleteMany.js +11 -0
  13. package/dist/server/operations/deleteMany.js.map +1 -1
  14. package/dist/server/operations/deleteOne.d.ts.map +1 -1
  15. package/dist/server/operations/deleteOne.js +4 -1
  16. package/dist/server/operations/deleteOne.js.map +1 -1
  17. package/dist/server/operations/find/idQuery.d.ts.map +1 -1
  18. package/dist/server/operations/find/idQuery.js +31 -22
  19. package/dist/server/operations/find/idQuery.js.map +1 -1
  20. package/dist/server/operations/find/utils.d.ts +11 -0
  21. package/dist/server/operations/find/utils.d.ts.map +1 -1
  22. package/dist/server/operations/find/utils.js +1 -1
  23. package/dist/server/operations/find/utils.js.map +1 -1
  24. package/dist/server/operations/findMany.d.ts.map +1 -1
  25. package/dist/server/operations/findMany.js +4 -1
  26. package/dist/server/operations/findMany.js.map +1 -1
  27. package/dist/server/operations/findOne.d.ts.map +1 -1
  28. package/dist/server/operations/findOne.js +1 -1
  29. package/dist/server/operations/findOne.js.map +1 -1
  30. package/dist/server/operations/parameterConverter.d.ts +1 -0
  31. package/dist/server/operations/parameterConverter.d.ts.map +1 -1
  32. package/dist/server/operations/parameterConverter.js +34 -41
  33. package/dist/server/operations/parameterConverter.js.map +1 -1
  34. package/dist/server/operations/updateMany.d.ts.map +1 -1
  35. package/dist/server/operations/updateMany.js +31 -14
  36. package/dist/server/operations/updateMany.js.map +1 -1
  37. package/dist/server/operations/updateOne.d.ts.map +1 -1
  38. package/dist/server/operations/updateOne.js +8 -1
  39. package/dist/server/operations/updateOne.js.map +1 -1
  40. package/dist/server/types.d.ts +16 -7
  41. package/dist/server/types.d.ts.map +1 -1
  42. package/dist/server/utils/idFilter.d.ts +15 -0
  43. package/dist/server/utils/idFilter.d.ts.map +1 -0
  44. package/dist/server/utils/idFilter.js +32 -0
  45. package/dist/server/utils/idFilter.js.map +1 -0
  46. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
- // @exabugs/dynamodb-client v1.25.0
2
- // Built: 2026-11-13T10:52:43.271Z
1
+ // @exabugs/dynamodb-client v1.26.0
2
+ // Built: 2026-11-14T13:53:42.297Z
3
3
  "use strict";
4
4
  var __create = Object.create;
5
5
  var __defProp = Object.defineProperty;
@@ -39750,6 +39750,253 @@ var init_cost_tracker = __esm({
39750
39750
  }
39751
39751
  });
39752
39752
 
39753
+ // src/server/utils/filter.ts
39754
+ function parseFilterField(fieldKey) {
39755
+ const parts = fieldKey.split(":");
39756
+ if (parts.length === 1) {
39757
+ return { field: parts[0], operator: "$eq", type: "string" };
39758
+ }
39759
+ if (parts.length === 2) {
39760
+ const operator = parts[1];
39761
+ if (!isValidOperator(operator)) {
39762
+ throw new Error(`Invalid filter operator: ${parts[1]}`);
39763
+ }
39764
+ return { field: parts[0], operator, type: "string" };
39765
+ }
39766
+ if (parts.length === 3) {
39767
+ const operator = parts[1];
39768
+ const type = parts[2];
39769
+ if (!isValidOperator(operator)) {
39770
+ throw new Error(`Invalid filter operator: ${parts[1]}`);
39771
+ }
39772
+ if (!isValidType(type)) {
39773
+ throw new Error(`Invalid filter type: ${parts[2]}`);
39774
+ }
39775
+ return { field: parts[0], operator, type };
39776
+ }
39777
+ throw new Error(`Invalid filter field syntax: ${fieldKey}`);
39778
+ }
39779
+ function isValidOperator(operator) {
39780
+ return [
39781
+ "$eq",
39782
+ "$ne",
39783
+ "$lt",
39784
+ "$lte",
39785
+ "$gt",
39786
+ "$gte",
39787
+ "$in",
39788
+ "$nin",
39789
+ "$starts",
39790
+ "$ends",
39791
+ "$contains",
39792
+ "$regex",
39793
+ "$exists",
39794
+ "$near"
39795
+ ].includes(operator);
39796
+ }
39797
+ function isValidType(type) {
39798
+ return ["string", "number", "date", "boolean"].includes(type);
39799
+ }
39800
+ var init_filter = __esm({
39801
+ "src/server/utils/filter.ts"() {
39802
+ "use strict";
39803
+ __name(parseFilterField, "parseFilterField");
39804
+ __name(isValidOperator, "isValidOperator");
39805
+ __name(isValidType, "isValidType");
39806
+ }
39807
+ });
39808
+
39809
+ // src/server/utils/validation.ts
39810
+ function validateSortField(_config, _resource, _sort) {
39811
+ return;
39812
+ }
39813
+ function normalizePagination(pagination) {
39814
+ const perPage = Math.min(pagination?.perPage || 50, 50);
39815
+ const nextToken = pagination?.nextToken;
39816
+ return { perPage, nextToken };
39817
+ }
39818
+ function normalizeSort(config, _resource, sort) {
39819
+ if (sort) {
39820
+ return sort;
39821
+ }
39822
+ return {
39823
+ field: config.updatedAtField,
39824
+ order: "DESC"
39825
+ };
39826
+ }
39827
+ var init_validation2 = __esm({
39828
+ "src/server/utils/validation.ts"() {
39829
+ "use strict";
39830
+ __name(validateSortField, "validateSortField");
39831
+ __name(normalizePagination, "normalizePagination");
39832
+ __name(normalizeSort, "normalizeSort");
39833
+ }
39834
+ });
39835
+
39836
+ // src/server/operations/find/utils.ts
39837
+ function initializeFindConfig() {
39838
+ return getShadowConfig();
39839
+ }
39840
+ function normalizeFindParams(config, resource, params) {
39841
+ const sort = normalizeSort(config, resource, params.sort);
39842
+ const pagination = normalizePagination(params.pagination);
39843
+ const parsedFilters = parseFilters(params.filter);
39844
+ return {
39845
+ sort,
39846
+ pagination,
39847
+ parsedFilters,
39848
+ schema: params.schema
39849
+ };
39850
+ }
39851
+ function withInferredType(parsed, fieldKey, value) {
39852
+ if (fieldKey.split(":").length >= 3) return parsed;
39853
+ if (typeof value === "number") return { ...parsed, type: "number" };
39854
+ if (typeof value === "boolean") return { ...parsed, type: "boolean" };
39855
+ return parsed;
39856
+ }
39857
+ function parseFilters(filter) {
39858
+ const parsedFilters = [];
39859
+ if (!filter || Object.keys(filter).length === 0) {
39860
+ return parsedFilters;
39861
+ }
39862
+ for (const [fieldKey, value] of Object.entries(filter)) {
39863
+ try {
39864
+ if (value && typeof value === "object" && !Array.isArray(value)) {
39865
+ for (const [operator, operatorValue] of Object.entries(value)) {
39866
+ const parsed = parseFilterField(`${fieldKey}:${operator}`);
39867
+ parsedFilters.push({
39868
+ parsed: withInferredType(parsed, fieldKey, operatorValue),
39869
+ value: operatorValue
39870
+ });
39871
+ }
39872
+ } else {
39873
+ const parsed = parseFilterField(fieldKey);
39874
+ parsedFilters.push({ parsed: withInferredType(parsed, fieldKey, value), value });
39875
+ }
39876
+ } catch (error2) {
39877
+ logger6.error("Invalid filter field syntax", {
39878
+ fieldKey,
39879
+ error: error2 instanceof Error ? error2.message : String(error2)
39880
+ });
39881
+ throw new InvalidFilterError(`Invalid filter field syntax: ${fieldKey}`, {
39882
+ field: fieldKey,
39883
+ error: error2 instanceof Error ? error2.message : String(error2)
39884
+ });
39885
+ }
39886
+ }
39887
+ return parsedFilters;
39888
+ }
39889
+ function findOptimizableFilter(sortField, parsedFilters) {
39890
+ return parsedFilters.find((filter) => filter.parsed.field === sortField);
39891
+ }
39892
+ function matchesAllFilters(record, parsedFilters) {
39893
+ return parsedFilters.every((filter) => {
39894
+ const { field, operator } = filter.parsed;
39895
+ const recordValue = record[field];
39896
+ const filterValue = filter.value;
39897
+ switch (operator) {
39898
+ case "$eq":
39899
+ return recordValue === filterValue;
39900
+ case "$ne":
39901
+ return recordValue !== filterValue;
39902
+ case "$gt":
39903
+ return recordValue != null && typeof recordValue === typeof filterValue && (typeof recordValue === "number" || typeof recordValue === "string") && recordValue > filterValue;
39904
+ case "$gte":
39905
+ return recordValue != null && typeof recordValue === typeof filterValue && (typeof recordValue === "number" || typeof recordValue === "string") && recordValue >= filterValue;
39906
+ case "$lt":
39907
+ return recordValue != null && typeof recordValue === typeof filterValue && (typeof recordValue === "number" || typeof recordValue === "string") && recordValue < filterValue;
39908
+ case "$lte":
39909
+ return recordValue != null && typeof recordValue === typeof filterValue && (typeof recordValue === "number" || typeof recordValue === "string") && recordValue <= filterValue;
39910
+ case "$in":
39911
+ return Array.isArray(filterValue) && filterValue.includes(recordValue);
39912
+ case "$nin":
39913
+ return Array.isArray(filterValue) && !filterValue.includes(recordValue);
39914
+ case "$starts":
39915
+ return typeof recordValue === "string" && typeof filterValue === "string" && recordValue.startsWith(filterValue);
39916
+ case "$ends":
39917
+ return typeof recordValue === "string" && typeof filterValue === "string" && recordValue.endsWith(filterValue);
39918
+ case "$contains":
39919
+ return typeof recordValue === "string" && typeof filterValue === "string" && recordValue.includes(filterValue);
39920
+ case "$regex":
39921
+ return typeof recordValue === "string" && typeof filterValue === "string" && recordValue.includes(filterValue);
39922
+ case "$exists":
39923
+ return filterValue ? recordValue !== void 0 && recordValue !== null : recordValue === void 0 || recordValue === null;
39924
+ default:
39925
+ return true;
39926
+ }
39927
+ });
39928
+ }
39929
+ function detectNearQuery(filter) {
39930
+ if (!filter || Object.keys(filter).length === 0) {
39931
+ return null;
39932
+ }
39933
+ for (const [fieldName, value] of Object.entries(filter)) {
39934
+ if (value && typeof value === "object" && !Array.isArray(value)) {
39935
+ const nearValue = value.$near;
39936
+ if (nearValue && typeof nearValue === "object") {
39937
+ return {
39938
+ fieldName,
39939
+ nearQuery: nearValue
39940
+ };
39941
+ }
39942
+ }
39943
+ }
39944
+ return null;
39945
+ }
39946
+ var logger6;
39947
+ var init_utils6 = __esm({
39948
+ "src/server/operations/find/utils.ts"() {
39949
+ "use strict";
39950
+ init_errors();
39951
+ init_shared();
39952
+ init_shadow();
39953
+ init_filter();
39954
+ init_validation2();
39955
+ logger6 = createLogger({
39956
+ service: "find-utils",
39957
+ level: process.env.LOG_LEVEL || "info"
39958
+ });
39959
+ __name(initializeFindConfig, "initializeFindConfig");
39960
+ __name(normalizeFindParams, "normalizeFindParams");
39961
+ __name(withInferredType, "withInferredType");
39962
+ __name(parseFilters, "parseFilters");
39963
+ __name(findOptimizableFilter, "findOptimizableFilter");
39964
+ __name(matchesAllFilters, "matchesAllFilters");
39965
+ __name(detectNearQuery, "detectNearQuery");
39966
+ }
39967
+ });
39968
+
39969
+ // src/server/utils/idFilter.ts
39970
+ function splitIdFilter(filter) {
39971
+ const { id, ...rest } = filter ?? {};
39972
+ if (typeof id === "string") {
39973
+ return { id, rest };
39974
+ }
39975
+ if (typeof id === "object" && id !== null && "$in" in id) {
39976
+ return { ids: (id.$in ?? []).slice(), rest };
39977
+ }
39978
+ return { rest: filter ?? {} };
39979
+ }
39980
+ function conditionOf(rest) {
39981
+ return Object.keys(rest).length > 0 ? rest : void 0;
39982
+ }
39983
+ function conditionMatcher(condition) {
39984
+ if (!condition || Object.keys(condition).length === 0) {
39985
+ return () => true;
39986
+ }
39987
+ const parsed = parseFilters(condition);
39988
+ return (record) => matchesAllFilters(record, parsed);
39989
+ }
39990
+ var init_idFilter = __esm({
39991
+ "src/server/utils/idFilter.ts"() {
39992
+ "use strict";
39993
+ init_utils6();
39994
+ __name(splitIdFilter, "splitIdFilter");
39995
+ __name(conditionOf, "conditionOf");
39996
+ __name(conditionMatcher, "conditionMatcher");
39997
+ }
39998
+ });
39999
+
39753
40000
  // src/server/utils/revision.ts
39754
40001
  function revisionOf(item) {
39755
40002
  const rev = item[REVISION_ATTRIBUTE];
@@ -39815,33 +40062,6 @@ var init_revision = __esm({
39815
40062
  }
39816
40063
  });
39817
40064
 
39818
- // src/server/utils/validation.ts
39819
- function validateSortField(_config, _resource, _sort) {
39820
- return;
39821
- }
39822
- function normalizePagination(pagination) {
39823
- const perPage = Math.min(pagination?.perPage || 50, 50);
39824
- const nextToken = pagination?.nextToken;
39825
- return { perPage, nextToken };
39826
- }
39827
- function normalizeSort(config, _resource, sort) {
39828
- if (sort) {
39829
- return sort;
39830
- }
39831
- return {
39832
- field: config.updatedAtField,
39833
- order: "DESC"
39834
- };
39835
- }
39836
- var init_validation2 = __esm({
39837
- "src/server/utils/validation.ts"() {
39838
- "use strict";
39839
- __name(validateSortField, "validateSortField");
39840
- __name(normalizePagination, "normalizePagination");
39841
- __name(normalizeSort, "normalizeSort");
39842
- }
39843
- });
39844
-
39845
40065
  // src/client/FindCursor.ts
39846
40066
  var init_FindCursor = __esm({
39847
40067
  "src/client/FindCursor.ts"() {
@@ -40141,12 +40361,12 @@ function getScanWarnThreshold() {
40141
40361
  const value = Number(raw);
40142
40362
  return Number.isInteger(value) && value >= 1 ? value : DEFAULT_SCAN_WARN_THRESHOLD;
40143
40363
  }
40144
- var logger6, SPARSE_SCAN_EVENT, DEFAULT_SCAN_WARN_THRESHOLD, ScanWatcher;
40364
+ var logger7, SPARSE_SCAN_EVENT, DEFAULT_SCAN_WARN_THRESHOLD, ScanWatcher;
40145
40365
  var init_scanWarning = __esm({
40146
40366
  "src/server/utils/scanWarning.ts"() {
40147
40367
  "use strict";
40148
40368
  init_shared();
40149
- logger6 = createLogger({ service: "scan-warning", level: "warn" });
40369
+ logger7 = createLogger({ service: "scan-warning", level: "warn" });
40150
40370
  SPARSE_SCAN_EVENT = "SPARSE_SCAN";
40151
40371
  DEFAULT_SCAN_WARN_THRESHOLD = 5e3;
40152
40372
  __name(getScanWarnThreshold, "getScanWarnThreshold");
@@ -40166,7 +40386,7 @@ var init_scanWarning = __esm({
40166
40386
  this.scanned += count;
40167
40387
  if (!this.warned && this.scanned >= this.threshold) {
40168
40388
  this.warned = true;
40169
- logger6.warn(
40389
+ logger7.warn(
40170
40390
  `${SPARSE_SCAN_EVENT}: 1\u30EA\u30AF\u30A8\u30B9\u30C8\u3067 ${this.scanned} \u4EF6\u4EE5\u4E0A\u3092\u8AAD\u307F\u307E\u3057\u305F\u3002\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u30FB\u30B9\u30AD\u30FC\u30DE\u30FB\u30ED\u30B8\u30C3\u30AF\u306E\u898B\u76F4\u3057\u3092\u691C\u8A0E\u3057\u3066\u304F\u3060\u3055\u3044\uFF08docs/SCAN_WARNING.md\uFF09`,
40171
40391
  {
40172
40392
  event: SPARSE_SCAN_EVENT,
@@ -40186,195 +40406,6 @@ var init_scanWarning = __esm({
40186
40406
  }
40187
40407
  });
40188
40408
 
40189
- // src/server/utils/filter.ts
40190
- function parseFilterField(fieldKey) {
40191
- const parts = fieldKey.split(":");
40192
- if (parts.length === 1) {
40193
- return { field: parts[0], operator: "$eq", type: "string" };
40194
- }
40195
- if (parts.length === 2) {
40196
- const operator = parts[1];
40197
- if (!isValidOperator(operator)) {
40198
- throw new Error(`Invalid filter operator: ${parts[1]}`);
40199
- }
40200
- return { field: parts[0], operator, type: "string" };
40201
- }
40202
- if (parts.length === 3) {
40203
- const operator = parts[1];
40204
- const type = parts[2];
40205
- if (!isValidOperator(operator)) {
40206
- throw new Error(`Invalid filter operator: ${parts[1]}`);
40207
- }
40208
- if (!isValidType(type)) {
40209
- throw new Error(`Invalid filter type: ${parts[2]}`);
40210
- }
40211
- return { field: parts[0], operator, type };
40212
- }
40213
- throw new Error(`Invalid filter field syntax: ${fieldKey}`);
40214
- }
40215
- function isValidOperator(operator) {
40216
- return [
40217
- "$eq",
40218
- "$ne",
40219
- "$lt",
40220
- "$lte",
40221
- "$gt",
40222
- "$gte",
40223
- "$in",
40224
- "$nin",
40225
- "$starts",
40226
- "$ends",
40227
- "$contains",
40228
- "$regex",
40229
- "$exists",
40230
- "$near"
40231
- ].includes(operator);
40232
- }
40233
- function isValidType(type) {
40234
- return ["string", "number", "date", "boolean"].includes(type);
40235
- }
40236
- var init_filter = __esm({
40237
- "src/server/utils/filter.ts"() {
40238
- "use strict";
40239
- __name(parseFilterField, "parseFilterField");
40240
- __name(isValidOperator, "isValidOperator");
40241
- __name(isValidType, "isValidType");
40242
- }
40243
- });
40244
-
40245
- // src/server/operations/find/utils.ts
40246
- function initializeFindConfig() {
40247
- return getShadowConfig();
40248
- }
40249
- function normalizeFindParams(config, resource, params) {
40250
- const sort = normalizeSort(config, resource, params.sort);
40251
- const pagination = normalizePagination(params.pagination);
40252
- const parsedFilters = parseFilters(params.filter);
40253
- return {
40254
- sort,
40255
- pagination,
40256
- parsedFilters,
40257
- schema: params.schema
40258
- };
40259
- }
40260
- function withInferredType(parsed, fieldKey, value) {
40261
- if (fieldKey.split(":").length >= 3) return parsed;
40262
- if (typeof value === "number") return { ...parsed, type: "number" };
40263
- if (typeof value === "boolean") return { ...parsed, type: "boolean" };
40264
- return parsed;
40265
- }
40266
- function parseFilters(filter) {
40267
- const parsedFilters = [];
40268
- if (!filter || Object.keys(filter).length === 0) {
40269
- return parsedFilters;
40270
- }
40271
- for (const [fieldKey, value] of Object.entries(filter)) {
40272
- try {
40273
- if (value && typeof value === "object" && !Array.isArray(value)) {
40274
- for (const [operator, operatorValue] of Object.entries(value)) {
40275
- const parsed = parseFilterField(`${fieldKey}:${operator}`);
40276
- parsedFilters.push({
40277
- parsed: withInferredType(parsed, fieldKey, operatorValue),
40278
- value: operatorValue
40279
- });
40280
- }
40281
- } else {
40282
- const parsed = parseFilterField(fieldKey);
40283
- parsedFilters.push({ parsed: withInferredType(parsed, fieldKey, value), value });
40284
- }
40285
- } catch (error2) {
40286
- logger7.error("Invalid filter field syntax", {
40287
- fieldKey,
40288
- error: error2 instanceof Error ? error2.message : String(error2)
40289
- });
40290
- throw new InvalidFilterError(`Invalid filter field syntax: ${fieldKey}`, {
40291
- field: fieldKey,
40292
- error: error2 instanceof Error ? error2.message : String(error2)
40293
- });
40294
- }
40295
- }
40296
- return parsedFilters;
40297
- }
40298
- function findOptimizableFilter(sortField, parsedFilters) {
40299
- return parsedFilters.find((filter) => filter.parsed.field === sortField);
40300
- }
40301
- function matchesAllFilters(record, parsedFilters) {
40302
- return parsedFilters.every((filter) => {
40303
- const { field, operator } = filter.parsed;
40304
- const recordValue = record[field];
40305
- const filterValue = filter.value;
40306
- switch (operator) {
40307
- case "$eq":
40308
- return recordValue === filterValue;
40309
- case "$ne":
40310
- return recordValue !== filterValue;
40311
- case "$gt":
40312
- return recordValue != null && typeof recordValue === typeof filterValue && (typeof recordValue === "number" || typeof recordValue === "string") && recordValue > filterValue;
40313
- case "$gte":
40314
- return recordValue != null && typeof recordValue === typeof filterValue && (typeof recordValue === "number" || typeof recordValue === "string") && recordValue >= filterValue;
40315
- case "$lt":
40316
- return recordValue != null && typeof recordValue === typeof filterValue && (typeof recordValue === "number" || typeof recordValue === "string") && recordValue < filterValue;
40317
- case "$lte":
40318
- return recordValue != null && typeof recordValue === typeof filterValue && (typeof recordValue === "number" || typeof recordValue === "string") && recordValue <= filterValue;
40319
- case "$in":
40320
- return Array.isArray(filterValue) && filterValue.includes(recordValue);
40321
- case "$nin":
40322
- return Array.isArray(filterValue) && !filterValue.includes(recordValue);
40323
- case "$starts":
40324
- return typeof recordValue === "string" && typeof filterValue === "string" && recordValue.startsWith(filterValue);
40325
- case "$ends":
40326
- return typeof recordValue === "string" && typeof filterValue === "string" && recordValue.endsWith(filterValue);
40327
- case "$contains":
40328
- return typeof recordValue === "string" && typeof filterValue === "string" && recordValue.includes(filterValue);
40329
- case "$regex":
40330
- return typeof recordValue === "string" && typeof filterValue === "string" && recordValue.includes(filterValue);
40331
- case "$exists":
40332
- return filterValue ? recordValue !== void 0 && recordValue !== null : recordValue === void 0 || recordValue === null;
40333
- default:
40334
- return true;
40335
- }
40336
- });
40337
- }
40338
- function detectNearQuery(filter) {
40339
- if (!filter || Object.keys(filter).length === 0) {
40340
- return null;
40341
- }
40342
- for (const [fieldName, value] of Object.entries(filter)) {
40343
- if (value && typeof value === "object" && !Array.isArray(value)) {
40344
- const nearValue = value.$near;
40345
- if (nearValue && typeof nearValue === "object") {
40346
- return {
40347
- fieldName,
40348
- nearQuery: nearValue
40349
- };
40350
- }
40351
- }
40352
- }
40353
- return null;
40354
- }
40355
- var logger7;
40356
- var init_utils6 = __esm({
40357
- "src/server/operations/find/utils.ts"() {
40358
- "use strict";
40359
- init_errors();
40360
- init_shared();
40361
- init_shadow();
40362
- init_filter();
40363
- init_validation2();
40364
- logger7 = createLogger({
40365
- service: "find-utils",
40366
- level: process.env.LOG_LEVEL || "info"
40367
- });
40368
- __name(initializeFindConfig, "initializeFindConfig");
40369
- __name(normalizeFindParams, "normalizeFindParams");
40370
- __name(withInferredType, "withInferredType");
40371
- __name(parseFilters, "parseFilters");
40372
- __name(findOptimizableFilter, "findOptimizableFilter");
40373
- __name(matchesAllFilters, "matchesAllFilters");
40374
- __name(detectNearQuery, "detectNearQuery");
40375
- }
40376
- });
40377
-
40378
40409
  // src/server/operations/find/idQuery.ts
40379
40410
  async function executeIdQuery(resource, normalizedParams, requestId) {
40380
40411
  const { sort, pagination, parsedFilters } = normalizedParams;
@@ -40386,14 +40417,30 @@ async function executeIdQuery(resource, normalizedParams, requestId) {
40386
40417
  hasFilters: parsedFilters.length > 0
40387
40418
  });
40388
40419
  const idFilter = parsedFilters.find((f5) => f5.parsed.field === "id");
40420
+ const otherFilters = parsedFilters.filter((f5) => f5 !== idFilter);
40389
40421
  if (idFilter && idFilter.parsed.operator === "$eq") {
40390
- return await executeSpecificIdQuery(resource, String(idFilter.value), requestId);
40422
+ return withOtherFilters(
40423
+ await executeSpecificIdQuery(resource, String(idFilter.value), requestId),
40424
+ otherFilters
40425
+ );
40391
40426
  }
40392
40427
  if (idFilter && idFilter.parsed.operator === "$in" && Array.isArray(idFilter.value)) {
40393
- return await executeInQuery(resource, idFilter.value.map(String), sort, requestId);
40428
+ return withOtherFilters(
40429
+ await executeInQuery(resource, idFilter.value.map(String), sort, requestId),
40430
+ otherFilters
40431
+ );
40394
40432
  }
40395
40433
  return await executeAllRecordsQuery(resource, sort, perPage, nextToken, parsedFilters, requestId);
40396
40434
  }
40435
+ function withOtherFilters(result, otherFilters) {
40436
+ if (otherFilters.length === 0) {
40437
+ return result;
40438
+ }
40439
+ return {
40440
+ ...result,
40441
+ items: result.items.filter((item) => matchesAllFilters(item, otherFilters))
40442
+ };
40443
+ }
40397
40444
  async function executeSpecificIdQuery(resource, targetId, requestId) {
40398
40445
  const dbClient2 = getDBClient();
40399
40446
  const tableName = getTableName();
@@ -40432,36 +40479,21 @@ async function executeSpecificIdQuery(resource, targetId, requestId) {
40432
40479
  };
40433
40480
  }
40434
40481
  async function executeInQuery(resource, targetIds, sort, requestId) {
40435
- const dbClient2 = getDBClient();
40436
- const tableName = getTableName();
40437
40482
  const costTracker = new CostTracker();
40438
- const results = await Promise.all(
40439
- targetIds.map(
40440
- (id) => executeDynamoDBOperation(
40441
- () => dbClient2.send(
40442
- new import_lib_dynamodb3.QueryCommand({
40443
- TableName: tableName,
40444
- KeyConditionExpression: "PK = :pk AND SK = :sk",
40445
- ExpressionAttributeValues: {
40446
- ":pk": resource,
40447
- ":sk": `id#${id}`
40448
- },
40449
- ConsistentRead: true,
40450
- ReturnConsumedCapacity: "TOTAL"
40451
- })
40452
- ),
40453
- "Query"
40454
- ).then((result) => {
40455
- costTracker.add(result.ConsumedCapacity);
40456
- return result.Items || [];
40457
- })
40458
- )
40483
+ const found = await batchGetAll(
40484
+ targetIds.map((id) => ({ PK: resource, SK: `id#${id}` })),
40485
+ { consistentRead: true, costTracker, requestId }
40459
40486
  );
40460
- let items = results.flat().map((item) => extractCleanRecord(item));
40487
+ const items = found.map((item) => extractCleanRecord(item));
40488
+ const direction = sort.order === "ASC" ? 1 : -1;
40461
40489
  items.sort((a5, b5) => {
40462
- const aVal = String(a5.id ?? "");
40463
- const bVal = String(b5.id ?? "");
40464
- return sort.order === "ASC" ? aVal.localeCompare(bVal) : bVal.localeCompare(aVal);
40490
+ const aVal = a5[sort.field];
40491
+ const bVal = b5[sort.field];
40492
+ if (aVal === bVal) return 0;
40493
+ if (aVal === void 0 || aVal === null) return 1;
40494
+ if (bVal === void 0 || bVal === null) return -1;
40495
+ if (typeof aVal === "number" && typeof bVal === "number") return (aVal - bVal) * direction;
40496
+ return String(aVal).localeCompare(String(bVal)) * direction;
40465
40497
  });
40466
40498
  logger8.info("ID $in query succeeded", {
40467
40499
  requestId,
@@ -40665,6 +40697,7 @@ var init_idQuery = __esm({
40665
40697
  "use strict";
40666
40698
  import_lib_dynamodb3 = __toESM(require_dist_cjs22(), 1);
40667
40699
  init_shared();
40700
+ init_batchGet();
40668
40701
  init_cost_tracker();
40669
40702
  init_dynamodb3();
40670
40703
  init_pagination();
@@ -40675,6 +40708,7 @@ var init_idQuery = __esm({
40675
40708
  level: process.env.LOG_LEVEL || "info"
40676
40709
  });
40677
40710
  __name(executeIdQuery, "executeIdQuery");
40711
+ __name(withOtherFilters, "withOtherFilters");
40678
40712
  __name(executeSpecificIdQuery, "executeSpecificIdQuery");
40679
40713
  __name(executeInQuery, "executeInQuery");
40680
40714
  __name(executeAllRecordsQuery, "executeAllRecordsQuery");
@@ -41430,8 +41464,10 @@ async function handleDeleteMany(resource, params, requestId) {
41430
41464
  const startTime = Date.now();
41431
41465
  const costTracker = new CostTracker();
41432
41466
  let ids;
41467
+ let condition;
41433
41468
  if ("ids" in params) {
41434
41469
  ids = params.ids;
41470
+ condition = params.condition;
41435
41471
  logger12.debug("Executing deleteMany with ids", {
41436
41472
  requestId,
41437
41473
  resource,
@@ -41456,6 +41492,7 @@ async function handleDeleteMany(resource, params, requestId) {
41456
41492
  requestId
41457
41493
  );
41458
41494
  ids = matched.map((item) => item.id);
41495
+ condition = params.filter;
41459
41496
  logger12.debug("Found records with filter", {
41460
41497
  requestId,
41461
41498
  resource,
@@ -41480,9 +41517,13 @@ async function handleDeleteMany(resource, params, requestId) {
41480
41517
  );
41481
41518
  const existingIds = /* @__PURE__ */ new Set();
41482
41519
  const preparedRecords = [];
41520
+ const matches = conditionMatcher(condition);
41483
41521
  for (const item of existingItems) {
41484
41522
  const existingData = item.data;
41485
41523
  const id = existingData.id;
41524
+ if (!matches(existingData)) {
41525
+ continue;
41526
+ }
41486
41527
  const shadowKeys = item.__shadowKeys ?? existingData.__shadowKeys ?? [];
41487
41528
  existingIds.add(id);
41488
41529
  preparedRecords.push({
@@ -41691,6 +41732,7 @@ var init_deleteMany = __esm({
41691
41732
  init_chunking();
41692
41733
  init_cost_tracker();
41693
41734
  init_dynamodb3();
41735
+ init_idFilter();
41694
41736
  init_revision();
41695
41737
  init_findAll();
41696
41738
  logger12 = createLogger({ service: "records-lambda" });
@@ -41714,7 +41756,8 @@ async function handleFindMany(resource, params, requestId) {
41714
41756
  ids.map((id) => ({ PK: resource, SK: generateMainRecordSK2(id) })),
41715
41757
  { consistentRead: true, requestId }
41716
41758
  );
41717
- const records = items.map((item) => extractCleanRecord(item));
41759
+ const matches = conditionMatcher(params.condition);
41760
+ const records = items.map((item) => extractCleanRecord(item)).filter(matches);
41718
41761
  logger14.info("findMany by ids succeeded", {
41719
41762
  requestId,
41720
41763
  resource,
@@ -41749,6 +41792,7 @@ var init_findMany = __esm({
41749
41792
  init_shadow();
41750
41793
  init_batchGet();
41751
41794
  init_dynamodb3();
41795
+ init_idFilter();
41752
41796
  init_findAll();
41753
41797
  logger14 = createLogger({ service: "records-lambda" });
41754
41798
  __name(handleFindMany, "handleFindMany");
@@ -41768,7 +41812,11 @@ async function handleFindOne(resource, params, requestId) {
41768
41812
  resource,
41769
41813
  id
41770
41814
  });
41771
- const results = await handleFindMany(resource, { ids: [id] }, requestId);
41815
+ const results = await handleFindMany(
41816
+ resource,
41817
+ { ids: [id], condition: params.condition },
41818
+ requestId
41819
+ );
41772
41820
  if (results.length === 0) {
41773
41821
  throw new ItemNotFoundError(`Record not found: ${id}`, { resource, id });
41774
41822
  }
@@ -42364,8 +42412,10 @@ async function handleUpdateMany(resource, params, requestId) {
42364
42412
  upsert
42365
42413
  });
42366
42414
  let ids;
42415
+ let condition;
42367
42416
  if ("ids" in params) {
42368
42417
  ids = params.ids;
42418
+ condition = params.condition;
42369
42419
  logger20.debug("Executing updateMany with ids", {
42370
42420
  requestId,
42371
42421
  resource,
@@ -42390,6 +42440,7 @@ async function handleUpdateMany(resource, params, requestId) {
42390
42440
  requestId
42391
42441
  );
42392
42442
  ids = matched.map((item) => item.id);
42443
+ condition = params.filter;
42393
42444
  logger20.debug("Found records with filter", {
42394
42445
  requestId,
42395
42446
  resource,
@@ -42428,6 +42479,8 @@ async function handleUpdateMany(resource, params, requestId) {
42428
42479
  targetIds.map((id) => ({ PK: resource, SK: generateMainRecordSK2(id) })),
42429
42480
  { consistentRead: true, costTracker, requestId }
42430
42481
  );
42482
+ const matches = conditionMatcher(condition);
42483
+ const mismatchedIds2 = /* @__PURE__ */ new Set();
42431
42484
  const existingIds = new Set(
42432
42485
  existingItems.map((item) => {
42433
42486
  const data = item.data;
@@ -42461,6 +42514,10 @@ async function handleUpdateMany(resource, params, requestId) {
42461
42514
  try {
42462
42515
  const existingData = item.data;
42463
42516
  const id = existingData.id;
42517
+ if (!matches(existingData)) {
42518
+ mismatchedIds2.add(id);
42519
+ continue;
42520
+ }
42464
42521
  const oldShadowKeys = item.__shadowKeys ?? existingData.__shadowKeys ?? [];
42465
42522
  const timestampedPatch = addUpdateTimestamp(update.patch);
42466
42523
  const mergedData = applyJsonMergePatch(removeShadowKeys(existingData), timestampedPatch);
@@ -42535,9 +42592,15 @@ async function handleUpdateMany(resource, params, requestId) {
42535
42592
  }
42536
42593
  }
42537
42594
  }
42538
- return { preparedRecords: preparedRecords2, notFoundIds: notFoundIds2, preparationFailedIds: preparationFailedIds2, preparationErrors: preparationErrors2 };
42595
+ return {
42596
+ preparedRecords: preparedRecords2,
42597
+ notFoundIds: notFoundIds2,
42598
+ mismatchedIds: mismatchedIds2,
42599
+ preparationFailedIds: preparationFailedIds2,
42600
+ preparationErrors: preparationErrors2
42601
+ };
42539
42602
  }, "prepare");
42540
- const { preparedRecords, notFoundIds, preparationFailedIds, preparationErrors } = await prepare(ids);
42603
+ const { preparedRecords, notFoundIds, mismatchedIds, preparationFailedIds, preparationErrors } = await prepare(ids);
42541
42604
  const getItemCount = /* @__PURE__ */ __name((record) => {
42542
42605
  const shadowDiff = calculateShadowDiff(record.oldShadowKeys, record.newShadowKeys);
42543
42606
  return 1 + shadowDiff.toDelete.length + shadowDiff.toAdd.length;
@@ -42651,17 +42714,15 @@ async function handleUpdateMany(resource, params, requestId) {
42651
42714
  }
42652
42715
  }
42653
42716
  }
42654
- if (!upsert) {
42655
- for (let i5 = 0; i5 < ids.length; i5++) {
42656
- const id = ids[i5];
42657
- if (notFoundIds.includes(id)) {
42658
- failedIdsMap[i5] = id;
42659
- errorsMap[i5] = {
42660
- id,
42661
- code: "ITEM_NOT_FOUND",
42662
- message: `Record not found: ${id}`
42663
- };
42664
- }
42717
+ for (let i5 = 0; i5 < ids.length; i5++) {
42718
+ const id = ids[i5];
42719
+ if (!upsert && notFoundIds.includes(id) || mismatchedIds.has(id)) {
42720
+ failedIdsMap[i5] = id;
42721
+ errorsMap[i5] = {
42722
+ id,
42723
+ code: "ITEM_NOT_FOUND",
42724
+ message: `Record not found: ${id}`
42725
+ };
42665
42726
  }
42666
42727
  }
42667
42728
  for (let i5 = 0; i5 < ids.length; i5++) {
@@ -42760,6 +42821,7 @@ var init_updateMany = __esm({
42760
42821
  init_chunking();
42761
42822
  init_cost_tracker();
42762
42823
  init_dynamodb3();
42824
+ init_idFilter();
42763
42825
  init_mergePatch();
42764
42826
  init_revision();
42765
42827
  init_timestamps();
@@ -42801,7 +42863,8 @@ async function handleDeleteOne(resource, params, requestId) {
42801
42863
  const deleteManyResult = await handleDeleteMany2(
42802
42864
  resource,
42803
42865
  {
42804
- ids: [targetId]
42866
+ ids: [targetId],
42867
+ condition: params.condition
42805
42868
  },
42806
42869
  requestId
42807
42870
  );
@@ -42830,7 +42893,12 @@ async function handleDeleteOne(resource, params, requestId) {
42830
42893
  params.filter,
42831
42894
  requestId
42832
42895
  );
42833
- const deleteManyResult = target ? await handleDeleteMany2(resource, { ids: [target.id] }, requestId) : await handleDeleteMany2(resource, { ids: [] }, requestId);
42896
+ const deleteManyResult = target ? await handleDeleteMany2(
42897
+ resource,
42898
+ // 選んでから消すまでの間に条件から外れたレコードを消さない
42899
+ { ids: [target.id], condition: params.filter },
42900
+ requestId
42901
+ ) : await handleDeleteMany2(resource, { ids: [] }, requestId);
42834
42902
  if (deleteManyResult.count === 0) {
42835
42903
  const error2 = Object.values(deleteManyResult.errors || {})[0];
42836
42904
  if (error2) {
@@ -43019,6 +43087,7 @@ async function handleInsertOne(resource, params, requestId) {
43019
43087
  __name(handleInsertOne, "handleInsertOne");
43020
43088
 
43021
43089
  // src/server/operations/parameterConverter.ts
43090
+ init_idFilter();
43022
43091
  function convertFindParams(mongoParams) {
43023
43092
  const { filter = {}, options = {} } = mongoParams;
43024
43093
  const { sort, limit, nextToken, schema } = options;
@@ -43045,9 +43114,10 @@ function convertFindOneParams(mongoParams) {
43045
43114
  if (!mongoParams.filter) {
43046
43115
  throw new Error("findOne requires filter");
43047
43116
  }
43048
- const id = typeof mongoParams.filter.id === "string" ? mongoParams.filter.id : void 0;
43117
+ const { id, rest } = splitIdFilter(mongoParams.filter);
43049
43118
  if (id) {
43050
- return { id };
43119
+ const condition = conditionOf(rest);
43120
+ return { id, ...condition && { condition } };
43051
43121
  }
43052
43122
  return { filter: mongoParams.filter };
43053
43123
  }
@@ -43059,10 +43129,10 @@ function convertFindManyParams(mongoParams) {
43059
43129
  if (!mongoParams.filter) {
43060
43130
  throw new Error("findMany requires either ids or filter");
43061
43131
  }
43062
- const idFilter = mongoParams.filter.id;
43063
- if (typeof idFilter === "object" && idFilter !== null && "$in" in idFilter) {
43064
- const ids = idFilter.$in || [];
43065
- return { ids };
43132
+ const { ids, rest } = splitIdFilter(mongoParams.filter);
43133
+ if (ids) {
43134
+ const condition = conditionOf(rest);
43135
+ return { ids, ...condition && { condition } };
43066
43136
  }
43067
43137
  return { filter: mongoParams.filter };
43068
43138
  }
@@ -43077,16 +43147,7 @@ function convertInsertOneParams(mongoParams) {
43077
43147
  }
43078
43148
  __name(convertInsertOneParams, "convertInsertOneParams");
43079
43149
  function convertUpdateOneParams(mongoParams) {
43080
- let updateData;
43081
- if (mongoParams.update && typeof mongoParams.update === "object") {
43082
- if ("$set" in mongoParams.update || "$setOnInsert" in mongoParams.update) {
43083
- updateData = mongoParams.update;
43084
- } else {
43085
- updateData = mongoParams.update;
43086
- }
43087
- } else {
43088
- updateData = {};
43089
- }
43150
+ const updateData = mongoParams.update && typeof mongoParams.update === "object" ? mongoParams.update : {};
43090
43151
  const directId = "id" in mongoParams && typeof mongoParams.id === "string" ? mongoParams.id : void 0;
43091
43152
  if (directId) {
43092
43153
  return {
@@ -43100,10 +43161,12 @@ function convertUpdateOneParams(mongoParams) {
43100
43161
  if (!mongoParams.filter) {
43101
43162
  throw new Error("updateOne requires filter");
43102
43163
  }
43103
- const id = typeof mongoParams.filter.id === "string" ? mongoParams.filter.id : void 0;
43164
+ const { id, rest } = splitIdFilter(mongoParams.filter);
43165
+ const condition = conditionOf(rest);
43104
43166
  if (id) {
43105
43167
  return {
43106
43168
  id,
43169
+ ...condition && { condition },
43107
43170
  data: updateData,
43108
43171
  ...mongoParams.options?.upsert !== void 0 && {
43109
43172
  options: { upsert: mongoParams.options.upsert }
@@ -43120,10 +43183,10 @@ function convertUpdateOneParams(mongoParams) {
43120
43183
  }
43121
43184
  __name(convertUpdateOneParams, "convertUpdateOneParams");
43122
43185
  function convertUpdateManyParams(mongoParams) {
43123
- const idFilter = mongoParams.filter?.id;
43124
- const hasIdIn = typeof idFilter === "object" && idFilter !== null && "$in" in idFilter;
43125
- const target = hasIdIn ? { ids: idFilter.$in || [] } : mongoParams.filter ? { filter: mongoParams.filter } : { ids: [] };
43126
- const updateData = mongoParams.update && typeof mongoParams.update === "object" ? "$set" in mongoParams.update ? mongoParams.update.$set || {} : mongoParams.update : {};
43186
+ const { ids, rest } = splitIdFilter(mongoParams.filter);
43187
+ const condition = conditionOf(rest);
43188
+ const target = ids ? { ids, ...condition && { condition } } : mongoParams.filter ? { filter: mongoParams.filter } : { ids: [] };
43189
+ const updateData = mongoParams.update && typeof mongoParams.update === "object" ? mongoParams.update : {};
43127
43190
  return {
43128
43191
  ...target,
43129
43192
  data: updateData,
@@ -43138,17 +43201,19 @@ function convertDeleteOneParams(mongoParams) {
43138
43201
  if (directId) {
43139
43202
  return { id: directId };
43140
43203
  }
43141
- const id = typeof mongoParams.filter?.id === "string" ? mongoParams.filter.id : void 0;
43204
+ const { id, rest } = splitIdFilter(mongoParams.filter);
43142
43205
  if (!id) {
43143
43206
  throw new Error("deleteOne requires filter.id");
43144
43207
  }
43145
- return { id };
43208
+ const condition = conditionOf(rest);
43209
+ return { id, ...condition && { condition } };
43146
43210
  }
43147
43211
  __name(convertDeleteOneParams, "convertDeleteOneParams");
43148
43212
  function convertDeleteManyParams(mongoParams) {
43149
- const idFilter = mongoParams.filter?.id;
43150
- if (typeof idFilter === "object" && idFilter !== null && "$in" in idFilter) {
43151
- return { ids: idFilter.$in || [] };
43213
+ const { ids, rest } = splitIdFilter(mongoParams.filter);
43214
+ if (ids) {
43215
+ const condition = conditionOf(rest);
43216
+ return { ids, ...condition && { condition } };
43152
43217
  }
43153
43218
  if (mongoParams.filter) {
43154
43219
  return { filter: mongoParams.filter };
@@ -43188,6 +43253,7 @@ async function handleUpdateOne(resource, params, requestId) {
43188
43253
  resource,
43189
43254
  {
43190
43255
  ids: [targetId],
43256
+ condition: params.condition,
43191
43257
  data: patchData,
43192
43258
  options
43193
43259
  },
@@ -43233,7 +43299,13 @@ async function handleUpdateOne(resource, params, requestId) {
43233
43299
  );
43234
43300
  const updateManyResult = await handleUpdateMany2(
43235
43301
  resource,
43236
- target ? { ids: [target.id], data: patchData, options } : { filter: params.filter, data: patchData, options },
43302
+ target ? {
43303
+ ids: [target.id],
43304
+ // 選んでから書くまでの間に条件から外れたレコードを書かない
43305
+ condition: params.filter,
43306
+ data: patchData,
43307
+ options
43308
+ } : { filter: params.filter, data: patchData, options },
43237
43309
  requestId
43238
43310
  );
43239
43311
  if (updateManyResult.count === 0) {
@@ -44817,7 +44889,7 @@ async function handler(event) {
44817
44889
  return createCorsResponse(HTTP_STATUS.OK);
44818
44890
  }
44819
44891
  if (event.requestContext.http.method === "GET" && event.requestContext.http.path === "/version") {
44820
- const version = "1.25.0";
44892
+ const version = "1.26.0";
44821
44893
  return createSuccessResponse({ version, timestamp: (/* @__PURE__ */ new Date()).toISOString() }, requestId);
44822
44894
  }
44823
44895
  if (event.requestContext.http.method !== "POST") {