@exabugs/dynamodb-client 1.25.1 → 1.27.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 (147) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/__generated__/models/apiOperation.d.ts +1 -0
  3. package/dist/__generated__/models/apiOperation.d.ts.map +1 -1
  4. package/dist/__generated__/models/apiOperation.js +1 -0
  5. package/dist/__generated__/models/apiOperation.js.map +1 -1
  6. package/dist/__generated__/models/bulkOperationResult.d.ts +2 -0
  7. package/dist/__generated__/models/bulkOperationResult.d.ts.map +1 -1
  8. package/dist/__generated__/models/countParams.d.ts +31 -0
  9. package/dist/__generated__/models/countParams.d.ts.map +1 -0
  10. package/dist/__generated__/models/countParams.js +2 -0
  11. package/dist/__generated__/models/countParams.js.map +1 -0
  12. package/dist/__generated__/models/countResult.d.ts +37 -0
  13. package/dist/__generated__/models/countResult.d.ts.map +1 -0
  14. package/dist/__generated__/models/countResult.js +2 -0
  15. package/dist/__generated__/models/countResult.js.map +1 -0
  16. package/dist/__generated__/models/countResultConsumedCapacity.d.ts +35 -0
  17. package/dist/__generated__/models/countResultConsumedCapacity.d.ts.map +1 -0
  18. package/dist/__generated__/models/countResultConsumedCapacity.js +25 -0
  19. package/dist/__generated__/models/countResultConsumedCapacity.js.map +1 -0
  20. package/dist/__generated__/models/executeOperationBodyOp.d.ts +1 -0
  21. package/dist/__generated__/models/executeOperationBodyOp.d.ts.map +1 -1
  22. package/dist/__generated__/models/executeOperationBodyOp.js +1 -0
  23. package/dist/__generated__/models/executeOperationBodyOp.js.map +1 -1
  24. package/dist/__generated__/models/index.d.ts +3 -0
  25. package/dist/__generated__/models/index.d.ts.map +1 -1
  26. package/dist/__generated__/models/index.js +3 -0
  27. package/dist/__generated__/models/index.js.map +1 -1
  28. package/dist/client/Collection.d.ts +7 -0
  29. package/dist/client/Collection.d.ts.map +1 -1
  30. package/dist/client/Collection.js +20 -1
  31. package/dist/client/Collection.js.map +1 -1
  32. package/dist/scripts/repair-shadows.js +86 -42
  33. package/dist/scripts/repair-shadows.js.map +1 -1
  34. package/dist/scripts/utils/cliParser.d.ts +9 -22
  35. package/dist/scripts/utils/cliParser.d.ts.map +1 -1
  36. package/dist/scripts/utils/cliParser.js +14 -37
  37. package/dist/scripts/utils/cliParser.js.map +1 -1
  38. package/dist/scripts/utils/shadowAudit.d.ts +49 -0
  39. package/dist/scripts/utils/shadowAudit.d.ts.map +1 -0
  40. package/dist/scripts/utils/shadowAudit.js +84 -0
  41. package/dist/scripts/utils/shadowAudit.js.map +1 -0
  42. package/dist/scripts/utils/shadowRepair.d.ts +42 -0
  43. package/dist/scripts/utils/shadowRepair.d.ts.map +1 -0
  44. package/dist/scripts/utils/shadowRepair.js +110 -0
  45. package/dist/scripts/utils/shadowRepair.js.map +1 -0
  46. package/dist/server/handler.cjs +1264 -1088
  47. package/dist/server/handler.cjs.map +4 -4
  48. package/dist/server/handler.js +2 -2
  49. package/dist/server/handler.js.map +1 -1
  50. package/dist/server/media-handler.cjs +2 -2
  51. package/dist/server/media-process-handler-dlq.cjs +19 -3
  52. package/dist/server/media-process-handler-dlq.cjs.map +2 -2
  53. package/dist/server/media-process-handler.cjs +19 -3
  54. package/dist/server/media-process-handler.cjs.map +2 -2
  55. package/dist/server/operations/count.d.ts +3 -0
  56. package/dist/server/operations/count.d.ts.map +1 -0
  57. package/dist/server/operations/count.js +81 -0
  58. package/dist/server/operations/count.js.map +1 -0
  59. package/dist/server/operations/deleteMany.d.ts.map +1 -1
  60. package/dist/server/operations/deleteMany.js +13 -1
  61. package/dist/server/operations/deleteMany.js.map +1 -1
  62. package/dist/server/operations/deleteOne.d.ts.map +1 -1
  63. package/dist/server/operations/deleteOne.js +7 -13
  64. package/dist/server/operations/deleteOne.js.map +1 -1
  65. package/dist/server/operations/find/idQuery.d.ts.map +1 -1
  66. package/dist/server/operations/find/idQuery.js +31 -22
  67. package/dist/server/operations/find/idQuery.js.map +1 -1
  68. package/dist/server/operations/find/keyCondition.d.ts +38 -0
  69. package/dist/server/operations/find/keyCondition.d.ts.map +1 -0
  70. package/dist/server/operations/find/keyCondition.js +184 -0
  71. package/dist/server/operations/find/keyCondition.js.map +1 -0
  72. package/dist/server/operations/find/shadowQuery.d.ts.map +1 -1
  73. package/dist/server/operations/find/shadowQuery.js +16 -143
  74. package/dist/server/operations/find/shadowQuery.js.map +1 -1
  75. package/dist/server/operations/find/utils.d.ts +11 -0
  76. package/dist/server/operations/find/utils.d.ts.map +1 -1
  77. package/dist/server/operations/find/utils.js +1 -6
  78. package/dist/server/operations/find/utils.js.map +1 -1
  79. package/dist/server/operations/findMany.d.ts.map +1 -1
  80. package/dist/server/operations/findMany.js +4 -1
  81. package/dist/server/operations/findMany.js.map +1 -1
  82. package/dist/server/operations/findOne.d.ts.map +1 -1
  83. package/dist/server/operations/findOne.js +1 -1
  84. package/dist/server/operations/findOne.js.map +1 -1
  85. package/dist/server/operations/insertMany.d.ts.map +1 -1
  86. package/dist/server/operations/insertMany.js +1 -4
  87. package/dist/server/operations/insertMany.js.map +1 -1
  88. package/dist/server/operations/insertOne.d.ts.map +1 -1
  89. package/dist/server/operations/insertOne.js +2 -6
  90. package/dist/server/operations/insertOne.js.map +1 -1
  91. package/dist/server/operations/operationDispatcher.d.ts.map +1 -1
  92. package/dist/server/operations/operationDispatcher.js +3 -0
  93. package/dist/server/operations/operationDispatcher.js.map +1 -1
  94. package/dist/server/operations/parameterConverter.d.ts +1 -0
  95. package/dist/server/operations/parameterConverter.d.ts.map +1 -1
  96. package/dist/server/operations/parameterConverter.js +34 -41
  97. package/dist/server/operations/parameterConverter.js.map +1 -1
  98. package/dist/server/operations/updateMany.d.ts.map +1 -1
  99. package/dist/server/operations/updateMany.js +37 -16
  100. package/dist/server/operations/updateMany.js.map +1 -1
  101. package/dist/server/operations/updateOne.d.ts.map +1 -1
  102. package/dist/server/operations/updateOne.js +18 -22
  103. package/dist/server/operations/updateOne.js.map +1 -1
  104. package/dist/server/types.d.ts +22 -7
  105. package/dist/server/types.d.ts.map +1 -1
  106. package/dist/server/utils/bulkError.d.ts +12 -0
  107. package/dist/server/utils/bulkError.d.ts.map +1 -0
  108. package/dist/server/utils/bulkError.js +21 -0
  109. package/dist/server/utils/bulkError.js.map +1 -0
  110. package/dist/server/utils/chunking.d.ts +9 -1
  111. package/dist/server/utils/chunking.d.ts.map +1 -1
  112. package/dist/server/utils/chunking.js +20 -3
  113. package/dist/server/utils/chunking.js.map +1 -1
  114. package/dist/server/utils/filter.d.ts +3 -105
  115. package/dist/server/utils/filter.d.ts.map +1 -1
  116. package/dist/server/utils/filter.js +14 -218
  117. package/dist/server/utils/filter.js.map +1 -1
  118. package/dist/server/utils/idFilter.d.ts +15 -0
  119. package/dist/server/utils/idFilter.d.ts.map +1 -0
  120. package/dist/server/utils/idFilter.js +32 -0
  121. package/dist/server/utils/idFilter.js.map +1 -0
  122. package/docs/README.md +9 -12
  123. package/package.json +1 -1
  124. package/dist/scripts/operations/bulkRecordRepair.d.ts +0 -17
  125. package/dist/scripts/operations/bulkRecordRepair.d.ts.map +0 -1
  126. package/dist/scripts/operations/bulkRecordRepair.js +0 -76
  127. package/dist/scripts/operations/bulkRecordRepair.js.map +0 -1
  128. package/dist/scripts/operations/singleRecordRepair.d.ts +0 -18
  129. package/dist/scripts/operations/singleRecordRepair.d.ts.map +0 -1
  130. package/dist/scripts/operations/singleRecordRepair.js +0 -46
  131. package/dist/scripts/operations/singleRecordRepair.js.map +0 -1
  132. package/dist/scripts/utils/awsUtils.d.ts +0 -15
  133. package/dist/scripts/utils/awsUtils.d.ts.map +0 -1
  134. package/dist/scripts/utils/awsUtils.js +0 -31
  135. package/dist/scripts/utils/awsUtils.js.map +0 -1
  136. package/dist/scripts/utils/clientFactory.d.ts +0 -22
  137. package/dist/scripts/utils/clientFactory.d.ts.map +0 -1
  138. package/dist/scripts/utils/clientFactory.js +0 -36
  139. package/dist/scripts/utils/clientFactory.js.map +0 -1
  140. package/dist/scripts/utils/repairUtils.d.ts +0 -58
  141. package/dist/scripts/utils/repairUtils.d.ts.map +0 -1
  142. package/dist/scripts/utils/repairUtils.js +0 -52
  143. package/dist/scripts/utils/repairUtils.js.map +0 -1
  144. package/dist/server/utils/ttl.d.ts +0 -17
  145. package/dist/server/utils/ttl.d.ts.map +0 -1
  146. package/dist/server/utils/ttl.js +0 -64
  147. package/dist/server/utils/ttl.js.map +0 -1
@@ -1,5 +1,5 @@
1
- // @exabugs/dynamodb-client v1.25.1
2
- // Built: 2026-11-13T23:34:00.545Z
1
+ // @exabugs/dynamodb-client v1.27.0
2
+ // Built: 2026-11-15T08:17:35.832Z
3
3
  "use strict";
4
4
  var __create = Object.create;
5
5
  var __defProp = Object.defineProperty;
@@ -2194,10 +2194,10 @@ var init_command = __esm({
2194
2194
  this.middlewareStack.use(mw);
2195
2195
  }
2196
2196
  const stack = clientStack.concat(this.middlewareStack);
2197
- const { logger: logger27 } = configuration;
2197
+ const { logger: logger26 } = configuration;
2198
2198
  const additionalSmithyContext = additionalContext[import_types2.SMITHY_CONTEXT_KEY];
2199
2199
  const handlerExecutionContext = {
2200
- logger: logger27,
2200
+ logger: logger26,
2201
2201
  clientName,
2202
2202
  commandName,
2203
2203
  inputFilterSensitiveLog,
@@ -4166,19 +4166,19 @@ var init_ProviderError = __esm({
4166
4166
  name = "ProviderError";
4167
4167
  tryNextLink;
4168
4168
  constructor(message, options = true) {
4169
- let logger27;
4169
+ let logger26;
4170
4170
  let tryNextLink = true;
4171
4171
  if (typeof options === "boolean") {
4172
- logger27 = void 0;
4172
+ logger26 = void 0;
4173
4173
  tryNextLink = options;
4174
4174
  } else if (options != null && typeof options === "object") {
4175
- logger27 = options.logger;
4175
+ logger26 = options.logger;
4176
4176
  tryNextLink = options.tryNextLink ?? true;
4177
4177
  }
4178
4178
  super(message);
4179
4179
  this.tryNextLink = tryNextLink;
4180
4180
  Object.setPrototypeOf(this, _ProviderError.prototype);
4181
- logger27?.debug?.(`@smithy/property-provider ${tryNextLink ? "->" : "(!)"} ${message}`);
4181
+ logger26?.debug?.(`@smithy/property-provider ${tryNextLink ? "->" : "(!)"} ${message}`);
4182
4182
  }
4183
4183
  static from(error2, options = true) {
4184
4184
  return Object.assign(new this(error2.message, options), error2);
@@ -4766,8 +4766,8 @@ var init_configLoader = __esm({
4766
4766
  init_fromSharedConfigFiles();
4767
4767
  init_fromStatic();
4768
4768
  loadConfig = /* @__PURE__ */ __name(({ environmentVariableSelector, configFileSelector, default: defaultValue }, configuration = {}) => {
4769
- const { signingName, logger: logger27 } = configuration;
4770
- const envOptions = { signingName, logger: logger27 };
4769
+ const { signingName, logger: logger26 } = configuration;
4770
+ const envOptions = { signingName, logger: logger26 };
4771
4771
  return memoize(chain(fromEnv(environmentVariableSelector, envOptions), fromSharedConfigFiles(configFileSelector, configuration), fromStatic(defaultValue)));
4772
4772
  }, "loadConfig");
4773
4773
  }
@@ -6490,7 +6490,7 @@ var init_resolveEndpoint = __esm({
6490
6490
  init_types3();
6491
6491
  init_utils();
6492
6492
  resolveEndpoint = /* @__PURE__ */ __name((ruleSetObject, options) => {
6493
- const { endpointParams, logger: logger27 } = options;
6493
+ const { endpointParams, logger: logger26 } = options;
6494
6494
  const { parameters, rules } = ruleSetObject;
6495
6495
  options.logger?.debug?.(`${debugId} Initial EndpointParams: ${toDebugString(endpointParams)}`);
6496
6496
  for (const paramKey in parameters) {
@@ -6507,7 +6507,7 @@ var init_resolveEndpoint = __esm({
6507
6507
  throw new EndpointError(`Missing required parameter: '${paramKey}'`);
6508
6508
  }
6509
6509
  }
6510
- const endpoint = evaluateRules(rules, { endpointParams, logger: logger27, referenceRecord: {} });
6510
+ const endpoint = evaluateRules(rules, { endpointParams, logger: logger26, referenceRecord: {} });
6511
6511
  options.logger?.debug?.(`${debugId} Resolved endpoint: ${toDebugString(endpoint)}`);
6512
6512
  return endpoint;
6513
6513
  }, "resolveEndpoint");
@@ -6947,7 +6947,7 @@ var init_ByteArrayCollector = __esm({
6947
6947
  });
6948
6948
 
6949
6949
  // node_modules/@smithy/core/dist-es/submodules/serde/util-stream/createBufferedReadable.browser.js
6950
- function createBufferedReadableStream(upstream, size, logger27) {
6950
+ function createBufferedReadableStream(upstream, size, logger26) {
6951
6951
  const reader = upstream.getReader();
6952
6952
  let streamBufferingLoggedWarning = false;
6953
6953
  let bytesSeen = 0;
@@ -6985,7 +6985,7 @@ function createBufferedReadableStream(upstream, size, logger27) {
6985
6985
  const newSize = merge(buffers, mode, chunk);
6986
6986
  if (!streamBufferingLoggedWarning && bytesSeen > size * 2) {
6987
6987
  streamBufferingLoggedWarning = true;
6988
- logger27?.warn(`@smithy/util-stream - stream chunk size ${chunkSize} is below threshold of ${size}, automatically buffering.`);
6988
+ logger26?.warn(`@smithy/util-stream - stream chunk size ${chunkSize} is below threshold of ${size}, automatically buffering.`);
6989
6989
  }
6990
6990
  if (newSize >= size) {
6991
6991
  controller.enqueue(flush(buffers, mode));
@@ -7049,9 +7049,9 @@ var init_createBufferedReadable_browser = __esm({
7049
7049
  });
7050
7050
 
7051
7051
  // node_modules/@smithy/core/dist-es/submodules/serde/util-stream/createBufferedReadable.js
7052
- function createBufferedReadable(upstream, size, logger27) {
7052
+ function createBufferedReadable(upstream, size, logger26) {
7053
7053
  if (isReadableStream(upstream)) {
7054
- return createBufferedReadableStream(upstream, size, logger27);
7054
+ return createBufferedReadableStream(upstream, size, logger26);
7055
7055
  }
7056
7056
  const downstream = new import_node_stream3.Readable({ read() {
7057
7057
  } });
@@ -7084,7 +7084,7 @@ function createBufferedReadable(upstream, size, logger27) {
7084
7084
  const newSize = merge(buffers, mode, chunk);
7085
7085
  if (!streamBufferingLoggedWarning && bytesSeen > size * 2) {
7086
7086
  streamBufferingLoggedWarning = true;
7087
- logger27?.warn(`@smithy/util-stream - stream chunk size ${chunkSize} is below threshold of ${size}, automatically buffering.`);
7087
+ logger26?.warn(`@smithy/util-stream - stream chunk size ${chunkSize} is below threshold of ${size}, automatically buffering.`);
7088
7088
  }
7089
7089
  if (newSize >= size) {
7090
7090
  downstream.push(flush(buffers, mode));
@@ -12769,7 +12769,7 @@ var init_constants5 = __esm({
12769
12769
  });
12770
12770
 
12771
12771
  // node_modules/@smithy/core/dist-es/submodules/retry/middleware-retry/parseRetryAfterHeader.js
12772
- function parseRetryAfterHeader(response, logger27) {
12772
+ function parseRetryAfterHeader(response, logger26) {
12773
12773
  if (!HttpResponse.isInstance(response)) {
12774
12774
  return;
12775
12775
  }
@@ -12786,8 +12786,8 @@ function parseRetryAfterHeader(response, logger27) {
12786
12786
  const date2 = parseRfc7231DateTime(retryAfter);
12787
12787
  retryAfterSeconds = (date2.getTime() - Date.now()) / 1e3;
12788
12788
  } catch (e5) {
12789
- logger27?.trace?.("Failed to parse retry-after header");
12790
- logger27?.trace?.(e5);
12789
+ logger26?.trace?.("Failed to parse retry-after header");
12790
+ logger26?.trace?.(e5);
12791
12791
  }
12792
12792
  } else if (retryAfter.match(/ GMT, ((\d+)|(\d+\.\d+))$/)) {
12793
12793
  retryAfterSeconds = Number(retryAfter.match(/ GMT, ([\d.]+)$/)?.[1]);
@@ -12804,15 +12804,15 @@ function parseRetryAfterHeader(response, logger27) {
12804
12804
  const v = response.headers[header];
12805
12805
  const backoffMilliseconds = Number(v);
12806
12806
  if (isNaN(backoffMilliseconds)) {
12807
- logger27?.trace?.(`Failed to parse x-amz-retry-after=${v}`);
12807
+ logger26?.trace?.(`Failed to parse x-amz-retry-after=${v}`);
12808
12808
  return;
12809
12809
  }
12810
12810
  return new Date(Date.now() + backoffMilliseconds);
12811
12811
  }
12812
12812
  }
12813
12813
  }
12814
- function getRetryAfterHint(response, logger27) {
12815
- return parseRetryAfterHeader(response, logger27);
12814
+ function getRetryAfterHint(response, logger26) {
12815
+ return parseRetryAfterHeader(response, logger26);
12816
12816
  }
12817
12817
  var init_parseRetryAfterHeader = __esm({
12818
12818
  "node_modules/@smithy/core/dist-es/submodules/retry/middleware-retry/parseRetryAfterHeader.js"() {
@@ -12924,12 +12924,12 @@ var init_retryMiddleware = __esm({
12924
12924
  __name(bindRetryMiddleware, "bindRetryMiddleware");
12925
12925
  cooldown = /* @__PURE__ */ __name((ms) => new Promise((resolve) => setTimeout(resolve, ms)), "cooldown");
12926
12926
  isRetryStrategyV2 = /* @__PURE__ */ __name((retryStrategy) => typeof retryStrategy.acquireInitialRetryToken !== "undefined" && typeof retryStrategy.refreshRetryTokenForRetry !== "undefined" && typeof retryStrategy.recordSuccess !== "undefined", "isRetryStrategyV2");
12927
- getRetryErrorInfo = /* @__PURE__ */ __name((error2, logger27) => {
12927
+ getRetryErrorInfo = /* @__PURE__ */ __name((error2, logger26) => {
12928
12928
  const errorInfo = {
12929
12929
  error: error2,
12930
12930
  errorType: getRetryErrorType(error2)
12931
12931
  };
12932
- const retryAfterHint = parseRetryAfterHeader(error2.$response, logger27);
12932
+ const retryAfterHint = parseRetryAfterHeader(error2.$response, logger26);
12933
12933
  if (retryAfterHint) {
12934
12934
  errorInfo.retryAfterHint = retryAfterHint;
12935
12935
  }
@@ -13804,12 +13804,12 @@ var init_loggerMiddleware = __esm({
13804
13804
  loggerMiddleware = /* @__PURE__ */ __name(() => (next, context) => async (args) => {
13805
13805
  try {
13806
13806
  const response = await next(args);
13807
- const { clientName, commandName, logger: logger27, dynamoDbDocumentClientOptions = {} } = context;
13807
+ const { clientName, commandName, logger: logger26, dynamoDbDocumentClientOptions = {} } = context;
13808
13808
  const { overrideInputFilterSensitiveLog, overrideOutputFilterSensitiveLog } = dynamoDbDocumentClientOptions;
13809
13809
  const inputFilterSensitiveLog = overrideInputFilterSensitiveLog ?? context.inputFilterSensitiveLog;
13810
13810
  const outputFilterSensitiveLog = overrideOutputFilterSensitiveLog ?? context.outputFilterSensitiveLog;
13811
13811
  const { $metadata, ...outputWithoutMetadata } = response.output;
13812
- logger27?.info?.({
13812
+ logger26?.info?.({
13813
13813
  clientName,
13814
13814
  commandName,
13815
13815
  input: inputFilterSensitiveLog(args.input),
@@ -13818,10 +13818,10 @@ var init_loggerMiddleware = __esm({
13818
13818
  });
13819
13819
  return response;
13820
13820
  } catch (error2) {
13821
- const { clientName, commandName, logger: logger27, dynamoDbDocumentClientOptions = {} } = context;
13821
+ const { clientName, commandName, logger: logger26, dynamoDbDocumentClientOptions = {} } = context;
13822
13822
  const { overrideInputFilterSensitiveLog } = dynamoDbDocumentClientOptions;
13823
13823
  const inputFilterSensitiveLog = overrideInputFilterSensitiveLog ?? context.inputFilterSensitiveLog;
13824
- logger27?.error?.({
13824
+ logger26?.error?.({
13825
13825
  clientName,
13826
13826
  commandName,
13827
13827
  input: inputFilterSensitiveLog(args.input),
@@ -14583,11 +14583,11 @@ function resolveUserAgentConfig(input) {
14583
14583
  userAgentAppId: /* @__PURE__ */ __name(async () => {
14584
14584
  const appId = await normalizedAppIdProvider();
14585
14585
  if (!isValidUserAgentAppId(appId)) {
14586
- const logger27 = input.logger?.constructor?.name === "NoOpLogger" || !input.logger ? console : input.logger;
14586
+ const logger26 = input.logger?.constructor?.name === "NoOpLogger" || !input.logger ? console : input.logger;
14587
14587
  if (typeof appId !== "string") {
14588
- logger27?.warn("userAgentAppId must be a string or undefined.");
14588
+ logger26?.warn("userAgentAppId must be a string or undefined.");
14589
14589
  } else if (appId.length > 50) {
14590
- logger27?.warn("The provided userAgentAppId exceeds the maximum length of 50 characters.");
14590
+ logger26?.warn("The provided userAgentAppId exceeds the maximum length of 50 characters.");
14591
14591
  }
14592
14592
  }
14593
14593
  return appId;
@@ -19526,7 +19526,7 @@ var require_dist_cjs6 = __commonJS({
19526
19526
  var CMDS_IP = "169.254.170.2";
19527
19527
  var GREENGRASS_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1"]);
19528
19528
  var GREENGRASS_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
19529
- var getCmdsUri = /* @__PURE__ */ __name(async ({ logger: logger27 }) => {
19529
+ var getCmdsUri = /* @__PURE__ */ __name(async ({ logger: logger26 }) => {
19530
19530
  if (process.env[ENV_CMDS_RELATIVE_URI]) {
19531
19531
  return {
19532
19532
  hostname: CMDS_IP,
@@ -19538,18 +19538,18 @@ var require_dist_cjs6 = __commonJS({
19538
19538
  try {
19539
19539
  parsed = new URL(process.env[ENV_CMDS_FULL_URI]);
19540
19540
  } catch {
19541
- throw new CredentialsProviderError2(`${process.env[ENV_CMDS_FULL_URI]} is not a valid container metadata service URL`, { tryNextLink: false, logger: logger27 });
19541
+ throw new CredentialsProviderError2(`${process.env[ENV_CMDS_FULL_URI]} is not a valid container metadata service URL`, { tryNextLink: false, logger: logger26 });
19542
19542
  }
19543
19543
  if (!parsed.hostname || !GREENGRASS_HOSTS.has(parsed.hostname)) {
19544
19544
  throw new CredentialsProviderError2(`${parsed.hostname} is not a valid container metadata service hostname`, {
19545
19545
  tryNextLink: false,
19546
- logger: logger27
19546
+ logger: logger26
19547
19547
  });
19548
19548
  }
19549
19549
  if (!parsed.protocol || !GREENGRASS_PROTOCOLS.has(parsed.protocol)) {
19550
19550
  throw new CredentialsProviderError2(`${parsed.protocol} is not a valid container metadata service protocol`, {
19551
19551
  tryNextLink: false,
19552
- logger: logger27
19552
+ logger: logger26
19553
19553
  });
19554
19554
  }
19555
19555
  return {
@@ -19561,7 +19561,7 @@ var require_dist_cjs6 = __commonJS({
19561
19561
  }
19562
19562
  throw new CredentialsProviderError2(`The container metadata credential provider cannot be used unless the ${ENV_CMDS_RELATIVE_URI} or ${ENV_CMDS_FULL_URI} environment variable is set`, {
19563
19563
  tryNextLink: false,
19564
- logger: logger27
19564
+ logger: logger26
19565
19565
  });
19566
19566
  }, "getCmdsUri");
19567
19567
  var InstanceMetadataV1FallbackError = class _InstanceMetadataV1FallbackError extends CredentialsProviderError2 {
@@ -19616,10 +19616,10 @@ var require_dist_cjs6 = __commonJS({
19616
19616
  var STATIC_STABILITY_REFRESH_INTERVAL_SECONDS = 5 * 60;
19617
19617
  var STATIC_STABILITY_REFRESH_INTERVAL_JITTER_WINDOW_SECONDS = 5 * 60;
19618
19618
  var STATIC_STABILITY_DOC_URL = "https://docs.aws.amazon.com/sdkref/latest/guide/feature-static-credentials.html";
19619
- var getExtendedInstanceMetadataCredentials = /* @__PURE__ */ __name((credentials, logger27) => {
19619
+ var getExtendedInstanceMetadataCredentials = /* @__PURE__ */ __name((credentials, logger26) => {
19620
19620
  const refreshInterval = STATIC_STABILITY_REFRESH_INTERVAL_SECONDS + Math.floor(Math.random() * STATIC_STABILITY_REFRESH_INTERVAL_JITTER_WINDOW_SECONDS);
19621
19621
  const newExpiration = new Date(Date.now() + refreshInterval * 1e3);
19622
- logger27.warn(`Attempting credential expiration extension due to a credential service availability issue. A refresh of these credentials will be attempted after ${new Date(newExpiration)}.
19622
+ logger26.warn(`Attempting credential expiration extension due to a credential service availability issue. A refresh of these credentials will be attempted after ${new Date(newExpiration)}.
19623
19623
  For more information, please visit: ` + STATIC_STABILITY_DOC_URL);
19624
19624
  const originalExpiration = credentials.originalExpiration ?? credentials.expiration;
19625
19625
  return {
@@ -19629,19 +19629,19 @@ For more information, please visit: ` + STATIC_STABILITY_DOC_URL);
19629
19629
  };
19630
19630
  }, "getExtendedInstanceMetadataCredentials");
19631
19631
  var staticStabilityProvider = /* @__PURE__ */ __name((provider, options = {}) => {
19632
- const logger27 = options?.logger || console;
19632
+ const logger26 = options?.logger || console;
19633
19633
  let pastCredentials;
19634
19634
  return async () => {
19635
19635
  let credentials;
19636
19636
  try {
19637
19637
  credentials = await provider();
19638
19638
  if (credentials.expiration && credentials.expiration.getTime() < Date.now()) {
19639
- credentials = getExtendedInstanceMetadataCredentials(credentials, logger27);
19639
+ credentials = getExtendedInstanceMetadataCredentials(credentials, logger26);
19640
19640
  }
19641
19641
  } catch (e5) {
19642
19642
  if (pastCredentials) {
19643
- logger27.warn("Credential renew failed: ", e5);
19644
- credentials = getExtendedInstanceMetadataCredentials(pastCredentials, logger27);
19643
+ logger26.warn("Credential renew failed: ", e5);
19644
+ credentials = getExtendedInstanceMetadataCredentials(pastCredentials, logger26);
19645
19645
  } else {
19646
19646
  throw e5;
19647
19647
  }
@@ -19658,7 +19658,7 @@ For more information, please visit: ` + STATIC_STABILITY_DOC_URL);
19658
19658
  var fromInstanceMetadata = /* @__PURE__ */ __name((init = {}) => staticStabilityProvider(getInstanceMetadataProvider(init), { logger: init.logger }), "fromInstanceMetadata");
19659
19659
  var getInstanceMetadataProvider = /* @__PURE__ */ __name((init = {}) => {
19660
19660
  let disableFetchToken = false;
19661
- const { logger: logger27, profile } = init;
19661
+ const { logger: logger26, profile } = init;
19662
19662
  const { timeout, maxRetries } = providerConfigFromInit(init);
19663
19663
  const getCredentials = /* @__PURE__ */ __name(async (maxRetries2, options) => {
19664
19664
  const isImdsV1Fallback = disableFetchToken || options.headers?.[X_AWS_EC2_METADATA_TOKEN2] == null;
@@ -19722,7 +19722,7 @@ For more information, please visit: ` + STATIC_STABILITY_DOC_URL);
19722
19722
  return async () => {
19723
19723
  const endpoint = await getInstanceMetadataEndpoint();
19724
19724
  if (disableFetchToken) {
19725
- logger27?.debug("AWS SDK Instance Metadata", "using v1 fallback (no token fetch)");
19725
+ logger26?.debug("AWS SDK Instance Metadata", "using v1 fallback (no token fetch)");
19726
19726
  return getCredentials(maxRetries, { ...endpoint, timeout });
19727
19727
  } else {
19728
19728
  let token;
@@ -19736,7 +19736,7 @@ For more information, please visit: ` + STATIC_STABILITY_DOC_URL);
19736
19736
  } else if (error2.message === "TimeoutError" || [403, 404, 405].includes(error2.statusCode)) {
19737
19737
  disableFetchToken = true;
19738
19738
  }
19739
- logger27?.debug("AWS SDK Instance Metadata", "using v1 fallback (initial)");
19739
+ logger26?.debug("AWS SDK Instance Metadata", "using v1 fallback (initial)");
19740
19740
  return getCredentials(maxRetries, { ...endpoint, timeout });
19741
19741
  }
19742
19742
  return getCredentials(maxRetries, {
@@ -19861,7 +19861,7 @@ var require_dist_cjs7 = __commonJS({
19861
19861
  }
19862
19862
  return timing.setTimeout(registerTimeout.bind(null, DEFER_EVENT_LISTENER_TIME$2), DEFER_EVENT_LISTENER_TIME$2);
19863
19863
  }, "setConnectionTimeout");
19864
- var setRequestTimeout = /* @__PURE__ */ __name((req, reject, timeoutInMs = 0, throwOnRequestTimeout, logger27) => {
19864
+ var setRequestTimeout = /* @__PURE__ */ __name((req, reject, timeoutInMs = 0, throwOnRequestTimeout, logger26) => {
19865
19865
  if (timeoutInMs) {
19866
19866
  return timing.setTimeout(() => {
19867
19867
  let msg = `@smithy/node-http-handler - [${throwOnRequestTimeout ? "ERROR" : "WARN"}] a request has exceeded the configured ${timeoutInMs} ms requestTimeout.`;
@@ -19874,7 +19874,7 @@ var require_dist_cjs7 = __commonJS({
19874
19874
  reject(error2);
19875
19875
  } else {
19876
19876
  msg += ` Init client requestHandler with throwOnRequestTimeout=true to turn this into an error.`;
19877
- logger27?.warn?.(msg);
19877
+ logger26?.warn?.(msg);
19878
19878
  }
19879
19879
  }, timeoutInMs);
19880
19880
  }
@@ -20015,7 +20015,7 @@ var require_dist_cjs7 = __commonJS({
20015
20015
  }
20016
20016
  return new _NodeHttpHandler(instanceOrOptions);
20017
20017
  }
20018
- static checkSocketUsage(agent, socketWarningTimestamp, logger27 = console) {
20018
+ static checkSocketUsage(agent, socketWarningTimestamp, logger26 = console) {
20019
20019
  const { sockets, requests, maxSockets } = agent;
20020
20020
  if (typeof maxSockets !== "number" || maxSockets === Infinity) {
20021
20021
  return socketWarningTimestamp;
@@ -20032,7 +20032,7 @@ var require_dist_cjs7 = __commonJS({
20032
20032
  const socketsInUse = sockets[origin]?.length ?? 0;
20033
20033
  const requestsEnqueued = requests[origin]?.length ?? 0;
20034
20034
  if (socketsInUse >= maxSockets && requestsEnqueued >= 2 * maxSockets) {
20035
- logger27?.warn?.(`@smithy/node-http-handler:WARN - socket usage at capacity=${socketsInUse} and ${requestsEnqueued} additional requests are enqueued.
20035
+ logger26?.warn?.(`@smithy/node-http-handler:WARN - socket usage at capacity=${socketsInUse} and ${requestsEnqueued} additional requests are enqueued.
20036
20036
  See https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-configuring-maxsockets.html
20037
20037
  or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler config.`);
20038
20038
  return Date.now();
@@ -20061,7 +20061,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
20061
20061
  this.config = await this.configProvider;
20062
20062
  }
20063
20063
  const config = this.config;
20064
- const logger27 = config.logger;
20064
+ const logger26 = config.logger;
20065
20065
  const isSSL = request2.protocol === "https:";
20066
20066
  if (!isSSL && !this.config.httpAgent) {
20067
20067
  this.config.httpAgent = await this.config.httpAgentProvider();
@@ -20105,7 +20105,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
20105
20105
  });
20106
20106
  }
20107
20107
  socketWarningTimeoutId = timing.setTimeout(() => {
20108
- this.socketWarningTimestamp = _NodeHttpHandler.checkSocketUsage(agent, this.socketWarningTimestamp, logger27);
20108
+ this.socketWarningTimestamp = _NodeHttpHandler.checkSocketUsage(agent, this.socketWarningTimestamp, logger26);
20109
20109
  }, config.socketAcquisitionWarningTimeout ?? (config.requestTimeout ?? 2e3) + (config.connectionTimeout ?? 1e3));
20110
20110
  const queryString = request2.query ? buildQueryString2(request2.query) : "";
20111
20111
  let auth = void 0;
@@ -20169,7 +20169,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
20169
20169
  }
20170
20170
  const effectiveRequestTimeout = requestTimeout ?? config.requestTimeout;
20171
20171
  connectionTimeoutId = setConnectionTimeout(req, reject, config.connectionTimeout);
20172
- requestTimeoutId = setRequestTimeout(req, reject, effectiveRequestTimeout, config.throwOnRequestTimeout, logger27 ?? console);
20172
+ requestTimeoutId = setRequestTimeout(req, reject, effectiveRequestTimeout, config.throwOnRequestTimeout, logger26 ?? console);
20173
20173
  const defaultSocketTimeout = config.socketTimeout === void 0 ? resolveDefaultSocketTimeout(config) : void 0;
20174
20174
  if (defaultSocketTimeout) {
20175
20175
  socketTimeoutId = setSocketTimeout(req, reject, defaultSocketTimeout, true);
@@ -20212,7 +20212,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
20212
20212
  return this.config ?? {};
20213
20213
  }
20214
20214
  resolveDefaultConfig(options) {
20215
- const { requestTimeout, connectionTimeout, socketTimeout, socketAcquisitionWarningTimeout, httpAgent, httpsAgent, throwOnRequestTimeout, logger: logger27 } = options || {};
20215
+ const { requestTimeout, connectionTimeout, socketTimeout, socketAcquisitionWarningTimeout, httpAgent, httpsAgent, throwOnRequestTimeout, logger: logger26 } = options || {};
20216
20216
  const keepAlive = true;
20217
20217
  const maxSockets = 50;
20218
20218
  let httpAgentPromise;
@@ -20241,7 +20241,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
20241
20241
  }
20242
20242
  return new node_https.Agent({ keepAlive, maxSockets, ...httpsAgent });
20243
20243
  })(),
20244
- logger: logger27
20244
+ logger: logger26
20245
20245
  };
20246
20246
  }
20247
20247
  };
@@ -20687,7 +20687,7 @@ var require_dist_cjs8 = __commonJS({
20687
20687
  var ECS_CONTAINER_HOST = "169.254.170.2";
20688
20688
  var EKS_CONTAINER_HOST_IPv4 = "169.254.170.23";
20689
20689
  var EKS_CONTAINER_HOST_IPv6 = "[fd00:ec2::23]";
20690
- var checkUrl = /* @__PURE__ */ __name((url, logger27) => {
20690
+ var checkUrl = /* @__PURE__ */ __name((url, logger26) => {
20691
20691
  if (url.protocol === "https:") {
20692
20692
  return;
20693
20693
  }
@@ -20714,7 +20714,7 @@ var require_dist_cjs8 = __commonJS({
20714
20714
  throw new CredentialsProviderError2(`URL not accepted. It must either be HTTPS or match one of the following:
20715
20715
  - loopback CIDR 127.0.0.0/8 or [::1/128]
20716
20716
  - ECS container host 169.254.170.2
20717
- - EKS container host 169.254.170.23 or [fd00:ec2::23]`, { logger: logger27 });
20717
+ - EKS container host 169.254.170.23 or [fd00:ec2::23]`, { logger: logger26 });
20718
20718
  }, "checkUrl");
20719
20719
  function createGetRequest(url) {
20720
20720
  return new HttpRequest2({
@@ -20730,13 +20730,13 @@ var require_dist_cjs8 = __commonJS({
20730
20730
  });
20731
20731
  }
20732
20732
  __name(createGetRequest, "createGetRequest");
20733
- async function getCredentials(response, logger27) {
20733
+ async function getCredentials(response, logger26) {
20734
20734
  const stream = sdkStreamMixin3(response.body);
20735
20735
  const str = await stream.transformToString();
20736
20736
  if (response.statusCode === 200) {
20737
20737
  const parsed = JSON.parse(str);
20738
20738
  if (typeof parsed.AccessKeyId !== "string" || typeof parsed.SecretAccessKey !== "string" || typeof parsed.Token !== "string" || typeof parsed.Expiration !== "string") {
20739
- throw new CredentialsProviderError2("HTTP credential provider response not of the required format, an object matching: { AccessKeyId: string, SecretAccessKey: string, Token: string, Expiration: string(rfc3339) }", { logger: logger27 });
20739
+ throw new CredentialsProviderError2("HTTP credential provider response not of the required format, an object matching: { AccessKeyId: string, SecretAccessKey: string, Token: string, Expiration: string(rfc3339) }", { logger: logger26 });
20740
20740
  }
20741
20741
  return {
20742
20742
  accessKeyId: parsed.AccessKeyId,
@@ -20751,12 +20751,12 @@ var require_dist_cjs8 = __commonJS({
20751
20751
  parsedBody = JSON.parse(str);
20752
20752
  } catch (e5) {
20753
20753
  }
20754
- throw Object.assign(new CredentialsProviderError2(`Server responded with status: ${response.statusCode}`, { logger: logger27 }), {
20754
+ throw Object.assign(new CredentialsProviderError2(`Server responded with status: ${response.statusCode}`, { logger: logger26 }), {
20755
20755
  Code: parsedBody.Code,
20756
20756
  Message: parsedBody.Message
20757
20757
  });
20758
20758
  }
20759
- throw new CredentialsProviderError2(`Server responded with status: ${response.statusCode}`, { logger: logger27 });
20759
+ throw new CredentialsProviderError2(`Server responded with status: ${response.statusCode}`, { logger: logger26 });
20760
20760
  }
20761
20761
  __name(getCredentials, "getCredentials");
20762
20762
  var retryWrapper = /* @__PURE__ */ __name((toRetry, maxRetries, delayMs) => {
@@ -25470,14 +25470,14 @@ var require_dist_cjs10 = __commonJS({
25470
25470
  var { getBearerTokenEnvKey: getBearerTokenEnvKey2 } = (init_httpAuthSchemes2(), __toCommonJS(httpAuthSchemes_exports));
25471
25471
  var { TokenProviderError: TokenProviderError2, getSSOTokenFilepath: getSSOTokenFilepath2, parseKnownFiles: parseKnownFiles2, getProfileName: getProfileName2, loadSsoSessionData: loadSsoSessionData2, getSSOTokenFromFile: getSSOTokenFromFile2, memoize: memoize2, chain: chain2 } = (init_config2(), __toCommonJS(config_exports));
25472
25472
  var { promises } = require("node:fs");
25473
- var fromEnvSigningName = /* @__PURE__ */ __name(({ logger: logger27, signingName } = {}) => async () => {
25474
- logger27?.debug?.("@aws-sdk/token-providers - fromEnvSigningName");
25473
+ var fromEnvSigningName = /* @__PURE__ */ __name(({ logger: logger26, signingName } = {}) => async () => {
25474
+ logger26?.debug?.("@aws-sdk/token-providers - fromEnvSigningName");
25475
25475
  if (!signingName) {
25476
- throw new TokenProviderError2("Please pass 'signingName' to compute environment variable key", { logger: logger27 });
25476
+ throw new TokenProviderError2("Please pass 'signingName' to compute environment variable key", { logger: logger26 });
25477
25477
  }
25478
25478
  const bearerTokenKey = getBearerTokenEnvKey2(signingName);
25479
25479
  if (!(bearerTokenKey in process.env)) {
25480
- throw new TokenProviderError2(`Token not present in '${bearerTokenKey}' environment variable`, { logger: logger27 });
25480
+ throw new TokenProviderError2(`Token not present in '${bearerTokenKey}' environment variable`, { logger: logger26 });
25481
25481
  }
25482
25482
  const token = { token: process.env[bearerTokenKey] };
25483
25483
  setTokenFeature2(token, "BEARER_SERVICE_ENV_VARS", "3");
@@ -25612,8 +25612,8 @@ var require_dist_cjs10 = __commonJS({
25612
25612
  inFlightRefreshes.delete(ssoSessionName);
25613
25613
  }
25614
25614
  }, "fromSso");
25615
- var fromStatic2 = /* @__PURE__ */ __name(({ token, logger: logger27 }) => async () => {
25616
- logger27?.debug("@aws-sdk/token-providers - fromStatic");
25615
+ var fromStatic2 = /* @__PURE__ */ __name(({ token, logger: logger26 }) => async () => {
25616
+ logger26?.debug("@aws-sdk/token-providers - fromStatic");
25617
25617
  if (!token || !token.token) {
25618
25618
  throw new TokenProviderError2(`Please pass a valid token to fromStatic`, false);
25619
25619
  }
@@ -26363,7 +26363,7 @@ var require_dist_cjs11 = __commonJS({
26363
26363
  var { fromSso } = require_dist_cjs10();
26364
26364
  var isSsoProfile = /* @__PURE__ */ __name((arg) => arg && (typeof arg.sso_start_url === "string" || typeof arg.sso_account_id === "string" || typeof arg.sso_session === "string" || typeof arg.sso_region === "string" || typeof arg.sso_role_name === "string"), "isSsoProfile");
26365
26365
  var SHOULD_FAIL_CREDENTIAL_CHAIN = false;
26366
- var resolveSSOCredentials = /* @__PURE__ */ __name(async ({ ssoStartUrl, ssoSession, ssoAccountId, ssoRegion, ssoRoleName, ssoClient, clientConfig, parentClientConfig, callerClientConfig, profile, filepath, configFilepath, ignoreCache, logger: logger27 }) => {
26366
+ var resolveSSOCredentials = /* @__PURE__ */ __name(async ({ ssoStartUrl, ssoSession, ssoAccountId, ssoRegion, ssoRoleName, ssoClient, clientConfig, parentClientConfig, callerClientConfig, profile, filepath, configFilepath, ignoreCache, logger: logger26 }) => {
26367
26367
  let token;
26368
26368
  const refreshMessage = `To refresh this SSO session run aws sso login with the corresponding profile.`;
26369
26369
  if (ssoSession) {
@@ -26375,7 +26375,7 @@ var require_dist_cjs11 = __commonJS({
26375
26375
  ignoreCache,
26376
26376
  clientConfig,
26377
26377
  parentClientConfig,
26378
- logger: logger27
26378
+ logger: logger26
26379
26379
  })({ callerClientConfig });
26380
26380
  token = {
26381
26381
  accessToken: _token.token,
@@ -26384,7 +26384,7 @@ var require_dist_cjs11 = __commonJS({
26384
26384
  } catch (e5) {
26385
26385
  throw new CredentialsProviderError2(e5.message, {
26386
26386
  tryNextLink: SHOULD_FAIL_CREDENTIAL_CHAIN,
26387
- logger: logger27
26387
+ logger: logger26
26388
26388
  });
26389
26389
  }
26390
26390
  } else {
@@ -26393,14 +26393,14 @@ var require_dist_cjs11 = __commonJS({
26393
26393
  } catch (e5) {
26394
26394
  throw new CredentialsProviderError2(`The SSO session associated with this profile is invalid. ${refreshMessage}`, {
26395
26395
  tryNextLink: SHOULD_FAIL_CREDENTIAL_CHAIN,
26396
- logger: logger27
26396
+ logger: logger26
26397
26397
  });
26398
26398
  }
26399
26399
  }
26400
26400
  if (new Date(token.expiresAt).getTime() - Date.now() <= 0) {
26401
26401
  throw new CredentialsProviderError2(`The SSO session associated with this profile has expired. ${refreshMessage}`, {
26402
26402
  tryNextLink: SHOULD_FAIL_CREDENTIAL_CHAIN,
26403
- logger: logger27
26403
+ logger: logger26
26404
26404
  });
26405
26405
  }
26406
26406
  const { accessToken } = token;
@@ -26420,14 +26420,14 @@ var require_dist_cjs11 = __commonJS({
26420
26420
  } catch (e5) {
26421
26421
  throw new CredentialsProviderError2(e5, {
26422
26422
  tryNextLink: SHOULD_FAIL_CREDENTIAL_CHAIN,
26423
- logger: logger27
26423
+ logger: logger26
26424
26424
  });
26425
26425
  }
26426
26426
  const { roleCredentials: { accessKeyId, secretAccessKey, sessionToken, expiration, credentialScope, accountId } = {} } = ssoResp;
26427
26427
  if (!accessKeyId || !secretAccessKey || !sessionToken || !expiration) {
26428
26428
  throw new CredentialsProviderError2("SSO returns an invalid temporary credential.", {
26429
26429
  tryNextLink: SHOULD_FAIL_CREDENTIAL_CHAIN,
26430
- logger: logger27
26430
+ logger: logger26
26431
26431
  });
26432
26432
  }
26433
26433
  const credentials = {
@@ -26445,11 +26445,11 @@ var require_dist_cjs11 = __commonJS({
26445
26445
  }
26446
26446
  return credentials;
26447
26447
  }, "resolveSSOCredentials");
26448
- var validateSsoProfile = /* @__PURE__ */ __name((profile, logger27) => {
26448
+ var validateSsoProfile = /* @__PURE__ */ __name((profile, logger26) => {
26449
26449
  const { sso_start_url, sso_account_id, sso_region, sso_role_name } = profile;
26450
26450
  if (!sso_start_url || !sso_account_id || !sso_region || !sso_role_name) {
26451
26451
  throw new CredentialsProviderError2(`Profile is configured with invalid SSO credentials. Required parameters "sso_account_id", "sso_region", "sso_role_name", "sso_start_url". Got ${Object.keys(profile).join(", ")}
26452
- Reference: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html`, { tryNextLink: false, logger: logger27 });
26452
+ Reference: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html`, { tryNextLink: false, logger: logger26 });
26453
26453
  }
26454
26454
  return profile;
26455
26455
  }, "validateSsoProfile");
@@ -28348,9 +28348,9 @@ var init_defaultStsRoleAssumers = __esm({
28348
28348
  return async (sourceCreds, params) => {
28349
28349
  closureSourceCreds = sourceCreds;
28350
28350
  if (!stsClient) {
28351
- const { logger: logger27 = stsOptions?.parentClientConfig?.logger, profile = stsOptions?.parentClientConfig?.profile, region, requestHandler = stsOptions?.parentClientConfig?.requestHandler, credentialProviderLogger, userAgentAppId = stsOptions?.parentClientConfig?.userAgentAppId } = stsOptions;
28351
+ const { logger: logger26 = stsOptions?.parentClientConfig?.logger, profile = stsOptions?.parentClientConfig?.profile, region, requestHandler = stsOptions?.parentClientConfig?.requestHandler, credentialProviderLogger, userAgentAppId = stsOptions?.parentClientConfig?.userAgentAppId } = stsOptions;
28352
28352
  const resolvedRegion = await resolveRegion(region, stsOptions?.parentClientConfig?.region, credentialProviderLogger, {
28353
- logger: logger27,
28353
+ logger: logger26,
28354
28354
  profile
28355
28355
  });
28356
28356
  const isCompatibleRequestHandler = !isH2(requestHandler);
@@ -28361,7 +28361,7 @@ var init_defaultStsRoleAssumers = __esm({
28361
28361
  credentialDefaultProvider: /* @__PURE__ */ __name(() => async () => closureSourceCreds, "credentialDefaultProvider"),
28362
28362
  region: resolvedRegion,
28363
28363
  requestHandler: isCompatibleRequestHandler ? requestHandler : void 0,
28364
- logger: logger27
28364
+ logger: logger26
28365
28365
  });
28366
28366
  }
28367
28367
  const { Credentials, AssumedRoleUser } = await stsClient.send(new AssumeRoleCommand(params));
@@ -28385,9 +28385,9 @@ var init_defaultStsRoleAssumers = __esm({
28385
28385
  let stsClient;
28386
28386
  return async (params) => {
28387
28387
  if (!stsClient) {
28388
- const { logger: logger27 = stsOptions?.parentClientConfig?.logger, profile = stsOptions?.parentClientConfig?.profile, region, requestHandler = stsOptions?.parentClientConfig?.requestHandler, credentialProviderLogger, userAgentAppId = stsOptions?.parentClientConfig?.userAgentAppId } = stsOptions;
28388
+ const { logger: logger26 = stsOptions?.parentClientConfig?.logger, profile = stsOptions?.parentClientConfig?.profile, region, requestHandler = stsOptions?.parentClientConfig?.requestHandler, credentialProviderLogger, userAgentAppId = stsOptions?.parentClientConfig?.userAgentAppId } = stsOptions;
28389
28389
  const resolvedRegion = await resolveRegion(region, stsOptions?.parentClientConfig?.region, credentialProviderLogger, {
28390
- logger: logger27,
28390
+ logger: logger26,
28391
28391
  profile
28392
28392
  });
28393
28393
  const isCompatibleRequestHandler = !isH2(requestHandler);
@@ -28397,7 +28397,7 @@ var init_defaultStsRoleAssumers = __esm({
28397
28397
  profile,
28398
28398
  region: resolvedRegion,
28399
28399
  requestHandler: isCompatibleRequestHandler ? requestHandler : void 0,
28400
- logger: logger27
28400
+ logger: logger26
28401
28401
  });
28402
28402
  }
28403
28403
  const { Credentials, AssumedRoleUser } = await stsClient.send(new AssumeRoleWithWebIdentityCommand(params));
@@ -29528,7 +29528,7 @@ var require_dist_cjs14 = __commonJS({
29528
29528
  return this.toCredentials(freshToken.accessToken);
29529
29529
  }
29530
29530
  const { SigninClient: SigninClient2, CreateOAuth2TokenCommand: CreateOAuth2TokenCommand2 } = (init_signin(), __toCommonJS(signin_exports));
29531
- const { logger: logger27, userAgentAppId } = this.callerClientConfig ?? {};
29531
+ const { logger: logger26, userAgentAppId } = this.callerClientConfig ?? {};
29532
29532
  const isH22 = /* @__PURE__ */ __name((requestHandler2) => {
29533
29533
  return requestHandler2?.metadata?.handlerProtocol === "h2";
29534
29534
  }, "isH2");
@@ -29541,7 +29541,7 @@ var require_dist_cjs14 = __commonJS({
29541
29541
  },
29542
29542
  region,
29543
29543
  requestHandler,
29544
- logger: logger27,
29544
+ logger: logger26,
29545
29545
  userAgentAppId,
29546
29546
  ...this.init?.clientConfig
29547
29547
  });
@@ -29789,7 +29789,7 @@ var require_dist_cjs15 = __commonJS({
29789
29789
  setCredentialFeature2(credentials, "CREDENTIALS_PROCESS", "w");
29790
29790
  return credentials;
29791
29791
  }, "getValidatedProcessCredentials");
29792
- var resolveProcessCredentials = /* @__PURE__ */ __name(async (profileName, profiles, logger27) => {
29792
+ var resolveProcessCredentials = /* @__PURE__ */ __name(async (profileName, profiles, logger26) => {
29793
29793
  const profile = profiles[profileName];
29794
29794
  if (profiles[profileName]) {
29795
29795
  const credentialProcess = profile["credential_process"];
@@ -29805,14 +29805,14 @@ var require_dist_cjs15 = __commonJS({
29805
29805
  }
29806
29806
  return getValidatedProcessCredentials(profileName, data, profiles);
29807
29807
  } catch (error2) {
29808
- throw new CredentialsProviderError2(error2.message, { logger: logger27 });
29808
+ throw new CredentialsProviderError2(error2.message, { logger: logger26 });
29809
29809
  }
29810
29810
  } else {
29811
- throw new CredentialsProviderError2(`Profile ${profileName} did not contain credential_process.`, { logger: logger27 });
29811
+ throw new CredentialsProviderError2(`Profile ${profileName} did not contain credential_process.`, { logger: logger26 });
29812
29812
  }
29813
29813
  } else {
29814
29814
  throw new CredentialsProviderError2(`Profile ${profileName} could not be found in shared credentials file.`, {
29815
- logger: logger27
29815
+ logger: logger26
29816
29816
  });
29817
29817
  }
29818
29818
  }, "resolveProcessCredentials");
@@ -29892,21 +29892,21 @@ var require_dist_cjs17 = __commonJS({
29892
29892
  "node_modules/@aws-sdk/credential-provider-ini/dist-cjs/index.js"(exports2) {
29893
29893
  var { CredentialsProviderError: CredentialsProviderError2, chain: chain2, getProfileName: getProfileName2, parseKnownFiles: parseKnownFiles2 } = (init_config2(), __toCommonJS(config_exports));
29894
29894
  var { setCredentialFeature: setCredentialFeature2 } = (init_client3(), __toCommonJS(client_exports2));
29895
- var resolveCredentialSource = /* @__PURE__ */ __name((credentialSource, profileName, logger27) => {
29895
+ var resolveCredentialSource = /* @__PURE__ */ __name((credentialSource, profileName, logger26) => {
29896
29896
  const sourceProvidersMap = {
29897
29897
  EcsContainer: /* @__PURE__ */ __name(async (options) => {
29898
29898
  const { fromHttp } = require_dist_cjs8();
29899
29899
  const { fromContainerMetadata } = require_dist_cjs6();
29900
- logger27?.debug("@aws-sdk/credential-provider-ini - credential_source is EcsContainer");
29900
+ logger26?.debug("@aws-sdk/credential-provider-ini - credential_source is EcsContainer");
29901
29901
  return async () => chain2(fromHttp(options ?? {}), fromContainerMetadata(options))().then(setNamedProvider);
29902
29902
  }, "EcsContainer"),
29903
29903
  Ec2InstanceMetadata: /* @__PURE__ */ __name(async (options) => {
29904
- logger27?.debug("@aws-sdk/credential-provider-ini - credential_source is Ec2InstanceMetadata");
29904
+ logger26?.debug("@aws-sdk/credential-provider-ini - credential_source is Ec2InstanceMetadata");
29905
29905
  const { fromInstanceMetadata } = require_dist_cjs6();
29906
29906
  return async () => fromInstanceMetadata(options)().then(setNamedProvider);
29907
29907
  }, "Ec2InstanceMetadata"),
29908
29908
  Environment: /* @__PURE__ */ __name(async (options) => {
29909
- logger27?.debug("@aws-sdk/credential-provider-ini - credential_source is Environment");
29909
+ logger26?.debug("@aws-sdk/credential-provider-ini - credential_source is Environment");
29910
29910
  const { fromEnv: fromEnv2 } = require_dist_cjs5();
29911
29911
  return async () => fromEnv2(options)().then(setNamedProvider);
29912
29912
  }, "Environment")
@@ -29914,24 +29914,24 @@ var require_dist_cjs17 = __commonJS({
29914
29914
  if (credentialSource in sourceProvidersMap) {
29915
29915
  return sourceProvidersMap[credentialSource];
29916
29916
  } else {
29917
- throw new CredentialsProviderError2(`Unsupported credential source in profile ${profileName}. Got ${credentialSource}, expected EcsContainer or Ec2InstanceMetadata or Environment.`, { logger: logger27 });
29917
+ throw new CredentialsProviderError2(`Unsupported credential source in profile ${profileName}. Got ${credentialSource}, expected EcsContainer or Ec2InstanceMetadata or Environment.`, { logger: logger26 });
29918
29918
  }
29919
29919
  }, "resolveCredentialSource");
29920
29920
  var setNamedProvider = /* @__PURE__ */ __name((creds) => setCredentialFeature2(creds, "CREDENTIALS_PROFILE_NAMED_PROVIDER", "p"), "setNamedProvider");
29921
- var isAssumeRoleProfile = /* @__PURE__ */ __name((arg, { profile = "default", logger: logger27 } = {}) => {
29922
- return Boolean(arg) && typeof arg === "object" && typeof arg.role_arn === "string" && ["undefined", "string"].indexOf(typeof arg.role_session_name) > -1 && ["undefined", "string"].indexOf(typeof arg.external_id) > -1 && ["undefined", "string"].indexOf(typeof arg.mfa_serial) > -1 && (isAssumeRoleWithSourceProfile(arg, { profile, logger: logger27 }) || isCredentialSourceProfile(arg, { profile, logger: logger27 }));
29921
+ var isAssumeRoleProfile = /* @__PURE__ */ __name((arg, { profile = "default", logger: logger26 } = {}) => {
29922
+ return Boolean(arg) && typeof arg === "object" && typeof arg.role_arn === "string" && ["undefined", "string"].indexOf(typeof arg.role_session_name) > -1 && ["undefined", "string"].indexOf(typeof arg.external_id) > -1 && ["undefined", "string"].indexOf(typeof arg.mfa_serial) > -1 && (isAssumeRoleWithSourceProfile(arg, { profile, logger: logger26 }) || isCredentialSourceProfile(arg, { profile, logger: logger26 }));
29923
29923
  }, "isAssumeRoleProfile");
29924
- var isAssumeRoleWithSourceProfile = /* @__PURE__ */ __name((arg, { profile, logger: logger27 }) => {
29924
+ var isAssumeRoleWithSourceProfile = /* @__PURE__ */ __name((arg, { profile, logger: logger26 }) => {
29925
29925
  const withSourceProfile = typeof arg.source_profile === "string" && typeof arg.credential_source === "undefined";
29926
29926
  if (withSourceProfile) {
29927
- logger27?.debug?.(` ${profile} isAssumeRoleWithSourceProfile source_profile=${arg.source_profile}`);
29927
+ logger26?.debug?.(` ${profile} isAssumeRoleWithSourceProfile source_profile=${arg.source_profile}`);
29928
29928
  }
29929
29929
  return withSourceProfile;
29930
29930
  }, "isAssumeRoleWithSourceProfile");
29931
- var isCredentialSourceProfile = /* @__PURE__ */ __name((arg, { profile, logger: logger27 }) => {
29931
+ var isCredentialSourceProfile = /* @__PURE__ */ __name((arg, { profile, logger: logger26 }) => {
29932
29932
  const withProviderProfile = typeof arg.credential_source === "string" && typeof arg.source_profile === "undefined";
29933
29933
  if (withProviderProfile) {
29934
- logger27?.debug?.(` ${profile} isCredentialSourceProfile credential_source=${arg.credential_source}`);
29934
+ logger26?.debug?.(` ${profile} isCredentialSourceProfile credential_source=${arg.credential_source}`);
29935
29935
  }
29936
29936
  return withProviderProfile;
29937
29937
  }, "isCredentialSourceProfile");
@@ -36066,7 +36066,7 @@ var require_dist_cjs20 = __commonJS({
36066
36066
  __name(this, "PutResourcePolicyCommand");
36067
36067
  }
36068
36068
  };
36069
- var QueryCommand5 = class extends command5(_ep2, _mw05, "Query", Query$) {
36069
+ var QueryCommand6 = class extends command5(_ep2, _mw05, "Query", Query$) {
36070
36070
  static {
36071
36071
  __name(this, "QueryCommand");
36072
36072
  }
@@ -36160,7 +36160,7 @@ var require_dist_cjs20 = __commonJS({
36160
36160
  var paginateListExports = createPaginator2(DynamoDBClient2, ListExportsCommand, "NextToken", "NextToken", "MaxResults");
36161
36161
  var paginateListImports = createPaginator2(DynamoDBClient2, ListImportsCommand, "NextToken", "NextToken", "PageSize");
36162
36162
  var paginateListTables = createPaginator2(DynamoDBClient2, ListTablesCommand, "ExclusiveStartTableName", "LastEvaluatedTableName", "Limit");
36163
- var paginateQuery = createPaginator2(DynamoDBClient2, QueryCommand5, "ExclusiveStartKey", "LastEvaluatedKey", "Limit");
36163
+ var paginateQuery = createPaginator2(DynamoDBClient2, QueryCommand6, "ExclusiveStartKey", "LastEvaluatedKey", "Limit");
36164
36164
  var paginateScan = createPaginator2(DynamoDBClient2, ScanCommand, "ExclusiveStartKey", "LastEvaluatedKey", "Limit");
36165
36165
  var checkState$5 = /* @__PURE__ */ __name(async (client, input) => {
36166
36166
  let reason;
@@ -36422,7 +36422,7 @@ var require_dist_cjs20 = __commonJS({
36422
36422
  ListTagsOfResourceCommand,
36423
36423
  PutItemCommand,
36424
36424
  PutResourcePolicyCommand,
36425
- QueryCommand: QueryCommand5,
36425
+ QueryCommand: QueryCommand6,
36426
36426
  RestoreTableFromBackupCommand,
36427
36427
  RestoreTableToPointInTimeCommand,
36428
36428
  ScanCommand,
@@ -37036,7 +37036,7 @@ var require_dist_cjs20 = __commonJS({
37036
37036
  exports2.PutResourcePolicyInput$ = PutResourcePolicyInput$;
37037
37037
  exports2.PutResourcePolicyOutput$ = PutResourcePolicyOutput$;
37038
37038
  exports2.Query$ = Query$;
37039
- exports2.QueryCommand = QueryCommand5;
37039
+ exports2.QueryCommand = QueryCommand6;
37040
37040
  exports2.QueryInput$ = QueryInput$;
37041
37041
  exports2.QueryOutput$ = QueryOutput$;
37042
37042
  exports2.Replica$ = Replica$;
@@ -37964,7 +37964,7 @@ var require_dist_cjs22 = __commonJS({
37964
37964
  return async () => handler2(this.clientCommand);
37965
37965
  }
37966
37966
  };
37967
- var QueryCommand5 = class extends DynamoDBDocumentClientCommand {
37967
+ var QueryCommand6 = class extends DynamoDBDocumentClientCommand {
37968
37968
  static {
37969
37969
  __name(this, "QueryCommand");
37970
37970
  }
@@ -38215,7 +38215,7 @@ var require_dist_cjs22 = __commonJS({
38215
38215
  const hasSerializer = middlewares.some((m3) => m3.includes?.("serializerMiddleware"));
38216
38216
  if (!hasSerializer) {
38217
38217
  const configuredLogger = this.config.logger;
38218
- const logger27 = configuredLogger && !configuredLogger.constructor?.name.includes("NoOp") ? configuredLogger : console;
38218
+ const logger26 = configuredLogger && !configuredLogger.constructor?.name.includes("NoOp") ? configuredLogger : console;
38219
38219
  const substituteClient = new DynamoDBClient2(Object.assign({}, this.config, {
38220
38220
  defaultUserAgentProvider: void 0,
38221
38221
  retryStrategy: void 0,
@@ -38228,7 +38228,7 @@ var require_dist_cjs22 = __commonJS({
38228
38228
  this.middlewareStack = substituteClient.middlewareStack;
38229
38229
  this.config = substituteClient.config;
38230
38230
  this.config.translateConfig = translateConfig;
38231
- logger27.warn("@aws-sdk/lib-dynamodb - WARN: incompatible version of DynamoDBClient given to DynamoDBDocumentClient. We have forwarded your client's configuration to a newer version of DynamoDBClient in the dependency closure to instantiate DynamoDBDocumentClient.");
38231
+ logger26.warn("@aws-sdk/lib-dynamodb - WARN: incompatible version of DynamoDBClient given to DynamoDBDocumentClient. We have forwarded your client's configuration to a newer version of DynamoDBClient in the dependency closure to instantiate DynamoDBDocumentClient.");
38232
38232
  }
38233
38233
  }
38234
38234
  }
@@ -38238,7 +38238,7 @@ var require_dist_cjs22 = __commonJS({
38238
38238
  destroy() {
38239
38239
  }
38240
38240
  };
38241
- var paginateQuery = createPaginator2(DynamoDBDocumentClient2, QueryCommand5, "ExclusiveStartKey", "LastEvaluatedKey", "Limit");
38241
+ var paginateQuery = createPaginator2(DynamoDBDocumentClient2, QueryCommand6, "ExclusiveStartKey", "LastEvaluatedKey", "Limit");
38242
38242
  var paginateScan = createPaginator2(DynamoDBDocumentClient2, ScanCommand, "ExclusiveStartKey", "LastEvaluatedKey", "Limit");
38243
38243
  async function* paginatedBatchGet(config, input) {
38244
38244
  let requestItems = input.RequestItems;
@@ -38390,7 +38390,7 @@ var require_dist_cjs22 = __commonJS({
38390
38390
  }
38391
38391
  }
38392
38392
  query(args, optionsOrCb, cb) {
38393
- const command5 = new QueryCommand5(args);
38393
+ const command5 = new QueryCommand6(args);
38394
38394
  if (typeof optionsOrCb === "function") {
38395
38395
  this.send(command5, optionsOrCb);
38396
38396
  } else if (typeof cb === "function") {
@@ -38481,7 +38481,7 @@ var require_dist_cjs22 = __commonJS({
38481
38481
  exports2.ExportTableToPointInTimeCommand = ExportTableToPointInTimeCommand;
38482
38482
  exports2.GetCommand = GetCommand;
38483
38483
  exports2.PutCommand = PutCommand;
38484
- exports2.QueryCommand = QueryCommand5;
38484
+ exports2.QueryCommand = QueryCommand6;
38485
38485
  exports2.ScanCommand = ScanCommand;
38486
38486
  exports2.SearchVectorsCommand = SearchVectorsCommand;
38487
38487
  exports2.TransactGetCommand = TransactGetCommand;
@@ -39034,6 +39034,128 @@ var init_shared = __esm({
39034
39034
  }
39035
39035
  });
39036
39036
 
39037
+ // src/server/utils/cost-tracker.ts
39038
+ var CostTracker;
39039
+ var init_cost_tracker = __esm({
39040
+ "src/server/utils/cost-tracker.ts"() {
39041
+ "use strict";
39042
+ CostTracker = class {
39043
+ static {
39044
+ __name(this, "CostTracker");
39045
+ }
39046
+ totalRCU = 0;
39047
+ totalWCU = 0;
39048
+ operationCount = 0;
39049
+ /**
39050
+ * ConsumedCapacityを追加
39051
+ *
39052
+ * DynamoDB操作のConsumedCapacityを累積します。
39053
+ * undefinedが渡された場合は何もしません(エラーにしない)。
39054
+ *
39055
+ * AWS SDKのConsumedCapacityは以下のフィールドを持ちます:
39056
+ * - CapacityUnits: 総キャパシティユニット(RCU + WCU)
39057
+ * - ReadCapacityUnits: 読み取りキャパシティユニット
39058
+ * - WriteCapacityUnits: 書き込みキャパシティユニット
39059
+ *
39060
+ * このメソッドはReadCapacityUnitsとWriteCapacityUnitsを優先的に使用し、
39061
+ * 存在しない場合はCapacityUnitsを読み取りとして扱います。
39062
+ *
39063
+ * @param consumedCapacity - DynamoDB操作のConsumedCapacity
39064
+ */
39065
+ add(consumedCapacity) {
39066
+ if (!consumedCapacity) {
39067
+ return;
39068
+ }
39069
+ const rcu = consumedCapacity.ReadCapacityUnits ?? 0;
39070
+ const wcu = consumedCapacity.WriteCapacityUnits ?? 0;
39071
+ this.totalRCU += rcu;
39072
+ this.totalWCU += wcu;
39073
+ this.operationCount += 1;
39074
+ }
39075
+ /**
39076
+ * 集計結果を取得
39077
+ *
39078
+ * これまでに追加されたConsumedCapacityの集計結果を返します。
39079
+ *
39080
+ * @returns 集計されたコスト情報
39081
+ */
39082
+ getAggregated() {
39083
+ return {
39084
+ totalRCU: this.totalRCU,
39085
+ totalWCU: this.totalWCU,
39086
+ operationCount: this.operationCount
39087
+ };
39088
+ }
39089
+ /**
39090
+ * リセット
39091
+ *
39092
+ * 累積されたコスト情報をクリアします。
39093
+ */
39094
+ reset() {
39095
+ this.totalRCU = 0;
39096
+ this.totalWCU = 0;
39097
+ this.operationCount = 0;
39098
+ }
39099
+ };
39100
+ }
39101
+ });
39102
+
39103
+ // src/server/utils/dynamodb.ts
39104
+ function getDBClient() {
39105
+ if (!dbClient) {
39106
+ dbClient = createDynamoDBClient({
39107
+ region: process.env.AWS_REGION || process.env.REGION
39108
+ });
39109
+ }
39110
+ return dbClient;
39111
+ }
39112
+ function getTableName() {
39113
+ const tableName = process.env.TABLE_NAME;
39114
+ if (!tableName) {
39115
+ throw new ConfigError("TABLE_NAME environment variable is not set");
39116
+ }
39117
+ return tableName;
39118
+ }
39119
+ function removeShadowKeys(record) {
39120
+ const { __shadowKeys, ...rest } = record;
39121
+ return rest;
39122
+ }
39123
+ function extractCleanRecord(item) {
39124
+ const data = item.data || item;
39125
+ return removeShadowKeys(data);
39126
+ }
39127
+ async function executeDynamoDBOperation(operation2, operationName) {
39128
+ try {
39129
+ return await operation2();
39130
+ } catch (error2) {
39131
+ if (error2 instanceof Error && error2.name === "AccessDeniedException") {
39132
+ logger2.error("DynamoDB access denied", {
39133
+ errorName: error2.name,
39134
+ errorMessage: error2.message,
39135
+ operation: operationName,
39136
+ tableName: process.env.TABLE_NAME,
39137
+ region: process.env.AWS_REGION || process.env.REGION
39138
+ });
39139
+ throw new Error(`Insufficient permissions to access DynamoDB: ${operationName}`);
39140
+ }
39141
+ throw error2;
39142
+ }
39143
+ }
39144
+ var logger2, dbClient;
39145
+ var init_dynamodb3 = __esm({
39146
+ "src/server/utils/dynamodb.ts"() {
39147
+ "use strict";
39148
+ init_shared();
39149
+ logger2 = createLogger({ service: "records-lambda" });
39150
+ dbClient = null;
39151
+ __name(getDBClient, "getDBClient");
39152
+ __name(getTableName, "getTableName");
39153
+ __name(removeShadowKeys, "removeShadowKeys");
39154
+ __name(extractCleanRecord, "extractCleanRecord");
39155
+ __name(executeDynamoDBOperation, "executeDynamoDBOperation");
39156
+ }
39157
+ });
39158
+
39037
39159
  // src/shared/constants/formatting.ts
39038
39160
  var init_formatting = __esm({
39039
39161
  "src/shared/constants/formatting.ts"() {
@@ -39318,59 +39440,371 @@ var init_shadow = __esm({
39318
39440
  }
39319
39441
  });
39320
39442
 
39321
- // src/server/utils/dynamodb.ts
39322
- function getDBClient() {
39323
- if (!dbClient) {
39324
- dbClient = createDynamoDBClient({
39325
- region: process.env.AWS_REGION || process.env.REGION
39326
- });
39443
+ // src/server/operations/find/keyCondition.ts
39444
+ function buildKeyCondition(resource, sortField, optimizableFilter, secondFilter) {
39445
+ const expressionAttributeValues = {
39446
+ ":pk": resource
39447
+ };
39448
+ if (!optimizableFilter) {
39449
+ return {
39450
+ keyConditionExpression: "PK = :pk AND begins_with(SK, :skPrefix)",
39451
+ expressionAttributeValues: {
39452
+ ...expressionAttributeValues,
39453
+ ":skPrefix": `${sortField}#`
39454
+ }
39455
+ };
39456
+ }
39457
+ if (secondFilter) {
39458
+ const first = rangeBounds(sortField, optimizableFilter);
39459
+ const second = rangeBounds(sortField, secondFilter);
39460
+ const low = first.low ?? second.low;
39461
+ const high = first.high ?? second.high;
39462
+ if (low !== void 0 && high !== void 0) {
39463
+ return rangeCondition(expressionAttributeValues, low, high);
39464
+ }
39465
+ }
39466
+ const { operator, type } = optimizableFilter.parsed;
39467
+ const value = optimizableFilter.value;
39468
+ const { encoded, exact } = encodeValueForShadowSK(value, type, operator);
39469
+ const skValue = `${sortField}#${encoded}`;
39470
+ const afterValue = `${skValue}#id#~`;
39471
+ const beforeValue = `${skValue}#id#`;
39472
+ switch (operator) {
39473
+ case "$eq":
39474
+ return {
39475
+ keyConditionExpression: "PK = :pk AND begins_with(SK, :skValue)",
39476
+ expressionAttributeValues: {
39477
+ ...expressionAttributeValues,
39478
+ ":skValue": beforeValue
39479
+ }
39480
+ };
39481
+ // 範囲検索は SK BETWEEN の 1 条件にする。
39482
+ // - DynamoDB はソートキーに 1 つの条件しか許さない(begins_with と比較を並べると ValidationException)
39483
+ // - 上限・下限を sortField の範囲に閉じないと、他の項目のシャドー(や本体 id#…)まで読む
39484
+ // BETWEEN は両端を含むが、端の値(`…#id#`、`…#id#~`、`{sortField}$`)と一致する SK は実在しない
39485
+ case "$gt":
39486
+ return rangeCondition(
39487
+ expressionAttributeValues,
39488
+ exact ? afterValue : beforeValue,
39489
+ fieldUpperBound(sortField)
39490
+ );
39491
+ case "$gte":
39492
+ return rangeCondition(expressionAttributeValues, beforeValue, fieldUpperBound(sortField));
39493
+ case "$lt":
39494
+ return rangeCondition(
39495
+ expressionAttributeValues,
39496
+ `${sortField}#`,
39497
+ exact ? beforeValue : afterValue
39498
+ );
39499
+ case "$lte":
39500
+ return rangeCondition(expressionAttributeValues, `${sortField}#`, afterValue);
39501
+ case "$starts":
39502
+ return {
39503
+ keyConditionExpression: "PK = :pk AND begins_with(SK, :skValue)",
39504
+ expressionAttributeValues: {
39505
+ ...expressionAttributeValues,
39506
+ ":skValue": skValue
39507
+ }
39508
+ };
39509
+ default:
39510
+ return {
39511
+ keyConditionExpression: "PK = :pk AND begins_with(SK, :skPrefix)",
39512
+ expressionAttributeValues: {
39513
+ ...expressionAttributeValues,
39514
+ ":skPrefix": `${sortField}#`
39515
+ }
39516
+ };
39327
39517
  }
39328
- return dbClient;
39329
39518
  }
39330
- function getTableName() {
39331
- const tableName = process.env.TABLE_NAME;
39332
- if (!tableName) {
39333
- throw new ConfigError("TABLE_NAME environment variable is not set");
39519
+ function rangeBounds(sortField, filter) {
39520
+ const { operator, type } = filter.parsed;
39521
+ const { encoded, exact } = encodeValueForShadowSK(filter.value, type, operator);
39522
+ const skValue = `${sortField}#${encoded}`;
39523
+ const afterValue = `${skValue}#id#~`;
39524
+ const beforeValue = `${skValue}#id#`;
39525
+ switch (operator) {
39526
+ case "$gt":
39527
+ return { low: exact ? afterValue : beforeValue };
39528
+ case "$gte":
39529
+ return { low: beforeValue };
39530
+ case "$lt":
39531
+ return { high: exact ? beforeValue : afterValue };
39532
+ case "$lte":
39533
+ return { high: afterValue };
39534
+ default:
39535
+ return {};
39334
39536
  }
39335
- return tableName;
39336
39537
  }
39337
- function removeShadowKeys(record) {
39338
- const { __shadowKeys, ...rest } = record;
39339
- return rest;
39538
+ function findComplementaryBound(primary, parsedFilters) {
39539
+ const op2 = primary.parsed.operator;
39540
+ const wanted = LOWER_BOUND_OPERATORS.has(op2) ? UPPER_BOUND_OPERATORS : UPPER_BOUND_OPERATORS.has(op2) ? LOWER_BOUND_OPERATORS : void 0;
39541
+ if (!wanted) return void 0;
39542
+ return parsedFilters.find(
39543
+ (f5) => f5 !== primary && f5.parsed.field === primary.parsed.field && wanted.has(f5.parsed.operator)
39544
+ );
39340
39545
  }
39341
- function extractCleanRecord(item) {
39342
- const data = item.data || item;
39343
- return removeShadowKeys(data);
39546
+ function fieldUpperBound(sortField) {
39547
+ return `${sortField}$`;
39344
39548
  }
39345
- async function executeDynamoDBOperation(operation2, operationName) {
39346
- try {
39347
- return await operation2();
39348
- } catch (error2) {
39349
- if (error2 instanceof Error && error2.name === "AccessDeniedException") {
39350
- logger2.error("DynamoDB access denied", {
39351
- errorName: error2.name,
39352
- errorMessage: error2.message,
39353
- operation: operationName,
39354
- tableName: process.env.TABLE_NAME,
39355
- region: process.env.AWS_REGION || process.env.REGION
39549
+ function rangeCondition(base, low, high) {
39550
+ return {
39551
+ keyConditionExpression: "PK = :pk AND SK BETWEEN :skLow AND :skHigh",
39552
+ expressionAttributeValues: { ...base, ":skLow": low, ":skHigh": high }
39553
+ };
39554
+ }
39555
+ function encodeValueForShadowSK(value, type, operator) {
39556
+ const config = getShadowConfig();
39557
+ if (type === "number" || typeof value === "number") {
39558
+ const num = Number(value);
39559
+ return { encoded: formatFieldValue2("number", num, config), exact: false };
39560
+ }
39561
+ if (type === "boolean" || typeof value === "boolean") {
39562
+ const bool = typeof value === "boolean" ? value : String(value).toLowerCase() === "true";
39563
+ return { encoded: formatFieldValue2("boolean", bool, config), exact: true };
39564
+ }
39565
+ const str = String(value);
39566
+ if (operator !== "$starts" && (type === "date" || inferFieldType(str) === "datetime")) {
39567
+ return { encoded: formatFieldValue2("datetime", str, config), exact: true };
39568
+ }
39569
+ const encoded = formatFieldValue2("string", str, config);
39570
+ const bytes = new TextEncoder().encode(str).length;
39571
+ return {
39572
+ encoded,
39573
+ exact: encoded === escapeString2(str) && bytes < config.stringMaxBytes - 3
39574
+ };
39575
+ }
39576
+ var KEY_CONDITION_OPERATORS, LOWER_BOUND_OPERATORS, UPPER_BOUND_OPERATORS;
39577
+ var init_keyCondition = __esm({
39578
+ "src/server/operations/find/keyCondition.ts"() {
39579
+ "use strict";
39580
+ init_shadow();
39581
+ KEY_CONDITION_OPERATORS = /* @__PURE__ */ new Set(["$eq", "$gt", "$gte", "$lt", "$lte", "$starts"]);
39582
+ __name(buildKeyCondition, "buildKeyCondition");
39583
+ LOWER_BOUND_OPERATORS = /* @__PURE__ */ new Set(["$gt", "$gte"]);
39584
+ UPPER_BOUND_OPERATORS = /* @__PURE__ */ new Set(["$lt", "$lte"]);
39585
+ __name(rangeBounds, "rangeBounds");
39586
+ __name(findComplementaryBound, "findComplementaryBound");
39587
+ __name(fieldUpperBound, "fieldUpperBound");
39588
+ __name(rangeCondition, "rangeCondition");
39589
+ __name(encodeValueForShadowSK, "encodeValueForShadowSK");
39590
+ }
39591
+ });
39592
+
39593
+ // src/server/utils/filter.ts
39594
+ function parseFilterField(fieldKey) {
39595
+ const parts = fieldKey.split(":");
39596
+ if (parts.length === 1) {
39597
+ return { field: parts[0], operator: "$eq", type: "string" };
39598
+ }
39599
+ if (parts.length === 2) {
39600
+ assertSupportedOperator(parts[1]);
39601
+ const operator = parts[1];
39602
+ return { field: parts[0], operator, type: "string" };
39603
+ }
39604
+ if (parts.length === 3) {
39605
+ assertSupportedOperator(parts[1]);
39606
+ const operator = parts[1];
39607
+ const type = parts[2];
39608
+ if (!isValidType(type)) {
39609
+ throw new Error(`Invalid filter type: ${parts[2]}`);
39610
+ }
39611
+ return { field: parts[0], operator, type };
39612
+ }
39613
+ throw new Error(`Invalid filter field syntax: ${fieldKey}`);
39614
+ }
39615
+ function isValidOperator(operator) {
39616
+ return [
39617
+ "$eq",
39618
+ "$ne",
39619
+ "$lt",
39620
+ "$lte",
39621
+ "$gt",
39622
+ "$gte",
39623
+ "$in",
39624
+ "$nin",
39625
+ "$starts",
39626
+ "$ends",
39627
+ "$contains",
39628
+ "$exists",
39629
+ "$near"
39630
+ ].includes(operator);
39631
+ }
39632
+ function assertSupportedOperator(operator) {
39633
+ if (operator === "$regex") {
39634
+ throw new Error("Invalid filter operator: $regex is not supported (use $contains or $starts)");
39635
+ }
39636
+ if (!isValidOperator(operator)) {
39637
+ throw new Error(`Invalid filter operator: ${operator}`);
39638
+ }
39639
+ }
39640
+ function isValidType(type) {
39641
+ return ["string", "number", "date", "boolean"].includes(type);
39642
+ }
39643
+ var init_filter = __esm({
39644
+ "src/server/utils/filter.ts"() {
39645
+ "use strict";
39646
+ __name(parseFilterField, "parseFilterField");
39647
+ __name(isValidOperator, "isValidOperator");
39648
+ __name(assertSupportedOperator, "assertSupportedOperator");
39649
+ __name(isValidType, "isValidType");
39650
+ }
39651
+ });
39652
+
39653
+ // src/server/utils/validation.ts
39654
+ function validateSortField(_config, _resource, _sort) {
39655
+ return;
39656
+ }
39657
+ function normalizePagination(pagination) {
39658
+ const perPage = Math.min(pagination?.perPage || 50, 50);
39659
+ const nextToken = pagination?.nextToken;
39660
+ return { perPage, nextToken };
39661
+ }
39662
+ function normalizeSort(config, _resource, sort) {
39663
+ if (sort) {
39664
+ return sort;
39665
+ }
39666
+ return {
39667
+ field: config.updatedAtField,
39668
+ order: "DESC"
39669
+ };
39670
+ }
39671
+ var init_validation2 = __esm({
39672
+ "src/server/utils/validation.ts"() {
39673
+ "use strict";
39674
+ __name(validateSortField, "validateSortField");
39675
+ __name(normalizePagination, "normalizePagination");
39676
+ __name(normalizeSort, "normalizeSort");
39677
+ }
39678
+ });
39679
+
39680
+ // src/server/operations/find/utils.ts
39681
+ function initializeFindConfig() {
39682
+ return getShadowConfig();
39683
+ }
39684
+ function normalizeFindParams(config, resource, params) {
39685
+ const sort = normalizeSort(config, resource, params.sort);
39686
+ const pagination = normalizePagination(params.pagination);
39687
+ const parsedFilters = parseFilters(params.filter);
39688
+ return {
39689
+ sort,
39690
+ pagination,
39691
+ parsedFilters,
39692
+ schema: params.schema
39693
+ };
39694
+ }
39695
+ function withInferredType(parsed, fieldKey, value) {
39696
+ if (fieldKey.split(":").length >= 3) return parsed;
39697
+ if (typeof value === "number") return { ...parsed, type: "number" };
39698
+ if (typeof value === "boolean") return { ...parsed, type: "boolean" };
39699
+ return parsed;
39700
+ }
39701
+ function parseFilters(filter) {
39702
+ const parsedFilters = [];
39703
+ if (!filter || Object.keys(filter).length === 0) {
39704
+ return parsedFilters;
39705
+ }
39706
+ for (const [fieldKey, value] of Object.entries(filter)) {
39707
+ try {
39708
+ if (value && typeof value === "object" && !Array.isArray(value)) {
39709
+ for (const [operator, operatorValue] of Object.entries(value)) {
39710
+ const parsed = parseFilterField(`${fieldKey}:${operator}`);
39711
+ parsedFilters.push({
39712
+ parsed: withInferredType(parsed, fieldKey, operatorValue),
39713
+ value: operatorValue
39714
+ });
39715
+ }
39716
+ } else {
39717
+ const parsed = parseFilterField(fieldKey);
39718
+ parsedFilters.push({ parsed: withInferredType(parsed, fieldKey, value), value });
39719
+ }
39720
+ } catch (error2) {
39721
+ logger3.error("Invalid filter field syntax", {
39722
+ fieldKey,
39723
+ error: error2 instanceof Error ? error2.message : String(error2)
39724
+ });
39725
+ throw new InvalidFilterError(`Invalid filter field syntax: ${fieldKey}`, {
39726
+ field: fieldKey,
39727
+ error: error2 instanceof Error ? error2.message : String(error2)
39356
39728
  });
39357
- throw new Error(`Insufficient permissions to access DynamoDB: ${operationName}`);
39358
39729
  }
39359
- throw error2;
39360
39730
  }
39731
+ return parsedFilters;
39361
39732
  }
39362
- var logger2, dbClient;
39363
- var init_dynamodb3 = __esm({
39364
- "src/server/utils/dynamodb.ts"() {
39733
+ function findOptimizableFilter(sortField, parsedFilters) {
39734
+ return parsedFilters.find((filter) => filter.parsed.field === sortField);
39735
+ }
39736
+ function matchesAllFilters(record, parsedFilters) {
39737
+ return parsedFilters.every((filter) => {
39738
+ const { field, operator } = filter.parsed;
39739
+ const recordValue = record[field];
39740
+ const filterValue = filter.value;
39741
+ switch (operator) {
39742
+ case "$eq":
39743
+ return recordValue === filterValue;
39744
+ case "$ne":
39745
+ return recordValue !== filterValue;
39746
+ case "$gt":
39747
+ return recordValue != null && typeof recordValue === typeof filterValue && (typeof recordValue === "number" || typeof recordValue === "string") && recordValue > filterValue;
39748
+ case "$gte":
39749
+ return recordValue != null && typeof recordValue === typeof filterValue && (typeof recordValue === "number" || typeof recordValue === "string") && recordValue >= filterValue;
39750
+ case "$lt":
39751
+ return recordValue != null && typeof recordValue === typeof filterValue && (typeof recordValue === "number" || typeof recordValue === "string") && recordValue < filterValue;
39752
+ case "$lte":
39753
+ return recordValue != null && typeof recordValue === typeof filterValue && (typeof recordValue === "number" || typeof recordValue === "string") && recordValue <= filterValue;
39754
+ case "$in":
39755
+ return Array.isArray(filterValue) && filterValue.includes(recordValue);
39756
+ case "$nin":
39757
+ return Array.isArray(filterValue) && !filterValue.includes(recordValue);
39758
+ case "$starts":
39759
+ return typeof recordValue === "string" && typeof filterValue === "string" && recordValue.startsWith(filterValue);
39760
+ case "$ends":
39761
+ return typeof recordValue === "string" && typeof filterValue === "string" && recordValue.endsWith(filterValue);
39762
+ case "$contains":
39763
+ return typeof recordValue === "string" && typeof filterValue === "string" && recordValue.includes(filterValue);
39764
+ case "$exists":
39765
+ return filterValue ? recordValue !== void 0 && recordValue !== null : recordValue === void 0 || recordValue === null;
39766
+ default:
39767
+ return true;
39768
+ }
39769
+ });
39770
+ }
39771
+ function detectNearQuery(filter) {
39772
+ if (!filter || Object.keys(filter).length === 0) {
39773
+ return null;
39774
+ }
39775
+ for (const [fieldName, value] of Object.entries(filter)) {
39776
+ if (value && typeof value === "object" && !Array.isArray(value)) {
39777
+ const nearValue = value.$near;
39778
+ if (nearValue && typeof nearValue === "object") {
39779
+ return {
39780
+ fieldName,
39781
+ nearQuery: nearValue
39782
+ };
39783
+ }
39784
+ }
39785
+ }
39786
+ return null;
39787
+ }
39788
+ var logger3;
39789
+ var init_utils6 = __esm({
39790
+ "src/server/operations/find/utils.ts"() {
39365
39791
  "use strict";
39792
+ init_errors();
39366
39793
  init_shared();
39367
- logger2 = createLogger({ service: "records-lambda" });
39368
- dbClient = null;
39369
- __name(getDBClient, "getDBClient");
39370
- __name(getTableName, "getTableName");
39371
- __name(removeShadowKeys, "removeShadowKeys");
39372
- __name(extractCleanRecord, "extractCleanRecord");
39373
- __name(executeDynamoDBOperation, "executeDynamoDBOperation");
39794
+ init_shadow();
39795
+ init_filter();
39796
+ init_validation2();
39797
+ logger3 = createLogger({
39798
+ service: "find-utils",
39799
+ level: process.env.LOG_LEVEL || "info"
39800
+ });
39801
+ __name(initializeFindConfig, "initializeFindConfig");
39802
+ __name(normalizeFindParams, "normalizeFindParams");
39803
+ __name(withInferredType, "withInferredType");
39804
+ __name(parseFilters, "parseFilters");
39805
+ __name(findOptimizableFilter, "findOptimizableFilter");
39806
+ __name(matchesAllFilters, "matchesAllFilters");
39807
+ __name(detectNearQuery, "detectNearQuery");
39374
39808
  }
39375
39809
  });
39376
39810
 
@@ -39390,7 +39824,7 @@ async function batchGetAll(keys, { consistentRead, costTracker, requestId, baseD
39390
39824
  let pending = unique.slice(i5, i5 + BATCH_GET_MAX_KEYS);
39391
39825
  for (let attempt = 0; pending.length > 0; attempt++) {
39392
39826
  if (attempt > BATCH_GET_MAX_RETRIES) {
39393
- logger3.error("BatchGetItem \u306E UnprocessedKeys \u304C\u89E3\u6D88\u3057\u306A\u304B\u3063\u305F", {
39827
+ logger4.error("BatchGetItem \u306E UnprocessedKeys \u304C\u89E3\u6D88\u3057\u306A\u304B\u3063\u305F", {
39394
39828
  requestId,
39395
39829
  unprocessed: pending.length,
39396
39830
  attempts: attempt
@@ -39434,14 +39868,14 @@ async function batchGetAll(keys, { consistentRead, costTracker, requestId, baseD
39434
39868
  }
39435
39869
  return records;
39436
39870
  }
39437
- var import_lib_dynamodb2, logger3, BATCH_GET_MAX_KEYS, BATCH_GET_MAX_RETRIES;
39871
+ var import_lib_dynamodb2, logger4, BATCH_GET_MAX_KEYS, BATCH_GET_MAX_RETRIES;
39438
39872
  var init_batchGet = __esm({
39439
39873
  "src/server/utils/batchGet.ts"() {
39440
39874
  "use strict";
39441
39875
  import_lib_dynamodb2 = __toESM(require_dist_cjs22(), 1);
39442
39876
  init_shared();
39443
39877
  init_dynamodb3();
39444
- logger3 = createLogger({
39878
+ logger4 = createLogger({
39445
39879
  service: "batch-get",
39446
39880
  level: process.env.LOG_LEVEL || "info"
39447
39881
  });
@@ -39452,396 +39886,6 @@ var init_batchGet = __esm({
39452
39886
  }
39453
39887
  });
39454
39888
 
39455
- // src/server/utils/bulkOperations.ts
39456
- function logLargeBatchWarning(operation2, recordCount, requestId, resource) {
39457
- if (recordCount > LARGE_BATCH_WARNING_THRESHOLD) {
39458
- logger4.warn(`Large batch ${operation2} operation detected`, {
39459
- requestId,
39460
- resource,
39461
- recordCount,
39462
- warningThreshold: LARGE_BATCH_WARNING_THRESHOLD,
39463
- estimatedTimeoutRisk: "high",
39464
- recommendation: "Consider splitting the batch into smaller requests to avoid Lambda timeout (15 min limit)"
39465
- });
39466
- }
39467
- }
39468
- function calculateTimeoutRisk(startTime) {
39469
- const elapsedMs = Date.now() - startTime;
39470
- const remainingMs = LAMBDA_TIMEOUT_MS - elapsedMs;
39471
- const utilizationPercent = Math.round(elapsedMs / LAMBDA_TIMEOUT_MS * 100);
39472
- const risk = remainingMs < LAMBDA_TIMEOUT_MS * TIMEOUT_RISK_THRESHOLD ? "high" : "low";
39473
- return {
39474
- elapsedMs,
39475
- remainingMs,
39476
- risk,
39477
- utilizationPercent
39478
- };
39479
- }
39480
- function logPreparationTimeoutRisk(requestId, resource, totalRecords, chunkCount, riskInfo) {
39481
- logger4.info("Records prepared for chunk execution", {
39482
- requestId,
39483
- resource,
39484
- totalRecords,
39485
- chunkCount,
39486
- preparationTimeMs: riskInfo.elapsedMs,
39487
- remainingTimeMs: riskInfo.remainingMs,
39488
- timeoutRisk: riskInfo.risk
39489
- });
39490
- if (riskInfo.risk === "high") {
39491
- logger4.warn("High timeout risk detected during preparation phase", {
39492
- requestId,
39493
- resource,
39494
- preparationElapsedMs: riskInfo.elapsedMs,
39495
- remainingTimeMs: riskInfo.remainingMs,
39496
- lambdaTimeoutMs: LAMBDA_TIMEOUT_MS,
39497
- recommendation: "Consider reducing batch size or optimizing preparation logic"
39498
- });
39499
- }
39500
- }
39501
- function logBulkOperationComplete(operation2, requestId, resource, requested, succeeded, failed, riskInfo, additionalInfo) {
39502
- const totalElapsedSeconds = Math.round(riskInfo.elapsedMs / 1e3);
39503
- logger4.info(`${operation2} completed`, {
39504
- requestId,
39505
- resource,
39506
- requested,
39507
- succeeded,
39508
- totalFailed: failed,
39509
- totalExecutionTimeMs: riskInfo.elapsedMs,
39510
- totalExecutionTimeSeconds: totalElapsedSeconds,
39511
- lambdaTimeoutMs: LAMBDA_TIMEOUT_MS,
39512
- timeoutUtilization: `${riskInfo.utilizationPercent}%`,
39513
- ...additionalInfo
39514
- });
39515
- }
39516
- function logPartialFailure(operation2, requestId, resource, requested, succeeded, failed, errorCodes, additionalInfo) {
39517
- const failureRate = Math.round(failed / requested * 100);
39518
- logger4.warn(`Partial failure in ${operation2} operation`, {
39519
- requestId,
39520
- resource,
39521
- totalRequested: requested,
39522
- successCount: succeeded,
39523
- failedCount: failed,
39524
- failureRate: `${failureRate}%`,
39525
- errorCodes: [...new Set(errorCodes)],
39526
- ...additionalInfo
39527
- });
39528
- }
39529
- var logger4;
39530
- var init_bulkOperations = __esm({
39531
- "src/server/utils/bulkOperations.ts"() {
39532
- "use strict";
39533
- init_shared();
39534
- logger4 = createLogger({ service: "records-lambda" });
39535
- __name(logLargeBatchWarning, "logLargeBatchWarning");
39536
- __name(calculateTimeoutRisk, "calculateTimeoutRisk");
39537
- __name(logPreparationTimeoutRisk, "logPreparationTimeoutRisk");
39538
- __name(logBulkOperationComplete, "logBulkOperationComplete");
39539
- __name(logPartialFailure, "logPartialFailure");
39540
- }
39541
- });
39542
-
39543
- // src/server/utils/chunking.ts
39544
- function calculateChunks(records, getItemCount) {
39545
- const chunks = [];
39546
- const itemCounts = [];
39547
- let currentChunk = [];
39548
- let currentItemCount = 0;
39549
- for (const record of records) {
39550
- const itemCount = getItemCount(record);
39551
- if (itemCount > DYNAMODB_TRANSACT_WRITE_MAX_ITEMS) {
39552
- const errorMsg = `Single record exceeds ${DYNAMODB_TRANSACT_WRITE_MAX_ITEMS} items limit: ${itemCount} items`;
39553
- logger5.error("Chunk validation failed", {
39554
- itemCount,
39555
- limit: DYNAMODB_TRANSACT_WRITE_MAX_ITEMS
39556
- });
39557
- throw new Error(errorMsg);
39558
- }
39559
- if (currentItemCount + itemCount > DYNAMODB_TRANSACT_WRITE_MAX_ITEMS) {
39560
- if (currentChunk.length > 0) {
39561
- chunks.push(currentChunk);
39562
- itemCounts.push(currentItemCount);
39563
- }
39564
- currentChunk = [record];
39565
- currentItemCount = itemCount;
39566
- } else {
39567
- currentChunk.push(record);
39568
- currentItemCount += itemCount;
39569
- }
39570
- }
39571
- if (currentChunk.length > 0) {
39572
- chunks.push(currentChunk);
39573
- itemCounts.push(currentItemCount);
39574
- }
39575
- logger5.info("Chunk calculation completed", {
39576
- totalRecords: records.length,
39577
- chunkCount: chunks.length,
39578
- itemCounts,
39579
- minItemsPerChunk: itemCounts.length > 0 ? Math.min(...itemCounts) : 0,
39580
- maxItemsPerChunk: itemCounts.length > 0 ? Math.max(...itemCounts) : 0,
39581
- avgItemsPerChunk: itemCounts.length > 0 ? Math.round(itemCounts.reduce((sum, count) => sum + count, 0) / itemCounts.length) : 0
39582
- });
39583
- return { chunks, itemCounts };
39584
- }
39585
- async function executeChunks(chunks, executeChunk, getRecordId) {
39586
- const successRecords = [];
39587
- const failedIds = [];
39588
- const errors = [];
39589
- const totalRecords = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
39590
- const executionStartTime = Date.now();
39591
- logger5.info("Starting chunk execution", {
39592
- totalChunks: chunks.length,
39593
- totalRecords
39594
- });
39595
- for (let i5 = 0; i5 < chunks.length; i5++) {
39596
- const chunk = chunks[i5];
39597
- const chunkStartTime = Date.now();
39598
- try {
39599
- logger5.debug(`Executing chunk ${i5 + 1}/${chunks.length}`, {
39600
- chunkIndex: i5,
39601
- recordCount: chunk.length
39602
- });
39603
- const successfulRecords = await executeChunk(chunk);
39604
- successRecords.push(...successfulRecords);
39605
- const chunkDuration = Date.now() - chunkStartTime;
39606
- logger5.info(`Chunk ${i5 + 1}/${chunks.length} succeeded`, {
39607
- chunkIndex: i5,
39608
- recordCount: chunk.length,
39609
- durationMs: chunkDuration
39610
- });
39611
- } catch (error2) {
39612
- const chunkDuration = Date.now() - chunkStartTime;
39613
- const errorMessage = error2 instanceof Error ? error2.message : "Unknown error";
39614
- const errorCode = getErrorCode(error2);
39615
- logger5.error(`Chunk ${i5 + 1}/${chunks.length} failed`, {
39616
- chunkIndex: i5,
39617
- recordCount: chunk.length,
39618
- durationMs: chunkDuration,
39619
- error: errorMessage,
39620
- errorCode
39621
- });
39622
- for (const record of chunk) {
39623
- const recordId = getRecordId(record);
39624
- failedIds.push(recordId);
39625
- errors.push({
39626
- id: recordId,
39627
- code: errorCode,
39628
- message: errorMessage
39629
- });
39630
- }
39631
- }
39632
- }
39633
- const totalExecutionTime = Date.now() - executionStartTime;
39634
- logger5.info("Chunk execution completed", {
39635
- totalChunks: chunks.length,
39636
- totalRecords,
39637
- successCount: successRecords.length,
39638
- failedCount: failedIds.length,
39639
- totalExecutionTimeMs: totalExecutionTime,
39640
- avgTimePerChunkMs: chunks.length > 0 ? Math.round(totalExecutionTime / chunks.length) : 0
39641
- });
39642
- if (failedIds.length > 0) {
39643
- logger5.warn("Partial failure detected in chunk execution", {
39644
- totalRecords,
39645
- successCount: successRecords.length,
39646
- failedCount: failedIds.length,
39647
- failureRate: `${Math.round(failedIds.length / totalRecords * 100)}%`,
39648
- failedIds: failedIds.slice(0, 10),
39649
- // 最初の10件のみログ出力
39650
- errorSummary: errors.slice(0, 5).map((e5) => ({
39651
- id: e5.id,
39652
- code: e5.code,
39653
- message: e5.message.substring(0, 100)
39654
- // メッセージを100文字に制限
39655
- }))
39656
- });
39657
- }
39658
- return {
39659
- successRecords,
39660
- failedIds,
39661
- errors
39662
- };
39663
- }
39664
- function getErrorCode(error2) {
39665
- if (error2 && typeof error2 === "object") {
39666
- if ("name" in error2 && typeof error2.name === "string") {
39667
- return error2.name;
39668
- }
39669
- if ("code" in error2 && typeof error2.code === "string") {
39670
- return error2.code;
39671
- }
39672
- }
39673
- return "TRANSACTION_FAILED";
39674
- }
39675
- var logger5;
39676
- var init_chunking = __esm({
39677
- "src/server/utils/chunking.ts"() {
39678
- "use strict";
39679
- init_shared();
39680
- logger5 = createLogger({ service: "records-lambda" });
39681
- __name(calculateChunks, "calculateChunks");
39682
- __name(executeChunks, "executeChunks");
39683
- __name(getErrorCode, "getErrorCode");
39684
- }
39685
- });
39686
-
39687
- // src/server/utils/cost-tracker.ts
39688
- var CostTracker;
39689
- var init_cost_tracker = __esm({
39690
- "src/server/utils/cost-tracker.ts"() {
39691
- "use strict";
39692
- CostTracker = class {
39693
- static {
39694
- __name(this, "CostTracker");
39695
- }
39696
- totalRCU = 0;
39697
- totalWCU = 0;
39698
- operationCount = 0;
39699
- /**
39700
- * ConsumedCapacityを追加
39701
- *
39702
- * DynamoDB操作のConsumedCapacityを累積します。
39703
- * undefinedが渡された場合は何もしません(エラーにしない)。
39704
- *
39705
- * AWS SDKのConsumedCapacityは以下のフィールドを持ちます:
39706
- * - CapacityUnits: 総キャパシティユニット(RCU + WCU)
39707
- * - ReadCapacityUnits: 読み取りキャパシティユニット
39708
- * - WriteCapacityUnits: 書き込みキャパシティユニット
39709
- *
39710
- * このメソッドはReadCapacityUnitsとWriteCapacityUnitsを優先的に使用し、
39711
- * 存在しない場合はCapacityUnitsを読み取りとして扱います。
39712
- *
39713
- * @param consumedCapacity - DynamoDB操作のConsumedCapacity
39714
- */
39715
- add(consumedCapacity) {
39716
- if (!consumedCapacity) {
39717
- return;
39718
- }
39719
- const rcu = consumedCapacity.ReadCapacityUnits ?? 0;
39720
- const wcu = consumedCapacity.WriteCapacityUnits ?? 0;
39721
- this.totalRCU += rcu;
39722
- this.totalWCU += wcu;
39723
- this.operationCount += 1;
39724
- }
39725
- /**
39726
- * 集計結果を取得
39727
- *
39728
- * これまでに追加されたConsumedCapacityの集計結果を返します。
39729
- *
39730
- * @returns 集計されたコスト情報
39731
- */
39732
- getAggregated() {
39733
- return {
39734
- totalRCU: this.totalRCU,
39735
- totalWCU: this.totalWCU,
39736
- operationCount: this.operationCount
39737
- };
39738
- }
39739
- /**
39740
- * リセット
39741
- *
39742
- * 累積されたコスト情報をクリアします。
39743
- */
39744
- reset() {
39745
- this.totalRCU = 0;
39746
- this.totalWCU = 0;
39747
- this.operationCount = 0;
39748
- }
39749
- };
39750
- }
39751
- });
39752
-
39753
- // src/server/utils/revision.ts
39754
- function revisionOf(item) {
39755
- const rev = item[REVISION_ATTRIBUTE];
39756
- return typeof rev === "number" ? rev : void 0;
39757
- }
39758
- function nextRevision(current) {
39759
- return (current ?? 0) + 1;
39760
- }
39761
- function notExistsCondition() {
39762
- return { ConditionExpression: "attribute_not_exists(PK)" };
39763
- }
39764
- function unchangedCondition(revision) {
39765
- const names = { "#rev": REVISION_ATTRIBUTE };
39766
- if (revision === void 0) {
39767
- return {
39768
- ConditionExpression: "attribute_exists(PK) AND attribute_not_exists(#rev)",
39769
- ExpressionAttributeNames: names
39770
- };
39771
- }
39772
- return {
39773
- ConditionExpression: "#rev = :rev",
39774
- ExpressionAttributeNames: names,
39775
- ExpressionAttributeValues: { ":rev": revision }
39776
- };
39777
- }
39778
- function isWriteConflict(error2) {
39779
- if (!error2 || typeof error2 !== "object") return false;
39780
- const { name, CancellationReasons } = error2;
39781
- if (name === "TransactionConflictException") return true;
39782
- if (name !== "TransactionCanceledException" || !Array.isArray(CancellationReasons)) return false;
39783
- const codes = CancellationReasons.map((r5) => r5?.Code).filter((c5) => c5 && c5 !== "None");
39784
- return codes.length > 0 && codes.every((c5) => c5 === "ConditionalCheckFailed" || c5 === "TransactionConflict");
39785
- }
39786
- function sleep3(ms) {
39787
- return new Promise((resolve) => setTimeout(resolve, ms));
39788
- }
39789
- async function writeWithConflictRetry(initial, write, refresh, baseDelayMs = 20) {
39790
- let records = initial;
39791
- for (let attempt = 0; ; attempt++) {
39792
- try {
39793
- if (records.length > 0) await write(records);
39794
- return records;
39795
- } catch (error2) {
39796
- if (!isWriteConflict(error2) || attempt >= MAX_CONFLICT_RETRIES) throw error2;
39797
- await sleep3(baseDelayMs * 2 ** attempt * (0.5 + Math.random() / 2));
39798
- records = await refresh(records);
39799
- }
39800
- }
39801
- }
39802
- var REVISION_ATTRIBUTE, MAX_CONFLICT_RETRIES;
39803
- var init_revision = __esm({
39804
- "src/server/utils/revision.ts"() {
39805
- "use strict";
39806
- REVISION_ATTRIBUTE = "__rev";
39807
- MAX_CONFLICT_RETRIES = 5;
39808
- __name(revisionOf, "revisionOf");
39809
- __name(nextRevision, "nextRevision");
39810
- __name(notExistsCondition, "notExistsCondition");
39811
- __name(unchangedCondition, "unchangedCondition");
39812
- __name(isWriteConflict, "isWriteConflict");
39813
- __name(sleep3, "sleep");
39814
- __name(writeWithConflictRetry, "writeWithConflictRetry");
39815
- }
39816
- });
39817
-
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
39889
  // src/client/FindCursor.ts
39846
39890
  var init_FindCursor = __esm({
39847
39891
  "src/client/FindCursor.ts"() {
@@ -40141,12 +40185,12 @@ function getScanWarnThreshold() {
40141
40185
  const value = Number(raw);
40142
40186
  return Number.isInteger(value) && value >= 1 ? value : DEFAULT_SCAN_WARN_THRESHOLD;
40143
40187
  }
40144
- var logger6, SPARSE_SCAN_EVENT, DEFAULT_SCAN_WARN_THRESHOLD, ScanWatcher;
40188
+ var logger5, SPARSE_SCAN_EVENT, DEFAULT_SCAN_WARN_THRESHOLD, ScanWatcher;
40145
40189
  var init_scanWarning = __esm({
40146
40190
  "src/server/utils/scanWarning.ts"() {
40147
40191
  "use strict";
40148
40192
  init_shared();
40149
- logger6 = createLogger({ service: "scan-warning", level: "warn" });
40193
+ logger5 = createLogger({ service: "scan-warning", level: "warn" });
40150
40194
  SPARSE_SCAN_EVENT = "SPARSE_SCAN";
40151
40195
  DEFAULT_SCAN_WARN_THRESHOLD = 5e3;
40152
40196
  __name(getScanWarnThreshold, "getScanWarnThreshold");
@@ -40166,7 +40210,7 @@ var init_scanWarning = __esm({
40166
40210
  this.scanned += count;
40167
40211
  if (!this.warned && this.scanned >= this.threshold) {
40168
40212
  this.warned = true;
40169
- logger6.warn(
40213
+ logger5.warn(
40170
40214
  `${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
40215
  {
40172
40216
  event: SPARSE_SCAN_EVENT,
@@ -40186,214 +40230,41 @@ var init_scanWarning = __esm({
40186
40230
  }
40187
40231
  });
40188
40232
 
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
40233
  // src/server/operations/find/idQuery.ts
40379
40234
  async function executeIdQuery(resource, normalizedParams, requestId) {
40380
40235
  const { sort, pagination, parsedFilters } = normalizedParams;
40381
40236
  const { perPage, nextToken } = pagination;
40382
- logger8.debug("Executing ID optimized query", {
40237
+ logger6.debug("Executing ID optimized query", {
40383
40238
  requestId,
40384
40239
  resource,
40385
40240
  sort,
40386
40241
  hasFilters: parsedFilters.length > 0
40387
40242
  });
40388
40243
  const idFilter = parsedFilters.find((f5) => f5.parsed.field === "id");
40244
+ const otherFilters = parsedFilters.filter((f5) => f5 !== idFilter);
40389
40245
  if (idFilter && idFilter.parsed.operator === "$eq") {
40390
- return await executeSpecificIdQuery(resource, String(idFilter.value), requestId);
40246
+ return withOtherFilters(
40247
+ await executeSpecificIdQuery(resource, String(idFilter.value), requestId),
40248
+ otherFilters
40249
+ );
40391
40250
  }
40392
40251
  if (idFilter && idFilter.parsed.operator === "$in" && Array.isArray(idFilter.value)) {
40393
- return await executeInQuery(resource, idFilter.value.map(String), sort, requestId);
40252
+ return withOtherFilters(
40253
+ await executeInQuery(resource, idFilter.value.map(String), sort, requestId),
40254
+ otherFilters
40255
+ );
40394
40256
  }
40395
40257
  return await executeAllRecordsQuery(resource, sort, perPage, nextToken, parsedFilters, requestId);
40396
40258
  }
40259
+ function withOtherFilters(result, otherFilters) {
40260
+ if (otherFilters.length === 0) {
40261
+ return result;
40262
+ }
40263
+ return {
40264
+ ...result,
40265
+ items: result.items.filter((item) => matchesAllFilters(item, otherFilters))
40266
+ };
40267
+ }
40397
40268
  async function executeSpecificIdQuery(resource, targetId, requestId) {
40398
40269
  const dbClient2 = getDBClient();
40399
40270
  const tableName = getTableName();
@@ -40416,7 +40287,7 @@ async function executeSpecificIdQuery(resource, targetId, requestId) {
40416
40287
  costTracker.add(queryResult.ConsumedCapacity);
40417
40288
  const mainRecords = queryResult.Items || [];
40418
40289
  const items = mainRecords.map((item) => extractCleanRecord(item));
40419
- logger8.info("ID specific query succeeded", {
40290
+ logger6.info("ID specific query succeeded", {
40420
40291
  requestId,
40421
40292
  resource,
40422
40293
  targetId,
@@ -40432,38 +40303,23 @@ async function executeSpecificIdQuery(resource, targetId, requestId) {
40432
40303
  };
40433
40304
  }
40434
40305
  async function executeInQuery(resource, targetIds, sort, requestId) {
40435
- const dbClient2 = getDBClient();
40436
- const tableName = getTableName();
40437
40306
  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
- )
40307
+ const found = await batchGetAll(
40308
+ targetIds.map((id) => ({ PK: resource, SK: `id#${id}` })),
40309
+ { consistentRead: true, costTracker, requestId }
40459
40310
  );
40460
- let items = results.flat().map((item) => extractCleanRecord(item));
40311
+ const items = found.map((item) => extractCleanRecord(item));
40312
+ const direction = sort.order === "ASC" ? 1 : -1;
40461
40313
  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);
40314
+ const aVal = a5[sort.field];
40315
+ const bVal = b5[sort.field];
40316
+ if (aVal === bVal) return 0;
40317
+ if (aVal === void 0 || aVal === null) return 1;
40318
+ if (bVal === void 0 || bVal === null) return -1;
40319
+ if (typeof aVal === "number" && typeof bVal === "number") return (aVal - bVal) * direction;
40320
+ return String(aVal).localeCompare(String(bVal)) * direction;
40465
40321
  });
40466
- logger8.info("ID $in query succeeded", {
40322
+ logger6.info("ID $in query succeeded", {
40467
40323
  requestId,
40468
40324
  resource,
40469
40325
  requestedCount: targetIds.length,
@@ -40539,7 +40395,7 @@ async function executeAllRecordsQuery(resource, sort, perPage, nextToken, parsed
40539
40395
  queryResult.LastEvaluatedKey.PK,
40540
40396
  queryResult.LastEvaluatedKey.SK
40541
40397
  ) : void 0;
40542
- logger8.info("ID all records query succeeded", {
40398
+ logger6.info("ID all records query succeeded", {
40543
40399
  requestId,
40544
40400
  resource,
40545
40401
  count: items.length,
@@ -40580,7 +40436,7 @@ async function executeAllRecordsQueryFullScan(resource, sort, perPage, nextToken
40580
40436
  });
40581
40437
  scan: while (true) {
40582
40438
  if (++iterations > SCAN_MAX_ITERATIONS) {
40583
- logger8.error("executeAllRecordsQueryFullScan: \u6700\u5927\u53CD\u5FA9\u56DE\u6570\u3092\u8D85\u904E", {
40439
+ logger6.error("executeAllRecordsQueryFullScan: \u6700\u5927\u53CD\u5FA9\u56DE\u6570\u3092\u8D85\u904E", {
40584
40440
  requestId,
40585
40441
  resource,
40586
40442
  iterations
@@ -40628,7 +40484,7 @@ async function executeAllRecordsQueryFullScan(resource, sort, perPage, nextToken
40628
40484
  }
40629
40485
  const nextKeySignature = `${nextKey.PK}#${nextKey.SK}`;
40630
40486
  if (nextKeySignature === previousKeySignature) {
40631
- logger8.error("executeAllRecordsQueryFullScan: \u540C\u4E00\u306ELastEvaluatedKey\u304C\u8FD4\u5374\u3055\u308C\u305F", {
40487
+ logger6.error("executeAllRecordsQueryFullScan: \u540C\u4E00\u306ELastEvaluatedKey\u304C\u8FD4\u5374\u3055\u308C\u305F", {
40632
40488
  requestId,
40633
40489
  resource,
40634
40490
  iterations
@@ -40645,7 +40501,7 @@ async function executeAllRecordsQueryFullScan(resource, sort, perPage, nextToken
40645
40501
  chunkSize = Math.min(chunkSize * 2, SCAN_CHUNK_MAX);
40646
40502
  }
40647
40503
  const nextTokenValue = hasNextPage && lastReturned ? encodeNextToken(lastReturned.PK, lastReturned.SK) : void 0;
40648
- logger8.info("ID filtered scan query succeeded", {
40504
+ logger6.info("ID filtered scan query succeeded", {
40649
40505
  requestId,
40650
40506
  resource,
40651
40507
  scanned,
@@ -40659,22 +40515,24 @@ async function executeAllRecordsQueryFullScan(resource, sort, perPage, nextToken
40659
40515
  consumedCapacity: costTracker.getAggregated()
40660
40516
  };
40661
40517
  }
40662
- var import_lib_dynamodb3, logger8, SCAN_CHUNK_INITIAL, SCAN_CHUNK_MAX, SCAN_MAX_ITERATIONS;
40518
+ var import_lib_dynamodb3, logger6, SCAN_CHUNK_INITIAL, SCAN_CHUNK_MAX, SCAN_MAX_ITERATIONS;
40663
40519
  var init_idQuery = __esm({
40664
40520
  "src/server/operations/find/idQuery.ts"() {
40665
40521
  "use strict";
40666
40522
  import_lib_dynamodb3 = __toESM(require_dist_cjs22(), 1);
40667
40523
  init_shared();
40524
+ init_batchGet();
40668
40525
  init_cost_tracker();
40669
40526
  init_dynamodb3();
40670
40527
  init_pagination();
40671
40528
  init_scanWarning();
40672
40529
  init_utils6();
40673
- logger8 = createLogger({
40530
+ logger6 = createLogger({
40674
40531
  service: "id-query",
40675
40532
  level: process.env.LOG_LEVEL || "info"
40676
40533
  });
40677
40534
  __name(executeIdQuery, "executeIdQuery");
40535
+ __name(withOtherFilters, "withOtherFilters");
40678
40536
  __name(executeSpecificIdQuery, "executeSpecificIdQuery");
40679
40537
  __name(executeInQuery, "executeInQuery");
40680
40538
  __name(executeAllRecordsQuery, "executeAllRecordsQuery");
@@ -40687,7 +40545,7 @@ var init_idQuery = __esm({
40687
40545
 
40688
40546
  // src/server/operations/find/nearQuery.ts
40689
40547
  async function executeNearQuery(resource, fieldName, nearQuery, limit, requestId) {
40690
- logger9.debug("Executing $near query", {
40548
+ logger7.debug("Executing $near query", {
40691
40549
  requestId,
40692
40550
  resource,
40693
40551
  fieldName,
@@ -40698,7 +40556,7 @@ async function executeNearQuery(resource, fieldName, nearQuery, limit, requestId
40698
40556
  const searchFunction = /* @__PURE__ */ __name(async (geohashPrefix) => {
40699
40557
  const dbClient2 = getDBClient();
40700
40558
  const tableName = getTableName();
40701
- logger9.debug("Searching shadow records", {
40559
+ logger7.debug("Searching shadow records", {
40702
40560
  requestId,
40703
40561
  resource,
40704
40562
  fieldName,
@@ -40749,7 +40607,7 @@ async function executeNearQuery(resource, fieldName, nearQuery, limit, requestId
40749
40607
  previousKeySignature = nextKeySignature;
40750
40608
  exclusiveStartKey = nextKey;
40751
40609
  } while (exclusiveStartKey);
40752
- logger9.debug("Shadow records found", {
40610
+ logger7.debug("Shadow records found", {
40753
40611
  requestId,
40754
40612
  resource,
40755
40613
  geohashPrefix,
@@ -40760,7 +40618,7 @@ async function executeNearQuery(resource, fieldName, nearQuery, limit, requestId
40760
40618
  const parts = sk.split("#id#");
40761
40619
  return parts.length === 2 ? parts[1] : null;
40762
40620
  }).filter((id) => id !== null);
40763
- logger9.debug("Main record IDs extracted", {
40621
+ logger7.debug("Main record IDs extracted", {
40764
40622
  requestId,
40765
40623
  resource,
40766
40624
  geohashPrefix,
@@ -40770,14 +40628,14 @@ async function executeNearQuery(resource, fieldName, nearQuery, limit, requestId
40770
40628
  mainRecordIds.map((id) => ({ PK: resource, SK: `id#${id}` })),
40771
40629
  { consistentRead: false, costTracker, requestId }
40772
40630
  );
40773
- logger9.debug("Main records retrieved", {
40631
+ logger7.debug("Main records retrieved", {
40774
40632
  requestId,
40775
40633
  resource,
40776
40634
  geohashPrefix,
40777
40635
  count: validRecords.length
40778
40636
  });
40779
40637
  const cleanRecords = validRecords.map((record) => extractCleanRecord(record));
40780
- logger9.debug("Clean records extracted", {
40638
+ logger7.debug("Clean records extracted", {
40781
40639
  requestId,
40782
40640
  resource,
40783
40641
  geohashPrefix,
@@ -40790,7 +40648,7 @@ async function executeNearQuery(resource, fieldName, nearQuery, limit, requestId
40790
40648
  const config = minPrecisionOverride !== void 0 ? { ...DEFAULT_GEOHASH_CONFIG, minPrecision: minPrecisionOverride } : DEFAULT_GEOHASH_CONFIG;
40791
40649
  const result = await executeNearSearch(nearQuery, fieldName, limit, searchFunction, config);
40792
40650
  const items = result.documents;
40793
- logger9.info("$near query succeeded", {
40651
+ logger7.info("$near query succeeded", {
40794
40652
  requestId,
40795
40653
  resource,
40796
40654
  fieldName,
@@ -40808,7 +40666,7 @@ async function executeNearQuery(resource, fieldName, nearQuery, limit, requestId
40808
40666
  consumedCapacity: costTracker.getAggregated()
40809
40667
  };
40810
40668
  }
40811
- var import_lib_dynamodb4, logger9;
40669
+ var import_lib_dynamodb4, logger7;
40812
40670
  var init_nearQuery = __esm({
40813
40671
  "src/server/operations/find/nearQuery.ts"() {
40814
40672
  "use strict";
@@ -40820,7 +40678,7 @@ var init_nearQuery = __esm({
40820
40678
  init_cost_tracker();
40821
40679
  init_dynamodb3();
40822
40680
  init_scanWarning();
40823
- logger9 = createLogger({
40681
+ logger7 = createLogger({
40824
40682
  service: "near-query",
40825
40683
  level: process.env.LOG_LEVEL || "info"
40826
40684
  });
@@ -40851,11 +40709,12 @@ async function executeShadowQuery(resource, normalizedParams, requestId) {
40851
40709
  }
40852
40710
  const optimizableFilter = findOptimizableFilter(sort.field, parsedFilters);
40853
40711
  const isKeyConditionOptimized = optimizableFilter !== void 0 && KEY_CONDITION_OPERATORS.has(optimizableFilter.parsed.operator);
40712
+ const upperFilter = isKeyConditionOptimized ? findComplementaryBound(optimizableFilter, parsedFilters) : void 0;
40854
40713
  const residualFilters = parsedFilters.filter(
40855
- (f5) => !(isKeyConditionOptimized && f5 === optimizableFilter)
40714
+ (f5) => !(isKeyConditionOptimized && (f5 === optimizableFilter || f5 === upperFilter))
40856
40715
  );
40857
40716
  if (residualFilters.length > 0) {
40858
- logger10.debug("Residual filters detected, falling back to full scan", {
40717
+ logger8.debug("Residual filters detected, falling back to full scan", {
40859
40718
  requestId,
40860
40719
  resource,
40861
40720
  sortField: sort.field,
@@ -40863,7 +40722,7 @@ async function executeShadowQuery(resource, normalizedParams, requestId) {
40863
40722
  });
40864
40723
  return executeFullScanQuery(resource, normalizedParams, costTracker, requestId);
40865
40724
  }
40866
- logger10.debug("Executing shadow query", {
40725
+ logger8.debug("Executing shadow query", {
40867
40726
  requestId,
40868
40727
  resource,
40869
40728
  sortField: sort.field,
@@ -40877,7 +40736,8 @@ async function executeShadowQuery(resource, normalizedParams, requestId) {
40877
40736
  nextToken,
40878
40737
  isKeyConditionOptimized ? optimizableFilter : void 0,
40879
40738
  costTracker,
40880
- requestId
40739
+ requestId,
40740
+ upperFilter
40881
40741
  );
40882
40742
  const recordIds = extractRecordIds(shadowRecords.Items || []);
40883
40743
  if (recordIds.length === 0) {
@@ -40911,7 +40771,7 @@ async function executeShadowQuery(resource, normalizedParams, requestId) {
40911
40771
  shadowRecords.LastEvaluatedKey.PK,
40912
40772
  shadowRecords.LastEvaluatedKey.SK
40913
40773
  ) : void 0;
40914
- logger10.info("Shadow query succeeded", {
40774
+ logger8.info("Shadow query succeeded", {
40915
40775
  requestId,
40916
40776
  resource,
40917
40777
  sortField: sort.field,
@@ -40935,8 +40795,8 @@ async function executeFilterFirstQuery(resource, normalizedParams, filterCandida
40935
40795
  const { perPage, nextToken } = pagination;
40936
40796
  const offset = nextToken ? decodeOffsetToken(nextToken) ?? 0 : 0;
40937
40797
  const filterSort = { field: filterCandidate.parsed.field, order: "ASC" };
40938
- const remainingFilters = parsedFilters.filter((f5) => f5 !== filterCandidate);
40939
- logger10.debug("Executing filter-first query", {
40798
+ const remainingFilters = parsedFilters;
40799
+ logger8.debug("Executing filter-first query", {
40940
40800
  requestId,
40941
40801
  resource,
40942
40802
  filterField: filterCandidate.parsed.field,
@@ -40959,7 +40819,7 @@ async function executeFilterFirstQuery(resource, normalizedParams, filterCandida
40959
40819
  const page = items.slice(offset, offset + perPage);
40960
40820
  const hasNextPage = offset + perPage < items.length;
40961
40821
  const nextTokenValue = hasNextPage ? encodeOffsetToken(offset + perPage) : void 0;
40962
- logger10.info("Filter-first query succeeded", {
40822
+ logger8.info("Filter-first query succeeded", {
40963
40823
  requestId,
40964
40824
  resource,
40965
40825
  filterField: filterCandidate.parsed.field,
@@ -40980,7 +40840,7 @@ async function executeFullScanQuery(resource, normalizedParams, costTracker, req
40980
40840
  const { sort, pagination, parsedFilters } = normalizedParams;
40981
40841
  const { perPage, nextToken } = pagination;
40982
40842
  const offset = nextToken ? decodeOffsetToken(nextToken) ?? 0 : 0;
40983
- logger10.debug("Executing full scan query", {
40843
+ logger8.debug("Executing full scan query", {
40984
40844
  requestId,
40985
40845
  resource,
40986
40846
  sortField: sort.field,
@@ -41001,7 +40861,7 @@ async function executeFullScanQuery(resource, normalizedParams, costTracker, req
41001
40861
  const page = items.slice(offset, offset + perPage);
41002
40862
  const hasNextPage = offset + perPage < items.length;
41003
40863
  const nextTokenValue = hasNextPage ? encodeOffsetToken(offset + perPage) : void 0;
41004
- logger10.info("Full scan query succeeded", {
40864
+ logger8.info("Full scan query succeeded", {
41005
40865
  requestId,
41006
40866
  resource,
41007
40867
  sortField: sort.field,
@@ -41032,7 +40892,7 @@ async function fetchAllRecordsViaShadowIndex(resource, indexSort, indexFilter, c
41032
40892
  let iterations = 0;
41033
40893
  do {
41034
40894
  if (++iterations > MAX_ITERATIONS) {
41035
- logger10.error("fetchAllRecordsViaShadowIndex: \u6700\u5927\u53CD\u5FA9\u56DE\u6570\u3092\u8D85\u904E", {
40895
+ logger8.error("fetchAllRecordsViaShadowIndex: \u6700\u5927\u53CD\u5FA9\u56DE\u6570\u3092\u8D85\u904E", {
41036
40896
  requestId,
41037
40897
  resource,
41038
40898
  iterations
@@ -41062,7 +40922,7 @@ async function fetchAllRecordsViaShadowIndex(resource, indexSort, indexFilter, c
41062
40922
  const nextKey = result.LastEvaluatedKey;
41063
40923
  const nextKeySignature = nextKey ? `${nextKey.PK}#${nextKey.SK}` : void 0;
41064
40924
  if (nextKeySignature && nextKeySignature === previousKeySignature) {
41065
- logger10.error("fetchAllRecordsViaShadowIndex: \u540C\u4E00\u306ELastEvaluatedKey\u304C\u8FD4\u5374\u3055\u308C\u305F", {
40925
+ logger8.error("fetchAllRecordsViaShadowIndex: \u540C\u4E00\u306ELastEvaluatedKey\u304C\u8FD4\u5374\u3055\u308C\u305F", {
41066
40926
  requestId,
41067
40927
  resource,
41068
40928
  iterations
@@ -41097,7 +40957,7 @@ function selectFilterFirstCandidate(parsedFilters, sortField, schema, perPage) {
41097
40957
  if (eqFilters.length === 0) return void 0;
41098
40958
  const cardinality = schema?.cardinality;
41099
40959
  if (!cardinality) {
41100
- return void 0;
40960
+ return eqFilters[0];
41101
40961
  }
41102
40962
  const threshold = perPage / 2;
41103
40963
  const scored = eqFilters.map((f5) => ({ f: f5, score: cardinality[f5.parsed.field] ?? 0 })).filter(({ score }) => score > threshold).sort((a5, b5) => b5.score - a5.score);
@@ -41116,7 +40976,7 @@ function sortInMemory(items, sort) {
41116
40976
  return 0;
41117
40977
  });
41118
40978
  }
41119
- async function executeShadowRecordQuery(resource, sort, perPage, nextToken, optimizableFilter, costTracker, _requestId) {
40979
+ async function executeShadowRecordQuery(resource, sort, perPage, nextToken, optimizableFilter, costTracker, _requestId, secondFilter) {
41120
40980
  const dbClient2 = getDBClient();
41121
40981
  const tableName = getTableName();
41122
40982
  let exclusiveStartKey;
@@ -41130,7 +40990,8 @@ async function executeShadowRecordQuery(resource, sort, perPage, nextToken, opti
41130
40990
  const { keyConditionExpression, expressionAttributeValues } = buildKeyCondition(
41131
40991
  resource,
41132
40992
  sort.field,
41133
- optimizableFilter
40993
+ optimizableFilter,
40994
+ secondFilter
41134
40995
  );
41135
40996
  const result = await executeDynamoDBOperation(
41136
40997
  () => dbClient2.send(
@@ -41150,102 +41011,6 @@ async function executeShadowRecordQuery(resource, sort, perPage, nextToken, opti
41150
41011
  costTracker.add(result.ConsumedCapacity);
41151
41012
  return result;
41152
41013
  }
41153
- function buildKeyCondition(resource, sortField, optimizableFilter) {
41154
- const expressionAttributeValues = {
41155
- ":pk": resource
41156
- };
41157
- if (!optimizableFilter) {
41158
- return {
41159
- keyConditionExpression: "PK = :pk AND begins_with(SK, :skPrefix)",
41160
- expressionAttributeValues: {
41161
- ...expressionAttributeValues,
41162
- ":skPrefix": `${sortField}#`
41163
- }
41164
- };
41165
- }
41166
- const { operator, type } = optimizableFilter.parsed;
41167
- const value = optimizableFilter.value;
41168
- const { encoded, exact } = encodeValueForShadowSK(value, type, operator);
41169
- const skValue = `${sortField}#${encoded}`;
41170
- const afterValue = `${skValue}#id#~`;
41171
- const beforeValue = `${skValue}#id#`;
41172
- switch (operator) {
41173
- case "$eq":
41174
- return {
41175
- keyConditionExpression: "PK = :pk AND begins_with(SK, :skValue)",
41176
- expressionAttributeValues: {
41177
- ...expressionAttributeValues,
41178
- ":skValue": beforeValue
41179
- }
41180
- };
41181
- // 範囲検索は SK BETWEEN の 1 条件にする。
41182
- // - DynamoDB はソートキーに 1 つの条件しか許さない(begins_with と比較を並べると ValidationException)
41183
- // - 上限・下限を sortField の範囲に閉じないと、他の項目のシャドー(や本体 id#…)まで読む
41184
- // BETWEEN は両端を含むが、端の値(`…#id#`、`…#id#~`、`{sortField}$`)と一致する SK は実在しない
41185
- case "$gt":
41186
- return rangeCondition(
41187
- expressionAttributeValues,
41188
- exact ? afterValue : beforeValue,
41189
- fieldUpperBound(sortField)
41190
- );
41191
- case "$gte":
41192
- return rangeCondition(expressionAttributeValues, beforeValue, fieldUpperBound(sortField));
41193
- case "$lt":
41194
- return rangeCondition(
41195
- expressionAttributeValues,
41196
- `${sortField}#`,
41197
- exact ? beforeValue : afterValue
41198
- );
41199
- case "$lte":
41200
- return rangeCondition(expressionAttributeValues, `${sortField}#`, afterValue);
41201
- case "$starts":
41202
- return {
41203
- keyConditionExpression: "PK = :pk AND begins_with(SK, :skValue)",
41204
- expressionAttributeValues: {
41205
- ...expressionAttributeValues,
41206
- ":skValue": skValue
41207
- }
41208
- };
41209
- default:
41210
- return {
41211
- keyConditionExpression: "PK = :pk AND begins_with(SK, :skPrefix)",
41212
- expressionAttributeValues: {
41213
- ...expressionAttributeValues,
41214
- ":skPrefix": `${sortField}#`
41215
- }
41216
- };
41217
- }
41218
- }
41219
- function fieldUpperBound(sortField) {
41220
- return `${sortField}$`;
41221
- }
41222
- function rangeCondition(base, low, high) {
41223
- return {
41224
- keyConditionExpression: "PK = :pk AND SK BETWEEN :skLow AND :skHigh",
41225
- expressionAttributeValues: { ...base, ":skLow": low, ":skHigh": high }
41226
- };
41227
- }
41228
- function encodeValueForShadowSK(value, type, operator) {
41229
- const config = getShadowConfig();
41230
- if (type === "number" || typeof value === "number") {
41231
- const num = Number(value);
41232
- return { encoded: formatFieldValue2("number", num, config), exact: false };
41233
- }
41234
- if (type === "boolean" || typeof value === "boolean") {
41235
- const bool = typeof value === "boolean" ? value : String(value).toLowerCase() === "true";
41236
- return { encoded: formatFieldValue2("boolean", bool, config), exact: true };
41237
- }
41238
- const str = String(value);
41239
- if (operator !== "$starts" && (type === "date" || inferFieldType(str) === "datetime")) {
41240
- return { encoded: formatFieldValue2("datetime", str, config), exact: true };
41241
- }
41242
- const encoded = formatFieldValue2("string", str, config);
41243
- const bytes = new TextEncoder().encode(str).length;
41244
- return {
41245
- encoded,
41246
- exact: encoded === escapeString2(str) && bytes < config.stringMaxBytes - 3
41247
- };
41248
- }
41249
41014
  function extractRecordIds(shadowRecords) {
41250
41015
  return shadowRecords.map((record) => {
41251
41016
  const sk = record.SK;
@@ -41258,7 +41023,7 @@ async function fetchMainRecords(resource, recordIds, costTracker, requestId) {
41258
41023
  recordIds.map((id) => ({ PK: resource, SK: `id#${id}` })),
41259
41024
  { consistentRead: true, costTracker, requestId }
41260
41025
  );
41261
- logger10.debug("Main records fetched", {
41026
+ logger8.debug("Main records fetched", {
41262
41027
  requestId,
41263
41028
  resource,
41264
41029
  requestedCount: new Set(recordIds).size,
@@ -41266,24 +41031,23 @@ async function fetchMainRecords(resource, recordIds, costTracker, requestId) {
41266
41031
  });
41267
41032
  return allRecords;
41268
41033
  }
41269
- var import_lib_dynamodb5, logger10, KEY_CONDITION_OPERATORS;
41034
+ var import_lib_dynamodb5, logger8;
41270
41035
  var init_shadowQuery = __esm({
41271
41036
  "src/server/operations/find/shadowQuery.ts"() {
41272
41037
  "use strict";
41273
41038
  import_lib_dynamodb5 = __toESM(require_dist_cjs22(), 1);
41274
41039
  init_shared();
41275
- init_shadow();
41276
41040
  init_batchGet();
41277
41041
  init_cost_tracker();
41278
41042
  init_dynamodb3();
41279
41043
  init_pagination();
41280
41044
  init_scanWarning();
41045
+ init_keyCondition();
41281
41046
  init_utils6();
41282
- logger10 = createLogger({
41047
+ logger8 = createLogger({
41283
41048
  service: "shadow-query",
41284
41049
  level: process.env.LOG_LEVEL || "info"
41285
41050
  });
41286
- KEY_CONDITION_OPERATORS = /* @__PURE__ */ new Set(["$eq", "$gt", "$gte", "$lt", "$lte", "$starts"]);
41287
41051
  __name(executeShadowQuery, "executeShadowQuery");
41288
41052
  __name(executeFilterFirstQuery, "executeFilterFirstQuery");
41289
41053
  __name(executeFullScanQuery, "executeFullScanQuery");
@@ -41291,10 +41055,6 @@ var init_shadowQuery = __esm({
41291
41055
  __name(selectFilterFirstCandidate, "selectFilterFirstCandidate");
41292
41056
  __name(sortInMemory, "sortInMemory");
41293
41057
  __name(executeShadowRecordQuery, "executeShadowRecordQuery");
41294
- __name(buildKeyCondition, "buildKeyCondition");
41295
- __name(fieldUpperBound, "fieldUpperBound");
41296
- __name(rangeCondition, "rangeCondition");
41297
- __name(encodeValueForShadowSK, "encodeValueForShadowSK");
41298
41058
  __name(extractRecordIds, "extractRecordIds");
41299
41059
  __name(fetchMainRecords, "fetchMainRecords");
41300
41060
  }
@@ -41302,14 +41062,14 @@ var init_shadowQuery = __esm({
41302
41062
 
41303
41063
  // src/server/operations/find/handler.ts
41304
41064
  async function handleFind(resource, params, requestId) {
41305
- logger11.debug("Executing find", {
41065
+ logger9.debug("Executing find", {
41306
41066
  requestId,
41307
41067
  resource,
41308
41068
  params
41309
41069
  });
41310
41070
  const nearDetection = detectNearQuery(params.filter);
41311
41071
  if (nearDetection) {
41312
- logger11.debug("$near operator detected, executing near search", {
41072
+ logger9.debug("$near operator detected, executing near search", {
41313
41073
  requestId,
41314
41074
  resource,
41315
41075
  fieldName: nearDetection.fieldName
@@ -41326,7 +41086,7 @@ async function handleFind(resource, params, requestId) {
41326
41086
  const config = initializeFindConfig();
41327
41087
  const normalizedParams = normalizeFindParams(config, resource, params);
41328
41088
  validateSortField(config, resource, normalizedParams.sort);
41329
- logger11.debug("Find parameters normalized", {
41089
+ logger9.debug("Find parameters normalized", {
41330
41090
  requestId,
41331
41091
  resource,
41332
41092
  sort: normalizedParams.sort,
@@ -41341,7 +41101,7 @@ async function handleFind(resource, params, requestId) {
41341
41101
  }
41342
41102
  return executeShadowQuery(resource, normalizedParams, requestId);
41343
41103
  }
41344
- var logger11;
41104
+ var logger9;
41345
41105
  var init_handler = __esm({
41346
41106
  "src/server/operations/find/handler.ts"() {
41347
41107
  "use strict";
@@ -41351,7 +41111,7 @@ var init_handler = __esm({
41351
41111
  init_nearQuery();
41352
41112
  init_shadowQuery();
41353
41113
  init_utils6();
41354
- logger11 = createLogger({
41114
+ logger9 = createLogger({
41355
41115
  service: "find-handler",
41356
41116
  level: process.env.LOG_LEVEL || "info"
41357
41117
  });
@@ -41421,6 +41181,343 @@ var init_findAll = __esm({
41421
41181
  }
41422
41182
  });
41423
41183
 
41184
+ // src/server/utils/bulkOperations.ts
41185
+ function logLargeBatchWarning(operation2, recordCount, requestId, resource) {
41186
+ if (recordCount > LARGE_BATCH_WARNING_THRESHOLD) {
41187
+ logger10.warn(`Large batch ${operation2} operation detected`, {
41188
+ requestId,
41189
+ resource,
41190
+ recordCount,
41191
+ warningThreshold: LARGE_BATCH_WARNING_THRESHOLD,
41192
+ estimatedTimeoutRisk: "high",
41193
+ recommendation: "Consider splitting the batch into smaller requests to avoid Lambda timeout (15 min limit)"
41194
+ });
41195
+ }
41196
+ }
41197
+ function calculateTimeoutRisk(startTime) {
41198
+ const elapsedMs = Date.now() - startTime;
41199
+ const remainingMs = LAMBDA_TIMEOUT_MS - elapsedMs;
41200
+ const utilizationPercent = Math.round(elapsedMs / LAMBDA_TIMEOUT_MS * 100);
41201
+ const risk = remainingMs < LAMBDA_TIMEOUT_MS * TIMEOUT_RISK_THRESHOLD ? "high" : "low";
41202
+ return {
41203
+ elapsedMs,
41204
+ remainingMs,
41205
+ risk,
41206
+ utilizationPercent
41207
+ };
41208
+ }
41209
+ function logPreparationTimeoutRisk(requestId, resource, totalRecords, chunkCount, riskInfo) {
41210
+ logger10.info("Records prepared for chunk execution", {
41211
+ requestId,
41212
+ resource,
41213
+ totalRecords,
41214
+ chunkCount,
41215
+ preparationTimeMs: riskInfo.elapsedMs,
41216
+ remainingTimeMs: riskInfo.remainingMs,
41217
+ timeoutRisk: riskInfo.risk
41218
+ });
41219
+ if (riskInfo.risk === "high") {
41220
+ logger10.warn("High timeout risk detected during preparation phase", {
41221
+ requestId,
41222
+ resource,
41223
+ preparationElapsedMs: riskInfo.elapsedMs,
41224
+ remainingTimeMs: riskInfo.remainingMs,
41225
+ lambdaTimeoutMs: LAMBDA_TIMEOUT_MS,
41226
+ recommendation: "Consider reducing batch size or optimizing preparation logic"
41227
+ });
41228
+ }
41229
+ }
41230
+ function logBulkOperationComplete(operation2, requestId, resource, requested, succeeded, failed, riskInfo, additionalInfo) {
41231
+ const totalElapsedSeconds = Math.round(riskInfo.elapsedMs / 1e3);
41232
+ logger10.info(`${operation2} completed`, {
41233
+ requestId,
41234
+ resource,
41235
+ requested,
41236
+ succeeded,
41237
+ totalFailed: failed,
41238
+ totalExecutionTimeMs: riskInfo.elapsedMs,
41239
+ totalExecutionTimeSeconds: totalElapsedSeconds,
41240
+ lambdaTimeoutMs: LAMBDA_TIMEOUT_MS,
41241
+ timeoutUtilization: `${riskInfo.utilizationPercent}%`,
41242
+ ...additionalInfo
41243
+ });
41244
+ }
41245
+ function logPartialFailure(operation2, requestId, resource, requested, succeeded, failed, errorCodes, additionalInfo) {
41246
+ const failureRate = Math.round(failed / requested * 100);
41247
+ logger10.warn(`Partial failure in ${operation2} operation`, {
41248
+ requestId,
41249
+ resource,
41250
+ totalRequested: requested,
41251
+ successCount: succeeded,
41252
+ failedCount: failed,
41253
+ failureRate: `${failureRate}%`,
41254
+ errorCodes: [...new Set(errorCodes)],
41255
+ ...additionalInfo
41256
+ });
41257
+ }
41258
+ var logger10;
41259
+ var init_bulkOperations = __esm({
41260
+ "src/server/utils/bulkOperations.ts"() {
41261
+ "use strict";
41262
+ init_shared();
41263
+ logger10 = createLogger({ service: "records-lambda" });
41264
+ __name(logLargeBatchWarning, "logLargeBatchWarning");
41265
+ __name(calculateTimeoutRisk, "calculateTimeoutRisk");
41266
+ __name(logPreparationTimeoutRisk, "logPreparationTimeoutRisk");
41267
+ __name(logBulkOperationComplete, "logBulkOperationComplete");
41268
+ __name(logPartialFailure, "logPartialFailure");
41269
+ }
41270
+ });
41271
+
41272
+ // src/server/utils/chunking.ts
41273
+ function estimateRecordBytes(record) {
41274
+ return Buffer.byteLength(JSON.stringify(record) ?? "", "utf8");
41275
+ }
41276
+ function calculateChunks(records, getItemCount, getByteSize = estimateRecordBytes) {
41277
+ const chunks = [];
41278
+ const itemCounts = [];
41279
+ let currentChunk = [];
41280
+ let currentItemCount = 0;
41281
+ let currentBytes = 0;
41282
+ for (const record of records) {
41283
+ const itemCount = getItemCount(record);
41284
+ const bytes = getByteSize(record);
41285
+ if (itemCount > DYNAMODB_TRANSACT_WRITE_MAX_ITEMS) {
41286
+ const errorMsg = `Single record exceeds ${DYNAMODB_TRANSACT_WRITE_MAX_ITEMS} items limit: ${itemCount} items`;
41287
+ logger11.error("Chunk validation failed", {
41288
+ itemCount,
41289
+ limit: DYNAMODB_TRANSACT_WRITE_MAX_ITEMS
41290
+ });
41291
+ throw new Error(errorMsg);
41292
+ }
41293
+ if (currentItemCount + itemCount > DYNAMODB_TRANSACT_WRITE_MAX_ITEMS || currentBytes + bytes > CHUNK_MAX_BYTES) {
41294
+ if (currentChunk.length > 0) {
41295
+ chunks.push(currentChunk);
41296
+ itemCounts.push(currentItemCount);
41297
+ }
41298
+ currentChunk = [record];
41299
+ currentItemCount = itemCount;
41300
+ currentBytes = bytes;
41301
+ } else {
41302
+ currentChunk.push(record);
41303
+ currentItemCount += itemCount;
41304
+ currentBytes += bytes;
41305
+ }
41306
+ }
41307
+ if (currentChunk.length > 0) {
41308
+ chunks.push(currentChunk);
41309
+ itemCounts.push(currentItemCount);
41310
+ }
41311
+ logger11.info("Chunk calculation completed", {
41312
+ totalRecords: records.length,
41313
+ chunkCount: chunks.length,
41314
+ itemCounts,
41315
+ minItemsPerChunk: itemCounts.length > 0 ? Math.min(...itemCounts) : 0,
41316
+ maxItemsPerChunk: itemCounts.length > 0 ? Math.max(...itemCounts) : 0,
41317
+ avgItemsPerChunk: itemCounts.length > 0 ? Math.round(itemCounts.reduce((sum, count) => sum + count, 0) / itemCounts.length) : 0
41318
+ });
41319
+ return { chunks, itemCounts };
41320
+ }
41321
+ async function executeChunks(chunks, executeChunk, getRecordId) {
41322
+ const successRecords = [];
41323
+ const failedIds = [];
41324
+ const errors = [];
41325
+ const totalRecords = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
41326
+ const executionStartTime = Date.now();
41327
+ logger11.info("Starting chunk execution", {
41328
+ totalChunks: chunks.length,
41329
+ totalRecords
41330
+ });
41331
+ for (let i5 = 0; i5 < chunks.length; i5++) {
41332
+ const chunk = chunks[i5];
41333
+ const chunkStartTime = Date.now();
41334
+ try {
41335
+ logger11.debug(`Executing chunk ${i5 + 1}/${chunks.length}`, {
41336
+ chunkIndex: i5,
41337
+ recordCount: chunk.length
41338
+ });
41339
+ const successfulRecords = await executeChunk(chunk);
41340
+ successRecords.push(...successfulRecords);
41341
+ const chunkDuration = Date.now() - chunkStartTime;
41342
+ logger11.info(`Chunk ${i5 + 1}/${chunks.length} succeeded`, {
41343
+ chunkIndex: i5,
41344
+ recordCount: chunk.length,
41345
+ durationMs: chunkDuration
41346
+ });
41347
+ } catch (error2) {
41348
+ const chunkDuration = Date.now() - chunkStartTime;
41349
+ const errorMessage = error2 instanceof Error ? error2.message : "Unknown error";
41350
+ const errorCode = getErrorCode(error2);
41351
+ logger11.error(`Chunk ${i5 + 1}/${chunks.length} failed`, {
41352
+ chunkIndex: i5,
41353
+ recordCount: chunk.length,
41354
+ durationMs: chunkDuration,
41355
+ error: errorMessage,
41356
+ errorCode
41357
+ });
41358
+ for (const record of chunk) {
41359
+ const recordId = getRecordId(record);
41360
+ failedIds.push(recordId);
41361
+ errors.push({
41362
+ id: recordId,
41363
+ code: errorCode,
41364
+ message: errorMessage
41365
+ });
41366
+ }
41367
+ }
41368
+ }
41369
+ const totalExecutionTime = Date.now() - executionStartTime;
41370
+ logger11.info("Chunk execution completed", {
41371
+ totalChunks: chunks.length,
41372
+ totalRecords,
41373
+ successCount: successRecords.length,
41374
+ failedCount: failedIds.length,
41375
+ totalExecutionTimeMs: totalExecutionTime,
41376
+ avgTimePerChunkMs: chunks.length > 0 ? Math.round(totalExecutionTime / chunks.length) : 0
41377
+ });
41378
+ if (failedIds.length > 0) {
41379
+ logger11.warn("Partial failure detected in chunk execution", {
41380
+ totalRecords,
41381
+ successCount: successRecords.length,
41382
+ failedCount: failedIds.length,
41383
+ failureRate: `${Math.round(failedIds.length / totalRecords * 100)}%`,
41384
+ failedIds: failedIds.slice(0, 10),
41385
+ // 最初の10件のみログ出力
41386
+ errorSummary: errors.slice(0, 5).map((e5) => ({
41387
+ id: e5.id,
41388
+ code: e5.code,
41389
+ message: e5.message.substring(0, 100)
41390
+ // メッセージを100文字に制限
41391
+ }))
41392
+ });
41393
+ }
41394
+ return {
41395
+ successRecords,
41396
+ failedIds,
41397
+ errors
41398
+ };
41399
+ }
41400
+ function getErrorCode(error2) {
41401
+ if (error2 && typeof error2 === "object") {
41402
+ if ("name" in error2 && typeof error2.name === "string") {
41403
+ return error2.name;
41404
+ }
41405
+ if ("code" in error2 && typeof error2.code === "string") {
41406
+ return error2.code;
41407
+ }
41408
+ }
41409
+ return "TRANSACTION_FAILED";
41410
+ }
41411
+ var logger11, CHUNK_MAX_BYTES;
41412
+ var init_chunking = __esm({
41413
+ "src/server/utils/chunking.ts"() {
41414
+ "use strict";
41415
+ init_shared();
41416
+ logger11 = createLogger({ service: "records-lambda" });
41417
+ CHUNK_MAX_BYTES = 3.5 * 1024 * 1024;
41418
+ __name(estimateRecordBytes, "estimateRecordBytes");
41419
+ __name(calculateChunks, "calculateChunks");
41420
+ __name(executeChunks, "executeChunks");
41421
+ __name(getErrorCode, "getErrorCode");
41422
+ }
41423
+ });
41424
+
41425
+ // src/server/utils/idFilter.ts
41426
+ function splitIdFilter(filter) {
41427
+ const { id, ...rest } = filter ?? {};
41428
+ if (typeof id === "string") {
41429
+ return { id, rest };
41430
+ }
41431
+ if (typeof id === "object" && id !== null && "$in" in id) {
41432
+ return { ids: (id.$in ?? []).slice(), rest };
41433
+ }
41434
+ return { rest: filter ?? {} };
41435
+ }
41436
+ function conditionOf(rest) {
41437
+ return Object.keys(rest).length > 0 ? rest : void 0;
41438
+ }
41439
+ function conditionMatcher(condition) {
41440
+ if (!condition || Object.keys(condition).length === 0) {
41441
+ return () => true;
41442
+ }
41443
+ const parsed = parseFilters(condition);
41444
+ return (record) => matchesAllFilters(record, parsed);
41445
+ }
41446
+ var init_idFilter = __esm({
41447
+ "src/server/utils/idFilter.ts"() {
41448
+ "use strict";
41449
+ init_utils6();
41450
+ __name(splitIdFilter, "splitIdFilter");
41451
+ __name(conditionOf, "conditionOf");
41452
+ __name(conditionMatcher, "conditionMatcher");
41453
+ }
41454
+ });
41455
+
41456
+ // src/server/utils/revision.ts
41457
+ function revisionOf(item) {
41458
+ const rev = item[REVISION_ATTRIBUTE];
41459
+ return typeof rev === "number" ? rev : void 0;
41460
+ }
41461
+ function nextRevision(current) {
41462
+ return (current ?? 0) + 1;
41463
+ }
41464
+ function notExistsCondition() {
41465
+ return { ConditionExpression: "attribute_not_exists(PK)" };
41466
+ }
41467
+ function unchangedCondition(revision) {
41468
+ const names = { "#rev": REVISION_ATTRIBUTE };
41469
+ if (revision === void 0) {
41470
+ return {
41471
+ ConditionExpression: "attribute_exists(PK) AND attribute_not_exists(#rev)",
41472
+ ExpressionAttributeNames: names
41473
+ };
41474
+ }
41475
+ return {
41476
+ ConditionExpression: "#rev = :rev",
41477
+ ExpressionAttributeNames: names,
41478
+ ExpressionAttributeValues: { ":rev": revision }
41479
+ };
41480
+ }
41481
+ function isWriteConflict(error2) {
41482
+ if (!error2 || typeof error2 !== "object") return false;
41483
+ const { name, CancellationReasons } = error2;
41484
+ if (name === "TransactionConflictException") return true;
41485
+ if (name !== "TransactionCanceledException" || !Array.isArray(CancellationReasons)) return false;
41486
+ const codes = CancellationReasons.map((r5) => r5?.Code).filter((c5) => c5 && c5 !== "None");
41487
+ return codes.length > 0 && codes.every((c5) => c5 === "ConditionalCheckFailed" || c5 === "TransactionConflict");
41488
+ }
41489
+ function sleep3(ms) {
41490
+ return new Promise((resolve) => setTimeout(resolve, ms));
41491
+ }
41492
+ async function writeWithConflictRetry(initial, write, refresh, baseDelayMs = 20) {
41493
+ let records = initial;
41494
+ for (let attempt = 0; ; attempt++) {
41495
+ try {
41496
+ if (records.length > 0) await write(records);
41497
+ return records;
41498
+ } catch (error2) {
41499
+ if (!isWriteConflict(error2) || attempt >= MAX_CONFLICT_RETRIES) throw error2;
41500
+ await sleep3(baseDelayMs * 2 ** attempt * (0.5 + Math.random() / 2));
41501
+ records = await refresh(records);
41502
+ }
41503
+ }
41504
+ }
41505
+ var REVISION_ATTRIBUTE, MAX_CONFLICT_RETRIES;
41506
+ var init_revision = __esm({
41507
+ "src/server/utils/revision.ts"() {
41508
+ "use strict";
41509
+ REVISION_ATTRIBUTE = "__rev";
41510
+ MAX_CONFLICT_RETRIES = 5;
41511
+ __name(revisionOf, "revisionOf");
41512
+ __name(nextRevision, "nextRevision");
41513
+ __name(notExistsCondition, "notExistsCondition");
41514
+ __name(unchangedCondition, "unchangedCondition");
41515
+ __name(isWriteConflict, "isWriteConflict");
41516
+ __name(sleep3, "sleep");
41517
+ __name(writeWithConflictRetry, "writeWithConflictRetry");
41518
+ }
41519
+ });
41520
+
41424
41521
  // src/server/operations/deleteMany.ts
41425
41522
  var deleteMany_exports = {};
41426
41523
  __export(deleteMany_exports, {
@@ -41430,8 +41527,10 @@ async function handleDeleteMany(resource, params, requestId) {
41430
41527
  const startTime = Date.now();
41431
41528
  const costTracker = new CostTracker();
41432
41529
  let ids;
41530
+ let condition;
41433
41531
  if ("ids" in params) {
41434
- ids = params.ids;
41532
+ ids = [...new Set(params.ids)];
41533
+ condition = params.condition;
41435
41534
  logger12.debug("Executing deleteMany with ids", {
41436
41535
  requestId,
41437
41536
  resource,
@@ -41456,6 +41555,7 @@ async function handleDeleteMany(resource, params, requestId) {
41456
41555
  requestId
41457
41556
  );
41458
41557
  ids = matched.map((item) => item.id);
41558
+ condition = params.filter;
41459
41559
  logger12.debug("Found records with filter", {
41460
41560
  requestId,
41461
41561
  resource,
@@ -41480,9 +41580,13 @@ async function handleDeleteMany(resource, params, requestId) {
41480
41580
  );
41481
41581
  const existingIds = /* @__PURE__ */ new Set();
41482
41582
  const preparedRecords = [];
41583
+ const matches = conditionMatcher(condition);
41483
41584
  for (const item of existingItems) {
41484
41585
  const existingData = item.data;
41485
41586
  const id = existingData.id;
41587
+ if (!matches(existingData)) {
41588
+ continue;
41589
+ }
41486
41590
  const shadowKeys = item.__shadowKeys ?? existingData.__shadowKeys ?? [];
41487
41591
  existingIds.add(id);
41488
41592
  preparedRecords.push({
@@ -41568,7 +41672,7 @@ async function handleDeleteMany(resource, params, requestId) {
41568
41672
  if (transactItems.length === 0) return;
41569
41673
  const result = await executeDynamoDBOperation(
41570
41674
  () => dbClient2.send(
41571
- new import_lib_dynamodb6.TransactWriteCommand({
41675
+ new import_lib_dynamodb7.TransactWriteCommand({
41572
41676
  TransactItems: transactItems,
41573
41677
  ReturnConsumedCapacity: "TOTAL"
41574
41678
  })
@@ -41679,11 +41783,11 @@ async function handleDeleteMany(resource, params, requestId) {
41679
41783
  consumedCapacity: costTracker.getAggregated()
41680
41784
  };
41681
41785
  }
41682
- var import_lib_dynamodb6, logger12;
41786
+ var import_lib_dynamodb7, logger12;
41683
41787
  var init_deleteMany = __esm({
41684
41788
  "src/server/operations/deleteMany.ts"() {
41685
41789
  "use strict";
41686
- import_lib_dynamodb6 = __toESM(require_dist_cjs22(), 1);
41790
+ import_lib_dynamodb7 = __toESM(require_dist_cjs22(), 1);
41687
41791
  init_shared();
41688
41792
  init_shadow();
41689
41793
  init_batchGet();
@@ -41691,6 +41795,7 @@ var init_deleteMany = __esm({
41691
41795
  init_chunking();
41692
41796
  init_cost_tracker();
41693
41797
  init_dynamodb3();
41798
+ init_idFilter();
41694
41799
  init_revision();
41695
41800
  init_findAll();
41696
41801
  logger12 = createLogger({ service: "records-lambda" });
@@ -41714,7 +41819,8 @@ async function handleFindMany(resource, params, requestId) {
41714
41819
  ids.map((id) => ({ PK: resource, SK: generateMainRecordSK2(id) })),
41715
41820
  { consistentRead: true, requestId }
41716
41821
  );
41717
- const records = items.map((item) => extractCleanRecord(item));
41822
+ const matches = conditionMatcher(params.condition);
41823
+ const records = items.map((item) => extractCleanRecord(item)).filter(matches);
41718
41824
  logger14.info("findMany by ids succeeded", {
41719
41825
  requestId,
41720
41826
  resource,
@@ -41749,6 +41855,7 @@ var init_findMany = __esm({
41749
41855
  init_shadow();
41750
41856
  init_batchGet();
41751
41857
  init_dynamodb3();
41858
+ init_idFilter();
41752
41859
  init_findAll();
41753
41860
  logger14 = createLogger({ service: "records-lambda" });
41754
41861
  __name(handleFindMany, "handleFindMany");
@@ -41768,7 +41875,11 @@ async function handleFindOne(resource, params, requestId) {
41768
41875
  resource,
41769
41876
  id
41770
41877
  });
41771
- const results = await handleFindMany(resource, { ids: [id] }, requestId);
41878
+ const results = await handleFindMany(
41879
+ resource,
41880
+ { ids: [id], condition: params.condition },
41881
+ requestId
41882
+ );
41772
41883
  if (results.length === 0) {
41773
41884
  throw new ItemNotFoundError(`Record not found: ${id}`, { resource, id });
41774
41885
  }
@@ -41857,56 +41968,6 @@ var init_timestamps = __esm({
41857
41968
  }
41858
41969
  });
41859
41970
 
41860
- // src/server/utils/ttl.ts
41861
- function calculateTTL(resource, createdAt) {
41862
- const envKey = `${resource.toUpperCase()}_TTL_DAYS`;
41863
- const ttlDaysStr = process.env[envKey];
41864
- if (!ttlDaysStr) {
41865
- return void 0;
41866
- }
41867
- const ttlDays = parseInt(ttlDaysStr, 10);
41868
- if (isNaN(ttlDays) || ttlDays <= 0) {
41869
- logger17.warn("Invalid TTL_DAYS value", { resource, envKey, value: ttlDaysStr });
41870
- return void 0;
41871
- }
41872
- const createdAtMs = new Date(createdAt).getTime();
41873
- const ttlMs = createdAtMs + ttlDays * 24 * 60 * 60 * 1e3;
41874
- const ttl = Math.floor(ttlMs / 1e3);
41875
- logger17.debug("TTL calculated", {
41876
- resource,
41877
- ttlDays,
41878
- createdAt,
41879
- ttl,
41880
- ttlDate: new Date(ttl * 1e3).toISOString()
41881
- });
41882
- return ttl;
41883
- }
41884
- function addTTL(resource, recordData) {
41885
- const createdAt = recordData.createdAt;
41886
- if (!createdAt) {
41887
- logger17.warn("createdAt not found, skipping TTL calculation", { resource });
41888
- return recordData;
41889
- }
41890
- const ttl = calculateTTL(resource, createdAt);
41891
- if (ttl === void 0) {
41892
- return recordData;
41893
- }
41894
- return {
41895
- ...recordData,
41896
- ttl
41897
- };
41898
- }
41899
- var logger17;
41900
- var init_ttl = __esm({
41901
- "src/server/utils/ttl.ts"() {
41902
- "use strict";
41903
- init_index2();
41904
- logger17 = createLogger({ service: "records-lambda" });
41905
- __name(calculateTTL, "calculateTTL");
41906
- __name(addTTL, "addTTL");
41907
- }
41908
- });
41909
-
41910
41971
  // src/server/operations/insertMany.ts
41911
41972
  var insertMany_exports = {};
41912
41973
  __export(insertMany_exports, {
@@ -41916,7 +41977,7 @@ async function handleInsertMany(resource, params, requestId) {
41916
41977
  const { data: recordsData } = params;
41917
41978
  const startTime = Date.now();
41918
41979
  const costTracker = new CostTracker();
41919
- logger18.debug("Executing insertMany", {
41980
+ logger17.debug("Executing insertMany", {
41920
41981
  requestId,
41921
41982
  resource,
41922
41983
  count: recordsData.length
@@ -41941,11 +42002,10 @@ async function handleInsertMany(resource, params, requestId) {
41941
42002
  const recordData = recordsData[i5];
41942
42003
  try {
41943
42004
  const id = recordData.id || ulid2();
41944
- let fullRecordData = addCreateTimestamps({
42005
+ const fullRecordData = addCreateTimestamps({
41945
42006
  ...recordData,
41946
42007
  id
41947
42008
  });
41948
- fullRecordData = addTTL(resource, fullRecordData);
41949
42009
  const shadowRecords = generateShadowRecords(fullRecordData, resource, shadowConfig);
41950
42010
  const shadowKeys = shadowRecords.map((shadow) => shadow.SK);
41951
42011
  const mainSK = generateMainRecordSK2(id);
@@ -41959,7 +42019,7 @@ async function handleInsertMany(resource, params, requestId) {
41959
42019
  const failedId = recordData.id || `temp-id-${i5}`;
41960
42020
  const errorMessage = error2 instanceof Error ? error2.message : "Unknown preparation error";
41961
42021
  const errorCode = getPreparationErrorCode(error2);
41962
- logger18.error("Failed to prepare record for creation", {
42022
+ logger17.error("Failed to prepare record for creation", {
41963
42023
  requestId,
41964
42024
  recordId: failedId,
41965
42025
  error: errorMessage,
@@ -42028,7 +42088,7 @@ async function handleInsertMany(resource, params, requestId) {
42028
42088
  }
42029
42089
  const result = await executeDynamoDBOperation(
42030
42090
  () => dbClient2.send(
42031
- new import_lib_dynamodb8.TransactWriteCommand({
42091
+ new import_lib_dynamodb9.TransactWriteCommand({
42032
42092
  TransactItems: transactItems,
42033
42093
  ReturnConsumedCapacity: "TOTAL"
42034
42094
  })
@@ -42153,11 +42213,11 @@ function getPreparationErrorCode(error2) {
42153
42213
  }
42154
42214
  return "VALIDATION_ERROR" /* VALIDATION_ERROR */;
42155
42215
  }
42156
- var import_lib_dynamodb8, logger18;
42216
+ var import_lib_dynamodb9, logger17;
42157
42217
  var init_insertMany = __esm({
42158
42218
  "src/server/operations/insertMany.ts"() {
42159
42219
  "use strict";
42160
- import_lib_dynamodb8 = __toESM(require_dist_cjs22(), 1);
42220
+ import_lib_dynamodb9 = __toESM(require_dist_cjs22(), 1);
42161
42221
  init_shared();
42162
42222
  init_shadow();
42163
42223
  init_shadow();
@@ -42168,8 +42228,7 @@ var init_insertMany = __esm({
42168
42228
  init_dynamodb3();
42169
42229
  init_revision();
42170
42230
  init_timestamps();
42171
- init_ttl();
42172
- logger18 = createLogger({ service: "records-lambda" });
42231
+ logger17 = createLogger({ service: "records-lambda" });
42173
42232
  __name(handleInsertMany, "handleInsertMany");
42174
42233
  __name(getPreparationErrorCode, "getPreparationErrorCode");
42175
42234
  }
@@ -42358,21 +42417,23 @@ async function handleUpdateMany(resource, params, requestId) {
42358
42417
  const startTime = Date.now();
42359
42418
  const costTracker = new CostTracker();
42360
42419
  const update = resolveUpdateOperators(patchData);
42361
- logger20.debug("Executing updateMany", {
42420
+ logger19.debug("Executing updateMany", {
42362
42421
  requestId,
42363
42422
  resource,
42364
42423
  upsert
42365
42424
  });
42366
42425
  let ids;
42426
+ let condition;
42367
42427
  if ("ids" in params) {
42368
- ids = params.ids;
42369
- logger20.debug("Executing updateMany with ids", {
42428
+ ids = [...new Set(params.ids)];
42429
+ condition = params.condition;
42430
+ logger19.debug("Executing updateMany with ids", {
42370
42431
  requestId,
42371
42432
  resource,
42372
42433
  count: ids.length
42373
42434
  });
42374
42435
  } else {
42375
- logger20.debug("Executing updateMany with filter", {
42436
+ logger19.debug("Executing updateMany with filter", {
42376
42437
  requestId,
42377
42438
  resource,
42378
42439
  filter: params.filter
@@ -42390,7 +42451,8 @@ async function handleUpdateMany(resource, params, requestId) {
42390
42451
  requestId
42391
42452
  );
42392
42453
  ids = matched.map((item) => item.id);
42393
- logger20.debug("Found records with filter", {
42454
+ condition = params.filter;
42455
+ logger19.debug("Found records with filter", {
42394
42456
  requestId,
42395
42457
  resource,
42396
42458
  count: ids.length
@@ -42399,7 +42461,7 @@ async function handleUpdateMany(resource, params, requestId) {
42399
42461
  if (upsert) {
42400
42462
  const newId = ulid2();
42401
42463
  ids = [newId];
42402
- logger20.info("Creating new record with filter (upsert: true)", {
42464
+ logger19.info("Creating new record with filter (upsert: true)", {
42403
42465
  requestId,
42404
42466
  resource,
42405
42467
  newId,
@@ -42428,6 +42490,8 @@ async function handleUpdateMany(resource, params, requestId) {
42428
42490
  targetIds.map((id) => ({ PK: resource, SK: generateMainRecordSK2(id) })),
42429
42491
  { consistentRead: true, costTracker, requestId }
42430
42492
  );
42493
+ const matches = conditionMatcher(condition);
42494
+ const mismatchedIds2 = /* @__PURE__ */ new Set();
42431
42495
  const existingIds = new Set(
42432
42496
  existingItems.map((item) => {
42433
42497
  const data = item.data;
@@ -42436,7 +42500,7 @@ async function handleUpdateMany(resource, params, requestId) {
42436
42500
  );
42437
42501
  const notFoundIds2 = targetIds.filter((id) => !existingIds.has(id));
42438
42502
  if (!upsert && notFoundIds2.length > 0) {
42439
- logger20.warn("Records not found (upsert: false)", {
42503
+ logger19.warn("Records not found (upsert: false)", {
42440
42504
  requestId,
42441
42505
  resource,
42442
42506
  notFoundCount: notFoundIds2.length,
@@ -42445,7 +42509,7 @@ async function handleUpdateMany(resource, params, requestId) {
42445
42509
  });
42446
42510
  }
42447
42511
  if (upsert && notFoundIds2.length > 0) {
42448
- logger20.info("Creating new records (upsert: true)", {
42512
+ logger19.info("Creating new records (upsert: true)", {
42449
42513
  requestId,
42450
42514
  resource,
42451
42515
  notFoundCount: notFoundIds2.length,
@@ -42461,6 +42525,10 @@ async function handleUpdateMany(resource, params, requestId) {
42461
42525
  try {
42462
42526
  const existingData = item.data;
42463
42527
  const id = existingData.id;
42528
+ if (!matches(existingData)) {
42529
+ mismatchedIds2.add(id);
42530
+ continue;
42531
+ }
42464
42532
  const oldShadowKeys = item.__shadowKeys ?? existingData.__shadowKeys ?? [];
42465
42533
  const timestampedPatch = addUpdateTimestamp(update.patch);
42466
42534
  const mergedData = applyJsonMergePatch(removeShadowKeys(existingData), timestampedPatch);
@@ -42482,7 +42550,7 @@ async function handleUpdateMany(resource, params, requestId) {
42482
42550
  const failedId = existingData.id || "unknown-id";
42483
42551
  const errorMessage = error2 instanceof Error ? error2.message : "Unknown preparation error";
42484
42552
  const errorCode = getPreparationErrorCode2(error2);
42485
- logger20.error("Failed to prepare record for update", {
42553
+ logger19.error("Failed to prepare record for update", {
42486
42554
  requestId,
42487
42555
  recordId: failedId,
42488
42556
  error: errorMessage,
@@ -42520,7 +42588,7 @@ async function handleUpdateMany(resource, params, requestId) {
42520
42588
  } catch (error2) {
42521
42589
  const errorMessage = error2 instanceof Error ? error2.message : "Unknown preparation error";
42522
42590
  const errorCode = getPreparationErrorCode2(error2);
42523
- logger20.error("Failed to prepare new record for upsert", {
42591
+ logger19.error("Failed to prepare new record for upsert", {
42524
42592
  requestId,
42525
42593
  recordId: id,
42526
42594
  error: errorMessage,
@@ -42535,9 +42603,15 @@ async function handleUpdateMany(resource, params, requestId) {
42535
42603
  }
42536
42604
  }
42537
42605
  }
42538
- return { preparedRecords: preparedRecords2, notFoundIds: notFoundIds2, preparationFailedIds: preparationFailedIds2, preparationErrors: preparationErrors2 };
42606
+ return {
42607
+ preparedRecords: preparedRecords2,
42608
+ notFoundIds: notFoundIds2,
42609
+ mismatchedIds: mismatchedIds2,
42610
+ preparationFailedIds: preparationFailedIds2,
42611
+ preparationErrors: preparationErrors2
42612
+ };
42539
42613
  }, "prepare");
42540
- const { preparedRecords, notFoundIds, preparationFailedIds, preparationErrors } = await prepare(ids);
42614
+ const { preparedRecords, notFoundIds, mismatchedIds, preparationFailedIds, preparationErrors } = await prepare(ids);
42541
42615
  const getItemCount = /* @__PURE__ */ __name((record) => {
42542
42616
  const shadowDiff = calculateShadowDiff(record.oldShadowKeys, record.newShadowKeys);
42543
42617
  return 1 + shadowDiff.toDelete.length + shadowDiff.toAdd.length;
@@ -42597,7 +42671,7 @@ async function handleUpdateMany(resource, params, requestId) {
42597
42671
  }
42598
42672
  const result = await executeDynamoDBOperation(
42599
42673
  () => dbClient2.send(
42600
- new import_lib_dynamodb9.TransactWriteCommand({
42674
+ new import_lib_dynamodb10.TransactWriteCommand({
42601
42675
  TransactItems: transactItems,
42602
42676
  ReturnConsumedCapacity: "TOTAL"
42603
42677
  })
@@ -42616,7 +42690,7 @@ async function handleUpdateMany(resource, params, requestId) {
42616
42690
  const fresh = await prepare(stale.map((record) => record.id));
42617
42691
  if (fresh.preparedRecords.length !== stale.length) {
42618
42692
  throw new AppError(
42619
- "INTERNAL_ERROR" /* INTERNAL_ERROR */,
42693
+ "VERSION_CONFLICT" /* VERSION_CONFLICT */,
42620
42694
  "Records changed concurrently and could not be re-read for update",
42621
42695
  409
42622
42696
  );
@@ -42633,11 +42707,13 @@ async function handleUpdateMany(resource, params, requestId) {
42633
42707
  const failedIdsMap = {};
42634
42708
  const errorsMap = {};
42635
42709
  const successIdSet = new Set(successRecords.map((r5) => r5.id));
42710
+ const upsertedIds = [];
42636
42711
  for (let i5 = 0; i5 < ids.length; i5++) {
42637
42712
  const id = ids[i5];
42638
42713
  if (successIdSet.has(id)) {
42639
42714
  successIds[i5] = id;
42640
42715
  if (upsert && notFoundIds.includes(id)) {
42716
+ upsertedIds.push(id);
42641
42717
  items.push({
42642
42718
  id,
42643
42719
  ...update.setOnInsert,
@@ -42651,17 +42727,15 @@ async function handleUpdateMany(resource, params, requestId) {
42651
42727
  }
42652
42728
  }
42653
42729
  }
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
- }
42730
+ for (let i5 = 0; i5 < ids.length; i5++) {
42731
+ const id = ids[i5];
42732
+ if (!upsert && notFoundIds.includes(id) || mismatchedIds.has(id)) {
42733
+ failedIdsMap[i5] = id;
42734
+ errorsMap[i5] = {
42735
+ id,
42736
+ code: "ITEM_NOT_FOUND",
42737
+ message: `Record not found: ${id}`
42738
+ };
42665
42739
  }
42666
42740
  }
42667
42741
  for (let i5 = 0; i5 < ids.length; i5++) {
@@ -42733,6 +42807,7 @@ async function handleUpdateMany(resource, params, requestId) {
42733
42807
  errors: errorsMap,
42734
42808
  items,
42735
42809
  // 更新したフィールドのみを含むレコード配列(ADR 001)
42810
+ ...upsertedIds.length > 0 && { upsertedIds },
42736
42811
  consumedCapacity: costTracker.getAggregated()
42737
42812
  };
42738
42813
  }
@@ -42747,11 +42822,11 @@ function getPreparationErrorCode2(error2) {
42747
42822
  }
42748
42823
  return "VALIDATION_ERROR" /* VALIDATION_ERROR */;
42749
42824
  }
42750
- var import_lib_dynamodb9, logger20;
42825
+ var import_lib_dynamodb10, logger19;
42751
42826
  var init_updateMany = __esm({
42752
42827
  "src/server/operations/updateMany.ts"() {
42753
42828
  "use strict";
42754
- import_lib_dynamodb9 = __toESM(require_dist_cjs22(), 1);
42829
+ import_lib_dynamodb10 = __toESM(require_dist_cjs22(), 1);
42755
42830
  init_shared();
42756
42831
  init_shadow();
42757
42832
  init_shadow();
@@ -42760,12 +42835,13 @@ var init_updateMany = __esm({
42760
42835
  init_chunking();
42761
42836
  init_cost_tracker();
42762
42837
  init_dynamodb3();
42838
+ init_idFilter();
42763
42839
  init_mergePatch();
42764
42840
  init_revision();
42765
42841
  init_timestamps();
42766
42842
  init_updateOperators();
42767
42843
  init_findAll();
42768
- logger20 = createLogger({ service: "records-lambda" });
42844
+ logger19 = createLogger({ service: "records-lambda" });
42769
42845
  __name(handleUpdateMany, "handleUpdateMany");
42770
42846
  __name(getPreparationErrorCode2, "getPreparationErrorCode");
42771
42847
  }
@@ -42782,10 +42858,115 @@ init_shared();
42782
42858
 
42783
42859
  // src/server/operations/operationDispatcher.ts
42784
42860
  init_shared();
42861
+
42862
+ // src/server/operations/count.ts
42863
+ var import_lib_dynamodb6 = __toESM(require_dist_cjs22(), 1);
42864
+ init_errors();
42865
+ init_cost_tracker();
42866
+ init_dynamodb3();
42867
+ init_keyCondition();
42868
+ init_utils6();
42869
+ init_findAll();
42870
+ function planKeyCountFilters(parsedFilters) {
42871
+ const [first] = parsedFilters;
42872
+ if (!first || first.parsed.field === "id") return void 0;
42873
+ if (!KEY_CONDITION_OPERATORS.has(first.parsed.operator)) return void 0;
42874
+ const second = parsedFilters.length === 2 ? findComplementaryBound(first, parsedFilters) : void 0;
42875
+ if (parsedFilters.length > 1 && !second) return void 0;
42876
+ if (parsedFilters.length > 2) return void 0;
42877
+ const planned = second ? [first, second] : [first];
42878
+ const allExact = planned.every(
42879
+ (f5) => encodeValueForShadowSK(f5.value, f5.parsed.type, f5.parsed.operator).exact
42880
+ );
42881
+ return allExact ? { first, second } : void 0;
42882
+ }
42883
+ __name(planKeyCountFilters, "planKeyCountFilters");
42884
+ async function countByKeyCondition(keyConditionExpression, expressionAttributeValues, costTracker) {
42885
+ const dbClient2 = getDBClient();
42886
+ const tableName = getTableName();
42887
+ let total = 0;
42888
+ let exclusiveStartKey;
42889
+ do {
42890
+ const result = await executeDynamoDBOperation(
42891
+ () => dbClient2.send(
42892
+ new import_lib_dynamodb6.QueryCommand({
42893
+ TableName: tableName,
42894
+ KeyConditionExpression: keyConditionExpression,
42895
+ ExpressionAttributeValues: expressionAttributeValues,
42896
+ Select: "COUNT",
42897
+ ExclusiveStartKey: exclusiveStartKey,
42898
+ ConsistentRead: true,
42899
+ ReturnConsumedCapacity: "TOTAL"
42900
+ })
42901
+ ),
42902
+ "Query"
42903
+ );
42904
+ costTracker.add(result.ConsumedCapacity);
42905
+ total += result.Count ?? 0;
42906
+ exclusiveStartKey = result.LastEvaluatedKey;
42907
+ } while (exclusiveStartKey);
42908
+ return total;
42909
+ }
42910
+ __name(countByKeyCondition, "countByKeyCondition");
42911
+ async function handleCount(resource, params, requestId) {
42912
+ const filter = params.filter ?? {};
42913
+ if (detectNearQuery(filter)) {
42914
+ throw new InvalidFilterError("count does not support $near", { filter });
42915
+ }
42916
+ const parsedFilters = parseFilters(filter);
42917
+ const costTracker = new CostTracker();
42918
+ if (parsedFilters.length === 0) {
42919
+ const count = await countByKeyCondition(
42920
+ "PK = :pk AND begins_with(SK, :skPrefix)",
42921
+ { ":pk": resource, ":skPrefix": "id#" },
42922
+ costTracker
42923
+ );
42924
+ return { count, consumedCapacity: costTracker.getAggregated() };
42925
+ }
42926
+ const plan = planKeyCountFilters(parsedFilters);
42927
+ if (plan) {
42928
+ const { keyConditionExpression, expressionAttributeValues } = buildKeyCondition(
42929
+ resource,
42930
+ plan.first.parsed.field,
42931
+ plan.first,
42932
+ plan.second
42933
+ );
42934
+ const count = await countByKeyCondition(
42935
+ keyConditionExpression,
42936
+ expressionAttributeValues,
42937
+ costTracker
42938
+ );
42939
+ return { count, consumedCapacity: costTracker.getAggregated() };
42940
+ }
42941
+ const items = await findAllByFilter(resource, filter, requestId);
42942
+ return { count: items.length };
42943
+ }
42944
+ __name(handleCount, "handleCount");
42945
+
42946
+ // src/server/operations/operationDispatcher.ts
42785
42947
  init_deleteMany();
42786
42948
 
42787
42949
  // src/server/operations/deleteOne.ts
42788
42950
  init_shared();
42951
+
42952
+ // src/server/utils/bulkError.ts
42953
+ init_shared();
42954
+ function toAppError(error2, fallbackMessage) {
42955
+ const message = error2?.message ?? fallbackMessage;
42956
+ switch (error2?.code) {
42957
+ case "VALIDATION_ERROR" /* VALIDATION_ERROR */:
42958
+ return new AppError("VALIDATION_ERROR" /* VALIDATION_ERROR */, message, 400);
42959
+ case "ITEM_NOT_FOUND" /* ITEM_NOT_FOUND */:
42960
+ return new AppError("ITEM_NOT_FOUND" /* ITEM_NOT_FOUND */, message, 404);
42961
+ case "VERSION_CONFLICT" /* VERSION_CONFLICT */:
42962
+ return new AppError("VERSION_CONFLICT" /* VERSION_CONFLICT */, message, 409);
42963
+ default:
42964
+ return new AppError("INTERNAL_ERROR" /* INTERNAL_ERROR */, message, 500);
42965
+ }
42966
+ }
42967
+ __name(toAppError, "toAppError");
42968
+
42969
+ // src/server/operations/deleteOne.ts
42789
42970
  init_findAll();
42790
42971
  var logger13 = createLogger({ service: "records-lambda" });
42791
42972
  async function handleDeleteOne(resource, params, requestId) {
@@ -42801,17 +42982,14 @@ async function handleDeleteOne(resource, params, requestId) {
42801
42982
  const deleteManyResult = await handleDeleteMany2(
42802
42983
  resource,
42803
42984
  {
42804
- ids: [targetId]
42985
+ ids: [targetId],
42986
+ condition: params.condition
42805
42987
  },
42806
42988
  requestId
42807
42989
  );
42808
42990
  if (deleteManyResult.count === 0) {
42809
42991
  const error2 = Object.values(deleteManyResult.errors || {})[0];
42810
- if (error2) {
42811
- throw new Error(`Failed to delete record: ${error2.message}`);
42812
- } else {
42813
- throw new Error(`Failed to delete record: ${targetId}`);
42814
- }
42992
+ throw toAppError(error2, `Failed to delete record: ${targetId}`);
42815
42993
  }
42816
42994
  return {
42817
42995
  acknowledged: true,
@@ -42830,14 +43008,15 @@ async function handleDeleteOne(resource, params, requestId) {
42830
43008
  params.filter,
42831
43009
  requestId
42832
43010
  );
42833
- const deleteManyResult = target ? await handleDeleteMany2(resource, { ids: [target.id] }, requestId) : await handleDeleteMany2(resource, { ids: [] }, requestId);
43011
+ const deleteManyResult = target ? await handleDeleteMany2(
43012
+ resource,
43013
+ // 選んでから消すまでの間に条件から外れたレコードを消さない
43014
+ { ids: [target.id], condition: params.filter },
43015
+ requestId
43016
+ ) : await handleDeleteMany2(resource, { ids: [] }, requestId);
42834
43017
  if (deleteManyResult.count === 0) {
42835
43018
  const error2 = Object.values(deleteManyResult.errors || {})[0];
42836
- if (error2) {
42837
- throw new Error(`Failed to delete record: ${error2.message}`);
42838
- } else {
42839
- throw new Error(`No records found matching filter`);
42840
- }
43019
+ throw toAppError(error2 ?? { code: "ITEM_NOT_FOUND" }, "No records found matching filter");
42841
43020
  }
42842
43021
  const deletedId = Object.values(deleteManyResult.successIds || {})[0];
42843
43022
  if (!deletedId) {
@@ -42863,7 +43042,7 @@ init_find();
42863
43042
  init_findMany();
42864
43043
 
42865
43044
  // src/server/operations/findManyReference.ts
42866
- var import_lib_dynamodb7 = __toESM(require_dist_cjs22(), 1);
43045
+ var import_lib_dynamodb8 = __toESM(require_dist_cjs22(), 1);
42867
43046
  init_shared();
42868
43047
  init_shadow();
42869
43048
  init_batchGet();
@@ -42896,7 +43075,7 @@ async function handleFindManyReference(resource, params, requestId) {
42896
43075
  }
42897
43076
  const queryResult = await executeDynamoDBOperation(
42898
43077
  () => dbClient2.send(
42899
- new import_lib_dynamodb7.QueryCommand({
43078
+ new import_lib_dynamodb8.QueryCommand({
42900
43079
  TableName: tableName,
42901
43080
  KeyConditionExpression: "PK = :pk AND begins_with(SK, :skPrefix)",
42902
43081
  ExpressionAttributeValues: {
@@ -42975,9 +43154,9 @@ init_insertMany();
42975
43154
 
42976
43155
  // src/server/operations/insertOne.ts
42977
43156
  init_shared();
42978
- var logger19 = createLogger({ service: "records-lambda" });
43157
+ var logger18 = createLogger({ service: "records-lambda" });
42979
43158
  async function handleInsertOne(resource, params, requestId) {
42980
- logger19.debug("Executing insertOne", {
43159
+ logger18.debug("Executing insertOne", {
42981
43160
  requestId,
42982
43161
  resource
42983
43162
  });
@@ -42991,11 +43170,7 @@ async function handleInsertOne(resource, params, requestId) {
42991
43170
  );
42992
43171
  if (insertManyResult.count === 0) {
42993
43172
  const error2 = Object.values(insertManyResult.errors || {})[0];
42994
- if (error2) {
42995
- throw new Error(`Failed to create record: ${error2.message}`);
42996
- } else {
42997
- throw new Error("Failed to create record");
42998
- }
43173
+ throw toAppError(error2, "Failed to create record");
42999
43174
  }
43000
43175
  const createdId = Object.values(insertManyResult.successIds || {})[0];
43001
43176
  if (!createdId) {
@@ -43003,7 +43178,7 @@ async function handleInsertOne(resource, params, requestId) {
43003
43178
  }
43004
43179
  const { handleFindOne: handleFindOne2 } = await Promise.resolve().then(() => (init_findOne(), findOne_exports));
43005
43180
  const createdRecord = await handleFindOne2(resource, { id: createdId }, requestId);
43006
- logger19.info("insertOne succeeded", {
43181
+ logger18.info("insertOne succeeded", {
43007
43182
  requestId,
43008
43183
  resource,
43009
43184
  id: createdId
@@ -43019,6 +43194,7 @@ async function handleInsertOne(resource, params, requestId) {
43019
43194
  __name(handleInsertOne, "handleInsertOne");
43020
43195
 
43021
43196
  // src/server/operations/parameterConverter.ts
43197
+ init_idFilter();
43022
43198
  function convertFindParams(mongoParams) {
43023
43199
  const { filter = {}, options = {} } = mongoParams;
43024
43200
  const { sort, limit, nextToken, schema } = options;
@@ -43045,9 +43221,10 @@ function convertFindOneParams(mongoParams) {
43045
43221
  if (!mongoParams.filter) {
43046
43222
  throw new Error("findOne requires filter");
43047
43223
  }
43048
- const id = typeof mongoParams.filter.id === "string" ? mongoParams.filter.id : void 0;
43224
+ const { id, rest } = splitIdFilter(mongoParams.filter);
43049
43225
  if (id) {
43050
- return { id };
43226
+ const condition = conditionOf(rest);
43227
+ return { id, ...condition && { condition } };
43051
43228
  }
43052
43229
  return { filter: mongoParams.filter };
43053
43230
  }
@@ -43059,10 +43236,10 @@ function convertFindManyParams(mongoParams) {
43059
43236
  if (!mongoParams.filter) {
43060
43237
  throw new Error("findMany requires either ids or filter");
43061
43238
  }
43062
- const idFilter = mongoParams.filter.id;
43063
- if (typeof idFilter === "object" && idFilter !== null && "$in" in idFilter) {
43064
- const ids = idFilter.$in || [];
43065
- return { ids };
43239
+ const { ids, rest } = splitIdFilter(mongoParams.filter);
43240
+ if (ids) {
43241
+ const condition = conditionOf(rest);
43242
+ return { ids, ...condition && { condition } };
43066
43243
  }
43067
43244
  return { filter: mongoParams.filter };
43068
43245
  }
@@ -43077,16 +43254,7 @@ function convertInsertOneParams(mongoParams) {
43077
43254
  }
43078
43255
  __name(convertInsertOneParams, "convertInsertOneParams");
43079
43256
  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
- }
43257
+ const updateData = mongoParams.update && typeof mongoParams.update === "object" ? mongoParams.update : {};
43090
43258
  const directId = "id" in mongoParams && typeof mongoParams.id === "string" ? mongoParams.id : void 0;
43091
43259
  if (directId) {
43092
43260
  return {
@@ -43100,10 +43268,12 @@ function convertUpdateOneParams(mongoParams) {
43100
43268
  if (!mongoParams.filter) {
43101
43269
  throw new Error("updateOne requires filter");
43102
43270
  }
43103
- const id = typeof mongoParams.filter.id === "string" ? mongoParams.filter.id : void 0;
43271
+ const { id, rest } = splitIdFilter(mongoParams.filter);
43272
+ const condition = conditionOf(rest);
43104
43273
  if (id) {
43105
43274
  return {
43106
43275
  id,
43276
+ ...condition && { condition },
43107
43277
  data: updateData,
43108
43278
  ...mongoParams.options?.upsert !== void 0 && {
43109
43279
  options: { upsert: mongoParams.options.upsert }
@@ -43120,10 +43290,10 @@ function convertUpdateOneParams(mongoParams) {
43120
43290
  }
43121
43291
  __name(convertUpdateOneParams, "convertUpdateOneParams");
43122
43292
  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 : {};
43293
+ const { ids, rest } = splitIdFilter(mongoParams.filter);
43294
+ const condition = conditionOf(rest);
43295
+ const target = ids ? { ids, ...condition && { condition } } : mongoParams.filter ? { filter: mongoParams.filter } : { ids: [] };
43296
+ const updateData = mongoParams.update && typeof mongoParams.update === "object" ? mongoParams.update : {};
43127
43297
  return {
43128
43298
  ...target,
43129
43299
  data: updateData,
@@ -43138,17 +43308,19 @@ function convertDeleteOneParams(mongoParams) {
43138
43308
  if (directId) {
43139
43309
  return { id: directId };
43140
43310
  }
43141
- const id = typeof mongoParams.filter?.id === "string" ? mongoParams.filter.id : void 0;
43311
+ const { id, rest } = splitIdFilter(mongoParams.filter);
43142
43312
  if (!id) {
43143
43313
  throw new Error("deleteOne requires filter.id");
43144
43314
  }
43145
- return { id };
43315
+ const condition = conditionOf(rest);
43316
+ return { id, ...condition && { condition } };
43146
43317
  }
43147
43318
  __name(convertDeleteOneParams, "convertDeleteOneParams");
43148
43319
  function convertDeleteManyParams(mongoParams) {
43149
- const idFilter = mongoParams.filter?.id;
43150
- if (typeof idFilter === "object" && idFilter !== null && "$in" in idFilter) {
43151
- return { ids: idFilter.$in || [] };
43320
+ const { ids, rest } = splitIdFilter(mongoParams.filter);
43321
+ if (ids) {
43322
+ const condition = conditionOf(rest);
43323
+ return { ids, ...condition && { condition } };
43152
43324
  }
43153
43325
  if (mongoParams.filter) {
43154
43326
  return { filter: mongoParams.filter };
@@ -43172,13 +43344,17 @@ init_updateMany();
43172
43344
  // src/server/operations/updateOne.ts
43173
43345
  init_shared();
43174
43346
  init_findAll();
43175
- var logger21 = createLogger({ service: "records-lambda" });
43347
+ var logger20 = createLogger({ service: "records-lambda" });
43348
+ function upsertedIdOf(result, id) {
43349
+ return result.upsertedIds?.includes(id) ? { upsertedId: id } : {};
43350
+ }
43351
+ __name(upsertedIdOf, "upsertedIdOf");
43176
43352
  async function handleUpdateOne(resource, params, requestId) {
43177
43353
  const { data: patchData, options } = params;
43178
43354
  const { handleUpdateMany: handleUpdateMany2 } = await Promise.resolve().then(() => (init_updateMany(), updateMany_exports));
43179
43355
  if ("id" in params) {
43180
43356
  const targetId = params.id;
43181
- logger21.debug("Executing updateOne with id", {
43357
+ logger20.debug("Executing updateOne with id", {
43182
43358
  requestId,
43183
43359
  resource,
43184
43360
  id: targetId,
@@ -43188,6 +43364,7 @@ async function handleUpdateOne(resource, params, requestId) {
43188
43364
  resource,
43189
43365
  {
43190
43366
  ids: [targetId],
43367
+ condition: params.condition,
43191
43368
  data: patchData,
43192
43369
  options
43193
43370
  },
@@ -43195,14 +43372,7 @@ async function handleUpdateOne(resource, params, requestId) {
43195
43372
  );
43196
43373
  if (updateManyResult.count === 0) {
43197
43374
  const error2 = Object.values(updateManyResult.errors || {})[0];
43198
- if (error2) {
43199
- if (error2.code === "VALIDATION_ERROR" /* VALIDATION_ERROR */) {
43200
- throw new AppError("VALIDATION_ERROR" /* VALIDATION_ERROR */, error2.message ?? "Invalid patch", 400);
43201
- }
43202
- throw new Error(`Failed to update record: ${error2.message}`);
43203
- } else {
43204
- throw new Error(`Failed to update record: ${targetId}`);
43205
- }
43375
+ throw toAppError(error2, `Failed to update record: ${targetId}`);
43206
43376
  }
43207
43377
  if (!updateManyResult.items || updateManyResult.items.length === 0) {
43208
43378
  throw new Error("updateMany did not return items");
@@ -43217,10 +43387,11 @@ async function handleUpdateOne(resource, params, requestId) {
43217
43387
  modifiedCount: 1,
43218
43388
  id: targetId,
43219
43389
  ...updatedItem,
43390
+ ...upsertedIdOf(updateManyResult, targetId),
43220
43391
  consumedCapacity: updateManyResult.consumedCapacity
43221
43392
  };
43222
43393
  } else {
43223
- logger21.debug("Executing updateOne with filter", {
43394
+ logger20.debug("Executing updateOne with filter", {
43224
43395
  requestId,
43225
43396
  resource,
43226
43397
  filter: params.filter,
@@ -43233,19 +43404,21 @@ async function handleUpdateOne(resource, params, requestId) {
43233
43404
  );
43234
43405
  const updateManyResult = await handleUpdateMany2(
43235
43406
  resource,
43236
- target ? { ids: [target.id], data: patchData, options } : { filter: params.filter, data: patchData, options },
43407
+ target ? {
43408
+ ids: [target.id],
43409
+ // 選んでから書くまでの間に条件から外れたレコードを書かない
43410
+ condition: params.filter,
43411
+ data: patchData,
43412
+ options
43413
+ } : { filter: params.filter, data: patchData, options },
43237
43414
  requestId
43238
43415
  );
43239
43416
  if (updateManyResult.count === 0) {
43240
43417
  const error2 = Object.values(updateManyResult.errors || {})[0];
43241
- if (error2) {
43242
- if (error2.code === "VALIDATION_ERROR" /* VALIDATION_ERROR */) {
43243
- throw new AppError("VALIDATION_ERROR" /* VALIDATION_ERROR */, error2.message ?? "Invalid patch", 400);
43244
- }
43245
- throw new Error(`Failed to update record: ${error2.message}`);
43246
- } else {
43247
- throw new Error(`No records found matching filter`);
43248
- }
43418
+ throw toAppError(
43419
+ error2 ?? { code: "ITEM_NOT_FOUND" /* ITEM_NOT_FOUND */ },
43420
+ "No records found matching filter"
43421
+ );
43249
43422
  }
43250
43423
  if (!updateManyResult.items || updateManyResult.items.length === 0) {
43251
43424
  throw new Error("updateMany did not return items");
@@ -43264,6 +43437,7 @@ async function handleUpdateOne(resource, params, requestId) {
43264
43437
  modifiedCount: 1,
43265
43438
  id: updatedId,
43266
43439
  ...updatedItem,
43440
+ ...upsertedIdOf(updateManyResult, updatedId),
43267
43441
  consumedCapacity: updateManyResult.consumedCapacity
43268
43442
  };
43269
43443
  }
@@ -43271,13 +43445,13 @@ async function handleUpdateOne(resource, params, requestId) {
43271
43445
  __name(handleUpdateOne, "handleUpdateOne");
43272
43446
 
43273
43447
  // src/server/operations/operationDispatcher.ts
43274
- var logger22 = createLogger({
43448
+ var logger21 = createLogger({
43275
43449
  service: "operation-dispatcher",
43276
43450
  level: process.env.LOG_LEVEL || "info"
43277
43451
  });
43278
43452
  async function executeOperation(request2, requestId) {
43279
43453
  const { op: op2, resource } = request2;
43280
- logger22.debug("Executing operation", {
43454
+ logger21.debug("Executing operation", {
43281
43455
  requestId,
43282
43456
  operation: op2,
43283
43457
  resource
@@ -43301,6 +43475,8 @@ async function executeOperation(request2, requestId) {
43301
43475
  request2.params,
43302
43476
  requestId
43303
43477
  );
43478
+ case "count":
43479
+ return await handleCount(resource, request2.params, requestId);
43304
43480
  case "insertOne": {
43305
43481
  const internalParams = convertInsertOneParams(request2.params);
43306
43482
  return await handleInsertOne(resource, internalParams, requestId);
@@ -44530,13 +44706,13 @@ CognitoJwtVerifier.USER_POOL_ID_REGEX = /^(?<region>(?:eusc-[a-z]{2}|[a-z]{2})-(
44530
44706
 
44531
44707
  // src/server/utils/auth.ts
44532
44708
  init_index2();
44533
- var logger23 = createLogger({ service: "records-lambda" });
44709
+ var logger22 = createLogger({ service: "records-lambda" });
44534
44710
  var verifierInstance = null;
44535
44711
  function getVerifier(userPoolId, clientId) {
44536
44712
  if (!verifierInstance) {
44537
- logger23.debug("Creating JWT verifier instance", { userPoolId, clientId });
44713
+ logger22.debug("Creating JWT verifier instance", { userPoolId, clientId });
44538
44714
  if (!clientId) {
44539
- logger23.warn(
44715
+ logger22.warn(
44540
44716
  "COGNITO_CLIENT_ID is not set: JWT audience (aud) verification is DISABLED. Tokens issued to ANY app client of this user pool are accepted. Set cognito_client_id (Terraform) / COGNITO_CLIENT_ID in production. See docs/AUTHORIZATION.md",
44541
44717
  { userPoolId }
44542
44718
  );
@@ -44553,18 +44729,18 @@ function getVerifier(userPoolId, clientId) {
44553
44729
  }
44554
44730
  __name(getVerifier, "getVerifier");
44555
44731
  async function verifyJwt(token, userPoolId, clientId) {
44556
- logger23.debug("Verifying JWT token with signature validation");
44732
+ logger22.debug("Verifying JWT token with signature validation");
44557
44733
  try {
44558
44734
  const verifier = getVerifier(userPoolId, clientId);
44559
44735
  const payload2 = await verifier.verify(token);
44560
- logger23.debug("JWT token verified successfully", {
44736
+ logger22.debug("JWT token verified successfully", {
44561
44737
  sub: payload2.sub,
44562
44738
  email: payload2.email,
44563
44739
  tokenUse: payload2.token_use
44564
44740
  });
44565
44741
  return payload2;
44566
44742
  } catch (error2) {
44567
- logger23.error("JWT verification failed", {
44743
+ logger22.error("JWT verification failed", {
44568
44744
  error: error2 instanceof Error ? error2.message : String(error2)
44569
44745
  });
44570
44746
  let message = "JWT verification failed";
@@ -44605,7 +44781,7 @@ async function verifyAuthHeader(authHeader, userPoolId, clientId) {
44605
44781
  __name(verifyAuthHeader, "verifyAuthHeader");
44606
44782
 
44607
44783
  // src/server/utils/authHandler.ts
44608
- var logger24 = createLogger({
44784
+ var logger23 = createLogger({
44609
44785
  service: "auth-handler",
44610
44786
  level: process.env.LOG_LEVEL || "info"
44611
44787
  });
@@ -44620,7 +44796,7 @@ async function handleAuthentication(event, requestId) {
44620
44796
  }
44621
44797
  __name(handleAuthentication, "handleAuthentication");
44622
44798
  function handleIAMAuthentication(iam, requestId) {
44623
- logger24.info("IAM authenticated request", {
44799
+ logger23.info("IAM authenticated request", {
44624
44800
  requestId,
44625
44801
  userArn: iam.userArn,
44626
44802
  accountId: iam.accountId,
@@ -44635,7 +44811,7 @@ async function handleCognitoAuthentication(authHeader, requestId) {
44635
44811
  throw new Error("COGNITO_USER_POOL_ID environment variable is required");
44636
44812
  }
44637
44813
  const jwtPayload = await verifyAuthHeader(authHeader, userPoolId, clientId);
44638
- logger24.debug("Cognito JWT verified", {
44814
+ logger23.debug("Cognito JWT verified", {
44639
44815
  requestId,
44640
44816
  sub: jwtPayload.sub
44641
44817
  });
@@ -44650,7 +44826,7 @@ init_shared();
44650
44826
  // src/server/utils/responseBuilder.ts
44651
44827
  init_http();
44652
44828
  init_shared();
44653
- var logger25 = createLogger({
44829
+ var logger24 = createLogger({
44654
44830
  service: "response-builder",
44655
44831
  level: process.env.LOG_LEVEL || "info"
44656
44832
  });
@@ -44660,7 +44836,7 @@ function createSuccessResponse(data, requestId) {
44660
44836
  success: true,
44661
44837
  data
44662
44838
  };
44663
- logger25.info("Request succeeded", { requestId });
44839
+ logger24.info("Request succeeded", { requestId });
44664
44840
  return {
44665
44841
  statusCode: HTTP_STATUS.OK,
44666
44842
  headers: {
@@ -44681,7 +44857,7 @@ function createErrorResponse(code, message, statusCode, requestId, logContext) {
44681
44857
  }
44682
44858
  };
44683
44859
  const level = statusCode >= 500 ? "error" : "warn";
44684
- logger25[level]("Request failed", {
44860
+ logger24[level]("Request failed", {
44685
44861
  requestId,
44686
44862
  event: code,
44687
44863
  message,
@@ -44800,14 +44976,14 @@ function parseRequestBody(body) {
44800
44976
  __name(parseRequestBody, "parseRequestBody");
44801
44977
 
44802
44978
  // src/server/handler.ts
44803
- var logger26 = createLogger({
44979
+ var logger25 = createLogger({
44804
44980
  service: "records-lambda",
44805
44981
  level: process.env.LOG_LEVEL || "info"
44806
44982
  });
44807
- logger26.info("Records Lambda started with automatic shadow field detection");
44983
+ logger25.info("Records Lambda started with automatic shadow field detection");
44808
44984
  async function handler(event) {
44809
44985
  const requestId = event.requestContext.requestId;
44810
- logger26.info("Received request", {
44986
+ logger25.info("Received request", {
44811
44987
  requestId,
44812
44988
  method: event.requestContext.http.method,
44813
44989
  path: event.requestContext.http.path
@@ -44817,15 +44993,15 @@ async function handler(event) {
44817
44993
  return createCorsResponse(HTTP_STATUS.OK);
44818
44994
  }
44819
44995
  if (event.requestContext.http.method === "GET" && event.requestContext.http.path === "/version") {
44820
- const version = "1.25.1";
44996
+ const version = "1.27.0";
44821
44997
  return createSuccessResponse({ version, timestamp: (/* @__PURE__ */ new Date()).toISOString() }, requestId);
44822
44998
  }
44823
44999
  if (event.requestContext.http.method !== "POST") {
44824
- throw new Error("Only POST method is allowed");
45000
+ throw new AppError("VALIDATION_ERROR" /* VALIDATION_ERROR */, "Only POST method is allowed", 405);
44825
45001
  }
44826
45002
  await handleAuthentication(event, requestId);
44827
45003
  const request2 = parseRequestBody(event.body);
44828
- logger26.info("Parsed request", {
45004
+ logger25.info("Parsed request", {
44829
45005
  requestId,
44830
45006
  operation: request2.op,
44831
45007
  resource: request2.resource