quidproquo-actionprocessor-awslambda 0.1.13 → 0.1.14

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.
@@ -27,7 +27,7 @@ const getProcessKeyValueStoreQuery = (qpqConfig) => {
27
27
  // composed form (throws when the key condition never constrains the pk).
28
28
  const scoped = (0, quidproquo_core_1.getScopedKvsTranslatorOrThrow)(qpqConfig, keyValueStoreName, options === null || options === void 0 ? void 0 : options.scope);
29
29
  const effectiveKeyCondition = scoped.keyCondition(keyCondition);
30
- const items = yield (0, dynamo_1.query)(dynamoTableName, region, effectiveKeyCondition, scoped.filter(options === null || options === void 0 ? void 0 : options.filter), options === null || options === void 0 ? void 0 : options.nextPageKey, (_b = (0, qpqDynamoOrm_1.getDynamoTableIndexByConfigAndQuery)(storeConfig, effectiveKeyCondition)) !== null && _b !== void 0 ? _b : undefined, options === null || options === void 0 ? void 0 : options.limit, options === null || options === void 0 ? void 0 : options.sortAscending);
30
+ const items = yield (0, dynamo_1.query)(dynamoTableName, region, effectiveKeyCondition, scoped.filter(options === null || options === void 0 ? void 0 : options.filter), options === null || options === void 0 ? void 0 : options.nextPageKey, (_b = (0, qpqDynamoOrm_1.getDynamoTableIndexByConfigAndQuery)(storeConfig, effectiveKeyCondition)) !== null && _b !== void 0 ? _b : undefined, options === null || options === void 0 ? void 0 : options.limit, options === null || options === void 0 ? void 0 : options.sortAscending, options === null || options === void 0 ? void 0 : options.consistentRead);
31
31
  items.items = items.items.map((item) => scoped.strip(item));
32
32
  return (0, quidproquo_core_2.actionResult)(items);
33
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"getKeyValueStoreQueryActionProcessor.js","sourceRoot":"","sources":["../../../../../src/getActionProcessor/core/keyValueStore/getKeyValueStoreQueryActionProcessor.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,iEAA0D;AAC1D,qDAQyB;AACzB,qDAA4I;AAE5I,4DAA0E;AAC1E,kDAA8C;AAC9C,qEAAyF;AAEzF,MAAM,4BAA4B,GAAG,CAAC,SAAoB,EAA0C,EAAE;IACpG,OAAO,KAAqD,EAAE,4CAAhD,EAAE,iBAAiB,EAAE,YAAY,EAAE,OAAO,EAAE;;QACxD,MAAM,eAAe,GAAG,IAAA,gDAA+B,EAAC,iBAAiB,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;QAC7F,MAAM,MAAM,GAAG,yCAAiB,CAAC,gCAAgC,CAAC,SAAS,CAAC,CAAC;QAE7E,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,IAAA,8CAA4B,EAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;YAE/E,0EAA0E;YAC1E,yEAAyE;YACzE,MAAM,MAAM,GAAG,IAAA,+CAA6B,EAAC,SAAS,EAAE,iBAAiB,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,KAAK,CAAC,CAAC;YAC3F,MAAM,qBAAqB,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;YAEhE,MAAM,KAAK,GAAG,MAAM,IAAA,cAAK,EACvB,eAAe,EACf,MAAM,EACN,qBAAqB,EACrB,MAAM,CAAC,MAAM,CAAC,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,MAAM,CAAC,EAC9B,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,WAAW,EACpB,MAAA,IAAA,kDAAmC,EAAC,WAAW,EAAE,qBAAqB,CAAC,mCAAI,SAAS,EACpF,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,KAAK,EACd,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,aAAa,CACvB,CAAC;YAEF,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YAEjE,OAAO,IAAA,8BAAY,EAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,IAAA,kDAAgC,EAAC,KAAK,EAAE;gBAC7C,mBAAmB,EAAE,GAAG,EAAE,CAAC,IAAA,mCAAiB,EAAC,iDAA+B,CAAC,kBAAkB,EAAE,yBAAyB,CAAC;gBAC3H,yBAAyB,EAAE,GAAG,EAAE,CAAC,IAAA,mCAAiB,EAAC,iDAA+B,CAAC,gBAAgB,EAAE,wBAAwB,CAAC;gBAC9H,iBAAiB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,mCAAiB,EAAC,iDAA+B,CAAC,YAAY,EAAE,KAAK,CAAC,OAAO,CAAC;gBAC5G,qBAAqB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,mCAAiB,EAAC,iDAA+B,CAAC,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC;aAClH,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAA,CAAC;AACJ,CAAC,CAAC;AAEK,MAAM,oCAAoC,GAAgC,CAAO,SAAoB,EAAgC,EAAE;IAAC,OAAA,CAAC;QAC9I,CAAC,yCAAuB,CAAC,KAAK,CAAC,EAAE,4BAA4B,CAAC,SAAS,CAAC;KACzE,CAAC,CAAA;EAAA,CAAC;AAFU,QAAA,oCAAoC,wCAE9C","sourcesContent":["import { qpqConfigAwsUtils } from 'quidproquo-config-aws';\nimport {\n ActionProcessorList,\n ActionProcessorListResolver,\n actionResultError,\n actionResultErrorFromCaughtError,\n getScopedKvsTranslatorOrThrow,\n QPQConfig,\n resolveKvsStoreConfigOrThrow,\n} from 'quidproquo-core';\nimport { actionResult, KeyValueStoreActionType, KeyValueStoreQueryActionProcessor, KeyValueStoreQueryErrorTypeEnum } from 'quidproquo-core';\n\nimport { getKvsDynamoTableNameFromConfig } from '../../../awsNamingUtils';\nimport { query } from '../../../logic/dynamo';\nimport { getDynamoTableIndexByConfigAndQuery } from '../../../logic/dynamo/qpqDynamoOrm';\n\nconst getProcessKeyValueStoreQuery = (qpqConfig: QPQConfig): KeyValueStoreQueryActionProcessor<any> => {\n return async ({ keyValueStoreName, keyCondition, options }) => {\n const dynamoTableName = getKvsDynamoTableNameFromConfig(keyValueStoreName, qpqConfig, 'kvs');\n const region = qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig);\n\n try {\n const storeConfig = resolveKvsStoreConfigOrThrow(qpqConfig, keyValueStoreName);\n\n // Scope lives inside the pk values, so pk conditions are rewritten to the\n // composed form (throws when the key condition never constrains the pk).\n const scoped = getScopedKvsTranslatorOrThrow(qpqConfig, keyValueStoreName, options?.scope);\n const effectiveKeyCondition = scoped.keyCondition(keyCondition);\n\n const items = await query<any>(\n dynamoTableName,\n region,\n effectiveKeyCondition,\n scoped.filter(options?.filter),\n options?.nextPageKey,\n getDynamoTableIndexByConfigAndQuery(storeConfig, effectiveKeyCondition) ?? undefined,\n options?.limit,\n options?.sortAscending,\n );\n\n items.items = items.items.map((item: any) => scoped.strip(item));\n\n return actionResult(items);\n } catch (error: unknown) {\n return actionResultErrorFromCaughtError(error, {\n InternalServerError: () => actionResultError(KeyValueStoreQueryErrorTypeEnum.ServiceUnavailable, 'KVS Service Unavailable'),\n ResourceNotFoundException: () => actionResultError(KeyValueStoreQueryErrorTypeEnum.ResourceNotFound, 'KVS Resource Not Found'),\n InvalidScopeError: (error) => actionResultError(KeyValueStoreQueryErrorTypeEnum.InvalidScope, error.message),\n KvsStoreNotFoundError: (error) => actionResultError(KeyValueStoreQueryErrorTypeEnum.StoreNotFound, error.message),\n });\n }\n };\n};\n\nexport const getKeyValueStoreQueryActionProcessor: ActionProcessorListResolver = async (qpqConfig: QPQConfig): Promise<ActionProcessorList> => ({\n [KeyValueStoreActionType.Query]: getProcessKeyValueStoreQuery(qpqConfig),\n});\n"]}
1
+ {"version":3,"file":"getKeyValueStoreQueryActionProcessor.js","sourceRoot":"","sources":["../../../../../src/getActionProcessor/core/keyValueStore/getKeyValueStoreQueryActionProcessor.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,iEAA0D;AAC1D,qDAQyB;AACzB,qDAA4I;AAE5I,4DAA0E;AAC1E,kDAA8C;AAC9C,qEAAyF;AAEzF,MAAM,4BAA4B,GAAG,CAAC,SAAoB,EAA0C,EAAE;IACpG,OAAO,KAAqD,EAAE,4CAAhD,EAAE,iBAAiB,EAAE,YAAY,EAAE,OAAO,EAAE;;QACxD,MAAM,eAAe,GAAG,IAAA,gDAA+B,EAAC,iBAAiB,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;QAC7F,MAAM,MAAM,GAAG,yCAAiB,CAAC,gCAAgC,CAAC,SAAS,CAAC,CAAC;QAE7E,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,IAAA,8CAA4B,EAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;YAE/E,0EAA0E;YAC1E,yEAAyE;YACzE,MAAM,MAAM,GAAG,IAAA,+CAA6B,EAAC,SAAS,EAAE,iBAAiB,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,KAAK,CAAC,CAAC;YAC3F,MAAM,qBAAqB,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;YAEhE,MAAM,KAAK,GAAG,MAAM,IAAA,cAAK,EACvB,eAAe,EACf,MAAM,EACN,qBAAqB,EACrB,MAAM,CAAC,MAAM,CAAC,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,MAAM,CAAC,EAC9B,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,WAAW,EACpB,MAAA,IAAA,kDAAmC,EAAC,WAAW,EAAE,qBAAqB,CAAC,mCAAI,SAAS,EACpF,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,KAAK,EACd,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,aAAa,EACtB,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,cAAc,CACxB,CAAC;YAEF,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YAEjE,OAAO,IAAA,8BAAY,EAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,IAAA,kDAAgC,EAAC,KAAK,EAAE;gBAC7C,mBAAmB,EAAE,GAAG,EAAE,CAAC,IAAA,mCAAiB,EAAC,iDAA+B,CAAC,kBAAkB,EAAE,yBAAyB,CAAC;gBAC3H,yBAAyB,EAAE,GAAG,EAAE,CAAC,IAAA,mCAAiB,EAAC,iDAA+B,CAAC,gBAAgB,EAAE,wBAAwB,CAAC;gBAC9H,iBAAiB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,mCAAiB,EAAC,iDAA+B,CAAC,YAAY,EAAE,KAAK,CAAC,OAAO,CAAC;gBAC5G,qBAAqB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,mCAAiB,EAAC,iDAA+B,CAAC,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC;aAClH,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAA,CAAC;AACJ,CAAC,CAAC;AAEK,MAAM,oCAAoC,GAAgC,CAAO,SAAoB,EAAgC,EAAE;IAAC,OAAA,CAAC;QAC9I,CAAC,yCAAuB,CAAC,KAAK,CAAC,EAAE,4BAA4B,CAAC,SAAS,CAAC;KACzE,CAAC,CAAA;EAAA,CAAC;AAFU,QAAA,oCAAoC,wCAE9C","sourcesContent":["import { qpqConfigAwsUtils } from 'quidproquo-config-aws';\nimport {\n ActionProcessorList,\n ActionProcessorListResolver,\n actionResultError,\n actionResultErrorFromCaughtError,\n getScopedKvsTranslatorOrThrow,\n QPQConfig,\n resolveKvsStoreConfigOrThrow,\n} from 'quidproquo-core';\nimport { actionResult, KeyValueStoreActionType, KeyValueStoreQueryActionProcessor, KeyValueStoreQueryErrorTypeEnum } from 'quidproquo-core';\n\nimport { getKvsDynamoTableNameFromConfig } from '../../../awsNamingUtils';\nimport { query } from '../../../logic/dynamo';\nimport { getDynamoTableIndexByConfigAndQuery } from '../../../logic/dynamo/qpqDynamoOrm';\n\nconst getProcessKeyValueStoreQuery = (qpqConfig: QPQConfig): KeyValueStoreQueryActionProcessor<any> => {\n return async ({ keyValueStoreName, keyCondition, options }) => {\n const dynamoTableName = getKvsDynamoTableNameFromConfig(keyValueStoreName, qpqConfig, 'kvs');\n const region = qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig);\n\n try {\n const storeConfig = resolveKvsStoreConfigOrThrow(qpqConfig, keyValueStoreName);\n\n // Scope lives inside the pk values, so pk conditions are rewritten to the\n // composed form (throws when the key condition never constrains the pk).\n const scoped = getScopedKvsTranslatorOrThrow(qpqConfig, keyValueStoreName, options?.scope);\n const effectiveKeyCondition = scoped.keyCondition(keyCondition);\n\n const items = await query<any>(\n dynamoTableName,\n region,\n effectiveKeyCondition,\n scoped.filter(options?.filter),\n options?.nextPageKey,\n getDynamoTableIndexByConfigAndQuery(storeConfig, effectiveKeyCondition) ?? undefined,\n options?.limit,\n options?.sortAscending,\n options?.consistentRead,\n );\n\n items.items = items.items.map((item: any) => scoped.strip(item));\n\n return actionResult(items);\n } catch (error: unknown) {\n return actionResultErrorFromCaughtError(error, {\n InternalServerError: () => actionResultError(KeyValueStoreQueryErrorTypeEnum.ServiceUnavailable, 'KVS Service Unavailable'),\n ResourceNotFoundException: () => actionResultError(KeyValueStoreQueryErrorTypeEnum.ResourceNotFound, 'KVS Resource Not Found'),\n InvalidScopeError: (error) => actionResultError(KeyValueStoreQueryErrorTypeEnum.InvalidScope, error.message),\n KvsStoreNotFoundError: (error) => actionResultError(KeyValueStoreQueryErrorTypeEnum.StoreNotFound, error.message),\n });\n }\n };\n};\n\nexport const getKeyValueStoreQueryActionProcessor: ActionProcessorListResolver = async (qpqConfig: QPQConfig): Promise<ActionProcessorList> => ({\n [KeyValueStoreActionType.Query]: getProcessKeyValueStoreQuery(qpqConfig),\n});\n"]}
@@ -18,6 +18,7 @@ exports.entryNames = [
18
18
  'customMessageTriggerEvent_defineAuthChallenge',
19
19
  'customMessageTriggerEvent_createAuthChallenge',
20
20
  'customMessageTriggerEvent_verifyAuthChallenge',
21
+ 'dynamoStreamEvent_kvsStreamEvent',
21
22
  'eventBridgeEvent_recurringSchedule',
22
23
  'eventBridgeEvent_stackDeploy',
23
24
  's3Event_fileEvent',
@@ -1 +1 @@
1
- {"version":3,"file":"getLambdaEntries.js","sourceRoot":"","sources":["../../src/getLambdaEntries.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AAExB,gFAAgF;AAChF,4DAA4D;AAC/C,QAAA,UAAU,GAAG;IACxB,gDAAgD;IAEhD,iCAAiC;IACjC,wBAAwB;IAExB,oDAAoD;IAEpD,sCAAsC;IACtC,sCAAsC;IAEtC,yCAAyC;IACzC,+CAA+C;IAC/C,+CAA+C;IAC/C,+CAA+C;IAE/C,oCAAoC;IACpC,8BAA8B;IAE9B,mBAAmB;IACnB,qBAAqB;CACtB,CAAC;AAEF;;;GAGG;AACI,MAAM,gBAAgB,GAAG,GAA2B,EAAE,CAC3D,MAAM,CAAC,WAAW,CAAC,kBAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AADrF,QAAA,gBAAgB,oBACqE","sourcesContent":["import path from 'path';\n\n// One entry per lambda handler under ./lambdas; each name must match its source\n// filename exactly (yes, including the apiGatway spelling).\nexport const entryNames = [\n 'anyExecuteServiceFunctionEvent_serviceFunction',\n\n 'apiGatewayEventHandler_redirect',\n 'apiGatewayEventHandler',\n\n 'apiGatwayEventWebsocketWithIdentity_websocketEvent',\n\n 'cloudFrontRequestEvent_originRequest',\n 'cloudFrontRequestEvent_viewerRequest',\n\n 'customMessageTriggerEvent_customMessage',\n 'customMessageTriggerEvent_defineAuthChallenge',\n 'customMessageTriggerEvent_createAuthChallenge',\n 'customMessageTriggerEvent_verifyAuthChallenge',\n\n 'eventBridgeEvent_recurringSchedule',\n 'eventBridgeEvent_stackDeploy',\n\n 's3Event_fileEvent',\n 'sqsEvent_queueEvent',\n];\n\n/**\n * Maps each lambda entry name to its handler path, for deploy bundlers\n * (quidproquo-deploy-rspack/webpack) to use as bundle entry points.\n */\nexport const getLambdaEntries = (): Record<string, string> =>\n Object.fromEntries(entryNames.map((name) => [name, path.join(__dirname, `./lambdas/${name}`)]));\n"]}
1
+ {"version":3,"file":"getLambdaEntries.js","sourceRoot":"","sources":["../../src/getLambdaEntries.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AAExB,gFAAgF;AAChF,4DAA4D;AAC/C,QAAA,UAAU,GAAG;IACxB,gDAAgD;IAEhD,iCAAiC;IACjC,wBAAwB;IAExB,oDAAoD;IAEpD,sCAAsC;IACtC,sCAAsC;IAEtC,yCAAyC;IACzC,+CAA+C;IAC/C,+CAA+C;IAC/C,+CAA+C;IAE/C,kCAAkC;IAElC,oCAAoC;IACpC,8BAA8B;IAE9B,mBAAmB;IACnB,qBAAqB;CACtB,CAAC;AAEF;;;GAGG;AACI,MAAM,gBAAgB,GAAG,GAA2B,EAAE,CAC3D,MAAM,CAAC,WAAW,CAAC,kBAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AADrF,QAAA,gBAAgB,oBACqE","sourcesContent":["import path from 'path';\n\n// One entry per lambda handler under ./lambdas; each name must match its source\n// filename exactly (yes, including the apiGatway spelling).\nexport const entryNames = [\n 'anyExecuteServiceFunctionEvent_serviceFunction',\n\n 'apiGatewayEventHandler_redirect',\n 'apiGatewayEventHandler',\n\n 'apiGatwayEventWebsocketWithIdentity_websocketEvent',\n\n 'cloudFrontRequestEvent_originRequest',\n 'cloudFrontRequestEvent_viewerRequest',\n\n 'customMessageTriggerEvent_customMessage',\n 'customMessageTriggerEvent_defineAuthChallenge',\n 'customMessageTriggerEvent_createAuthChallenge',\n 'customMessageTriggerEvent_verifyAuthChallenge',\n\n 'dynamoStreamEvent_kvsStreamEvent',\n\n 'eventBridgeEvent_recurringSchedule',\n 'eventBridgeEvent_stackDeploy',\n\n 's3Event_fileEvent',\n 'sqsEvent_queueEvent',\n];\n\n/**\n * Maps each lambda entry name to its handler path, for deploy bundlers\n * (quidproquo-deploy-rspack/webpack) to use as bundle entry points.\n */\nexport const getLambdaEntries = (): Record<string, string> =>\n Object.fromEntries(entryNames.map((name) => [name, path.join(__dirname, `./lambdas/${name}`)]));\n"]}
@@ -1,2 +1,2 @@
1
1
  import { KvsQueryOperation, QpqPagedData } from 'quidproquo-core';
2
- export declare function query<Item>(tableName: string, region: string, keyExpression: KvsQueryOperation, filterExpression?: KvsQueryOperation, pageKey?: string, indexName?: string, limit?: number, sortAscending?: boolean): Promise<QpqPagedData<Item>>;
2
+ export declare function query<Item>(tableName: string, region: string, keyExpression: KvsQueryOperation, filterExpression?: KvsQueryOperation, pageKey?: string, indexName?: string, limit?: number, sortAscending?: boolean, consistentRead?: boolean): Promise<QpqPagedData<Item>>;
@@ -16,7 +16,7 @@ const itemsToQpqPagedData_1 = require("./utils/itemsToQpqPagedData");
16
16
  const stringToLastEvaluatedKey_1 = require("./utils/stringToLastEvaluatedKey");
17
17
  const convertDynamoMapToObject_1 = require("./convertDynamoMapToObject");
18
18
  const qpqDynamoOrm_1 = require("./qpqDynamoOrm");
19
- function query(tableName, region, keyExpression, filterExpression, pageKey, indexName, limit, sortAscending) {
19
+ function query(tableName, region, keyExpression, filterExpression, pageKey, indexName, limit, sortAscending, consistentRead) {
20
20
  return __awaiter(this, void 0, void 0, function* () {
21
21
  const dynamoDBClient = (0, createAwsClient_1.createAwsClient)(client_dynamodb_1.DynamoDBClient, { region });
22
22
  const params = {
@@ -28,6 +28,10 @@ function query(tableName, region, keyExpression, filterExpression, pageKey, inde
28
28
  IndexName: indexName,
29
29
  Limit: limit,
30
30
  ScanIndexForward: sortAscending,
31
+ // Only set when asked. A strongly consistent read costs twice the RCU and cannot be served from a
32
+ // global secondary index, so it must stay opt-in — but without it a caller cannot read back what it
33
+ // just wrote, which some callers genuinely need.
34
+ ConsistentRead: consistentRead,
31
35
  };
32
36
  if (pageKey) {
33
37
  params.ExclusiveStartKey = (0, stringToLastEvaluatedKey_1.stringToLastEvaluatedKey)(pageKey);
@@ -1 +1 @@
1
- {"version":3,"file":"query.js","sourceRoot":"","sources":["../../../../src/logic/dynamo/query.ts"],"names":[],"mappings":";;;;;;;;;;;AAUA,sBAgCC;AAxCD,8DAA2F;AAE3F,wDAAqD;AACrD,qEAAkE;AAClE,+EAA4E;AAC5E,yEAAsE;AACtE,iDAA2H;AAE3H,SAAsB,KAAK,CACzB,SAAiB,EACjB,MAAc,EACd,aAAgC,EAChC,gBAAoC,EACpC,OAAgB,EAChB,SAAkB,EAClB,KAAc,EACd,aAAuB;;QAEvB,MAAM,cAAc,GAAG,IAAA,iCAAe,EAAC,gCAAc,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAEnE,MAAM,MAAM,GAAsB;YAChC,SAAS,EAAE,SAAS;YACpB,sBAAsB,EAAE,IAAA,yCAA0B,EAAC,aAAa,CAAC;YACjE,gBAAgB,EAAE,gBAAgB,IAAI,IAAA,yCAA0B,EAAC,gBAAgB,CAAC;YAClF,yBAAyB,EAAE,IAAA,6CAA8B,EAAC,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;YAC5F,wBAAwB,EAAE,IAAA,4CAA6B,EAAC,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;YAC1F,SAAS,EAAE,SAAS;YACpB,KAAK,EAAE,KAAK;YACZ,gBAAgB,EAAE,aAAa;SAChC,CAAC;QAEF,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,CAAC,iBAAiB,GAAG,IAAA,mDAAwB,EAAC,OAAO,CAAC,CAAC;QAC/D,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,IAAI,8BAAY,CAAC,MAAM,CAAC,CAAC,CAAC;QAEjE,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAA,mDAAwB,EAAC,IAAI,CAAC,CAAW,CAAC;QAEzF,OAAO,IAAA,yCAAmB,EAAO,KAAK,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACjE,CAAC;CAAA","sourcesContent":["import { KvsQueryOperation, QpqPagedData } from 'quidproquo-core';\n\nimport { DynamoDBClient, QueryCommand, QueryCommandInput } from '@aws-sdk/client-dynamodb';\n\nimport { createAwsClient } from '../createAwsClient';\nimport { itemsToQpqPagedData } from './utils/itemsToQpqPagedData';\nimport { stringToLastEvaluatedKey } from './utils/stringToLastEvaluatedKey';\nimport { convertDynamoMapToObject } from './convertDynamoMapToObject';\nimport { buildDynamoQueryExpression, buildExpressionAttributeNames, buildExpressionAttributeValues } from './qpqDynamoOrm';\n\nexport async function query<Item>(\n tableName: string,\n region: string,\n keyExpression: KvsQueryOperation,\n filterExpression?: KvsQueryOperation,\n pageKey?: string,\n indexName?: string,\n limit?: number,\n sortAscending?: boolean,\n): Promise<QpqPagedData<Item>> {\n const dynamoDBClient = createAwsClient(DynamoDBClient, { region });\n\n const params: QueryCommandInput = {\n TableName: tableName,\n KeyConditionExpression: buildDynamoQueryExpression(keyExpression),\n FilterExpression: filterExpression && buildDynamoQueryExpression(filterExpression),\n ExpressionAttributeValues: buildExpressionAttributeValues([keyExpression, filterExpression]),\n ExpressionAttributeNames: buildExpressionAttributeNames([keyExpression, filterExpression]),\n IndexName: indexName,\n Limit: limit,\n ScanIndexForward: sortAscending,\n };\n\n if (pageKey) {\n params.ExclusiveStartKey = stringToLastEvaluatedKey(pageKey);\n }\n\n const data = await dynamoDBClient.send(new QueryCommand(params));\n\n const items = (data.Items || []).map((item) => convertDynamoMapToObject(item)) as Item[];\n\n return itemsToQpqPagedData<Item>(items, data.LastEvaluatedKey);\n}\n"]}
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../../../../src/logic/dynamo/query.ts"],"names":[],"mappings":";;;;;;;;;;;AAUA,sBAqCC;AA7CD,8DAA2F;AAE3F,wDAAqD;AACrD,qEAAkE;AAClE,+EAA4E;AAC5E,yEAAsE;AACtE,iDAA2H;AAE3H,SAAsB,KAAK,CACzB,SAAiB,EACjB,MAAc,EACd,aAAgC,EAChC,gBAAoC,EACpC,OAAgB,EAChB,SAAkB,EAClB,KAAc,EACd,aAAuB,EACvB,cAAwB;;QAExB,MAAM,cAAc,GAAG,IAAA,iCAAe,EAAC,gCAAc,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAEnE,MAAM,MAAM,GAAsB;YAChC,SAAS,EAAE,SAAS;YACpB,sBAAsB,EAAE,IAAA,yCAA0B,EAAC,aAAa,CAAC;YACjE,gBAAgB,EAAE,gBAAgB,IAAI,IAAA,yCAA0B,EAAC,gBAAgB,CAAC;YAClF,yBAAyB,EAAE,IAAA,6CAA8B,EAAC,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;YAC5F,wBAAwB,EAAE,IAAA,4CAA6B,EAAC,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;YAC1F,SAAS,EAAE,SAAS;YACpB,KAAK,EAAE,KAAK;YACZ,gBAAgB,EAAE,aAAa;YAC/B,kGAAkG;YAClG,oGAAoG;YACpG,iDAAiD;YACjD,cAAc,EAAE,cAAc;SAC/B,CAAC;QAEF,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,CAAC,iBAAiB,GAAG,IAAA,mDAAwB,EAAC,OAAO,CAAC,CAAC;QAC/D,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,IAAI,8BAAY,CAAC,MAAM,CAAC,CAAC,CAAC;QAEjE,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAA,mDAAwB,EAAC,IAAI,CAAC,CAAW,CAAC;QAEzF,OAAO,IAAA,yCAAmB,EAAO,KAAK,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACjE,CAAC;CAAA","sourcesContent":["import { KvsQueryOperation, QpqPagedData } from 'quidproquo-core';\n\nimport { DynamoDBClient, QueryCommand, QueryCommandInput } from '@aws-sdk/client-dynamodb';\n\nimport { createAwsClient } from '../createAwsClient';\nimport { itemsToQpqPagedData } from './utils/itemsToQpqPagedData';\nimport { stringToLastEvaluatedKey } from './utils/stringToLastEvaluatedKey';\nimport { convertDynamoMapToObject } from './convertDynamoMapToObject';\nimport { buildDynamoQueryExpression, buildExpressionAttributeNames, buildExpressionAttributeValues } from './qpqDynamoOrm';\n\nexport async function query<Item>(\n tableName: string,\n region: string,\n keyExpression: KvsQueryOperation,\n filterExpression?: KvsQueryOperation,\n pageKey?: string,\n indexName?: string,\n limit?: number,\n sortAscending?: boolean,\n consistentRead?: boolean,\n): Promise<QpqPagedData<Item>> {\n const dynamoDBClient = createAwsClient(DynamoDBClient, { region });\n\n const params: QueryCommandInput = {\n TableName: tableName,\n KeyConditionExpression: buildDynamoQueryExpression(keyExpression),\n FilterExpression: filterExpression && buildDynamoQueryExpression(filterExpression),\n ExpressionAttributeValues: buildExpressionAttributeValues([keyExpression, filterExpression]),\n ExpressionAttributeNames: buildExpressionAttributeNames([keyExpression, filterExpression]),\n IndexName: indexName,\n Limit: limit,\n ScanIndexForward: sortAscending,\n // Only set when asked. A strongly consistent read costs twice the RCU and cannot be served from a\n // global secondary index, so it must stay opt-in — but without it a caller cannot read back what it\n // just wrote, which some callers genuinely need.\n ConsistentRead: consistentRead,\n };\n\n if (pageKey) {\n params.ExclusiveStartKey = stringToLastEvaluatedKey(pageKey);\n }\n\n const data = await dynamoDBClient.send(new QueryCommand(params));\n\n const items = (data.Items || []).map((item) => convertDynamoMapToObject(item)) as Item[];\n\n return itemsToQpqPagedData<Item>(items, data.LastEvaluatedKey);\n}\n"]}
@@ -14,7 +14,7 @@ const getProcessKeyValueStoreQuery = (qpqConfig) => {
14
14
  // composed form (throws when the key condition never constrains the pk).
15
15
  const scoped = getScopedKvsTranslatorOrThrow(qpqConfig, keyValueStoreName, options?.scope);
16
16
  const effectiveKeyCondition = scoped.keyCondition(keyCondition);
17
- const items = await query(dynamoTableName, region, effectiveKeyCondition, scoped.filter(options?.filter), options?.nextPageKey, getDynamoTableIndexByConfigAndQuery(storeConfig, effectiveKeyCondition) ?? undefined, options?.limit, options?.sortAscending);
17
+ const items = await query(dynamoTableName, region, effectiveKeyCondition, scoped.filter(options?.filter), options?.nextPageKey, getDynamoTableIndexByConfigAndQuery(storeConfig, effectiveKeyCondition) ?? undefined, options?.limit, options?.sortAscending, options?.consistentRead);
18
18
  items.items = items.items.map((item) => scoped.strip(item));
19
19
  return actionResult(items);
20
20
  }
@@ -1 +1 @@
1
- {"version":3,"file":"getKeyValueStoreQueryActionProcessor.js","sourceRoot":"","sources":["../../../../../src/getActionProcessor/core/keyValueStore/getKeyValueStoreQueryActionProcessor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAGL,iBAAiB,EACjB,gCAAgC,EAChC,6BAA6B,EAE7B,4BAA4B,GAC7B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAqC,+BAA+B,EAAE,MAAM,iBAAiB,CAAC;AAE5I,OAAO,EAAE,+BAA+B,EAAE,MAAM,yBAAyB,CAAC;AAC1E,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,mCAAmC,EAAE,MAAM,oCAAoC,CAAC;AAEzF,MAAM,4BAA4B,GAAG,CAAC,SAAoB,EAA0C,EAAE;IACpG,OAAO,KAAK,EAAE,EAAE,iBAAiB,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE,EAAE;QAC5D,MAAM,eAAe,GAAG,+BAA+B,CAAC,iBAAiB,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;QAC7F,MAAM,MAAM,GAAG,iBAAiB,CAAC,gCAAgC,CAAC,SAAS,CAAC,CAAC;QAE7E,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,4BAA4B,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;YAE/E,0EAA0E;YAC1E,yEAAyE;YACzE,MAAM,MAAM,GAAG,6BAA6B,CAAC,SAAS,EAAE,iBAAiB,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;YAC3F,MAAM,qBAAqB,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;YAEhE,MAAM,KAAK,GAAG,MAAM,KAAK,CACvB,eAAe,EACf,MAAM,EACN,qBAAqB,EACrB,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,EAC9B,OAAO,EAAE,WAAW,EACpB,mCAAmC,CAAC,WAAW,EAAE,qBAAqB,CAAC,IAAI,SAAS,EACpF,OAAO,EAAE,KAAK,EACd,OAAO,EAAE,aAAa,CACvB,CAAC;YAEF,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YAEjE,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,gCAAgC,CAAC,KAAK,EAAE;gBAC7C,mBAAmB,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,+BAA+B,CAAC,kBAAkB,EAAE,yBAAyB,CAAC;gBAC3H,yBAAyB,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,+BAA+B,CAAC,gBAAgB,EAAE,wBAAwB,CAAC;gBAC9H,iBAAiB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,+BAA+B,CAAC,YAAY,EAAE,KAAK,CAAC,OAAO,CAAC;gBAC5G,qBAAqB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,+BAA+B,CAAC,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC;aAClH,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oCAAoC,GAAgC,KAAK,EAAE,SAAoB,EAAgC,EAAE,CAAC,CAAC;IAC9I,CAAC,uBAAuB,CAAC,KAAK,CAAC,EAAE,4BAA4B,CAAC,SAAS,CAAC;CACzE,CAAC,CAAC","sourcesContent":["import { qpqConfigAwsUtils } from 'quidproquo-config-aws';\nimport {\n ActionProcessorList,\n ActionProcessorListResolver,\n actionResultError,\n actionResultErrorFromCaughtError,\n getScopedKvsTranslatorOrThrow,\n QPQConfig,\n resolveKvsStoreConfigOrThrow,\n} from 'quidproquo-core';\nimport { actionResult, KeyValueStoreActionType, KeyValueStoreQueryActionProcessor, KeyValueStoreQueryErrorTypeEnum } from 'quidproquo-core';\n\nimport { getKvsDynamoTableNameFromConfig } from '../../../awsNamingUtils';\nimport { query } from '../../../logic/dynamo';\nimport { getDynamoTableIndexByConfigAndQuery } from '../../../logic/dynamo/qpqDynamoOrm';\n\nconst getProcessKeyValueStoreQuery = (qpqConfig: QPQConfig): KeyValueStoreQueryActionProcessor<any> => {\n return async ({ keyValueStoreName, keyCondition, options }) => {\n const dynamoTableName = getKvsDynamoTableNameFromConfig(keyValueStoreName, qpqConfig, 'kvs');\n const region = qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig);\n\n try {\n const storeConfig = resolveKvsStoreConfigOrThrow(qpqConfig, keyValueStoreName);\n\n // Scope lives inside the pk values, so pk conditions are rewritten to the\n // composed form (throws when the key condition never constrains the pk).\n const scoped = getScopedKvsTranslatorOrThrow(qpqConfig, keyValueStoreName, options?.scope);\n const effectiveKeyCondition = scoped.keyCondition(keyCondition);\n\n const items = await query<any>(\n dynamoTableName,\n region,\n effectiveKeyCondition,\n scoped.filter(options?.filter),\n options?.nextPageKey,\n getDynamoTableIndexByConfigAndQuery(storeConfig, effectiveKeyCondition) ?? undefined,\n options?.limit,\n options?.sortAscending,\n );\n\n items.items = items.items.map((item: any) => scoped.strip(item));\n\n return actionResult(items);\n } catch (error: unknown) {\n return actionResultErrorFromCaughtError(error, {\n InternalServerError: () => actionResultError(KeyValueStoreQueryErrorTypeEnum.ServiceUnavailable, 'KVS Service Unavailable'),\n ResourceNotFoundException: () => actionResultError(KeyValueStoreQueryErrorTypeEnum.ResourceNotFound, 'KVS Resource Not Found'),\n InvalidScopeError: (error) => actionResultError(KeyValueStoreQueryErrorTypeEnum.InvalidScope, error.message),\n KvsStoreNotFoundError: (error) => actionResultError(KeyValueStoreQueryErrorTypeEnum.StoreNotFound, error.message),\n });\n }\n };\n};\n\nexport const getKeyValueStoreQueryActionProcessor: ActionProcessorListResolver = async (qpqConfig: QPQConfig): Promise<ActionProcessorList> => ({\n [KeyValueStoreActionType.Query]: getProcessKeyValueStoreQuery(qpqConfig),\n});\n"]}
1
+ {"version":3,"file":"getKeyValueStoreQueryActionProcessor.js","sourceRoot":"","sources":["../../../../../src/getActionProcessor/core/keyValueStore/getKeyValueStoreQueryActionProcessor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAGL,iBAAiB,EACjB,gCAAgC,EAChC,6BAA6B,EAE7B,4BAA4B,GAC7B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAqC,+BAA+B,EAAE,MAAM,iBAAiB,CAAC;AAE5I,OAAO,EAAE,+BAA+B,EAAE,MAAM,yBAAyB,CAAC;AAC1E,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,mCAAmC,EAAE,MAAM,oCAAoC,CAAC;AAEzF,MAAM,4BAA4B,GAAG,CAAC,SAAoB,EAA0C,EAAE;IACpG,OAAO,KAAK,EAAE,EAAE,iBAAiB,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE,EAAE;QAC5D,MAAM,eAAe,GAAG,+BAA+B,CAAC,iBAAiB,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;QAC7F,MAAM,MAAM,GAAG,iBAAiB,CAAC,gCAAgC,CAAC,SAAS,CAAC,CAAC;QAE7E,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,4BAA4B,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;YAE/E,0EAA0E;YAC1E,yEAAyE;YACzE,MAAM,MAAM,GAAG,6BAA6B,CAAC,SAAS,EAAE,iBAAiB,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;YAC3F,MAAM,qBAAqB,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;YAEhE,MAAM,KAAK,GAAG,MAAM,KAAK,CACvB,eAAe,EACf,MAAM,EACN,qBAAqB,EACrB,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,EAC9B,OAAO,EAAE,WAAW,EACpB,mCAAmC,CAAC,WAAW,EAAE,qBAAqB,CAAC,IAAI,SAAS,EACpF,OAAO,EAAE,KAAK,EACd,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,cAAc,CACxB,CAAC;YAEF,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YAEjE,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,gCAAgC,CAAC,KAAK,EAAE;gBAC7C,mBAAmB,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,+BAA+B,CAAC,kBAAkB,EAAE,yBAAyB,CAAC;gBAC3H,yBAAyB,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,+BAA+B,CAAC,gBAAgB,EAAE,wBAAwB,CAAC;gBAC9H,iBAAiB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,+BAA+B,CAAC,YAAY,EAAE,KAAK,CAAC,OAAO,CAAC;gBAC5G,qBAAqB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,+BAA+B,CAAC,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC;aAClH,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oCAAoC,GAAgC,KAAK,EAAE,SAAoB,EAAgC,EAAE,CAAC,CAAC;IAC9I,CAAC,uBAAuB,CAAC,KAAK,CAAC,EAAE,4BAA4B,CAAC,SAAS,CAAC;CACzE,CAAC,CAAC","sourcesContent":["import { qpqConfigAwsUtils } from 'quidproquo-config-aws';\nimport {\n ActionProcessorList,\n ActionProcessorListResolver,\n actionResultError,\n actionResultErrorFromCaughtError,\n getScopedKvsTranslatorOrThrow,\n QPQConfig,\n resolveKvsStoreConfigOrThrow,\n} from 'quidproquo-core';\nimport { actionResult, KeyValueStoreActionType, KeyValueStoreQueryActionProcessor, KeyValueStoreQueryErrorTypeEnum } from 'quidproquo-core';\n\nimport { getKvsDynamoTableNameFromConfig } from '../../../awsNamingUtils';\nimport { query } from '../../../logic/dynamo';\nimport { getDynamoTableIndexByConfigAndQuery } from '../../../logic/dynamo/qpqDynamoOrm';\n\nconst getProcessKeyValueStoreQuery = (qpqConfig: QPQConfig): KeyValueStoreQueryActionProcessor<any> => {\n return async ({ keyValueStoreName, keyCondition, options }) => {\n const dynamoTableName = getKvsDynamoTableNameFromConfig(keyValueStoreName, qpqConfig, 'kvs');\n const region = qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig);\n\n try {\n const storeConfig = resolveKvsStoreConfigOrThrow(qpqConfig, keyValueStoreName);\n\n // Scope lives inside the pk values, so pk conditions are rewritten to the\n // composed form (throws when the key condition never constrains the pk).\n const scoped = getScopedKvsTranslatorOrThrow(qpqConfig, keyValueStoreName, options?.scope);\n const effectiveKeyCondition = scoped.keyCondition(keyCondition);\n\n const items = await query<any>(\n dynamoTableName,\n region,\n effectiveKeyCondition,\n scoped.filter(options?.filter),\n options?.nextPageKey,\n getDynamoTableIndexByConfigAndQuery(storeConfig, effectiveKeyCondition) ?? undefined,\n options?.limit,\n options?.sortAscending,\n options?.consistentRead,\n );\n\n items.items = items.items.map((item: any) => scoped.strip(item));\n\n return actionResult(items);\n } catch (error: unknown) {\n return actionResultErrorFromCaughtError(error, {\n InternalServerError: () => actionResultError(KeyValueStoreQueryErrorTypeEnum.ServiceUnavailable, 'KVS Service Unavailable'),\n ResourceNotFoundException: () => actionResultError(KeyValueStoreQueryErrorTypeEnum.ResourceNotFound, 'KVS Resource Not Found'),\n InvalidScopeError: (error) => actionResultError(KeyValueStoreQueryErrorTypeEnum.InvalidScope, error.message),\n KvsStoreNotFoundError: (error) => actionResultError(KeyValueStoreQueryErrorTypeEnum.StoreNotFound, error.message),\n });\n }\n };\n};\n\nexport const getKeyValueStoreQueryActionProcessor: ActionProcessorListResolver = async (qpqConfig: QPQConfig): Promise<ActionProcessorList> => ({\n [KeyValueStoreActionType.Query]: getProcessKeyValueStoreQuery(qpqConfig),\n});\n"]}
@@ -12,6 +12,7 @@ export const entryNames = [
12
12
  'customMessageTriggerEvent_defineAuthChallenge',
13
13
  'customMessageTriggerEvent_createAuthChallenge',
14
14
  'customMessageTriggerEvent_verifyAuthChallenge',
15
+ 'dynamoStreamEvent_kvsStreamEvent',
15
16
  'eventBridgeEvent_recurringSchedule',
16
17
  'eventBridgeEvent_stackDeploy',
17
18
  's3Event_fileEvent',
@@ -1 +1 @@
1
- {"version":3,"file":"getLambdaEntries.js","sourceRoot":"","sources":["../../src/getLambdaEntries.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,gFAAgF;AAChF,4DAA4D;AAC5D,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,gDAAgD;IAEhD,iCAAiC;IACjC,wBAAwB;IAExB,oDAAoD;IAEpD,sCAAsC;IACtC,sCAAsC;IAEtC,yCAAyC;IACzC,+CAA+C;IAC/C,+CAA+C;IAC/C,+CAA+C;IAE/C,oCAAoC;IACpC,8BAA8B;IAE9B,mBAAmB;IACnB,qBAAqB;CACtB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAA2B,EAAE,CAC3D,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC","sourcesContent":["import path from 'path';\n\n// One entry per lambda handler under ./lambdas; each name must match its source\n// filename exactly (yes, including the apiGatway spelling).\nexport const entryNames = [\n 'anyExecuteServiceFunctionEvent_serviceFunction',\n\n 'apiGatewayEventHandler_redirect',\n 'apiGatewayEventHandler',\n\n 'apiGatwayEventWebsocketWithIdentity_websocketEvent',\n\n 'cloudFrontRequestEvent_originRequest',\n 'cloudFrontRequestEvent_viewerRequest',\n\n 'customMessageTriggerEvent_customMessage',\n 'customMessageTriggerEvent_defineAuthChallenge',\n 'customMessageTriggerEvent_createAuthChallenge',\n 'customMessageTriggerEvent_verifyAuthChallenge',\n\n 'eventBridgeEvent_recurringSchedule',\n 'eventBridgeEvent_stackDeploy',\n\n 's3Event_fileEvent',\n 'sqsEvent_queueEvent',\n];\n\n/**\n * Maps each lambda entry name to its handler path, for deploy bundlers\n * (quidproquo-deploy-rspack/webpack) to use as bundle entry points.\n */\nexport const getLambdaEntries = (): Record<string, string> =>\n Object.fromEntries(entryNames.map((name) => [name, path.join(__dirname, `./lambdas/${name}`)]));\n"]}
1
+ {"version":3,"file":"getLambdaEntries.js","sourceRoot":"","sources":["../../src/getLambdaEntries.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,gFAAgF;AAChF,4DAA4D;AAC5D,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,gDAAgD;IAEhD,iCAAiC;IACjC,wBAAwB;IAExB,oDAAoD;IAEpD,sCAAsC;IACtC,sCAAsC;IAEtC,yCAAyC;IACzC,+CAA+C;IAC/C,+CAA+C;IAC/C,+CAA+C;IAE/C,kCAAkC;IAElC,oCAAoC;IACpC,8BAA8B;IAE9B,mBAAmB;IACnB,qBAAqB;CACtB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAA2B,EAAE,CAC3D,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC","sourcesContent":["import path from 'path';\n\n// One entry per lambda handler under ./lambdas; each name must match its source\n// filename exactly (yes, including the apiGatway spelling).\nexport const entryNames = [\n 'anyExecuteServiceFunctionEvent_serviceFunction',\n\n 'apiGatewayEventHandler_redirect',\n 'apiGatewayEventHandler',\n\n 'apiGatwayEventWebsocketWithIdentity_websocketEvent',\n\n 'cloudFrontRequestEvent_originRequest',\n 'cloudFrontRequestEvent_viewerRequest',\n\n 'customMessageTriggerEvent_customMessage',\n 'customMessageTriggerEvent_defineAuthChallenge',\n 'customMessageTriggerEvent_createAuthChallenge',\n 'customMessageTriggerEvent_verifyAuthChallenge',\n\n 'dynamoStreamEvent_kvsStreamEvent',\n\n 'eventBridgeEvent_recurringSchedule',\n 'eventBridgeEvent_stackDeploy',\n\n 's3Event_fileEvent',\n 'sqsEvent_queueEvent',\n];\n\n/**\n * Maps each lambda entry name to its handler path, for deploy bundlers\n * (quidproquo-deploy-rspack/webpack) to use as bundle entry points.\n */\nexport const getLambdaEntries = (): Record<string, string> =>\n Object.fromEntries(entryNames.map((name) => [name, path.join(__dirname, `./lambdas/${name}`)]));\n"]}
@@ -1,2 +1,2 @@
1
1
  import { KvsQueryOperation, QpqPagedData } from 'quidproquo-core';
2
- export declare function query<Item>(tableName: string, region: string, keyExpression: KvsQueryOperation, filterExpression?: KvsQueryOperation, pageKey?: string, indexName?: string, limit?: number, sortAscending?: boolean): Promise<QpqPagedData<Item>>;
2
+ export declare function query<Item>(tableName: string, region: string, keyExpression: KvsQueryOperation, filterExpression?: KvsQueryOperation, pageKey?: string, indexName?: string, limit?: number, sortAscending?: boolean, consistentRead?: boolean): Promise<QpqPagedData<Item>>;
@@ -4,7 +4,7 @@ import { itemsToQpqPagedData } from './utils/itemsToQpqPagedData';
4
4
  import { stringToLastEvaluatedKey } from './utils/stringToLastEvaluatedKey';
5
5
  import { convertDynamoMapToObject } from './convertDynamoMapToObject';
6
6
  import { buildDynamoQueryExpression, buildExpressionAttributeNames, buildExpressionAttributeValues } from './qpqDynamoOrm';
7
- export async function query(tableName, region, keyExpression, filterExpression, pageKey, indexName, limit, sortAscending) {
7
+ export async function query(tableName, region, keyExpression, filterExpression, pageKey, indexName, limit, sortAscending, consistentRead) {
8
8
  const dynamoDBClient = createAwsClient(DynamoDBClient, { region });
9
9
  const params = {
10
10
  TableName: tableName,
@@ -15,6 +15,10 @@ export async function query(tableName, region, keyExpression, filterExpression,
15
15
  IndexName: indexName,
16
16
  Limit: limit,
17
17
  ScanIndexForward: sortAscending,
18
+ // Only set when asked. A strongly consistent read costs twice the RCU and cannot be served from a
19
+ // global secondary index, so it must stay opt-in — but without it a caller cannot read back what it
20
+ // just wrote, which some callers genuinely need.
21
+ ConsistentRead: consistentRead,
18
22
  };
19
23
  if (pageKey) {
20
24
  params.ExclusiveStartKey = stringToLastEvaluatedKey(pageKey);
@@ -1 +1 @@
1
- {"version":3,"file":"query.js","sourceRoot":"","sources":["../../../../src/logic/dynamo/query.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAqB,MAAM,0BAA0B,CAAC;AAE3F,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,0BAA0B,EAAE,6BAA6B,EAAE,8BAA8B,EAAE,MAAM,gBAAgB,CAAC;AAE3H,MAAM,CAAC,KAAK,UAAU,KAAK,CACzB,SAAiB,EACjB,MAAc,EACd,aAAgC,EAChC,gBAAoC,EACpC,OAAgB,EAChB,SAAkB,EAClB,KAAc,EACd,aAAuB;IAEvB,MAAM,cAAc,GAAG,eAAe,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IAEnE,MAAM,MAAM,GAAsB;QAChC,SAAS,EAAE,SAAS;QACpB,sBAAsB,EAAE,0BAA0B,CAAC,aAAa,CAAC;QACjE,gBAAgB,EAAE,gBAAgB,IAAI,0BAA0B,CAAC,gBAAgB,CAAC;QAClF,yBAAyB,EAAE,8BAA8B,CAAC,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;QAC5F,wBAAwB,EAAE,6BAA6B,CAAC,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;QAC1F,SAAS,EAAE,SAAS;QACpB,KAAK,EAAE,KAAK;QACZ,gBAAgB,EAAE,aAAa;KAChC,CAAC;IAEF,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,CAAC,iBAAiB,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;IAEjE,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAW,CAAC;IAEzF,OAAO,mBAAmB,CAAO,KAAK,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;AACjE,CAAC","sourcesContent":["import { KvsQueryOperation, QpqPagedData } from 'quidproquo-core';\n\nimport { DynamoDBClient, QueryCommand, QueryCommandInput } from '@aws-sdk/client-dynamodb';\n\nimport { createAwsClient } from '../createAwsClient';\nimport { itemsToQpqPagedData } from './utils/itemsToQpqPagedData';\nimport { stringToLastEvaluatedKey } from './utils/stringToLastEvaluatedKey';\nimport { convertDynamoMapToObject } from './convertDynamoMapToObject';\nimport { buildDynamoQueryExpression, buildExpressionAttributeNames, buildExpressionAttributeValues } from './qpqDynamoOrm';\n\nexport async function query<Item>(\n tableName: string,\n region: string,\n keyExpression: KvsQueryOperation,\n filterExpression?: KvsQueryOperation,\n pageKey?: string,\n indexName?: string,\n limit?: number,\n sortAscending?: boolean,\n): Promise<QpqPagedData<Item>> {\n const dynamoDBClient = createAwsClient(DynamoDBClient, { region });\n\n const params: QueryCommandInput = {\n TableName: tableName,\n KeyConditionExpression: buildDynamoQueryExpression(keyExpression),\n FilterExpression: filterExpression && buildDynamoQueryExpression(filterExpression),\n ExpressionAttributeValues: buildExpressionAttributeValues([keyExpression, filterExpression]),\n ExpressionAttributeNames: buildExpressionAttributeNames([keyExpression, filterExpression]),\n IndexName: indexName,\n Limit: limit,\n ScanIndexForward: sortAscending,\n };\n\n if (pageKey) {\n params.ExclusiveStartKey = stringToLastEvaluatedKey(pageKey);\n }\n\n const data = await dynamoDBClient.send(new QueryCommand(params));\n\n const items = (data.Items || []).map((item) => convertDynamoMapToObject(item)) as Item[];\n\n return itemsToQpqPagedData<Item>(items, data.LastEvaluatedKey);\n}\n"]}
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../../../../src/logic/dynamo/query.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAqB,MAAM,0BAA0B,CAAC;AAE3F,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,0BAA0B,EAAE,6BAA6B,EAAE,8BAA8B,EAAE,MAAM,gBAAgB,CAAC;AAE3H,MAAM,CAAC,KAAK,UAAU,KAAK,CACzB,SAAiB,EACjB,MAAc,EACd,aAAgC,EAChC,gBAAoC,EACpC,OAAgB,EAChB,SAAkB,EAClB,KAAc,EACd,aAAuB,EACvB,cAAwB;IAExB,MAAM,cAAc,GAAG,eAAe,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IAEnE,MAAM,MAAM,GAAsB;QAChC,SAAS,EAAE,SAAS;QACpB,sBAAsB,EAAE,0BAA0B,CAAC,aAAa,CAAC;QACjE,gBAAgB,EAAE,gBAAgB,IAAI,0BAA0B,CAAC,gBAAgB,CAAC;QAClF,yBAAyB,EAAE,8BAA8B,CAAC,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;QAC5F,wBAAwB,EAAE,6BAA6B,CAAC,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;QAC1F,SAAS,EAAE,SAAS;QACpB,KAAK,EAAE,KAAK;QACZ,gBAAgB,EAAE,aAAa;QAC/B,kGAAkG;QAClG,oGAAoG;QACpG,iDAAiD;QACjD,cAAc,EAAE,cAAc;KAC/B,CAAC;IAEF,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,CAAC,iBAAiB,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;IAEjE,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAW,CAAC;IAEzF,OAAO,mBAAmB,CAAO,KAAK,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;AACjE,CAAC","sourcesContent":["import { KvsQueryOperation, QpqPagedData } from 'quidproquo-core';\n\nimport { DynamoDBClient, QueryCommand, QueryCommandInput } from '@aws-sdk/client-dynamodb';\n\nimport { createAwsClient } from '../createAwsClient';\nimport { itemsToQpqPagedData } from './utils/itemsToQpqPagedData';\nimport { stringToLastEvaluatedKey } from './utils/stringToLastEvaluatedKey';\nimport { convertDynamoMapToObject } from './convertDynamoMapToObject';\nimport { buildDynamoQueryExpression, buildExpressionAttributeNames, buildExpressionAttributeValues } from './qpqDynamoOrm';\n\nexport async function query<Item>(\n tableName: string,\n region: string,\n keyExpression: KvsQueryOperation,\n filterExpression?: KvsQueryOperation,\n pageKey?: string,\n indexName?: string,\n limit?: number,\n sortAscending?: boolean,\n consistentRead?: boolean,\n): Promise<QpqPagedData<Item>> {\n const dynamoDBClient = createAwsClient(DynamoDBClient, { region });\n\n const params: QueryCommandInput = {\n TableName: tableName,\n KeyConditionExpression: buildDynamoQueryExpression(keyExpression),\n FilterExpression: filterExpression && buildDynamoQueryExpression(filterExpression),\n ExpressionAttributeValues: buildExpressionAttributeValues([keyExpression, filterExpression]),\n ExpressionAttributeNames: buildExpressionAttributeNames([keyExpression, filterExpression]),\n IndexName: indexName,\n Limit: limit,\n ScanIndexForward: sortAscending,\n // Only set when asked. A strongly consistent read costs twice the RCU and cannot be served from a\n // global secondary index, so it must stay opt-in — but without it a caller cannot read back what it\n // just wrote, which some callers genuinely need.\n ConsistentRead: consistentRead,\n };\n\n if (pageKey) {\n params.ExclusiveStartKey = stringToLastEvaluatedKey(pageKey);\n }\n\n const data = await dynamoDBClient.send(new QueryCommand(params));\n\n const items = (data.Items || []).map((item) => convertDynamoMapToObject(item)) as Item[];\n\n return itemsToQpqPagedData<Item>(items, data.LastEvaluatedKey);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quidproquo-actionprocessor-awslambda",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
4
4
  "description": "",
5
5
  "main": "./lib/commonjs/index.js",
6
6
  "module": "./lib/esm/index.js",
@@ -63,11 +63,11 @@
63
63
  "lodash": "^4.17.21",
64
64
  "node-cache": "^5.1.2",
65
65
  "node-match-path": "^0.6.3",
66
- "quidproquo-actionprocessor-js": "0.1.13",
67
- "quidproquo-actionprocessor-node": "0.1.13",
68
- "quidproquo-config-aws": "0.1.13",
69
- "quidproquo-core": "0.1.13",
70
- "quidproquo-webserver": "0.1.13"
66
+ "quidproquo-actionprocessor-js": "0.1.14",
67
+ "quidproquo-actionprocessor-node": "0.1.14",
68
+ "quidproquo-config-aws": "0.1.14",
69
+ "quidproquo-core": "0.1.14",
70
+ "quidproquo-webserver": "0.1.14"
71
71
  },
72
72
  "devDependencies": {
73
73
  "@types/busboy": "^1.5.0",
@@ -75,7 +75,7 @@
75
75
  "@types/lodash": "^4.14.194",
76
76
  "@types/node": "^22.13.13",
77
77
  "esbuild": "^0.25.8",
78
- "quidproquo-tsconfig": "0.1.13",
78
+ "quidproquo-tsconfig": "0.1.14",
79
79
  "typescript": "^5.8.2"
80
80
  }
81
81
  }