ts-ag 1.1.20 → 1.1.21

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.
package/dist/index.mjs CHANGED
@@ -7,6 +7,7 @@ import { AdminGetUserCommand, AdminInitiateAuthCommand, AdminListGroupsForUserCo
7
7
  import { createHmac } from "crypto";
8
8
  import { GetObjectCommand, HeadObjectCommand, S3Client } from "@aws-sdk/client-s3";
9
9
  import { getSignedUrl as getSignedUrl$1 } from "@aws-sdk/s3-request-presigner";
10
+ import { DynamoDBToolboxError } from "dynamodb-toolbox";
10
11
  import rehypeParse from "rehype-parse";
11
12
  import { unified } from "unified";
12
13
  import { isEqual, isObject } from "radash";
@@ -116,33 +117,33 @@ function wrapHandler(handler) {
116
117
  * Im not sure it this is optimal behaviour and if not we will migrate to only using the errorResponse function
117
118
  */
118
119
  const error_lambda_badRequest = (message, fieldName, fieldValue) => ({
119
- type: "lambda_badRequest",
120
+ type: "badRequest",
120
121
  message,
121
122
  fieldName,
122
123
  fieldValue
123
124
  });
124
125
  const error_lambda_unauthorized = (message) => ({
125
- type: "lambda_unauthorized",
126
+ type: "unauthorized",
126
127
  message
127
128
  });
128
129
  const error_lambda_forbidden = (message) => ({
129
- type: "lambda_forbidden",
130
+ type: "forbidden",
130
131
  message
131
132
  });
132
133
  const error_lambda_notFound = (message, fieldName, fieldValue) => ({
133
- type: "lambda_notFound",
134
+ type: "notFound",
134
135
  message,
135
136
  fieldName,
136
137
  fieldValue
137
138
  });
138
139
  const error_lambda_conflict = (message, fieldName, fieldValue) => ({
139
- type: "lambda_conflict",
140
+ type: "conflict",
140
141
  message,
141
142
  fieldName,
142
143
  fieldValue
143
144
  });
144
145
  const error_lambda_internal = (message) => ({
145
- type: "lambda_internal",
146
+ type: "internal",
146
147
  message
147
148
  });
148
149
  //#endregion
@@ -153,9 +154,17 @@ function field(obj) {
153
154
  value: obj.fieldValue
154
155
  } };
155
156
  }
157
+ /**
158
+ * Maps lambda errors to responses suitable to return from lambda functions
159
+ * @param e
160
+ * @param headers
161
+ * @param type
162
+ * @param extras
163
+ * @returns
164
+ */
156
165
  function response_error(e, headers, type = "", extras = {}) {
157
166
  switch (e.type) {
158
- case "lambda_badRequest": return {
167
+ case "badRequest": return {
159
168
  headers,
160
169
  statusCode: 400,
161
170
  body: {
@@ -165,7 +174,7 @@ function response_error(e, headers, type = "", extras = {}) {
165
174
  ...extras
166
175
  }
167
176
  };
168
- case "lambda_unauthorized": return {
177
+ case "unauthorized": return {
169
178
  headers,
170
179
  statusCode: 401,
171
180
  body: {
@@ -174,7 +183,7 @@ function response_error(e, headers, type = "", extras = {}) {
174
183
  ...extras
175
184
  }
176
185
  };
177
- case "lambda_forbidden": return {
186
+ case "forbidden": return {
178
187
  headers,
179
188
  statusCode: 403,
180
189
  body: {
@@ -183,7 +192,7 @@ function response_error(e, headers, type = "", extras = {}) {
183
192
  ...extras
184
193
  }
185
194
  };
186
- case "lambda_notFound": return {
195
+ case "notFound": return {
187
196
  headers,
188
197
  statusCode: 404,
189
198
  body: {
@@ -193,7 +202,7 @@ function response_error(e, headers, type = "", extras = {}) {
193
202
  ...extras
194
203
  }
195
204
  };
196
- case "lambda_conflict": return {
205
+ case "conflict": return {
197
206
  headers,
198
207
  statusCode: 409,
199
208
  body: {
@@ -256,126 +265,185 @@ function getCognitoClient() {
256
265
  }
257
266
  //#endregion
258
267
  //#region src/cognito/errors.ts
259
- const error_cognito_forbidden = {
260
- group: "cognito",
261
- type: "cognito_forbidden"
262
- };
263
- const error_cognito_internal = {
264
- group: "cognito",
265
- type: "cognito_internal"
266
- };
267
- const error_cognito_role = {
268
- group: "cognito",
269
- type: "cognito_role"
270
- };
271
- const error_cognito_input = {
272
- group: "cognito",
273
- type: "cognito_input"
274
- };
275
- const error_cognito_auth = {
276
- group: "cognito",
277
- type: "cognito_auth"
278
- };
279
- const error_cognito_notFound = {
280
- group: "cognito",
281
- type: "cognito_notFound"
282
- };
283
- const error_cognito_userNotFound = {
284
- group: "cognito",
285
- type: "cognito_userNotFound"
286
- };
287
- const error_cognito_tooManyRequests = {
288
- group: "cognito",
289
- type: "cognito_tooManyRequests"
290
- };
291
- const error_cognito_passwordPolicy = {
292
- group: "cognito",
293
- type: "cognito_passwordPolicy"
294
- };
295
- const error_cognito_passwordHistory = {
296
- group: "cognito",
297
- type: "cognito_passwordHistory"
298
- };
299
- const error_cognito_passwordResetRequired = {
300
- group: "cognito",
301
- type: "cognito_passwordResetRequired"
302
- };
303
- const error_cognito_codeExpired = {
304
- group: "cognito",
305
- type: "cognito_codeExpired"
306
- };
307
- const error_cognito_codeMismatch = {
308
- group: "cognito",
309
- type: "cognito_codeMismatch"
310
- };
311
- const error_cognito_delivery = {
312
- group: "cognito",
313
- type: "cognito_delivery"
314
- };
315
- const error_cognito_userExists = {
316
- group: "cognito",
317
- type: "cognito_userExists"
318
- };
319
- const awsToCognitoErrorMap = {
320
- ForbiddenException: error_cognito_forbidden,
321
- NotAuthorizedException: error_cognito_auth,
322
- UserNotConfirmedException: error_cognito_auth,
323
- UserNotFoundException: error_cognito_userNotFound,
324
- ResourceNotFoundException: error_cognito_notFound,
325
- InvalidParameterException: error_cognito_input,
326
- InvalidPasswordException: error_cognito_passwordPolicy,
327
- PasswordHistoryPolicyViolationException: error_cognito_passwordHistory,
328
- PasswordResetRequiredException: error_cognito_passwordResetRequired,
329
- LimitExceededException: error_cognito_tooManyRequests,
330
- TooManyRequestsException: error_cognito_tooManyRequests,
331
- InternalErrorException: error_cognito_internal,
332
- CodeMismatchException: error_cognito_codeMismatch,
333
- ExpiredCodeException: error_cognito_codeExpired,
334
- TooManyFailedAttemptsException: error_cognito_tooManyRequests,
335
- UnexpectedLambdaException: error_cognito_internal,
336
- InvalidLambdaResponseException: error_cognito_internal,
337
- UserLambdaValidationException: error_cognito_internal,
338
- InvalidEmailRoleAccessPolicyException: error_cognito_role,
339
- InvalidSmsRoleAccessPolicyException: error_cognito_role,
340
- InvalidSmsRoleTrustRelationshipException: error_cognito_role,
341
- CodeDelliveryFailureException: error_cognito_delivery,
342
- AliasExistsException: error_cognito_userExists,
343
- InvalidUserPoolConfigurationException: error_cognito_internal,
344
- MFAMethodNotFoundException: error_cognito_notFound,
345
- UnsupportedOperationException: error_cognito_internal,
346
- SoftwareTokenMFANotFoundException: error_cognito_notFound,
347
- UsernameExistsException: error_cognito_userExists
268
+ const defaultErrors$3 = {
269
+ auth: {
270
+ type: "unauthorized",
271
+ message: "Not authorized"
272
+ },
273
+ forbidden: {
274
+ type: "forbidden",
275
+ message: "Forbidden"
276
+ },
277
+ invalidInput: {
278
+ type: "badRequest",
279
+ message: "There is an issue with your request"
280
+ },
281
+ userNotFound: {
282
+ type: "notFound",
283
+ message: "User not found"
284
+ },
285
+ resourceNotFound: {
286
+ type: "notFound",
287
+ message: "Resource not found"
288
+ },
289
+ tooManyRequests: {
290
+ type: "badRequest",
291
+ message: "Too many requests"
292
+ },
293
+ passwordPolicy: {
294
+ type: "badRequest",
295
+ message: "Password does not meet policy requirements"
296
+ },
297
+ passwordHistory: {
298
+ type: "conflict",
299
+ message: "Password was used recently"
300
+ },
301
+ passwordResetRequired: {
302
+ type: "badRequest",
303
+ message: "Password reset required"
304
+ },
305
+ codeExpired: {
306
+ type: "badRequest",
307
+ message: "Code expired"
308
+ },
309
+ codeMismatch: {
310
+ type: "badRequest",
311
+ message: "Invalid code"
312
+ },
313
+ delivery: {
314
+ type: "internal",
315
+ message: "Internal server error"
316
+ },
317
+ userExists: {
318
+ type: "conflict",
319
+ message: "User already exists"
320
+ },
321
+ conflict: {
322
+ type: "conflict",
323
+ message: "The request conflicts with the current Cognito resource state"
324
+ },
325
+ internal: {
326
+ type: "internal",
327
+ message: "Internal server error"
328
+ }
348
329
  };
349
- /**
350
- * Gets a generic error from the name of the aws error
351
- */
330
+ /** Wrap an unknown caught value as a Cognito-domain error for neverthrow flows. */
352
331
  function error_cognito(error) {
353
- const type = error.name;
354
- if (awsToCognitoErrorMap[type] === void 0) console.warn(`${type} is not present in the cognito error map`);
355
- console.error(`Cognito error: ${type}`, error);
356
- return awsToCognitoErrorMap[type] || error_cognito_internal;
332
+ return {
333
+ type: "cognito",
334
+ error
335
+ };
357
336
  }
358
- /**
359
- * Converts a cognito error to a lambda error.
360
- * Basically just for narrowing it down a bit
361
- */
362
- function error_lambda_fromCognito(e) {
363
- switch (e.type) {
364
- case "cognito_auth": return error_lambda_unauthorized("Not authorized");
365
- case "cognito_forbidden": return error_lambda_forbidden("Forbidden");
366
- case "cognito_internal":
367
- case "cognito_role": return error_lambda_internal("Internal server error");
368
- case "cognito_input": return error_lambda_badRequest("There is an issue with your request");
369
- case "cognito_notFound": return error_lambda_notFound("Resource not found");
370
- case "cognito_userNotFound": return error_lambda_notFound("User not found");
371
- case "cognito_tooManyRequests": return error_lambda_badRequest("Too many requests");
372
- case "cognito_passwordPolicy": return error_lambda_badRequest("Password does not meet policy requirements");
373
- case "cognito_passwordHistory": return error_lambda_conflict("Password was used recently");
374
- case "cognito_passwordResetRequired": return error_lambda_badRequest("Password reset required");
375
- case "cognito_delivery": return error_lambda_internal("Delivery failed for the provided email or phone number");
376
- default: return error_lambda_internal("Unknown error");
337
+ /** Convert AWS SDK Cognito errors into a safe lambda error for API responses. */
338
+ function error_lambda_fromCognito(e, options = {}) {
339
+ return fromReason$2(getCognitoReason(e.error), options);
340
+ }
341
+ /** Apply endpoint overrides and build the concrete lambda error object. */
342
+ function fromReason$2(reason, options) {
343
+ const base = defaultErrors$3[reason];
344
+ const override = options[reason];
345
+ const args = {
346
+ ...base,
347
+ ...override
348
+ };
349
+ switch (args.type) {
350
+ case "badRequest": return error_lambda_badRequest(args.message, args.fieldName, args.fieldValue);
351
+ case "unauthorized": return error_lambda_unauthorized(args.message);
352
+ case "forbidden": return error_lambda_forbidden(args.message);
353
+ case "notFound": return error_lambda_notFound(args.message, args.fieldName, args.fieldValue);
354
+ case "conflict": return error_lambda_conflict(args.message, args.fieldName, args.fieldValue);
355
+ default: return error_lambda_internal(args.message);
377
356
  }
378
357
  }
358
+ /** Classify AWS SDK / Cognito service errors. */
359
+ function getCognitoReason(error) {
360
+ switch (getErrorName$2(error)) {
361
+ case "NotAuthorizedException":
362
+ case "UnauthorizedException":
363
+ case "UserNotConfirmedException":
364
+ case "RefreshTokenReuseException": return "auth";
365
+ case "AccessDeniedException":
366
+ case "ForbiddenException": return "forbidden";
367
+ case "InvalidParameterException":
368
+ case "InvalidOAuthFlowException":
369
+ case "ScopeDoesNotExistException":
370
+ case "UnsupportedIdentityProviderException":
371
+ case "UnsupportedTokenTypeException": return "invalidInput";
372
+ case "UserNotFoundException": return "userNotFound";
373
+ case "ResourceNotFoundException":
374
+ case "MFAMethodNotFoundException":
375
+ case "SoftwareTokenMFANotFoundException":
376
+ case "WebAuthnChallengeNotFoundException": return "resourceNotFound";
377
+ case "LimitExceededException":
378
+ case "TooManyFailedAttemptsException":
379
+ case "TooManyRequestsException": return "tooManyRequests";
380
+ case "InvalidPasswordException": return "passwordPolicy";
381
+ case "PasswordHistoryPolicyViolationException": return "passwordHistory";
382
+ case "PasswordResetRequiredException": return "passwordResetRequired";
383
+ case "ExpiredCodeException": return "codeExpired";
384
+ case "CodeMismatchException": return "codeMismatch";
385
+ case "CodeDeliveryFailureException": return "delivery";
386
+ case "AliasExistsException":
387
+ case "DeviceKeyExistsException":
388
+ case "DuplicateProviderException":
389
+ case "GroupExistsException":
390
+ case "ManagedLoginBrandingExistsException":
391
+ case "TermsExistsException":
392
+ case "UsernameExistsException": return "userExists";
393
+ case "ConcurrentModificationException":
394
+ case "PreconditionNotMetException":
395
+ case "UnsupportedUserStateException": return "conflict";
396
+ case "EnableSoftwareTokenMFAException":
397
+ case "FeatureUnavailableInTierException":
398
+ case "InternalErrorException":
399
+ case "InternalServerException":
400
+ case "InvalidEmailRoleAccessPolicyException":
401
+ case "InvalidLambdaResponseException":
402
+ case "InvalidSmsRoleAccessPolicyException":
403
+ case "InvalidSmsRoleTrustRelationshipException":
404
+ case "InvalidUserPoolConfigurationException":
405
+ case "TierChangeNotAllowedException":
406
+ case "UnexpectedLambdaException":
407
+ case "UnsupportedOperationException":
408
+ case "UserImportInProgressException":
409
+ case "UserLambdaValidationException":
410
+ case "UserPoolAddOnNotEnabledException":
411
+ case "UserPoolTaggingException":
412
+ case "WebAuthnClientMismatchException":
413
+ case "WebAuthnConfigurationMissingException":
414
+ case "WebAuthnCredentialNotSupportedException":
415
+ case "WebAuthnNotEnabledException":
416
+ case "WebAuthnOriginNotAllowedException":
417
+ case "WebAuthnRelyingPartyMismatchException": return "internal";
418
+ default: return getHttpStatusReason$2(error);
419
+ }
420
+ }
421
+ function getHttpStatusReason$2(error) {
422
+ const status = getHttpStatusCode$2(error);
423
+ if (status === 400) return "invalidInput";
424
+ if (status === 401) return "auth";
425
+ if (status === 403) return "forbidden";
426
+ if (status === 404) return "resourceNotFound";
427
+ if (status === 409 || status === 412) return "conflict";
428
+ if (status === 429) return "tooManyRequests";
429
+ return "internal";
430
+ }
431
+ function getErrorName$2(error) {
432
+ if (!isRecord$2(error)) return void 0;
433
+ const name = error.name;
434
+ if (typeof name === "string") return name;
435
+ const code = error.code ?? error.Code;
436
+ if (typeof code === "string") return code;
437
+ }
438
+ function getHttpStatusCode$2(error) {
439
+ if (!isRecord$2(error)) return void 0;
440
+ const metadata = error.$metadata;
441
+ if (!isRecord$2(metadata)) return void 0;
442
+ return typeof metadata.httpStatusCode === "number" ? metadata.httpStatusCode : void 0;
443
+ }
444
+ function isRecord$2(value) {
445
+ return typeof value === "object" && value !== null;
446
+ }
379
447
  //#endregion
380
448
  //#region src/cognito/user.ts
381
449
  /**
@@ -646,12 +714,12 @@ const verifyOAuthToken = ResultAsync.fromThrowable(async (a) => {
646
714
  });
647
715
  if (!tokenRes.ok) {
648
716
  console.error("verifyOAuthToken: token exchange failed", await tokenRes.text());
649
- throw new Error("");
717
+ throw Object.assign(/* @__PURE__ */ new Error("OAuth token exchange failed"), { name: "NotAuthorizedException" });
650
718
  }
651
719
  return await tokenRes.json();
652
720
  }, (e) => {
653
721
  console.error("verifyOAuthToken:error", e);
654
- return error_cognito_auth;
722
+ return error_cognito(e);
655
723
  });
656
724
  /**
657
725
  * Exchanges an OAuth2 refresh token for Cognito tokens using the oauth token endpoint.
@@ -679,12 +747,12 @@ const refreshOAuthToken = ResultAsync.fromThrowable(async (a) => {
679
747
  });
680
748
  if (!tokenRes.ok) {
681
749
  console.error("refreshOAuthToken: token exchange failed", await tokenRes.text());
682
- throw new Error("");
750
+ throw Object.assign(/* @__PURE__ */ new Error("OAuth token refresh failed"), { name: "NotAuthorizedException" });
683
751
  }
684
752
  return await tokenRes.json();
685
753
  }, (e) => {
686
754
  console.error("refreshOAuthToken:error", e);
687
- return error_cognito_auth;
755
+ return error_cognito(e);
688
756
  });
689
757
  //#endregion
690
758
  //#region src/s3/client.ts
@@ -695,12 +763,190 @@ function getS3() {
695
763
  return new S3Client({});
696
764
  }
697
765
  //#endregion
766
+ //#region src/utils/errors.ts
767
+ function isRecord(value) {
768
+ return typeof value === "object" && value !== null;
769
+ }
770
+ function getErrorName(error) {
771
+ if (!isRecord(error)) return void 0;
772
+ const name = error.name;
773
+ if (typeof name === "string") return name;
774
+ const code = error.code ?? error.Code;
775
+ if (typeof code === "string") return code;
776
+ }
777
+ //#endregion
698
778
  //#region src/s3/errors.ts
699
- const error_s3_internal = { type: "s3_internal" };
700
- const error_s3_get = { type: "s3_get" };
779
+ const defaultErrors$2 = {
780
+ invalidInput: {
781
+ type: "badRequest",
782
+ message: "Invalid S3 request"
783
+ },
784
+ objectNotFound: {
785
+ type: "notFound",
786
+ message: "S3 object not found"
787
+ },
788
+ bucketNotFound: {
789
+ type: "internal",
790
+ message: "Internal server error"
791
+ },
792
+ conflict: {
793
+ type: "conflict",
794
+ message: "The request conflicts with the current S3 resource state"
795
+ },
796
+ throttled: {
797
+ type: "internal",
798
+ message: "Internal server error"
799
+ },
800
+ accessDenied: {
801
+ type: "internal",
802
+ message: "Internal server error"
803
+ },
804
+ internal: {
805
+ type: "internal",
806
+ message: "Internal server error"
807
+ }
808
+ };
809
+ /** Wrap an unknown caught value as an S3-domain error for neverthrow flows. */
810
+ function error_s3(error) {
811
+ return {
812
+ type: "s3",
813
+ error
814
+ };
815
+ }
816
+ /** Convert AWS SDK S3 errors into a safe lambda error for API responses. */
817
+ function error_lambda_fromS3(e, options = {}) {
818
+ const reason = getS3Reason(e.error);
819
+ const base = defaultErrors$2[reason];
820
+ const override = options[reason];
821
+ const args = {
822
+ ...base,
823
+ ...override
824
+ };
825
+ switch (args.type) {
826
+ case "badRequest": return error_lambda_badRequest(args.message, args.fieldName, args.fieldValue);
827
+ case "unauthorized": return error_lambda_unauthorized(args.message);
828
+ case "forbidden": return error_lambda_forbidden(args.message);
829
+ case "notFound": return error_lambda_notFound(args.message, args.fieldName, args.fieldValue);
830
+ case "conflict": return error_lambda_conflict(args.message, args.fieldName, args.fieldValue);
831
+ default: return error_lambda_internal(args.message);
832
+ }
833
+ }
834
+ /** Returns true for normal S3 object-missing responses. */
835
+ function is_s3_notFound(error) {
836
+ return getS3Reason(error) === "objectNotFound";
837
+ }
838
+ /** Classify AWS SDK / S3 service errors. */
839
+ function getS3Reason(error) {
840
+ switch (getErrorName(error)) {
841
+ case "NoSuchKey":
842
+ case "NotFound":
843
+ case "NoSuchVersion": return "objectNotFound";
844
+ case "NoSuchBucket":
845
+ case "NoSuchBucketPolicy":
846
+ case "NoSuchLifecycleConfiguration":
847
+ case "NoLoggingStatusForKey": return "bucketNotFound";
848
+ case "AmbiguousGrantByEmailAddress":
849
+ case "BadDigest":
850
+ case "EntityTooLarge":
851
+ case "EntityTooSmall":
852
+ case "IncompleteBody":
853
+ case "IncorrectNumberOfFilesInPostRequest":
854
+ case "InlineDataTooLarge":
855
+ case "InvalidAddressingHeader":
856
+ case "InvalidArgument":
857
+ case "InvalidBucketName":
858
+ case "InvalidDigest":
859
+ case "InvalidLocationConstraint":
860
+ case "InvalidPart":
861
+ case "InvalidPartOrder":
862
+ case "InvalidPayer":
863
+ case "InvalidPolicyDocument":
864
+ case "InvalidRange":
865
+ case "InvalidRequest":
866
+ case "InvalidSOAPRequest":
867
+ case "InvalidStorageClass":
868
+ case "InvalidTargetBucketForLogging":
869
+ case "InvalidURI":
870
+ case "KeyTooLongError":
871
+ case "MalformedACLError":
872
+ case "MalformedPOSTRequest":
873
+ case "MalformedXML":
874
+ case "MaxMessageLengthExceeded":
875
+ case "MaxPostPreDataLengthExceededError":
876
+ case "MetadataTooLarge":
877
+ case "MissingAttachment":
878
+ case "MissingContentLength":
879
+ case "MissingRequestBodyError":
880
+ case "RequestIsNotMultiPartContent":
881
+ case "RequestTorrentOfBucketError":
882
+ case "NoSuchUpload": return "invalidInput";
883
+ case "BucketAlreadyExists":
884
+ case "BucketAlreadyOwnedByYou":
885
+ case "BucketNotEmpty":
886
+ case "EncryptionTypeMismatch":
887
+ case "IdempotencyParameterMismatch":
888
+ case "IllegalVersioningConfigurationException":
889
+ case "InvalidBucketState":
890
+ case "InvalidEncryptionAlgorithmError":
891
+ case "InvalidObjectState":
892
+ case "InvalidWriteOffset":
893
+ case "ObjectAlreadyInActiveTierError":
894
+ case "ObjectNotInActiveTierError":
895
+ case "OperationAborted":
896
+ case "PreconditionFailed":
897
+ case "RestoreAlreadyInProgress":
898
+ case "TooManyParts": return "conflict";
899
+ case "RequestLimitExceeded":
900
+ case "RequestTimeout":
901
+ case "ServiceUnavailable":
902
+ case "SlowDown":
903
+ case "Throttling":
904
+ case "ThrottlingException": return "throttled";
905
+ case "AccessDenied":
906
+ case "AccountProblem":
907
+ case "AllAccessDisabled":
908
+ case "CredentialsNotSupported":
909
+ case "CrossLocationLoggingProhibited":
910
+ case "ExpiredToken":
911
+ case "InvalidAccessKeyId":
912
+ case "InvalidSecurity":
913
+ case "InvalidToken":
914
+ case "MethodNotAllowed":
915
+ case "MissingSecurityElement":
916
+ case "MissingSecurityHeader":
917
+ case "NotSignedUp":
918
+ case "SignatureDoesNotMatch": return "accessDenied";
919
+ case "AuthorizationHeaderMalformed":
920
+ case "InternalError":
921
+ case "NotImplemented":
922
+ case "PermanentRedirect":
923
+ case "Redirect":
924
+ case "RequestTimeTooSkewed":
925
+ case "TemporaryRedirect": return "internal";
926
+ default: return getHttpStatusReason$1(error);
927
+ }
928
+ }
929
+ function getHttpStatusReason$1(error) {
930
+ const status = getHttpStatusCode$1(error);
931
+ if (status === 400) return "invalidInput";
932
+ if (status === 404) return "objectNotFound";
933
+ if (status === 409 || status === 412) return "conflict";
934
+ if (status === 429 || status === 503) return "throttled";
935
+ if (status === 401 || status === 403) return "accessDenied";
936
+ return "internal";
937
+ }
938
+ function getHttpStatusCode$1(error) {
939
+ if (!isRecord(error)) return void 0;
940
+ const metadata = error.$metadata;
941
+ if (!isRecord(metadata)) return void 0;
942
+ return typeof metadata.httpStatusCode === "number" ? metadata.httpStatusCode : void 0;
943
+ }
701
944
  //#endregion
702
945
  //#region src/s3/signedUrl.ts
703
- const getSignedUrl = ResultAsync.fromThrowable(getSignedUrl$1, (e) => e);
946
+ const getSignedUrl = ResultAsync.fromThrowable(getSignedUrl$1, (e) => {
947
+ console.error("getSignedUrl: Failed to get signed url", e);
948
+ error_s3(e);
949
+ });
704
950
  //#endregion
705
951
  //#region src/s3/object.ts
706
952
  /**
@@ -724,8 +970,8 @@ const getObject = ResultAsync.fromThrowable(async (bucketName, key) => {
724
970
  stream.on("error", reject);
725
971
  });
726
972
  }, (e) => {
727
- console.error(`Error getting object from S3: ${e}`);
728
- return error_s3_get;
973
+ console.error(`getObjectt: Error getting object from S3: ${e}`);
974
+ return error_s3(e);
729
975
  });
730
976
  /**
731
977
  * Convenience function to get an object from S3 and return it as a string.
@@ -749,22 +995,313 @@ const objectExists = ResultAsync.fromThrowable(async (bucketName, key) => {
749
995
  });
750
996
  return (await s3.send(cmd)).$metadata.httpStatusCode === 200;
751
997
  } catch (e) {
752
- if (e.$metadata.httpStatusCode === 404) return false;
753
- else throw e;
998
+ if (is_s3_notFound(e)) return false;
999
+ throw e;
754
1000
  }
755
1001
  }, (e) => {
756
- console.error(`Error getting object head from S3: ${e}`);
757
- return error_s3_get;
1002
+ console.error(`objectExists: Error getting object head from S3: ${e}`);
1003
+ return error_s3(e);
758
1004
  });
759
1005
  //#endregion
760
1006
  //#region src/dynamo/errors.ts
761
- const error_dynamo = { type: "dynamo" };
762
- function error_lambda_fromDynamo(_e) {
763
- return error_lambda_internal("Internal server error");
1007
+ const defaultErrors$1 = {
1008
+ invalidInput: {
1009
+ type: "badRequest",
1010
+ message: "Invalid request"
1011
+ },
1012
+ conditionalCheckFailed: {
1013
+ type: "conflict",
1014
+ message: "The request conflicts with the current resource state"
1015
+ },
1016
+ transactionConflict: {
1017
+ type: "conflict",
1018
+ message: "The request conflicts with the current resource state"
1019
+ },
1020
+ resourceNotFound: {
1021
+ type: "internal",
1022
+ message: "Internal server error"
1023
+ },
1024
+ throttled: {
1025
+ type: "internal",
1026
+ message: "Internal server error"
1027
+ },
1028
+ accessDenied: {
1029
+ type: "internal",
1030
+ message: "Internal server error"
1031
+ },
1032
+ internal: {
1033
+ type: "internal",
1034
+ message: "Internal server error"
1035
+ }
1036
+ };
1037
+ /** Wrap an unknown caught value as a Dynamo-domain error for neverthrow flows. */
1038
+ function error_dynamo(error) {
1039
+ return {
1040
+ type: "dynamo",
1041
+ error
1042
+ };
1043
+ }
1044
+ /** Convert DynamoDB Toolbox or AWS SDK errors into a safe lambda error for API responses. */
1045
+ function error_lambda_fromDynamo(e, options = {}) {
1046
+ if (e.error instanceof DynamoDBToolboxError) return fromReason$1(getToolboxReason(e.error), options, toolboxField(e.error, options.includeToolboxPath));
1047
+ return fromReason$1(getAwsReason(e.error), options);
1048
+ }
1049
+ /** Apply endpoint overrides and build the concrete lambda error object. */
1050
+ function fromReason$1(reason, options, defaults = {}) {
1051
+ const base = {
1052
+ ...defaultErrors$1[reason],
1053
+ ...defaults
1054
+ };
1055
+ const override = options[reason];
1056
+ const args = {
1057
+ ...base,
1058
+ ...override
1059
+ };
1060
+ switch (args.type) {
1061
+ case "badRequest": return error_lambda_badRequest(args.message, args.fieldName, args.fieldValue);
1062
+ case "unauthorized": return error_lambda_unauthorized(args.message);
1063
+ case "forbidden": return error_lambda_forbidden(args.message);
1064
+ case "notFound": return error_lambda_notFound(args.message, args.fieldName, args.fieldValue);
1065
+ case "conflict": return error_lambda_conflict(args.message, args.fieldName, args.fieldValue);
1066
+ default: return error_lambda_internal(args.message);
1067
+ }
1068
+ }
1069
+ /** Classify errors produced by Toolbox before sending, or while formatting returned items. */
1070
+ function getToolboxReason(error) {
1071
+ if (error.code.startsWith("parsing.") || error.code === "actions.parsePrimaryKey.invalidKeyPart") return "invalidInput";
1072
+ if (error.code.startsWith("formatter.") || error.code.startsWith("schema.") || error.code.startsWith("entity.")) return "internal";
1073
+ switch (error.code) {
1074
+ case "actions.invalidCondition":
1075
+ case "actions.invalidExpressionAttributePath":
1076
+ case "queryCommand.invalidIndex":
1077
+ case "queryCommand.invalidPartition":
1078
+ case "queryCommand.invalidProjectionExpression":
1079
+ case "queryCommand.invalidRange":
1080
+ case "queryCommand.invalidReverseOption":
1081
+ case "scanCommand.invalidProjectionExpression":
1082
+ case "scanCommand.invalidSegmentOption":
1083
+ case "batchGetCommand.invalidProjectionExpression":
1084
+ case "options.invalidCapacityOption":
1085
+ case "options.invalidClientRequestToken":
1086
+ case "options.invalidConsistentOption":
1087
+ case "options.invalidIndexOption":
1088
+ case "options.invalidLimitOption":
1089
+ case "options.invalidMaxPagesOption":
1090
+ case "options.invalidMetricsOption":
1091
+ case "options.invalidReturnValuesOption":
1092
+ case "options.invalidReturnValuesOnConditionFalseOption":
1093
+ case "options.invalidSelectOption": return "invalidInput";
1094
+ case "actions.incompleteAction":
1095
+ case "actions.invalidAction":
1096
+ case "actions.missingDocumentClient":
1097
+ case "queryCommand.invalidTagEntitiesOption":
1098
+ case "queryCommand.noEntityMatched":
1099
+ case "scanCommand.noEntityMatched":
1100
+ case "options.invalidEntityAttrFilterOption":
1101
+ case "options.invalidNoEntityMatchBehaviorOption":
1102
+ case "options.invalidShowEntityAttrOption":
1103
+ case "options.invalidTableNameOption":
1104
+ case "options.unknownOption":
1105
+ case "table.missingTableName": return "internal";
1106
+ default: return "internal";
1107
+ }
1108
+ }
1109
+ function toolboxField(error, includeToolboxPath) {
1110
+ if (!includeToolboxPath || typeof error.path !== "string") return {};
1111
+ return {
1112
+ fieldName: error.path,
1113
+ fieldValue: error.message
1114
+ };
1115
+ }
1116
+ /** Classify AWS SDK / DynamoDB service errors that bubble out of Toolbox send calls. */
1117
+ function getAwsReason(error) {
1118
+ switch (getErrorName(error)) {
1119
+ case "ConditionalCheckFailedException": return "conditionalCheckFailed";
1120
+ case "TransactionCanceledException": return getTransactionReason(error);
1121
+ case "TransactionConflictException":
1122
+ case "ReplicatedWriteConflictException":
1123
+ case "IdempotentParameterMismatchException":
1124
+ case "ItemCollectionSizeLimitExceededException": return "transactionConflict";
1125
+ case "ValidationException": return "invalidInput";
1126
+ case "ResourceNotFoundException": return "resourceNotFound";
1127
+ case "ProvisionedThroughputExceededException":
1128
+ case "RequestLimitExceeded":
1129
+ case "ThrottlingException":
1130
+ case "ThrottlingError": return "throttled";
1131
+ case "AccessDeniedException":
1132
+ case "ExpiredTokenException":
1133
+ case "IncompleteSignatureException":
1134
+ case "InvalidSignatureException":
1135
+ case "UnrecognizedClientException": return "accessDenied";
1136
+ default: return "internal";
1137
+ }
1138
+ }
1139
+ /** Pick the most useful public reason from DynamoDB transaction cancellation details. */
1140
+ function getTransactionReason(error) {
1141
+ const cancellationReasons = getCancellationReasons(error);
1142
+ if (cancellationReasons.some((reason) => reason === "ConditionalCheckFailed")) return "conditionalCheckFailed";
1143
+ if (cancellationReasons.some((reason) => reason === "TransactionConflict")) return "transactionConflict";
1144
+ if (cancellationReasons.some((reason) => reason === "ValidationError")) return "invalidInput";
1145
+ if (cancellationReasons.some((reason) => [
1146
+ "ProvisionedThroughputExceeded",
1147
+ "RequestLimitExceeded",
1148
+ "ThrottlingError"
1149
+ ].includes(reason))) return "throttled";
1150
+ return "internal";
1151
+ }
1152
+ function getCancellationReasons(error) {
1153
+ if (!isRecord(error)) return [];
1154
+ const cancellationReasons = error.CancellationReasons ?? error.cancellationReasons;
1155
+ if (!Array.isArray(cancellationReasons)) return [];
1156
+ return cancellationReasons.map((reason) => isRecord(reason) && typeof reason.Code === "string" ? reason.Code : void 0).filter((reason) => reason !== void 0);
764
1157
  }
765
1158
  //#endregion
766
1159
  //#region src/ses/errors.ts
767
- const error_ses = { type: "ses" };
1160
+ const defaultErrors = {
1161
+ invalidInput: {
1162
+ type: "badRequest",
1163
+ message: "Invalid SES request"
1164
+ },
1165
+ messageRejected: {
1166
+ type: "badRequest",
1167
+ message: "Email message was rejected"
1168
+ },
1169
+ identityNotVerified: {
1170
+ type: "internal",
1171
+ message: "Internal server error"
1172
+ },
1173
+ notFound: {
1174
+ type: "internal",
1175
+ message: "Internal server error"
1176
+ },
1177
+ alreadyExists: {
1178
+ type: "conflict",
1179
+ message: "SES resource already exists"
1180
+ },
1181
+ conflict: {
1182
+ type: "conflict",
1183
+ message: "The request conflicts with the current SES resource state"
1184
+ },
1185
+ throttled: {
1186
+ type: "internal",
1187
+ message: "Internal server error"
1188
+ },
1189
+ accessDenied: {
1190
+ type: "internal",
1191
+ message: "Internal server error"
1192
+ },
1193
+ internal: {
1194
+ type: "internal",
1195
+ message: "Internal server error"
1196
+ }
1197
+ };
1198
+ /** Wrap an unknown caught value as an SES-domain error for neverthrow flows. */
1199
+ function error_ses(error) {
1200
+ return {
1201
+ type: "ses",
1202
+ error
1203
+ };
1204
+ }
1205
+ /** Convert AWS SDK SES errors into a safe lambda error for API responses. */
1206
+ function error_lambda_fromSes(e, options = {}) {
1207
+ return fromReason(getSesReason(e.error), options);
1208
+ }
1209
+ /** Apply endpoint overrides and build the concrete lambda error object. */
1210
+ function fromReason(reason, options) {
1211
+ const base = defaultErrors[reason];
1212
+ const override = options[reason];
1213
+ const args = {
1214
+ ...base,
1215
+ ...override
1216
+ };
1217
+ switch (args.type) {
1218
+ case "badRequest": return error_lambda_badRequest(args.message, args.fieldName, args.fieldValue);
1219
+ case "unauthorized": return error_lambda_unauthorized(args.message);
1220
+ case "forbidden": return error_lambda_forbidden(args.message);
1221
+ case "notFound": return error_lambda_notFound(args.message, args.fieldName, args.fieldValue);
1222
+ case "conflict": return error_lambda_conflict(args.message, args.fieldName, args.fieldValue);
1223
+ default: return error_lambda_internal(args.message);
1224
+ }
1225
+ }
1226
+ /** Classify AWS SDK / SES service errors. */
1227
+ function getSesReason(error) {
1228
+ switch (getErrorName$1(error)) {
1229
+ case "BadRequestException":
1230
+ case "CustomVerificationEmailInvalidContentException":
1231
+ case "InvalidParameterValue":
1232
+ case "InvalidPolicyException":
1233
+ case "InvalidRenderingParameterException":
1234
+ case "InvalidSnsTopic":
1235
+ case "InvalidSnsTopicException":
1236
+ case "InvalidTemplateException":
1237
+ case "InvalidTrackingOptionsException":
1238
+ case "MissingRenderingAttributeException": return "invalidInput";
1239
+ case "MessageRejected":
1240
+ case "MessageRejectedException": return "messageRejected";
1241
+ case "ConfigurationSetDoesNotExist":
1242
+ case "ConfigurationSetDoesNotExistException":
1243
+ case "NotFoundException":
1244
+ case "RuleSetDoesNotExist":
1245
+ case "TemplateDoesNotExist":
1246
+ case "TemplateDoesNotExistException": return "notFound";
1247
+ case "AlreadyExistsException":
1248
+ case "ConfigurationSetAlreadyExists":
1249
+ case "RuleSetNameAlreadyExists":
1250
+ case "TemplateNameAlreadyExists": return "alreadyExists";
1251
+ case "AccountSendingPausedException":
1252
+ case "ConfigurationSetSendingPausedException":
1253
+ case "ConcurrentModificationException":
1254
+ case "ConflictException":
1255
+ case "MailFromDomainNotVerified":
1256
+ case "MailFromDomainNotVerifiedException":
1257
+ case "SendingPausedException": return "conflict";
1258
+ case "FromEmailAddressNotVerified":
1259
+ case "IdentityNotVerifiedException": return "identityNotVerified";
1260
+ case "LimitExceededException":
1261
+ case "Throttling":
1262
+ case "ThrottlingException":
1263
+ case "TooManyRequestsException": return "throttled";
1264
+ case "AccessDeniedException":
1265
+ case "AccountSuspendedException":
1266
+ case "ExpiredTokenException":
1267
+ case "InvalidClientTokenId":
1268
+ case "InvalidSignatureException":
1269
+ case "ProductionAccessNotGrantedException":
1270
+ case "SignatureDoesNotMatch":
1271
+ case "UnauthorizedException": return "accessDenied";
1272
+ case "InternalFailure":
1273
+ case "InternalServerError":
1274
+ case "InternalServiceError":
1275
+ case "ServiceUnavailable": return "internal";
1276
+ default: return getHttpStatusReason(error);
1277
+ }
1278
+ }
1279
+ function getHttpStatusReason(error) {
1280
+ const status = getHttpStatusCode(error);
1281
+ if (status === 400) return "invalidInput";
1282
+ if (status === 401) return "accessDenied";
1283
+ if (status === 403) return "accessDenied";
1284
+ if (status === 404) return "notFound";
1285
+ if (status === 409 || status === 412) return "conflict";
1286
+ if (status === 429) return "throttled";
1287
+ return "internal";
1288
+ }
1289
+ function getErrorName$1(error) {
1290
+ if (!isRecord$1(error)) return void 0;
1291
+ const name = error.name;
1292
+ if (typeof name === "string") return name;
1293
+ const code = error.code ?? error.Code;
1294
+ if (typeof code === "string") return code;
1295
+ }
1296
+ function getHttpStatusCode(error) {
1297
+ if (!isRecord$1(error)) return void 0;
1298
+ const metadata = error.$metadata;
1299
+ if (!isRecord$1(metadata)) return void 0;
1300
+ return typeof metadata.httpStatusCode === "number" ? metadata.httpStatusCode : void 0;
1301
+ }
1302
+ function isRecord$1(value) {
1303
+ return typeof value === "object" && value !== null;
1304
+ }
768
1305
  //#endregion
769
1306
  //#region src/rehype/flat-toc.ts
770
1307
  /**
@@ -1062,6 +1599,6 @@ async function readPackageJson(filePath) {
1062
1599
  return JSON.parse(await readFile(filePath, { encoding: "utf-8" }));
1063
1600
  }
1064
1601
  //#endregion
1065
- export { HTTPMethods, changePassword, colorText, computeSecretHash, confirmForgotPassword, confirmSignup, createApiRequest, deepDiff, error_cognito, error_cognito_auth, error_cognito_codeExpired, error_cognito_codeMismatch, error_cognito_delivery, error_cognito_forbidden, error_cognito_input, error_cognito_internal, error_cognito_notFound, error_cognito_passwordHistory, error_cognito_passwordPolicy, error_cognito_passwordResetRequired, error_cognito_role, error_cognito_tooManyRequests, error_cognito_userExists, error_cognito_userNotFound, error_dynamo, error_lambda_badRequest, error_lambda_conflict, error_lambda_forbidden, error_lambda_fromCognito, error_lambda_fromDynamo, error_lambda_internal, error_lambda_notFound, error_lambda_unauthorized, error_s3_get, error_s3_internal, error_ses, exists, extractAttributes, extractToc, forgotPassword, getByPath, getCognitoClient, getCookies, getObject, getObjectString, getS3, getSchemaByPath, getSignedUrl, getUserDetails, getUserGroups, isSchema, login, logout, objectExists, parseRaw, pruneToShape, readPackageJson, refreshOAuthToken, refreshTokens, resetPassword, response_error, response_ok, response_valibotError, setByPath, signUp, unwrap, verifyOAuthToken, wrapHandler, writeIfDifferent };
1602
+ export { HTTPMethods, changePassword, colorText, computeSecretHash, confirmForgotPassword, confirmSignup, createApiRequest, deepDiff, error_cognito, error_dynamo, error_lambda_badRequest, error_lambda_conflict, error_lambda_forbidden, error_lambda_fromCognito, error_lambda_fromDynamo, error_lambda_fromS3, error_lambda_fromSes, error_lambda_internal, error_lambda_notFound, error_lambda_unauthorized, error_s3, error_ses, exists, extractAttributes, extractToc, forgotPassword, getByPath, getCognitoClient, getCookies, getErrorName, getObject, getObjectString, getS3, getSchemaByPath, getSignedUrl, getUserDetails, getUserGroups, isRecord, isSchema, is_s3_notFound, login, logout, objectExists, parseRaw, pruneToShape, readPackageJson, refreshOAuthToken, refreshTokens, resetPassword, response_error, response_ok, response_valibotError, setByPath, signUp, unwrap, verifyOAuthToken, wrapHandler, writeIfDifferent };
1066
1603
 
1067
1604
  //# sourceMappingURL=index.mjs.map