quidproquo-actionprocessor-awslambda 0.1.22 → 0.1.24

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 (81) hide show
  1. package/lib/commonjs/getActionProcessor/core/crypto/getCryptoGetPublicKeyActionProcessor.d.ts +1 -0
  2. package/lib/commonjs/getActionProcessor/core/crypto/getCryptoGetPublicKeyActionProcessor.js +34 -0
  3. package/lib/commonjs/getActionProcessor/core/crypto/getCryptoGetPublicKeyActionProcessor.js.map +1 -0
  4. package/lib/commonjs/getActionProcessor/core/crypto/getCryptoSignActionProcessor.d.ts +1 -0
  5. package/lib/commonjs/getActionProcessor/core/crypto/getCryptoSignActionProcessor.js +36 -0
  6. package/lib/commonjs/getActionProcessor/core/crypto/getCryptoSignActionProcessor.js.map +1 -0
  7. package/lib/commonjs/getActionProcessor/core/crypto/getCryptoVerifyActionProcessor.d.ts +1 -0
  8. package/lib/commonjs/getActionProcessor/core/crypto/getCryptoVerifyActionProcessor.js +38 -0
  9. package/lib/commonjs/getActionProcessor/core/crypto/getCryptoVerifyActionProcessor.js.map +1 -0
  10. package/lib/commonjs/getActionProcessor/core/crypto/index.js +4 -1
  11. package/lib/commonjs/getActionProcessor/core/crypto/index.js.map +1 -1
  12. package/lib/commonjs/getActionProcessor/core/crypto/kmsSigningErrorMap.d.ts +13 -0
  13. package/lib/commonjs/getActionProcessor/core/crypto/kmsSigningErrorMap.js +17 -0
  14. package/lib/commonjs/getActionProcessor/core/crypto/kmsSigningErrorMap.js.map +1 -0
  15. package/lib/commonjs/getActionProcessor/core/crypto/utils/index.d.ts +1 -0
  16. package/lib/commonjs/getActionProcessor/core/crypto/utils/index.js +1 -0
  17. package/lib/commonjs/getActionProcessor/core/crypto/utils/index.js.map +1 -1
  18. package/lib/commonjs/getActionProcessor/core/crypto/utils/resolveSigningKeyAlias.d.ts +2 -0
  19. package/lib/commonjs/getActionProcessor/core/crypto/utils/resolveSigningKeyAlias.js +19 -0
  20. package/lib/commonjs/getActionProcessor/core/crypto/utils/resolveSigningKeyAlias.js.map +1 -0
  21. package/lib/commonjs/getActionProcessor/core/file/getFileCopyActionProcessor.d.ts +1 -0
  22. package/lib/commonjs/getActionProcessor/core/file/getFileCopyActionProcessor.js +37 -0
  23. package/lib/commonjs/getActionProcessor/core/file/getFileCopyActionProcessor.js.map +1 -0
  24. package/lib/commonjs/getActionProcessor/core/file/index.js +2 -1
  25. package/lib/commonjs/getActionProcessor/core/file/index.js.map +1 -1
  26. package/lib/commonjs/logic/dynamo/qpqDynamoOrm/getDynamoTableIndexByConfigAndQuery.d.ts +8 -0
  27. package/lib/commonjs/logic/dynamo/qpqDynamoOrm/getDynamoTableIndexByConfigAndQuery.js +10 -5
  28. package/lib/commonjs/logic/dynamo/qpqDynamoOrm/getDynamoTableIndexByConfigAndQuery.js.map +1 -1
  29. package/lib/commonjs/logic/kms/getCachedPublicKey.d.ts +1 -0
  30. package/lib/commonjs/logic/kms/getCachedPublicKey.js +45 -0
  31. package/lib/commonjs/logic/kms/getCachedPublicKey.js.map +1 -0
  32. package/lib/commonjs/logic/kms/signWithKey.d.ts +1 -0
  33. package/lib/commonjs/logic/kms/signWithKey.js +34 -0
  34. package/lib/commonjs/logic/kms/signWithKey.js.map +1 -0
  35. package/lib/commonjs/logic/s3/copyFile.d.ts +5 -0
  36. package/lib/commonjs/logic/s3/copyFile.js +31 -0
  37. package/lib/commonjs/logic/s3/copyFile.js.map +1 -0
  38. package/lib/commonjs/logic/s3/s3Utils.d.ts +1 -0
  39. package/lib/commonjs/logic/s3/s3Utils.js +1 -0
  40. package/lib/commonjs/logic/s3/s3Utils.js.map +1 -1
  41. package/lib/esm/getActionProcessor/core/crypto/getCryptoGetPublicKeyActionProcessor.d.ts +1 -0
  42. package/lib/esm/getActionProcessor/core/crypto/getCryptoGetPublicKeyActionProcessor.js +22 -0
  43. package/lib/esm/getActionProcessor/core/crypto/getCryptoGetPublicKeyActionProcessor.js.map +1 -0
  44. package/lib/esm/getActionProcessor/core/crypto/getCryptoSignActionProcessor.d.ts +1 -0
  45. package/lib/esm/getActionProcessor/core/crypto/getCryptoSignActionProcessor.js +24 -0
  46. package/lib/esm/getActionProcessor/core/crypto/getCryptoSignActionProcessor.js.map +1 -0
  47. package/lib/esm/getActionProcessor/core/crypto/getCryptoVerifyActionProcessor.d.ts +1 -0
  48. package/lib/esm/getActionProcessor/core/crypto/getCryptoVerifyActionProcessor.js +29 -0
  49. package/lib/esm/getActionProcessor/core/crypto/getCryptoVerifyActionProcessor.js.map +1 -0
  50. package/lib/esm/getActionProcessor/core/crypto/index.js +6 -0
  51. package/lib/esm/getActionProcessor/core/crypto/index.js.map +1 -1
  52. package/lib/esm/getActionProcessor/core/crypto/kmsSigningErrorMap.d.ts +13 -0
  53. package/lib/esm/getActionProcessor/core/crypto/kmsSigningErrorMap.js +12 -0
  54. package/lib/esm/getActionProcessor/core/crypto/kmsSigningErrorMap.js.map +1 -0
  55. package/lib/esm/getActionProcessor/core/crypto/utils/index.d.ts +1 -0
  56. package/lib/esm/getActionProcessor/core/crypto/utils/index.js +1 -0
  57. package/lib/esm/getActionProcessor/core/crypto/utils/index.js.map +1 -1
  58. package/lib/esm/getActionProcessor/core/crypto/utils/resolveSigningKeyAlias.d.ts +2 -0
  59. package/lib/esm/getActionProcessor/core/crypto/utils/resolveSigningKeyAlias.js +14 -0
  60. package/lib/esm/getActionProcessor/core/crypto/utils/resolveSigningKeyAlias.js.map +1 -0
  61. package/lib/esm/getActionProcessor/core/file/getFileCopyActionProcessor.d.ts +1 -0
  62. package/lib/esm/getActionProcessor/core/file/getFileCopyActionProcessor.js +25 -0
  63. package/lib/esm/getActionProcessor/core/file/getFileCopyActionProcessor.js.map +1 -0
  64. package/lib/esm/getActionProcessor/core/file/index.js +2 -0
  65. package/lib/esm/getActionProcessor/core/file/index.js.map +1 -1
  66. package/lib/esm/logic/dynamo/qpqDynamoOrm/getDynamoTableIndexByConfigAndQuery.d.ts +8 -0
  67. package/lib/esm/logic/dynamo/qpqDynamoOrm/getDynamoTableIndexByConfigAndQuery.js +10 -5
  68. package/lib/esm/logic/dynamo/qpqDynamoOrm/getDynamoTableIndexByConfigAndQuery.js.map +1 -1
  69. package/lib/esm/logic/kms/getCachedPublicKey.d.ts +1 -0
  70. package/lib/esm/logic/kms/getCachedPublicKey.js +32 -0
  71. package/lib/esm/logic/kms/getCachedPublicKey.js.map +1 -0
  72. package/lib/esm/logic/kms/signWithKey.d.ts +1 -0
  73. package/lib/esm/logic/kms/signWithKey.js +21 -0
  74. package/lib/esm/logic/kms/signWithKey.js.map +1 -0
  75. package/lib/esm/logic/s3/copyFile.d.ts +5 -0
  76. package/lib/esm/logic/s3/copyFile.js +18 -0
  77. package/lib/esm/logic/s3/copyFile.js.map +1 -0
  78. package/lib/esm/logic/s3/s3Utils.d.ts +1 -0
  79. package/lib/esm/logic/s3/s3Utils.js +1 -0
  80. package/lib/esm/logic/s3/s3Utils.js.map +1 -1
  81. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"s3Utils.js","sourceRoot":"","sources":["../../../../src/logic/s3/s3Utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oFAAoF;AACpF,8CAA8C;AAC9C,gDAA8B;AAC9B,+DAA6C;AAC7C,yDAAuC;AACvC,0DAAwC;AACxC,8CAA4B;AAC5B,iDAA+B;AAC/B,mDAAiC;AACjC,iDAA+B;AAC/B,oDAAkC;AAClC,kDAAgC","sourcesContent":["// The s3 folder's barrel (kept under its historical name: many processors and their\n// vi.mock calls point at 'logic/s3/s3Utils').\nexport * from './deleteFiles';\nexport * from './generatePresignedUploadUrl';\nexport * from './generatePresignedUrl';\nexport * from './getObjectStorageClass';\nexport * from './listFiles';\nexport * from './objectExists';\nexport * from './readBinaryFile';\nexport * from './readTextFile';\nexport * from './writeBinaryFile';\nexport * from './writeTextFile';\n"]}
1
+ {"version":3,"file":"s3Utils.js","sourceRoot":"","sources":["../../../../src/logic/s3/s3Utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oFAAoF;AACpF,8CAA8C;AAC9C,6CAA2B;AAC3B,gDAA8B;AAC9B,+DAA6C;AAC7C,yDAAuC;AACvC,0DAAwC;AACxC,8CAA4B;AAC5B,iDAA+B;AAC/B,mDAAiC;AACjC,iDAA+B;AAC/B,oDAAkC;AAClC,kDAAgC","sourcesContent":["// The s3 folder's barrel (kept under its historical name: many processors and their\n// vi.mock calls point at 'logic/s3/s3Utils').\nexport * from './copyFile';\nexport * from './deleteFiles';\nexport * from './generatePresignedUploadUrl';\nexport * from './generatePresignedUrl';\nexport * from './getObjectStorageClass';\nexport * from './listFiles';\nexport * from './objectExists';\nexport * from './readBinaryFile';\nexport * from './readTextFile';\nexport * from './writeBinaryFile';\nexport * from './writeTextFile';\n"]}
@@ -0,0 +1 @@
1
+ export declare const getCryptoGetPublicKeyActionProcessor: import("quidproquo-core").ActionProcessorListResolver;
@@ -0,0 +1,22 @@
1
+ import { qpqConfigAwsUtils } from 'quidproquo-config-aws';
2
+ import { actionResult, actionResultError, actionResultErrorFromCaughtError, askCryptoGetPublicKey, createActionProcessor, } from 'quidproquo-core';
3
+ import { getCachedPublicKey } from '../../../logic/kms/getCachedPublicKey';
4
+ import { kmsSigningErrorMap, signingKeyNotConfiguredMessage } from './kmsSigningErrorMap';
5
+ import { resolveSigningKeyAlias } from './utils';
6
+ const getProcessCryptoGetPublicKey = (qpqConfig) => {
7
+ return async ({ keyName }) => {
8
+ const keyAlias = resolveSigningKeyAlias(keyName, qpqConfig);
9
+ if (!keyAlias) {
10
+ return actionResultError(askCryptoGetPublicKey.errorType.KeyNotConfigured, signingKeyNotConfiguredMessage(keyName));
11
+ }
12
+ const region = qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig);
13
+ try {
14
+ return actionResult(await getCachedPublicKey(keyAlias, region));
15
+ }
16
+ catch (error) {
17
+ return actionResultErrorFromCaughtError(error, kmsSigningErrorMap(askCryptoGetPublicKey.errorType, keyName));
18
+ }
19
+ };
20
+ };
21
+ export const getCryptoGetPublicKeyActionProcessor = createActionProcessor(askCryptoGetPublicKey, getProcessCryptoGetPublicKey);
22
+ //# sourceMappingURL=getCryptoGetPublicKeyActionProcessor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getCryptoGetPublicKeyActionProcessor.js","sourceRoot":"","sources":["../../../../../src/getActionProcessor/core/crypto/getCryptoGetPublicKeyActionProcessor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,gCAAgC,EAChC,qBAAqB,EACrB,qBAAqB,GAGtB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,8BAA8B,EAAE,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAEjD,MAAM,4BAA4B,GAAG,CAAC,SAAoB,EAA8C,EAAE;IACxG,OAAO,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;QAC3B,MAAM,QAAQ,GAAG,sBAAsB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAC5D,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,iBAAiB,CAAC,qBAAqB,CAAC,SAAS,CAAC,gBAAgB,EAAE,8BAA8B,CAAC,OAAO,CAAC,CAAC,CAAC;QACtH,CAAC;QAED,MAAM,MAAM,GAAG,iBAAiB,CAAC,gCAAgC,CAAC,SAAS,CAAC,CAAC;QAE7E,IAAI,CAAC;YACH,OAAO,YAAY,CAAC,MAAM,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;QAClE,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,gCAAgC,CAAC,KAAK,EAAE,kBAAkB,CAAC,qBAAqB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;QAC/G,CAAC;IACH,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oCAAoC,GAAG,qBAAqB,CAAC,qBAAqB,EAAE,4BAA4B,CAAC,CAAC","sourcesContent":["import { qpqConfigAwsUtils } from 'quidproquo-config-aws';\nimport {\n actionResult,\n actionResultError,\n actionResultErrorFromCaughtError,\n askCryptoGetPublicKey,\n createActionProcessor,\n ProcessorFor,\n QPQConfig,\n} from 'quidproquo-core';\n\nimport { getCachedPublicKey } from '../../../logic/kms/getCachedPublicKey';\nimport { kmsSigningErrorMap, signingKeyNotConfiguredMessage } from './kmsSigningErrorMap';\nimport { resolveSigningKeyAlias } from './utils';\n\nconst getProcessCryptoGetPublicKey = (qpqConfig: QPQConfig): ProcessorFor<typeof askCryptoGetPublicKey> => {\n return async ({ keyName }) => {\n const keyAlias = resolveSigningKeyAlias(keyName, qpqConfig);\n if (!keyAlias) {\n return actionResultError(askCryptoGetPublicKey.errorType.KeyNotConfigured, signingKeyNotConfiguredMessage(keyName));\n }\n\n const region = qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig);\n\n try {\n return actionResult(await getCachedPublicKey(keyAlias, region));\n } catch (error: unknown) {\n return actionResultErrorFromCaughtError(error, kmsSigningErrorMap(askCryptoGetPublicKey.errorType, keyName));\n }\n };\n};\n\nexport const getCryptoGetPublicKeyActionProcessor = createActionProcessor(askCryptoGetPublicKey, getProcessCryptoGetPublicKey);\n"]}
@@ -0,0 +1 @@
1
+ export declare const getCryptoSignActionProcessor: import("quidproquo-core").ActionProcessorListResolver;
@@ -0,0 +1,24 @@
1
+ import { base64UrlEncode } from 'quidproquo-actionprocessor-node';
2
+ import { qpqConfigAwsUtils } from 'quidproquo-config-aws';
3
+ import { actionResult, actionResultError, actionResultErrorFromCaughtError, askCryptoSign, createActionProcessor, } from 'quidproquo-core';
4
+ import { signWithKey } from '../../../logic/kms/signWithKey';
5
+ import { kmsSigningErrorMap, signingKeyNotConfiguredMessage } from './kmsSigningErrorMap';
6
+ import { resolveSigningKeyAlias } from './utils';
7
+ const getProcessCryptoSign = (qpqConfig) => {
8
+ return async ({ keyName, message }) => {
9
+ const keyAlias = resolveSigningKeyAlias(keyName, qpqConfig);
10
+ if (!keyAlias) {
11
+ return actionResultError(askCryptoSign.errorType.KeyNotConfigured, signingKeyNotConfiguredMessage(keyName));
12
+ }
13
+ const region = qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig);
14
+ try {
15
+ const signature = await signWithKey(keyAlias, message, region);
16
+ return actionResult(base64UrlEncode(signature));
17
+ }
18
+ catch (error) {
19
+ return actionResultErrorFromCaughtError(error, kmsSigningErrorMap(askCryptoSign.errorType, keyName));
20
+ }
21
+ };
22
+ };
23
+ export const getCryptoSignActionProcessor = createActionProcessor(askCryptoSign, getProcessCryptoSign);
24
+ //# sourceMappingURL=getCryptoSignActionProcessor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getCryptoSignActionProcessor.js","sourceRoot":"","sources":["../../../../../src/getActionProcessor/core/crypto/getCryptoSignActionProcessor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,gCAAgC,EAChC,aAAa,EACb,qBAAqB,GAGtB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,8BAA8B,EAAE,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAEjD,MAAM,oBAAoB,GAAG,CAAC,SAAoB,EAAsC,EAAE;IACxF,OAAO,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE;QACpC,MAAM,QAAQ,GAAG,sBAAsB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAC5D,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,iBAAiB,CAAC,aAAa,CAAC,SAAS,CAAC,gBAAgB,EAAE,8BAA8B,CAAC,OAAO,CAAC,CAAC,CAAC;QAC9G,CAAC;QAED,MAAM,MAAM,GAAG,iBAAiB,CAAC,gCAAgC,CAAC,SAAS,CAAC,CAAC;QAE7E,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;YAC/D,OAAO,YAAY,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,gCAAgC,CAAC,KAAK,EAAE,kBAAkB,CAAC,aAAa,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;QACvG,CAAC;IACH,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,4BAA4B,GAAG,qBAAqB,CAAC,aAAa,EAAE,oBAAoB,CAAC,CAAC","sourcesContent":["import { base64UrlEncode } from 'quidproquo-actionprocessor-node';\nimport { qpqConfigAwsUtils } from 'quidproquo-config-aws';\nimport {\n actionResult,\n actionResultError,\n actionResultErrorFromCaughtError,\n askCryptoSign,\n createActionProcessor,\n ProcessorFor,\n QPQConfig,\n} from 'quidproquo-core';\n\nimport { signWithKey } from '../../../logic/kms/signWithKey';\nimport { kmsSigningErrorMap, signingKeyNotConfiguredMessage } from './kmsSigningErrorMap';\nimport { resolveSigningKeyAlias } from './utils';\n\nconst getProcessCryptoSign = (qpqConfig: QPQConfig): ProcessorFor<typeof askCryptoSign> => {\n return async ({ keyName, message }) => {\n const keyAlias = resolveSigningKeyAlias(keyName, qpqConfig);\n if (!keyAlias) {\n return actionResultError(askCryptoSign.errorType.KeyNotConfigured, signingKeyNotConfiguredMessage(keyName));\n }\n\n const region = qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig);\n\n try {\n const signature = await signWithKey(keyAlias, message, region);\n return actionResult(base64UrlEncode(signature));\n } catch (error: unknown) {\n return actionResultErrorFromCaughtError(error, kmsSigningErrorMap(askCryptoSign.errorType, keyName));\n }\n };\n};\n\nexport const getCryptoSignActionProcessor = createActionProcessor(askCryptoSign, getProcessCryptoSign);\n"]}
@@ -0,0 +1 @@
1
+ export declare const getCryptoVerifyActionProcessor: import("quidproquo-core").ActionProcessorListResolver;
@@ -0,0 +1,29 @@
1
+ import { rs256Verify } from 'quidproquo-actionprocessor-node';
2
+ import { qpqConfigAwsUtils } from 'quidproquo-config-aws';
3
+ import { actionResult, actionResultError, actionResultErrorFromCaughtError, askCryptoVerify, createActionProcessor, } from 'quidproquo-core';
4
+ import { getCachedPublicKey } from '../../../logic/kms/getCachedPublicKey';
5
+ import { kmsSigningErrorMap, signingKeyNotConfiguredMessage } from './kmsSigningErrorMap';
6
+ import { resolveSigningKeyAlias } from './utils';
7
+ // Verifies locally against the cached public key rather than calling kms:Verify,
8
+ // so the hot path (every authenticated request) costs no KMS round trip.
9
+ const getProcessCryptoVerify = (qpqConfig) => {
10
+ return async ({ keyName, message, signature }) => {
11
+ const keyAlias = resolveSigningKeyAlias(keyName, qpqConfig);
12
+ if (!keyAlias) {
13
+ return actionResultError(askCryptoVerify.errorType.KeyNotConfigured, signingKeyNotConfiguredMessage(keyName));
14
+ }
15
+ const region = qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig);
16
+ try {
17
+ const publicKeyPem = await getCachedPublicKey(keyAlias, region);
18
+ return actionResult(rs256Verify(publicKeyPem, message, signature));
19
+ }
20
+ catch (error) {
21
+ return actionResultErrorFromCaughtError(error, {
22
+ QpqSigningMalformedSignature: (e) => actionResultError(askCryptoVerify.errorType.MalformedSignature, e.message),
23
+ ...kmsSigningErrorMap(askCryptoVerify.errorType, keyName),
24
+ });
25
+ }
26
+ };
27
+ };
28
+ export const getCryptoVerifyActionProcessor = createActionProcessor(askCryptoVerify, getProcessCryptoVerify);
29
+ //# sourceMappingURL=getCryptoVerifyActionProcessor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getCryptoVerifyActionProcessor.js","sourceRoot":"","sources":["../../../../../src/getActionProcessor/core/crypto/getCryptoVerifyActionProcessor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,gCAAgC,EAChC,eAAe,EACf,qBAAqB,GAGtB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,8BAA8B,EAAE,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAEjD,iFAAiF;AACjF,yEAAyE;AACzE,MAAM,sBAAsB,GAAG,CAAC,SAAoB,EAAwC,EAAE;IAC5F,OAAO,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE;QAC/C,MAAM,QAAQ,GAAG,sBAAsB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAC5D,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,iBAAiB,CAAC,eAAe,CAAC,SAAS,CAAC,gBAAgB,EAAE,8BAA8B,CAAC,OAAO,CAAC,CAAC,CAAC;QAChH,CAAC;QAED,MAAM,MAAM,GAAG,iBAAiB,CAAC,gCAAgC,CAAC,SAAS,CAAC,CAAC;QAE7E,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAChE,OAAO,YAAY,CAAC,WAAW,CAAC,YAAY,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;QACrE,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,gCAAgC,CAAC,KAAK,EAAE;gBAC7C,4BAA4B,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,eAAe,CAAC,SAAS,CAAC,kBAAkB,EAAE,CAAC,CAAC,OAAO,CAAC;gBAC/G,GAAG,kBAAkB,CAAC,eAAe,CAAC,SAAS,EAAE,OAAO,CAAC;aAC1D,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,8BAA8B,GAAG,qBAAqB,CAAC,eAAe,EAAE,sBAAsB,CAAC,CAAC","sourcesContent":["import { rs256Verify } from 'quidproquo-actionprocessor-node';\nimport { qpqConfigAwsUtils } from 'quidproquo-config-aws';\nimport {\n actionResult,\n actionResultError,\n actionResultErrorFromCaughtError,\n askCryptoVerify,\n createActionProcessor,\n ProcessorFor,\n QPQConfig,\n} from 'quidproquo-core';\n\nimport { getCachedPublicKey } from '../../../logic/kms/getCachedPublicKey';\nimport { kmsSigningErrorMap, signingKeyNotConfiguredMessage } from './kmsSigningErrorMap';\nimport { resolveSigningKeyAlias } from './utils';\n\n// Verifies locally against the cached public key rather than calling kms:Verify,\n// so the hot path (every authenticated request) costs no KMS round trip.\nconst getProcessCryptoVerify = (qpqConfig: QPQConfig): ProcessorFor<typeof askCryptoVerify> => {\n return async ({ keyName, message, signature }) => {\n const keyAlias = resolveSigningKeyAlias(keyName, qpqConfig);\n if (!keyAlias) {\n return actionResultError(askCryptoVerify.errorType.KeyNotConfigured, signingKeyNotConfiguredMessage(keyName));\n }\n\n const region = qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig);\n\n try {\n const publicKeyPem = await getCachedPublicKey(keyAlias, region);\n return actionResult(rs256Verify(publicKeyPem, message, signature));\n } catch (error: unknown) {\n return actionResultErrorFromCaughtError(error, {\n QpqSigningMalformedSignature: (e) => actionResultError(askCryptoVerify.errorType.MalformedSignature, e.message),\n ...kmsSigningErrorMap(askCryptoVerify.errorType, keyName),\n });\n }\n };\n};\n\nexport const getCryptoVerifyActionProcessor = createActionProcessor(askCryptoVerify, getProcessCryptoVerify);\n"]}
@@ -1,7 +1,13 @@
1
1
  import { getCryptoDecryptActionProcessor } from './getCryptoDecryptActionProcessor';
2
2
  import { getCryptoEncryptActionProcessor } from './getCryptoEncryptActionProcessor';
3
+ import { getCryptoGetPublicKeyActionProcessor } from './getCryptoGetPublicKeyActionProcessor';
4
+ import { getCryptoSignActionProcessor } from './getCryptoSignActionProcessor';
5
+ import { getCryptoVerifyActionProcessor } from './getCryptoVerifyActionProcessor';
3
6
  export const getCryptoActionProcessor = async (qpqConfig, dynamicModuleLoader) => ({
4
7
  ...(await getCryptoEncryptActionProcessor(qpqConfig, dynamicModuleLoader)),
5
8
  ...(await getCryptoDecryptActionProcessor(qpqConfig, dynamicModuleLoader)),
9
+ ...(await getCryptoSignActionProcessor(qpqConfig, dynamicModuleLoader)),
10
+ ...(await getCryptoVerifyActionProcessor(qpqConfig, dynamicModuleLoader)),
11
+ ...(await getCryptoGetPublicKeyActionProcessor(qpqConfig, dynamicModuleLoader)),
6
12
  });
7
13
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/getActionProcessor/core/crypto/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,+BAA+B,EAAE,MAAM,mCAAmC,CAAC;AACpF,OAAO,EAAE,+BAA+B,EAAE,MAAM,mCAAmC,CAAC;AAEpF,MAAM,CAAC,MAAM,wBAAwB,GAAgC,KAAK,EACxE,SAAoB,EACpB,mBAAwC,EACV,EAAE,CAAC,CAAC;IAClC,GAAG,CAAC,MAAM,+BAA+B,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAC1E,GAAG,CAAC,MAAM,+BAA+B,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;CAC3E,CAAC,CAAC","sourcesContent":["import { ActionProcessorList, ActionProcessorListResolver, DynamicModuleLoader, QPQConfig } from 'quidproquo-core';\n\nimport { getCryptoDecryptActionProcessor } from './getCryptoDecryptActionProcessor';\nimport { getCryptoEncryptActionProcessor } from './getCryptoEncryptActionProcessor';\n\nexport const getCryptoActionProcessor: ActionProcessorListResolver = async (\n qpqConfig: QPQConfig,\n dynamicModuleLoader: DynamicModuleLoader,\n): Promise<ActionProcessorList> => ({\n ...(await getCryptoEncryptActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getCryptoDecryptActionProcessor(qpqConfig, dynamicModuleLoader)),\n});\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/getActionProcessor/core/crypto/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,+BAA+B,EAAE,MAAM,mCAAmC,CAAC;AACpF,OAAO,EAAE,+BAA+B,EAAE,MAAM,mCAAmC,CAAC;AACpF,OAAO,EAAE,oCAAoC,EAAE,MAAM,wCAAwC,CAAC;AAC9F,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,8BAA8B,EAAE,MAAM,kCAAkC,CAAC;AAElF,MAAM,CAAC,MAAM,wBAAwB,GAAgC,KAAK,EACxE,SAAoB,EACpB,mBAAwC,EACV,EAAE,CAAC,CAAC;IAClC,GAAG,CAAC,MAAM,+BAA+B,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAC1E,GAAG,CAAC,MAAM,+BAA+B,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAC1E,GAAG,CAAC,MAAM,4BAA4B,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IACvE,GAAG,CAAC,MAAM,8BAA8B,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IACzE,GAAG,CAAC,MAAM,oCAAoC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;CAChF,CAAC,CAAC","sourcesContent":["import { ActionProcessorList, ActionProcessorListResolver, DynamicModuleLoader, QPQConfig } from 'quidproquo-core';\n\nimport { getCryptoDecryptActionProcessor } from './getCryptoDecryptActionProcessor';\nimport { getCryptoEncryptActionProcessor } from './getCryptoEncryptActionProcessor';\nimport { getCryptoGetPublicKeyActionProcessor } from './getCryptoGetPublicKeyActionProcessor';\nimport { getCryptoSignActionProcessor } from './getCryptoSignActionProcessor';\nimport { getCryptoVerifyActionProcessor } from './getCryptoVerifyActionProcessor';\n\nexport const getCryptoActionProcessor: ActionProcessorListResolver = async (\n qpqConfig: QPQConfig,\n dynamicModuleLoader: DynamicModuleLoader,\n): Promise<ActionProcessorList> => ({\n ...(await getCryptoEncryptActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getCryptoDecryptActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getCryptoSignActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getCryptoVerifyActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getCryptoGetPublicKeyActionProcessor(qpqConfig, dynamicModuleLoader)),\n});\n"]}
@@ -0,0 +1,13 @@
1
+ type SigningErrorTypes = {
2
+ KeyUnavailable: string;
3
+ Throttling: string;
4
+ };
5
+ export declare const kmsSigningErrorMap: (errorType: SigningErrorTypes, keyName: string) => {
6
+ NotFoundException: () => import("quidproquo-core").ActionProcessorResult<any>;
7
+ DisabledException: () => import("quidproquo-core").ActionProcessorResult<any>;
8
+ KMSInvalidStateException: () => import("quidproquo-core").ActionProcessorResult<any>;
9
+ AccessDeniedException: () => import("quidproquo-core").ActionProcessorResult<any>;
10
+ ThrottlingException: () => import("quidproquo-core").ActionProcessorResult<any>;
11
+ };
12
+ export declare const signingKeyNotConfiguredMessage: (keyName: string) => string;
13
+ export {};
@@ -0,0 +1,12 @@
1
+ import { actionResultError } from 'quidproquo-core';
2
+ // The KMS exceptions every signing-key processor maps the same way, keyed by
3
+ // error.name as actionResultErrorFromCaughtError expects.
4
+ export const kmsSigningErrorMap = (errorType, keyName) => ({
5
+ NotFoundException: () => actionResultError(errorType.KeyUnavailable, `Signing key not found: [${keyName}]`),
6
+ DisabledException: () => actionResultError(errorType.KeyUnavailable, `Signing key is disabled: [${keyName}]`),
7
+ KMSInvalidStateException: () => actionResultError(errorType.KeyUnavailable, `Signing key is in an unusable state: [${keyName}]`),
8
+ AccessDeniedException: () => actionResultError(errorType.KeyUnavailable, `Access denied to signing key: [${keyName}]`),
9
+ ThrottlingException: () => actionResultError(errorType.Throttling, 'Throttling: Rate exceeded'),
10
+ });
11
+ export const signingKeyNotConfiguredMessage = (keyName) => `Signing key not configured: [${keyName}] - declare it with defineSigningKey`;
12
+ //# sourceMappingURL=kmsSigningErrorMap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kmsSigningErrorMap.js","sourceRoot":"","sources":["../../../../../src/getActionProcessor/core/crypto/kmsSigningErrorMap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAOpD,6EAA6E;AAC7E,0DAA0D;AAC1D,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,SAA4B,EAAE,OAAe,EAAE,EAAE,CAAC,CAAC;IACpF,iBAAiB,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,cAAc,EAAE,2BAA2B,OAAO,GAAG,CAAC;IAC3G,iBAAiB,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,cAAc,EAAE,6BAA6B,OAAO,GAAG,CAAC;IAC7G,wBAAwB,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,cAAc,EAAE,yCAAyC,OAAO,GAAG,CAAC;IAChI,qBAAqB,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,cAAc,EAAE,kCAAkC,OAAO,GAAG,CAAC;IACtH,mBAAmB,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,UAAU,EAAE,2BAA2B,CAAC;CAChG,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,gCAAgC,OAAO,sCAAsC,CAAC","sourcesContent":["import { actionResultError } from 'quidproquo-core';\n\ntype SigningErrorTypes = {\n KeyUnavailable: string;\n Throttling: string;\n};\n\n// The KMS exceptions every signing-key processor maps the same way, keyed by\n// error.name as actionResultErrorFromCaughtError expects.\nexport const kmsSigningErrorMap = (errorType: SigningErrorTypes, keyName: string) => ({\n NotFoundException: () => actionResultError(errorType.KeyUnavailable, `Signing key not found: [${keyName}]`),\n DisabledException: () => actionResultError(errorType.KeyUnavailable, `Signing key is disabled: [${keyName}]`),\n KMSInvalidStateException: () => actionResultError(errorType.KeyUnavailable, `Signing key is in an unusable state: [${keyName}]`),\n AccessDeniedException: () => actionResultError(errorType.KeyUnavailable, `Access denied to signing key: [${keyName}]`),\n ThrottlingException: () => actionResultError(errorType.Throttling, 'Throttling: Rate exceeded'),\n});\n\nexport const signingKeyNotConfiguredMessage = (keyName: string) => `Signing key not configured: [${keyName}] - declare it with defineSigningKey`;\n"]}
@@ -1,2 +1,3 @@
1
1
  export * from './createKmsDataKeyProvider';
2
2
  export * from './resolveCryptoKeyAlias';
3
+ export * from './resolveSigningKeyAlias';
@@ -1,3 +1,4 @@
1
1
  export * from './createKmsDataKeyProvider';
2
2
  export * from './resolveCryptoKeyAlias';
3
+ export * from './resolveSigningKeyAlias';
3
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/getActionProcessor/core/crypto/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC","sourcesContent":["export * from './createKmsDataKeyProvider';\nexport * from './resolveCryptoKeyAlias';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/getActionProcessor/core/crypto/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC","sourcesContent":["export * from './createKmsDataKeyProvider';\nexport * from './resolveCryptoKeyAlias';\nexport * from './resolveSigningKeyAlias';\n"]}
@@ -0,0 +1,2 @@
1
+ import { Nullable, QPQConfig } from 'quidproquo-core';
2
+ export declare const resolveSigningKeyAlias: (signingKeyName: string, qpqConfig: QPQConfig) => Nullable<string>;
@@ -0,0 +1,14 @@
1
+ import { qpqCoreUtils } from 'quidproquo-core';
2
+ import { getConfigRuntimeResourceNameFromConfigWithServiceOverride } from '../../../../awsNamingUtils';
3
+ // The signing-key twin of resolveCryptoKeyAlias: the deterministic KMS alias the
4
+ // CDK construct derives for a defineSigningKey, or null when none matches so
5
+ // processors can fail with KeyNotConfigured instead of a generic error.
6
+ export const resolveSigningKeyAlias = (signingKeyName, qpqConfig) => {
7
+ const signingKeyConfig = qpqCoreUtils.getAllSigningKeyConfigs(qpqConfig).find((k) => k.keyName === signingKeyName);
8
+ if (!signingKeyConfig) {
9
+ return null;
10
+ }
11
+ const resolvedName = getConfigRuntimeResourceNameFromConfigWithServiceOverride(signingKeyConfig.owner?.resourceNameOverride || signingKeyName, qpqConfig, signingKeyConfig.owner?.module);
12
+ return `alias/${resolvedName}`;
13
+ };
14
+ //# sourceMappingURL=resolveSigningKeyAlias.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveSigningKeyAlias.js","sourceRoot":"","sources":["../../../../../../src/getActionProcessor/core/crypto/utils/resolveSigningKeyAlias.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpE,OAAO,EAAE,yDAAyD,EAAE,MAAM,4BAA4B,CAAC;AAEvG,iFAAiF;AACjF,6EAA6E;AAC7E,wEAAwE;AACxE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,cAAsB,EAAE,SAAoB,EAAoB,EAAE;IACvG,MAAM,gBAAgB,GAAG,YAAY,CAAC,uBAAuB,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,cAAc,CAAC,CAAC;IAEnH,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,YAAY,GAAG,yDAAyD,CAC5E,gBAAgB,CAAC,KAAK,EAAE,oBAAoB,IAAI,cAAc,EAC9D,SAAS,EACT,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAC/B,CAAC;IAEF,OAAO,SAAS,YAAY,EAAE,CAAC;AACjC,CAAC,CAAC","sourcesContent":["import { Nullable, QPQConfig, qpqCoreUtils } from 'quidproquo-core';\n\nimport { getConfigRuntimeResourceNameFromConfigWithServiceOverride } from '../../../../awsNamingUtils';\n\n// The signing-key twin of resolveCryptoKeyAlias: the deterministic KMS alias the\n// CDK construct derives for a defineSigningKey, or null when none matches so\n// processors can fail with KeyNotConfigured instead of a generic error.\nexport const resolveSigningKeyAlias = (signingKeyName: string, qpqConfig: QPQConfig): Nullable<string> => {\n const signingKeyConfig = qpqCoreUtils.getAllSigningKeyConfigs(qpqConfig).find((k) => k.keyName === signingKeyName);\n\n if (!signingKeyConfig) {\n return null;\n }\n\n const resolvedName = getConfigRuntimeResourceNameFromConfigWithServiceOverride(\n signingKeyConfig.owner?.resourceNameOverride || signingKeyName,\n qpqConfig,\n signingKeyConfig.owner?.module,\n );\n\n return `alias/${resolvedName}`;\n};\n"]}
@@ -0,0 +1 @@
1
+ export declare const getFileCopyActionProcessor: import("quidproquo-core").ActionProcessorListResolver;
@@ -0,0 +1,25 @@
1
+ import { qpqConfigAwsUtils } from 'quidproquo-config-aws';
2
+ import { actionResult, actionResultError, actionResultErrorFromCaughtError, askFileCopy, composeScopedFilePath, createActionProcessor, } from 'quidproquo-core';
3
+ import { copyFile } from '../../../logic/s3/s3Utils';
4
+ import { resolveStorageDriveBucketName } from './utils';
5
+ const getProcessFileCopy = (qpqConfig) => {
6
+ return async ({ sourceDrive, sourceFilepath, targetDrive, targetFilepath, scope }) => {
7
+ try {
8
+ const sourceBucketName = resolveStorageDriveBucketName(sourceDrive, qpqConfig);
9
+ const targetBucketName = resolveStorageDriveBucketName(targetDrive, qpqConfig);
10
+ await copyFile(sourceBucketName, composeScopedFilePath(scope, sourceFilepath), targetBucketName, composeScopedFilePath(scope, targetFilepath), qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig));
11
+ return actionResult(void 0);
12
+ }
13
+ catch (error) {
14
+ return actionResultErrorFromCaughtError(error, {
15
+ AccessDenied: () => actionResultError(askFileCopy.errorType.AccessDenied, 'Access denied copying file'),
16
+ NoSuchBucket: () => actionResultError(askFileCopy.errorType.DriveNotFound, `Storage drive not found: ${sourceDrive} or ${targetDrive}`),
17
+ NoSuchKey: () => actionResultError(askFileCopy.errorType.FileNotFound, `File not found: ${sourceFilepath}`),
18
+ StorageDriveNotFoundError: (error) => actionResultError(askFileCopy.errorType.DriveNotFound, error.message),
19
+ InvalidScopeError: (error) => actionResultError(askFileCopy.errorType.InvalidScope, error.message),
20
+ });
21
+ }
22
+ };
23
+ };
24
+ export const getFileCopyActionProcessor = createActionProcessor(askFileCopy, getProcessFileCopy);
25
+ //# sourceMappingURL=getFileCopyActionProcessor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getFileCopyActionProcessor.js","sourceRoot":"","sources":["../../../../../src/getActionProcessor/core/file/getFileCopyActionProcessor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,gCAAgC,EAChC,WAAW,EACX,qBAAqB,EACrB,qBAAqB,GAItB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,6BAA6B,EAAE,MAAM,SAAS,CAAC;AAExD,MAAM,kBAAkB,GAAG,CAAC,SAAoB,EAAoC,EAAE;IACpF,OAAO,KAAK,EAAE,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc,EAAE,KAAK,EAAE,EAAE,EAAE;QACnF,IAAI,CAAC;YACH,MAAM,gBAAgB,GAAG,6BAA6B,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;YAC/E,MAAM,gBAAgB,GAAG,6BAA6B,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;YAE/E,MAAM,QAAQ,CACZ,gBAAgB,EAChB,qBAAqB,CAAC,KAAK,EAAE,cAAc,CAAC,EAC5C,gBAAgB,EAChB,qBAAqB,CAAC,KAAK,EAAE,cAAc,CAAC,EAC5C,iBAAiB,CAAC,gCAAgC,CAAC,SAAS,CAAC,CAC9D,CAAC;YAEF,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,gCAAgC,CAAC,KAAK,EAAE;gBAC7C,YAAY,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,WAAW,CAAC,SAAS,CAAC,YAAY,EAAE,4BAA4B,CAAC;gBACvG,YAAY,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,WAAW,CAAC,SAAS,CAAC,aAAa,EAAE,4BAA4B,WAAW,OAAO,WAAW,EAAE,CAAC;gBACvI,SAAS,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,WAAW,CAAC,SAAS,CAAC,YAAY,EAAE,mBAAmB,cAAc,EAAE,CAAC;gBAC3G,yBAAyB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,WAAW,CAAC,SAAS,CAAC,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC;gBAC3G,iBAAiB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,WAAW,CAAC,SAAS,CAAC,YAAY,EAAE,KAAK,CAAC,OAAO,CAAC;aACnG,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,0BAA0B,GAAG,qBAAqB,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC","sourcesContent":["import { qpqConfigAwsUtils } from 'quidproquo-config-aws';\nimport {\n actionResult,\n actionResultError,\n actionResultErrorFromCaughtError,\n askFileCopy,\n composeScopedFilePath,\n createActionProcessor,\n FileActionType,\n ProcessorFor,\n QPQConfig,\n} from 'quidproquo-core';\n\nimport { copyFile } from '../../../logic/s3/s3Utils';\nimport { resolveStorageDriveBucketName } from './utils';\n\nconst getProcessFileCopy = (qpqConfig: QPQConfig): ProcessorFor<typeof askFileCopy> => {\n return async ({ sourceDrive, sourceFilepath, targetDrive, targetFilepath, scope }) => {\n try {\n const sourceBucketName = resolveStorageDriveBucketName(sourceDrive, qpqConfig);\n const targetBucketName = resolveStorageDriveBucketName(targetDrive, qpqConfig);\n\n await copyFile(\n sourceBucketName,\n composeScopedFilePath(scope, sourceFilepath),\n targetBucketName,\n composeScopedFilePath(scope, targetFilepath),\n qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig),\n );\n\n return actionResult(void 0);\n } catch (error: unknown) {\n return actionResultErrorFromCaughtError(error, {\n AccessDenied: () => actionResultError(askFileCopy.errorType.AccessDenied, 'Access denied copying file'),\n NoSuchBucket: () => actionResultError(askFileCopy.errorType.DriveNotFound, `Storage drive not found: ${sourceDrive} or ${targetDrive}`),\n NoSuchKey: () => actionResultError(askFileCopy.errorType.FileNotFound, `File not found: ${sourceFilepath}`),\n StorageDriveNotFoundError: (error) => actionResultError(askFileCopy.errorType.DriveNotFound, error.message),\n InvalidScopeError: (error) => actionResultError(askFileCopy.errorType.InvalidScope, error.message),\n });\n }\n };\n};\n\nexport const getFileCopyActionProcessor = createActionProcessor(askFileCopy, getProcessFileCopy);\n"]}
@@ -1,3 +1,4 @@
1
+ import { getFileCopyActionProcessor } from './getFileCopyActionProcessor';
1
2
  import { getFileDeleteActionProcessor } from './getFileDeleteActionProcessor';
2
3
  import { getFileExistsActionProcessor } from './getFileExistsActionProcessor';
3
4
  import { getFileGenerateTemporarySecureUrlActionProcessor } from './getFileGenerateTemporarySecureUrlActionProcessor';
@@ -12,6 +13,7 @@ import { getFileWriteBinaryContentsActionProcessor } from './getFileWriteBinaryC
12
13
  import { getFileWriteObjectJsonActionProcessor } from './getFileWriteObjectJsonActionProcessor';
13
14
  import { getFileWriteTextContentsActionProcessor } from './getFileWriteTextContentsActionProcessor';
14
15
  export const getFileActionProcessor = async (qpqConfig, dynamicModuleLoader) => ({
16
+ ...(await getFileCopyActionProcessor(qpqConfig, dynamicModuleLoader)),
15
17
  ...(await getFileDeleteActionProcessor(qpqConfig, dynamicModuleLoader)),
16
18
  ...(await getFileExistsActionProcessor(qpqConfig, dynamicModuleLoader)),
17
19
  ...(await getFileGenerateTemporarySecureUrlActionProcessor(qpqConfig, dynamicModuleLoader)),
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/getActionProcessor/core/file/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,gDAAgD,EAAE,MAAM,oDAAoD,CAAC;AACtH,OAAO,EAAE,sDAAsD,EAAE,MAAM,0DAA0D,CAAC;AAClI,OAAO,EAAE,mCAAmC,EAAE,MAAM,uCAAuC,CAAC;AAC5F,OAAO,EAAE,mCAAmC,EAAE,MAAM,uCAAuC,CAAC;AAC5F,OAAO,EAAE,wCAAwC,EAAE,MAAM,4CAA4C,CAAC;AACtG,OAAO,EAAE,oCAAoC,EAAE,MAAM,wCAAwC,CAAC;AAC9F,OAAO,EAAE,sCAAsC,EAAE,MAAM,0CAA0C,CAAC;AAClG,OAAO,EAAE,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,EAAE,yCAAyC,EAAE,MAAM,6CAA6C,CAAC;AACxG,OAAO,EAAE,qCAAqC,EAAE,MAAM,yCAAyC,CAAC;AAChG,OAAO,EAAE,uCAAuC,EAAE,MAAM,2CAA2C,CAAC;AAEpG,MAAM,CAAC,MAAM,sBAAsB,GAAgC,KAAK,EACtE,SAAoB,EACpB,mBAAwC,EACV,EAAE,CAAC,CAAC;IAClC,GAAG,CAAC,MAAM,4BAA4B,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IACvE,GAAG,CAAC,MAAM,4BAA4B,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IACvE,GAAG,CAAC,MAAM,gDAAgD,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAC3F,GAAG,CAAC,MAAM,sDAAsD,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IACjG,GAAG,CAAC,MAAM,mCAAmC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAC9E,GAAG,CAAC,MAAM,mCAAmC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAC9E,GAAG,CAAC,MAAM,sCAAsC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IACjF,GAAG,CAAC,MAAM,oCAAoC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAC/E,GAAG,CAAC,MAAM,uCAAuC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAClF,GAAG,CAAC,MAAM,wCAAwC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IACnF,GAAG,CAAC,MAAM,qCAAqC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAChF,GAAG,CAAC,MAAM,yCAAyC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IACpF,GAAG,CAAC,MAAM,gCAAgC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;CAC5E,CAAC,CAAC","sourcesContent":["import { ActionProcessorList, ActionProcessorListResolver, DynamicModuleLoader, QPQConfig } from 'quidproquo-core';\n\nimport { getFileDeleteActionProcessor } from './getFileDeleteActionProcessor';\nimport { getFileExistsActionProcessor } from './getFileExistsActionProcessor';\nimport { getFileGenerateTemporarySecureUrlActionProcessor } from './getFileGenerateTemporarySecureUrlActionProcessor';\nimport { getFileGenerateTemporaryUploadSecureUrlActionProcessor } from './getFileGenerateTemporaryUploadSecureUrlActionProcessor';\nimport { getFileIsColdStorageActionProcessor } from './getFileIsColdStorageActionProcessor';\nimport { getFileListDirectoryActionProcessor } from './getFileListDirectoryActionProcessor';\nimport { getFileReadBinaryContentsActionProcessor } from './getFileReadBinaryContentsActionProcessor';\nimport { getFileReadObjectJsonActionProcessor } from './getFileReadObjectJsonActionProcessor';\nimport { getFileReadTextContentsActionProcessor } from './getFileReadTextContentsActionProcessor';\nimport { getFileStreamOpenActionProcessor } from './getFileStreamOpenActionProcessor';\nimport { getFileWriteBinaryContentsActionProcessor } from './getFileWriteBinaryContentsActionProcessor';\nimport { getFileWriteObjectJsonActionProcessor } from './getFileWriteObjectJsonActionProcessor';\nimport { getFileWriteTextContentsActionProcessor } from './getFileWriteTextContentsActionProcessor';\n\nexport const getFileActionProcessor: ActionProcessorListResolver = async (\n qpqConfig: QPQConfig,\n dynamicModuleLoader: DynamicModuleLoader,\n): Promise<ActionProcessorList> => ({\n ...(await getFileDeleteActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileExistsActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileGenerateTemporarySecureUrlActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileGenerateTemporaryUploadSecureUrlActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileIsColdStorageActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileListDirectoryActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileReadTextContentsActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileReadObjectJsonActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileWriteTextContentsActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileReadBinaryContentsActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileWriteObjectJsonActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileWriteBinaryContentsActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileStreamOpenActionProcessor(qpqConfig, dynamicModuleLoader)),\n});\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/getActionProcessor/core/file/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,gDAAgD,EAAE,MAAM,oDAAoD,CAAC;AACtH,OAAO,EAAE,sDAAsD,EAAE,MAAM,0DAA0D,CAAC;AAClI,OAAO,EAAE,mCAAmC,EAAE,MAAM,uCAAuC,CAAC;AAC5F,OAAO,EAAE,mCAAmC,EAAE,MAAM,uCAAuC,CAAC;AAC5F,OAAO,EAAE,wCAAwC,EAAE,MAAM,4CAA4C,CAAC;AACtG,OAAO,EAAE,oCAAoC,EAAE,MAAM,wCAAwC,CAAC;AAC9F,OAAO,EAAE,sCAAsC,EAAE,MAAM,0CAA0C,CAAC;AAClG,OAAO,EAAE,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,EAAE,yCAAyC,EAAE,MAAM,6CAA6C,CAAC;AACxG,OAAO,EAAE,qCAAqC,EAAE,MAAM,yCAAyC,CAAC;AAChG,OAAO,EAAE,uCAAuC,EAAE,MAAM,2CAA2C,CAAC;AAEpG,MAAM,CAAC,MAAM,sBAAsB,GAAgC,KAAK,EACtE,SAAoB,EACpB,mBAAwC,EACV,EAAE,CAAC,CAAC;IAClC,GAAG,CAAC,MAAM,0BAA0B,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IACrE,GAAG,CAAC,MAAM,4BAA4B,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IACvE,GAAG,CAAC,MAAM,4BAA4B,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IACvE,GAAG,CAAC,MAAM,gDAAgD,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAC3F,GAAG,CAAC,MAAM,sDAAsD,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IACjG,GAAG,CAAC,MAAM,mCAAmC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAC9E,GAAG,CAAC,MAAM,mCAAmC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAC9E,GAAG,CAAC,MAAM,sCAAsC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IACjF,GAAG,CAAC,MAAM,oCAAoC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAC/E,GAAG,CAAC,MAAM,uCAAuC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAClF,GAAG,CAAC,MAAM,wCAAwC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IACnF,GAAG,CAAC,MAAM,qCAAqC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAChF,GAAG,CAAC,MAAM,yCAAyC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IACpF,GAAG,CAAC,MAAM,gCAAgC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;CAC5E,CAAC,CAAC","sourcesContent":["import { ActionProcessorList, ActionProcessorListResolver, DynamicModuleLoader, QPQConfig } from 'quidproquo-core';\n\nimport { getFileCopyActionProcessor } from './getFileCopyActionProcessor';\nimport { getFileDeleteActionProcessor } from './getFileDeleteActionProcessor';\nimport { getFileExistsActionProcessor } from './getFileExistsActionProcessor';\nimport { getFileGenerateTemporarySecureUrlActionProcessor } from './getFileGenerateTemporarySecureUrlActionProcessor';\nimport { getFileGenerateTemporaryUploadSecureUrlActionProcessor } from './getFileGenerateTemporaryUploadSecureUrlActionProcessor';\nimport { getFileIsColdStorageActionProcessor } from './getFileIsColdStorageActionProcessor';\nimport { getFileListDirectoryActionProcessor } from './getFileListDirectoryActionProcessor';\nimport { getFileReadBinaryContentsActionProcessor } from './getFileReadBinaryContentsActionProcessor';\nimport { getFileReadObjectJsonActionProcessor } from './getFileReadObjectJsonActionProcessor';\nimport { getFileReadTextContentsActionProcessor } from './getFileReadTextContentsActionProcessor';\nimport { getFileStreamOpenActionProcessor } from './getFileStreamOpenActionProcessor';\nimport { getFileWriteBinaryContentsActionProcessor } from './getFileWriteBinaryContentsActionProcessor';\nimport { getFileWriteObjectJsonActionProcessor } from './getFileWriteObjectJsonActionProcessor';\nimport { getFileWriteTextContentsActionProcessor } from './getFileWriteTextContentsActionProcessor';\n\nexport const getFileActionProcessor: ActionProcessorListResolver = async (\n qpqConfig: QPQConfig,\n dynamicModuleLoader: DynamicModuleLoader,\n): Promise<ActionProcessorList> => ({\n ...(await getFileCopyActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileDeleteActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileExistsActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileGenerateTemporarySecureUrlActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileGenerateTemporaryUploadSecureUrlActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileIsColdStorageActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileListDirectoryActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileReadTextContentsActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileReadObjectJsonActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileWriteTextContentsActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileReadBinaryContentsActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileWriteObjectJsonActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileWriteBinaryContentsActionProcessor(qpqConfig, dynamicModuleLoader)),\n ...(await getFileStreamOpenActionProcessor(qpqConfig, dynamicModuleLoader)),\n});\n"]}
@@ -3,5 +3,13 @@ import { KeyValueStoreQPQConfigSetting, KvsQueryOperation, Nullable } from 'quid
3
3
  * Pick the GSI that can serve the query, or null to query the primary table.
4
4
  * Returns the GSI's partition key name, which is also its index name (the CDK
5
5
  * construct names each GSI after its partition key).
6
+ *
7
+ * A Query MUST constrain the partition key of whatever it runs against. So: if
8
+ * the query names the primary partition key, the primary table can serve it
9
+ * (strongly consistent, and its sort key is available) - prefer it over any GSI.
10
+ * Otherwise route to the GSI whose partition key the query names. Deciding on
11
+ * the primary SORT key instead is wrong: a GSI commonly has the primary sort key
12
+ * as its partition key (pk userId / sk tenantId with a GSI on tenantId), and a
13
+ * query on that key alone can only be served by the GSI.
6
14
  */
7
15
  export declare const getDynamoTableIndexByConfigAndQuery: (setting: KeyValueStoreQPQConfigSetting, query: KvsQueryOperation) => Nullable<string>;
@@ -3,14 +3,19 @@ import { flattenKvsQueryConditions } from './flattenKvsQueryConditions';
3
3
  * Pick the GSI that can serve the query, or null to query the primary table.
4
4
  * Returns the GSI's partition key name, which is also its index name (the CDK
5
5
  * construct names each GSI after its partition key).
6
+ *
7
+ * A Query MUST constrain the partition key of whatever it runs against. So: if
8
+ * the query names the primary partition key, the primary table can serve it
9
+ * (strongly consistent, and its sort key is available) - prefer it over any GSI.
10
+ * Otherwise route to the GSI whose partition key the query names. Deciding on
11
+ * the primary SORT key instead is wrong: a GSI commonly has the primary sort key
12
+ * as its partition key (pk userId / sk tenantId with a GSI on tenantId), and a
13
+ * query on that key alone can only be served by the GSI.
6
14
  */
7
15
  export const getDynamoTableIndexByConfigAndQuery = (setting, query) => {
8
16
  const queriedKeys = flattenKvsQueryConditions(query).map((condition) => condition.key);
9
- // If the query includes the primary sort key, the primary table is a direct
10
- // match: prefer it over any GSI so we never land on a GSI with a non-SK
11
- // condition.
12
- const primarySortKey = setting.sortKeys[0]?.key;
13
- if (primarySortKey && queriedKeys.includes(primarySortKey)) {
17
+ const primaryPartitionKey = setting.partitionKey?.key;
18
+ if (primaryPartitionKey && queriedKeys.includes(primaryPartitionKey)) {
14
19
  return null;
15
20
  }
16
21
  const matchingIndex = setting.indexes.find((index) => queriedKeys.includes(index.partitionKey.key));
@@ -1 +1 @@
1
- {"version":3,"file":"getDynamoTableIndexByConfigAndQuery.js","sourceRoot":"","sources":["../../../../../src/logic/dynamo/qpqDynamoOrm/getDynamoTableIndexByConfigAndQuery.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAExE;;;;GAIG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAG,CAAC,OAAsC,EAAE,KAAwB,EAAoB,EAAE;IACxI,MAAM,WAAW,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAEvF,4EAA4E;IAC5E,wEAAwE;IACxE,aAAa;IACb,MAAM,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC;IAChD,IAAI,cAAc,IAAI,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;QAC3D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;IAEpG,OAAO,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/D,CAAC,CAAC","sourcesContent":["import { KeyValueStoreQPQConfigSetting, KvsQueryOperation, Nullable } from 'quidproquo-core';\n\nimport { flattenKvsQueryConditions } from './flattenKvsQueryConditions';\n\n/**\n * Pick the GSI that can serve the query, or null to query the primary table.\n * Returns the GSI's partition key name, which is also its index name (the CDK\n * construct names each GSI after its partition key).\n */\nexport const getDynamoTableIndexByConfigAndQuery = (setting: KeyValueStoreQPQConfigSetting, query: KvsQueryOperation): Nullable<string> => {\n const queriedKeys = flattenKvsQueryConditions(query).map((condition) => condition.key);\n\n // If the query includes the primary sort key, the primary table is a direct\n // match: prefer it over any GSI so we never land on a GSI with a non-SK\n // condition.\n const primarySortKey = setting.sortKeys[0]?.key;\n if (primarySortKey && queriedKeys.includes(primarySortKey)) {\n return null;\n }\n\n const matchingIndex = setting.indexes.find((index) => queriedKeys.includes(index.partitionKey.key));\n\n return matchingIndex ? matchingIndex.partitionKey.key : null;\n};\n"]}
1
+ {"version":3,"file":"getDynamoTableIndexByConfigAndQuery.js","sourceRoot":"","sources":["../../../../../src/logic/dynamo/qpqDynamoOrm/getDynamoTableIndexByConfigAndQuery.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAExE;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAG,CAAC,OAAsC,EAAE,KAAwB,EAAoB,EAAE;IACxI,MAAM,WAAW,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAEvF,MAAM,mBAAmB,GAAG,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC;IACtD,IAAI,mBAAmB,IAAI,WAAW,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACrE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;IAEpG,OAAO,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/D,CAAC,CAAC","sourcesContent":["import { KeyValueStoreQPQConfigSetting, KvsQueryOperation, Nullable } from 'quidproquo-core';\n\nimport { flattenKvsQueryConditions } from './flattenKvsQueryConditions';\n\n/**\n * Pick the GSI that can serve the query, or null to query the primary table.\n * Returns the GSI's partition key name, which is also its index name (the CDK\n * construct names each GSI after its partition key).\n *\n * A Query MUST constrain the partition key of whatever it runs against. So: if\n * the query names the primary partition key, the primary table can serve it\n * (strongly consistent, and its sort key is available) - prefer it over any GSI.\n * Otherwise route to the GSI whose partition key the query names. Deciding on\n * the primary SORT key instead is wrong: a GSI commonly has the primary sort key\n * as its partition key (pk userId / sk tenantId with a GSI on tenantId), and a\n * query on that key alone can only be served by the GSI.\n */\nexport const getDynamoTableIndexByConfigAndQuery = (setting: KeyValueStoreQPQConfigSetting, query: KvsQueryOperation): Nullable<string> => {\n const queriedKeys = flattenKvsQueryConditions(query).map((condition) => condition.key);\n\n const primaryPartitionKey = setting.partitionKey?.key;\n if (primaryPartitionKey && queriedKeys.includes(primaryPartitionKey)) {\n return null;\n }\n\n const matchingIndex = setting.indexes.find((index) => queriedKeys.includes(index.partitionKey.key));\n\n return matchingIndex ? matchingIndex.partitionKey.key : null;\n};\n"]}
@@ -0,0 +1 @@
1
+ export declare const getCachedPublicKey: (keyAlias: string, region: string) => Promise<string>;
@@ -0,0 +1,32 @@
1
+ import { spkiDerToPem } from 'quidproquo-actionprocessor-node';
2
+ import { GetPublicKeyCommand, KMSClient } from '@aws-sdk/client-kms';
3
+ import { createAwsClient } from '../createAwsClient';
4
+ // The public half of a signing key is immutable for the life of the key, so it is
5
+ // fetched once per alias per runtime and verification runs locally from then on:
6
+ // askCryptoVerify costs no KMS call after warm-up, and needs no kms:Verify grant.
7
+ // Bounded by age only so a key replaced under the same alias is picked up.
8
+ const PUBLIC_KEY_MAX_AGE_MS = 60 * 60 * 1000;
9
+ const cache = new Map();
10
+ export const getCachedPublicKey = async (keyAlias, region) => {
11
+ const cacheKey = `${region}|${keyAlias}`;
12
+ const cached = cache.get(cacheKey);
13
+ if (cached && cached.expiresAt > Date.now()) {
14
+ return cached.publicKeyPem;
15
+ }
16
+ const kmsClient = createAwsClient(KMSClient, {
17
+ region,
18
+ });
19
+ const response = await kmsClient.send(new GetPublicKeyCommand({
20
+ KeyId: keyAlias,
21
+ }));
22
+ if (!response.PublicKey) {
23
+ throw new Error(`KMS returned no public key for [${keyAlias}]`);
24
+ }
25
+ const publicKeyPem = spkiDerToPem(Buffer.from(response.PublicKey));
26
+ cache.set(cacheKey, {
27
+ publicKeyPem,
28
+ expiresAt: Date.now() + PUBLIC_KEY_MAX_AGE_MS,
29
+ });
30
+ return publicKeyPem;
31
+ };
32
+ //# sourceMappingURL=getCachedPublicKey.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getCachedPublicKey.js","sourceRoot":"","sources":["../../../../src/logic/kms/getCachedPublicKey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAE/D,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,kFAAkF;AAClF,iFAAiF;AACjF,kFAAkF;AAClF,2EAA2E;AAC3E,MAAM,qBAAqB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAO7C,MAAM,KAAK,GAAG,IAAI,GAAG,EAA2B,CAAC;AAEjD,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,EAAE,QAAgB,EAAE,MAAc,EAAmB,EAAE;IAC5F,MAAM,QAAQ,GAAG,GAAG,MAAM,IAAI,QAAQ,EAAE,CAAC;IAEzC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,MAAM,IAAI,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QAC5C,OAAO,MAAM,CAAC,YAAY,CAAC;IAC7B,CAAC;IAED,MAAM,SAAS,GAAG,eAAe,CAAC,SAAS,EAAE;QAC3C,MAAM;KACP,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,IAAI,CACnC,IAAI,mBAAmB,CAAC;QACtB,KAAK,EAAE,QAAQ;KAChB,CAAC,CACH,CAAC;IAEF,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,mCAAmC,QAAQ,GAAG,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,YAAY,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;IAEnE,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE;QAClB,YAAY;QACZ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,qBAAqB;KAC9C,CAAC,CAAC;IAEH,OAAO,YAAY,CAAC;AACtB,CAAC,CAAC","sourcesContent":["import { spkiDerToPem } from 'quidproquo-actionprocessor-node';\n\nimport { GetPublicKeyCommand, KMSClient } from '@aws-sdk/client-kms';\n\nimport { createAwsClient } from '../createAwsClient';\n\n// The public half of a signing key is immutable for the life of the key, so it is\n// fetched once per alias per runtime and verification runs locally from then on:\n// askCryptoVerify costs no KMS call after warm-up, and needs no kms:Verify grant.\n// Bounded by age only so a key replaced under the same alias is picked up.\nconst PUBLIC_KEY_MAX_AGE_MS = 60 * 60 * 1000;\n\ntype CachedPublicKey = {\n publicKeyPem: string;\n expiresAt: number;\n};\n\nconst cache = new Map<string, CachedPublicKey>();\n\nexport const getCachedPublicKey = async (keyAlias: string, region: string): Promise<string> => {\n const cacheKey = `${region}|${keyAlias}`;\n\n const cached = cache.get(cacheKey);\n if (cached && cached.expiresAt > Date.now()) {\n return cached.publicKeyPem;\n }\n\n const kmsClient = createAwsClient(KMSClient, {\n region,\n });\n\n const response = await kmsClient.send(\n new GetPublicKeyCommand({\n KeyId: keyAlias,\n }),\n );\n\n if (!response.PublicKey) {\n throw new Error(`KMS returned no public key for [${keyAlias}]`);\n }\n\n const publicKeyPem = spkiDerToPem(Buffer.from(response.PublicKey));\n\n cache.set(cacheKey, {\n publicKeyPem,\n expiresAt: Date.now() + PUBLIC_KEY_MAX_AGE_MS,\n });\n\n return publicKeyPem;\n};\n"]}
@@ -0,0 +1 @@
1
+ export declare const signWithKey: (keyAlias: string, message: string, region: string) => Promise<Buffer>;
@@ -0,0 +1,21 @@
1
+ import { RS256_KMS_SIGNING_ALGORITHM } from 'quidproquo-actionprocessor-node';
2
+ import { KMSClient, SignCommand } from '@aws-sdk/client-kms';
3
+ import { createAwsClient } from '../createAwsClient';
4
+ // One kms:Sign per call: the private key never leaves KMS, so there is nothing
5
+ // to cache here. Returns the raw signature bytes.
6
+ export const signWithKey = async (keyAlias, message, region) => {
7
+ const kmsClient = createAwsClient(KMSClient, {
8
+ region,
9
+ });
10
+ const response = await kmsClient.send(new SignCommand({
11
+ KeyId: keyAlias,
12
+ Message: Buffer.from(message, 'utf8'),
13
+ MessageType: 'RAW',
14
+ SigningAlgorithm: RS256_KMS_SIGNING_ALGORITHM,
15
+ }));
16
+ if (!response.Signature) {
17
+ throw new Error(`KMS returned no signature for [${keyAlias}]`);
18
+ }
19
+ return Buffer.from(response.Signature);
20
+ };
21
+ //# sourceMappingURL=signWithKey.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signWithKey.js","sourceRoot":"","sources":["../../../../src/logic/kms/signWithKey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAE9E,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAE7D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,+EAA+E;AAC/E,kDAAkD;AAClD,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,QAAgB,EAAE,OAAe,EAAE,MAAc,EAAmB,EAAE;IACtG,MAAM,SAAS,GAAG,eAAe,CAAC,SAAS,EAAE;QAC3C,MAAM;KACP,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,IAAI,CACnC,IAAI,WAAW,CAAC;QACd,KAAK,EAAE,QAAQ;QACf,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC;QACrC,WAAW,EAAE,KAAK;QAClB,gBAAgB,EAAE,2BAA2B;KAC9C,CAAC,CACH,CAAC;IAEF,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,kCAAkC,QAAQ,GAAG,CAAC,CAAC;IACjE,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AACzC,CAAC,CAAC","sourcesContent":["import { RS256_KMS_SIGNING_ALGORITHM } from 'quidproquo-actionprocessor-node';\n\nimport { KMSClient, SignCommand } from '@aws-sdk/client-kms';\n\nimport { createAwsClient } from '../createAwsClient';\n\n// One kms:Sign per call: the private key never leaves KMS, so there is nothing\n// to cache here. Returns the raw signature bytes.\nexport const signWithKey = async (keyAlias: string, message: string, region: string): Promise<Buffer> => {\n const kmsClient = createAwsClient(KMSClient, {\n region,\n });\n\n const response = await kmsClient.send(\n new SignCommand({\n KeyId: keyAlias,\n Message: Buffer.from(message, 'utf8'),\n MessageType: 'RAW',\n SigningAlgorithm: RS256_KMS_SIGNING_ALGORITHM,\n }),\n );\n\n if (!response.Signature) {\n throw new Error(`KMS returned no signature for [${keyAlias}]`);\n }\n\n return Buffer.from(response.Signature);\n};\n"]}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Server-side copies one object to another key (same or another bucket). The default COPY metadata
3
+ * directive carries the stored Content-Type / Content-Disposition across unchanged.
4
+ */
5
+ export declare const copyFile: (sourceBucketName: string, sourceKey: string, targetBucketName: string, targetKey: string, region: string) => Promise<void>;
@@ -0,0 +1,18 @@
1
+ import { CopyObjectCommand, S3Client } from '@aws-sdk/client-s3';
2
+ import { createAwsClient } from '../createAwsClient';
3
+ // CopySource is a URL path, so each key segment is percent-encoded (a key can hold spaces, '+', '#'...);
4
+ // the '/' between segments stays a separator.
5
+ const encodeCopySource = (bucketName, key) => `${bucketName}/${key.split('/').map(encodeURIComponent).join('/')}`;
6
+ /**
7
+ * Server-side copies one object to another key (same or another bucket). The default COPY metadata
8
+ * directive carries the stored Content-Type / Content-Disposition across unchanged.
9
+ */
10
+ export const copyFile = async (sourceBucketName, sourceKey, targetBucketName, targetKey, region) => {
11
+ const s3Client = createAwsClient(S3Client, { region });
12
+ await s3Client.send(new CopyObjectCommand({
13
+ CopySource: encodeCopySource(sourceBucketName, sourceKey),
14
+ Bucket: targetBucketName,
15
+ Key: targetKey,
16
+ }));
17
+ };
18
+ //# sourceMappingURL=copyFile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copyFile.js","sourceRoot":"","sources":["../../../../src/logic/s3/copyFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEjE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,yGAAyG;AACzG,8CAA8C;AAC9C,MAAM,gBAAgB,GAAG,CAAC,UAAkB,EAAE,GAAW,EAAU,EAAE,CAAC,GAAG,UAAU,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AAE1I;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,EAC3B,gBAAwB,EACxB,SAAiB,EACjB,gBAAwB,EACxB,SAAiB,EACjB,MAAc,EACC,EAAE;IACjB,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IAEvD,MAAM,QAAQ,CAAC,IAAI,CACjB,IAAI,iBAAiB,CAAC;QACpB,UAAU,EAAE,gBAAgB,CAAC,gBAAgB,EAAE,SAAS,CAAC;QACzD,MAAM,EAAE,gBAAgB;QACxB,GAAG,EAAE,SAAS;KACf,CAAC,CACH,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { CopyObjectCommand, S3Client } from '@aws-sdk/client-s3';\n\nimport { createAwsClient } from '../createAwsClient';\n\n// CopySource is a URL path, so each key segment is percent-encoded (a key can hold spaces, '+', '#'...);\n// the '/' between segments stays a separator.\nconst encodeCopySource = (bucketName: string, key: string): string => `${bucketName}/${key.split('/').map(encodeURIComponent).join('/')}`;\n\n/**\n * Server-side copies one object to another key (same or another bucket). The default COPY metadata\n * directive carries the stored Content-Type / Content-Disposition across unchanged.\n */\nexport const copyFile = async (\n sourceBucketName: string,\n sourceKey: string,\n targetBucketName: string,\n targetKey: string,\n region: string,\n): Promise<void> => {\n const s3Client = createAwsClient(S3Client, { region });\n\n await s3Client.send(\n new CopyObjectCommand({\n CopySource: encodeCopySource(sourceBucketName, sourceKey),\n Bucket: targetBucketName,\n Key: targetKey,\n }),\n );\n};\n"]}
@@ -1,3 +1,4 @@
1
+ export * from './copyFile';
1
2
  export * from './deleteFiles';
2
3
  export * from './generatePresignedUploadUrl';
3
4
  export * from './generatePresignedUrl';
@@ -1,5 +1,6 @@
1
1
  // The s3 folder's barrel (kept under its historical name: many processors and their
2
2
  // vi.mock calls point at 'logic/s3/s3Utils').
3
+ export * from './copyFile';
3
4
  export * from './deleteFiles';
4
5
  export * from './generatePresignedUploadUrl';
5
6
  export * from './generatePresignedUrl';
@@ -1 +1 @@
1
- {"version":3,"file":"s3Utils.js","sourceRoot":"","sources":["../../../../src/logic/s3/s3Utils.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,8CAA8C;AAC9C,cAAc,eAAe,CAAC;AAC9B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC","sourcesContent":["// The s3 folder's barrel (kept under its historical name: many processors and their\n// vi.mock calls point at 'logic/s3/s3Utils').\nexport * from './deleteFiles';\nexport * from './generatePresignedUploadUrl';\nexport * from './generatePresignedUrl';\nexport * from './getObjectStorageClass';\nexport * from './listFiles';\nexport * from './objectExists';\nexport * from './readBinaryFile';\nexport * from './readTextFile';\nexport * from './writeBinaryFile';\nexport * from './writeTextFile';\n"]}
1
+ {"version":3,"file":"s3Utils.js","sourceRoot":"","sources":["../../../../src/logic/s3/s3Utils.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,8CAA8C;AAC9C,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC","sourcesContent":["// The s3 folder's barrel (kept under its historical name: many processors and their\n// vi.mock calls point at 'logic/s3/s3Utils').\nexport * from './copyFile';\nexport * from './deleteFiles';\nexport * from './generatePresignedUploadUrl';\nexport * from './generatePresignedUrl';\nexport * from './getObjectStorageClass';\nexport * from './listFiles';\nexport * from './objectExists';\nexport * from './readBinaryFile';\nexport * from './readTextFile';\nexport * from './writeBinaryFile';\nexport * from './writeTextFile';\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quidproquo-actionprocessor-awslambda",
3
- "version": "0.1.22",
3
+ "version": "0.1.24",
4
4
  "description": "",
5
5
  "main": "./lib/commonjs/index.js",
6
6
  "module": "./lib/esm/index.js",
@@ -66,11 +66,11 @@
66
66
  "lodash": "^4.17.21",
67
67
  "node-cache": "^5.1.2",
68
68
  "node-match-path": "^0.6.3",
69
- "quidproquo-actionprocessor-js": "0.1.22",
70
- "quidproquo-actionprocessor-node": "0.1.22",
71
- "quidproquo-config-aws": "0.1.22",
72
- "quidproquo-core": "0.1.22",
73
- "quidproquo-webserver": "0.1.22"
69
+ "quidproquo-actionprocessor-js": "0.1.24",
70
+ "quidproquo-actionprocessor-node": "0.1.24",
71
+ "quidproquo-config-aws": "0.1.24",
72
+ "quidproquo-core": "0.1.24",
73
+ "quidproquo-webserver": "0.1.24"
74
74
  },
75
75
  "devDependencies": {
76
76
  "@types/busboy": "^1.5.0",
@@ -78,7 +78,7 @@
78
78
  "@types/lodash": "^4.14.194",
79
79
  "@types/node": "^22.13.13",
80
80
  "esbuild": "^0.25.8",
81
- "quidproquo-tsconfig": "0.1.22",
81
+ "quidproquo-tsconfig": "0.1.24",
82
82
  "typescript": "^5.8.2"
83
83
  }
84
84
  }