pika-shared 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/types/chatbot/bedrock.d.mts +1 -0
- package/dist/types/chatbot/bedrock.d.ts +1 -0
- package/dist/types/chatbot/chatbot-types.d.mts +584 -22
- package/dist/types/chatbot/chatbot-types.d.ts +584 -22
- package/dist/types/chatbot/chatbot-types.js +19 -3
- package/dist/types/chatbot/chatbot-types.js.map +1 -1
- package/dist/types/chatbot/chatbot-types.mjs +15 -4
- package/dist/types/chatbot/chatbot-types.mjs.map +1 -1
- package/dist/util/api-gateway-utils.js +14 -1
- package/dist/util/api-gateway-utils.js.map +1 -1
- package/dist/util/api-gateway-utils.mjs +14 -1
- package/dist/util/api-gateway-utils.mjs.map +1 -1
- package/dist/util/bad-request-error.d.mts +7 -0
- package/dist/util/bad-request-error.d.ts +7 -0
- package/dist/util/bad-request-error.js +20 -0
- package/dist/util/bad-request-error.js.map +1 -0
- package/dist/util/bad-request-error.mjs +18 -0
- package/dist/util/bad-request-error.mjs.map +1 -0
- package/dist/util/bedrock.d.mts +1 -0
- package/dist/util/bedrock.d.ts +1 -0
- package/dist/util/forbidden-error.d.mts +7 -0
- package/dist/util/forbidden-error.d.ts +7 -0
- package/dist/util/forbidden-error.js +20 -0
- package/dist/util/forbidden-error.js.map +1 -0
- package/dist/util/forbidden-error.mjs +18 -0
- package/dist/util/forbidden-error.mjs.map +1 -0
- package/dist/util/instruction-assistance-utils.d.mts +1 -0
- package/dist/util/instruction-assistance-utils.d.ts +1 -0
- package/dist/util/jwt.d.mts +1 -0
- package/dist/util/jwt.d.ts +1 -0
- package/dist/util/server-utils.d.mts +41 -1
- package/dist/util/server-utils.d.ts +41 -1
- package/dist/util/server-utils.js +303 -0
- package/dist/util/server-utils.js.map +1 -1
- package/dist/util/server-utils.mjs +301 -1
- package/dist/util/server-utils.mjs.map +1 -1
- package/dist/util/unauthorized-error.d.mts +7 -0
- package/dist/util/unauthorized-error.d.ts +7 -0
- package/dist/util/unauthorized-error.js +20 -0
- package/dist/util/unauthorized-error.js.map +1 -0
- package/dist/util/unauthorized-error.mjs +18 -0
- package/dist/util/unauthorized-error.mjs.map +1 -0
- package/package.json +3 -2
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
// src/util/http-status-error.ts
|
|
4
|
+
var HttpStatusError = class extends Error {
|
|
5
|
+
constructor(message, statusCode) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.statusCode = statusCode;
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
|
|
3
11
|
// src/util/api-gateway-utils.ts
|
|
4
12
|
function isObjectResponse(data) {
|
|
5
13
|
return data !== null && data !== void 0 && typeof data === "object" && ("statusCode" in data || "body" in data);
|
|
@@ -25,7 +33,12 @@ function apiGatewayFunctionDecorator(fn) {
|
|
|
25
33
|
}
|
|
26
34
|
if (error) {
|
|
27
35
|
console.error(error);
|
|
28
|
-
|
|
36
|
+
if (error instanceof HttpStatusError) {
|
|
37
|
+
return toResponse(error.message, error.statusCode);
|
|
38
|
+
}
|
|
39
|
+
const httpError = error;
|
|
40
|
+
const statusCode = httpError.statusCode || 500;
|
|
41
|
+
return toResponse(typeof error === "string" ? error : error.message, statusCode);
|
|
29
42
|
}
|
|
30
43
|
if (response === void 0) {
|
|
31
44
|
return toResponse(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/util/api-gateway-utils.ts"],"names":[],"mappings":";;;AAwEA,SAAS,iBAA4B,IAAwG,EAAA;AACzI,EAAO,OAAA,IAAA,KAAS,QAAQ,IAAS,KAAA,MAAA,IAAa,OAAO,IAAS,KAAA,QAAA,KAAa,YAAgB,IAAA,IAAA,IAAQ,MAAU,IAAA,IAAA,CAAA;AACjH;AAaO,SAAS,4BAAqD,EAA8F,EAAA;AAC/J,EAAO,OAAA,OAAO,OAAO,OAAY,KAAA;AAC7B,IAAI,IAAA,KAAA;AACJ,IAAI,IAAA,QAAA;AAIJ,IAAA,MAAA,CAAO,KAAK,KAAM,CAAA,OAAO,CAAE,CAAA,OAAA,CAAQ,CAAC,CAAM,KAAA;AACtC,MAAI,IAAA,MAAA,GAAS,EAAE,WAAY,EAAA;AAC3B,MAAA,IAAI,CAAC,KAAA,CAAM,OAAQ,CAAA,MAAM,CAAG,EAAA;AACxB,QAAA,KAAA,CAAM,OAAQ,CAAA,MAAM,CAAI,GAAA,KAAA,CAAM,QAAQ,CAAC,CAAA;AAAA;AAC3C,KACH,CAAA;AACD,IAAI,IAAA;AAEA,MAAA,MAAM,aAAwD,GAAA;AAAA,QAC1D,GAAI,KAAA;AAAA,QACJ,MAAM,KAAM,CAAA,IAAA,GAAO,KAAK,KAAM,CAAA,KAAA,CAAM,IAAI,CAAI,GAAA,KAAA;AAAA,OAChD;AAGA,MAAW,QAAA,GAAA,MAAM,EAAG,CAAA,aAAA,EAAe,OAAO,CAAA;AAAA,aACrC,GAAK,EAAA;AAEV,MAAQ,KAAA,GAAA,GAAA;AAAA;AAIZ,IAAA,IAAI,KAAO,EAAA;AACP,MAAA,OAAA,CAAQ,MAAM,KAAK,CAAA;AACnB,MAAO,OAAA,UAAA,CAAW,OAAO,KAAU,KAAA,QAAA,GAAW,QAAQ,KAAM,CAAA,OAAA,EAAS,KAAM,CAAA,UAAA,IAAc,GAAG,CAAA;AAAA;AAIhG,IAAA,IAAI,aAAa,MAAW,EAAA;AACxB,MAAO,OAAA,UAAA;AAAA,QACH;AAAA,UACI,OAAS,EAAA,oBAAA;AAAA,UACT,IAAM,EAAA;AAAA,SACV;AAAA,QACA;AAAA,OACJ;AAAA;AAIJ,IAAA,OAAO,iBAAiB,QAAQ,CAAA,GAAI,QAAW,GAAA,UAAA,CAAW,UAAU,GAAG,CAAA;AAAA,GAC3E;AACJ;AAWO,SAAS,UAAA,CAAc,IAAS,EAAA,UAAA,GAAa,GAAwC,EAAA;AACxF,EAAO,OAAA;AAAA,IACH,MAAM,OAAO,IAAA,KAAS,WAAW,IAAO,GAAA,IAAA,CAAK,UAAU,IAAI,CAAA;AAAA,IAC3D;AAAA,GACJ;AACJ;AA0DO,SAAS,iDAAoD,KAAwE,EAAA;AACxI,EAAI,IAAA,KAAA,CAAM,eAAe,QAAY,IAAA,IAAA,IAAQ,MAAM,cAAe,CAAA,UAAA,EAAY,OAAO,IAAM,EAAA;AACvF,IAAA,KAAA,CAAM,cAAe,CAAA,QAAA,GAAW,KAAM,CAAA,cAAA,CAAe,UAAW,CAAA,GAAA;AAChE,IAAA,KAAA,CAAM,eAAe,UAAW,CAAA,GAAA,CAAI,iBAAoB,GAAA,KAAA,CAAM,QAAQ,qBAAqB,CAAA;AAC3F,IAAA,KAAA,CAAM,eAAe,UAAW,CAAA,GAAA,CAAI,OAAO,KAAM,CAAA,cAAA,CAAe,WAAW,GAAI,CAAA,MAAA;AAC/E,IAAA,KAAA,CAAM,eAAe,UAAW,CAAA,GAAA,CAAI,SAAS,KAAM,CAAA,cAAA,CAAe,WAAW,GAAI,CAAA,QAAA;AAAA;AAIrF,EAAA,IAAI,KAAM,CAAA,IAAA,IAAQ,OAAO,KAAA,CAAM,SAAS,QAAU,EAAA;AAC9C,IAAI,IAAA;AAEA,MAAA,MAAM,cAAc,KAAM,CAAA,OAAA,CAAQ,cAAc,CAAK,IAAA,KAAA,CAAM,QAAQ,cAAc,CAAA;AACjF,MAAA,IAAI,WAAe,IAAA,WAAA,CAAY,QAAS,CAAA,kBAAkB,CAAG,EAAA;AACzD,QAAA,KAAA,CAAM,IAAO,GAAA,IAAA,CAAK,KAAM,CAAA,KAAA,CAAM,IAAI,CAAA;AAAA;AACtC,aACK,KAAO,EAAA;AACZ,MAAA,OAAA,CAAQ,MAAM,qCAAuC,EAAA;AAAA,QACjD,MAAM,KAAM,CAAA,IAAA;AAAA,QACZ,cAAc,KAAiB,YAAA,KAAA,GAAQ,KAAM,CAAA,OAAA,GAAU,OAAO,KAAK,CAAA;AAAA,QACnE,UAAY,EAAA,KAAA,YAAiB,KAAQ,GAAA,KAAA,CAAM,KAAQ,GAAA;AAAA,OACtD,CAAA;AACD,MAAM,MAAA,KAAA;AAAA;AACV;AAGJ,EAAO,OAAA,KAAA;AACX","file":"api-gateway-utils.js","sourcesContent":["/**\n * Utility functions and types for AWS API Gateway Lambda integration.\n * This module provides type-safe wrappers and helpers for handling\n * API Gateway events and responses in AWS Lambda functions.\n */\nimport type {\n APIGatewayEventRequestContextV2,\n APIGatewayProxyEventV2WithRequestContext,\n APIGatewayProxyHandlerV2,\n APIGatewayProxyResultV2,\n APIGatewayProxyStructuredResultV2,\n Context\n} from 'aws-lambda';\n\n/**\n * Extends the standard Error interface to include an optional HTTP status code.\n * This allows for standardized error handling with appropriate HTTP responses.\n */\nexport interface HttpError extends Error {\n statusCode?: number;\n}\n\n/**\n * A type that enhances the standard API Gateway event by replacing the body property\n * with a strongly-typed version rather than the default string representation.\n *\n * @template TRequestBody - The type of the request body after parsing\n * @template TRequestContext - The type of the request context\n */\ninterface APIGatewayProxyEventPikaWithRequestContext<TRequestBody, TRequestContext> extends Omit<APIGatewayProxyEventV2WithRequestContext<TRequestContext>, 'body'> {\n body: TRequestBody;\n}\n\n/**\n * A specialized API Gateway event type that includes:\n * 1. A strongly-typed request body\n * 2. The standard API Gateway request context\n * 3. Additional path and httpMethod properties for routing\n *\n * @template TRequestBody - The type of the parsed request body (defaults to never if not provided)\n */\nexport type APIGatewayProxyEventPika<TRequestBody = never> = APIGatewayProxyEventPikaWithRequestContext<TRequestBody, APIGatewayEventRequestContextV2> & {\n path: string;\n httpMethod: string;\n resource: string;\n};\n\n/**\n * A generic handler type for AWS Lambda functions.\n *\n * @template TEvent - The event type (input) for the handler\n * @template TResult - The result type (output) returned by the handler\n * @returns Either void or a Promise containing the result\n */\nexport type HandlerPika<TEvent = unknown, TResult = unknown> = (event: TEvent, context: Context) => void | Promise<TResult>;\n\n/**\n * A specialized handler type for API Gateway Lambda integrations with typed request and response.\n *\n * @template B - The request body type (defaults to never if not provided)\n * @template T - The response type (defaults to never if not provided)\n */\nexport type APIGatewayProxyHandlerPika<B = never, T = never> = HandlerPika<APIGatewayProxyEventPika<B>, APIGatewayProxyResultV2<T>>;\n\n/**\n * Type guard function that determines if the provided data is a structured API Gateway response.\n * A structured response must be an object containing either 'statusCode' or 'body' properties.\n *\n * @template TResponse - The expected response type\n * @param data - The data to check\n * @returns A type predicate indicating if the data is a structured API Gateway response\n */\nfunction isObjectResponse<TResponse>(data: undefined | void | APIGatewayProxyResultV2<TResponse>): data is APIGatewayProxyStructuredResultV2 {\n return data !== null && data !== undefined && typeof data === 'object' && ('statusCode' in data || 'body' in data);\n}\n\n/**\n * A higher-order function that wraps a typed Lambda handler to provide:\n * 1. Automatic JSON parsing of the request body\n * 2. Error handling with appropriate status codes\n * 3. Consistent response formatting\n *\n * @template TRequestBody - The expected type of the request body after parsing\n * @template TResponse - The expected type of the response\n * @param fn - The Lambda handler function to wrap\n * @returns A standard API Gateway Lambda handler with error handling and type safety\n */\nexport function apiGatewayFunctionDecorator<TRequestBody, TResponse>(fn: APIGatewayProxyHandlerPika<TRequestBody, TResponse>): APIGatewayProxyHandlerV2<TResponse> {\n return async (event, context) => {\n let error: HttpError | undefined;\n let response: undefined | void | APIGatewayProxyResultV2<TResponse>;\n\n // Just in case, add another version of the headers with all lowercase keys;\n // helps when running locally. Seems APIGateway automatically converts to lowercase\n Object.keys(event.headers).forEach((k) => {\n let lowerK = k.toLowerCase();\n if (!event.headers[lowerK]) {\n event.headers[lowerK] = event.headers[k];\n }\n });\n try {\n // Parse the request body if present and create a typed event object\n const eventWithType: APIGatewayProxyEventPika<TRequestBody> = {\n ...(event as any),\n body: event.body ? JSON.parse(event.body) : undefined\n };\n\n // Call the handler with the typed event\n response = await fn(eventWithType, context);\n } catch (err) {\n // Capture any errors that occur during processing\n error = err as HttpError;\n }\n\n // Handle errors by returning an appropriate error response\n if (error) {\n console.error(error);\n return toResponse(typeof error === 'string' ? error : error.message, error.statusCode ?? 500);\n }\n\n // Return resource not found if the response is undefined\n if (response === undefined) {\n return toResponse(\n {\n message: 'Resource not found',\n code: 'RESOURCE_NOT_FOUND'\n },\n 404\n );\n }\n\n // Either return the structured response directly or wrap the result in a standard response\n return isObjectResponse(response) ? response : toResponse(response, 200);\n };\n}\n\n/**\n * Creates a standardized API Gateway response object.\n * Handles both string and non-string body types by automatically stringifying as needed.\n *\n * @template T - The type of the response body\n * @param body - The response body to send\n * @param statusCode - The HTTP status code (defaults to 200 OK)\n * @returns A properly formatted API Gateway response object\n */\nexport function toResponse<T>(body: T, statusCode = 200): APIGatewayProxyStructuredResultV2 {\n return {\n body: typeof body === 'string' ? body : JSON.stringify(body),\n statusCode\n };\n}\n\n/**\n * Type definition for Lambda Function URL events with additional IAM authorization details.\n * Extends the standard API Gateway event with specific requestContext properties for\n * Function URL integration patterns.\n *\n * @template T - The request body type\n */\nexport type LambdaFunctionUrlProxyEventPika<T = never> = APIGatewayProxyEventPika<T> & {\n requestContext: {\n authorizer?: {\n iam: {\n cognitoIdentity?: string;\n cognitoIdentityId?: string;\n userId?: string;\n user?: string;\n callerId?: string;\n caller?: string;\n accessKey?: string;\n principalOrgId?: string;\n accountId?: string;\n userArn?: string;\n [key: string]: any;\n };\n };\n identity?: {\n cognitoIdentity?: string;\n cognitoIdentityId?: string;\n user?: string;\n userId?: string;\n caller?: string;\n callerId?: string;\n accessKey?: string;\n principalOrgId?: string;\n accountId?: string;\n userArn?: string;\n [key: string]: any;\n };\n };\n};\n\n/**\n * Converts a Lambda Function URL event into a standardized API Gateway event.\n * This function ensures that IAM authorization details are properly mapped\n * from the authorizer to the identity property for consistent access patterns.\n *\n * Also, parses the body string into the generic type T if it exists and is a string\n *\n * This exists because the Lambda Function URL event has a different structure\n * than the API Gateway event and we almost never use Lambdas that are Function URL based\n * and so it's easier to just convert the event to a standard API Gateway event than\n * to handle the different event types.\n *\n * @template T - The request body type\n * @param event - The Lambda Function URL event to convert\n * @returns A standardized API Gateway event\n */\nexport function convertFunctionUrlEventToStandardApiGatewayEvent<T>(event: LambdaFunctionUrlProxyEventPika<T>): APIGatewayProxyEventPika<T> {\n if (event.requestContext.identity == null && event.requestContext.authorizer?.iam != null) {\n event.requestContext.identity = event.requestContext.authorizer.iam;\n event.requestContext.authorizer.iam.cognitoIdentityId = event.headers['cognito-identity-id'];\n event.requestContext.authorizer.iam.user = event.requestContext.authorizer.iam.userId;\n event.requestContext.authorizer.iam.caller = event.requestContext.authorizer.iam.callerId;\n }\n\n // Parse the body string into the generic type T if it exists and is a string\n if (event.body && typeof event.body === 'string') {\n try {\n // If content-type is not application/json, don't attempt to parse\n const contentType = event.headers['content-type'] || event.headers['Content-Type'];\n if (contentType && contentType.includes('application/json')) {\n event.body = JSON.parse(event.body) as T;\n }\n } catch (error) {\n console.error('Error parsing request body as JSON:', {\n body: event.body,\n errorMessage: error instanceof Error ? error.message : String(error),\n errorStack: error instanceof Error ? error.stack : undefined\n });\n throw error;\n }\n }\n\n return event;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/util/http-status-error.ts","../../src/util/api-gateway-utils.ts"],"names":[],"mappings":"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","file":"api-gateway-utils.js","sourcesContent":["/**\n * Throw this error to return a specific HTTP status code from an API Gateway Lambda function.\n */\nexport class HttpStatusError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number\n ) {\n super(message);\n }\n}\n","/**\n * Utility functions and types for AWS API Gateway Lambda integration.\n * This module provides type-safe wrappers and helpers for handling\n * API Gateway events and responses in AWS Lambda functions.\n */\nimport type {\n APIGatewayEventRequestContextV2,\n APIGatewayProxyEventV2WithRequestContext,\n APIGatewayProxyHandlerV2,\n APIGatewayProxyResultV2,\n APIGatewayProxyStructuredResultV2,\n Context\n} from 'aws-lambda';\nimport { HttpStatusError } from './http-status-error';\n\n/**\n * Extends the standard Error interface to include an optional HTTP status code.\n * This allows for standardized error handling with appropriate HTTP responses.\n */\nexport interface HttpError extends Error {\n statusCode?: number;\n}\n\n/**\n * A type that enhances the standard API Gateway event by replacing the body property\n * with a strongly-typed version rather than the default string representation.\n *\n * @template TRequestBody - The type of the request body after parsing\n * @template TRequestContext - The type of the request context\n */\ninterface APIGatewayProxyEventPikaWithRequestContext<TRequestBody, TRequestContext> extends Omit<APIGatewayProxyEventV2WithRequestContext<TRequestContext>, 'body'> {\n body: TRequestBody;\n}\n\n/**\n * A specialized API Gateway event type that includes:\n * 1. A strongly-typed request body\n * 2. The standard API Gateway request context\n * 3. Additional path and httpMethod properties for routing\n *\n * @template TRequestBody - The type of the parsed request body (defaults to never if not provided)\n */\nexport type APIGatewayProxyEventPika<TRequestBody = never> = APIGatewayProxyEventPikaWithRequestContext<TRequestBody, APIGatewayEventRequestContextV2> & {\n path: string;\n httpMethod: string;\n resource: string;\n};\n\n/**\n * A generic handler type for AWS Lambda functions.\n *\n * @template TEvent - The event type (input) for the handler\n * @template TResult - The result type (output) returned by the handler\n * @returns Either void or a Promise containing the result\n */\nexport type HandlerPika<TEvent = unknown, TResult = unknown> = (event: TEvent, context: Context) => void | Promise<TResult>;\n\n/**\n * A specialized handler type for API Gateway Lambda integrations with typed request and response.\n *\n * @template B - The request body type (defaults to never if not provided)\n * @template T - The response type (defaults to never if not provided)\n */\nexport type APIGatewayProxyHandlerPika<B = never, T = never> = HandlerPika<APIGatewayProxyEventPika<B>, APIGatewayProxyResultV2<T>>;\n\n/**\n * Type guard function that determines if the provided data is a structured API Gateway response.\n * A structured response must be an object containing either 'statusCode' or 'body' properties.\n *\n * @template TResponse - The expected response type\n * @param data - The data to check\n * @returns A type predicate indicating if the data is a structured API Gateway response\n */\nfunction isObjectResponse<TResponse>(data: undefined | void | APIGatewayProxyResultV2<TResponse>): data is APIGatewayProxyStructuredResultV2 {\n return data !== null && data !== undefined && typeof data === 'object' && ('statusCode' in data || 'body' in data);\n}\n\n/**\n * A higher-order function that wraps a typed Lambda handler to provide:\n * 1. Automatic JSON parsing of the request body\n * 2. Error handling with appropriate status codes\n * 3. Consistent response formatting\n *\n * @template TRequestBody - The expected type of the request body after parsing\n * @template TResponse - The expected type of the response\n * @param fn - The Lambda handler function to wrap\n * @returns A standard API Gateway Lambda handler with error handling and type safety\n */\nexport function apiGatewayFunctionDecorator<TRequestBody, TResponse>(fn: APIGatewayProxyHandlerPika<TRequestBody, TResponse>): APIGatewayProxyHandlerV2<TResponse> {\n return async (event, context) => {\n let error: any; // Use 'any' to preserve original error type for instanceof checks\n let response: undefined | void | APIGatewayProxyResultV2<TResponse>;\n\n // Just in case, add another version of the headers with all lowercase keys;\n // helps when running locally. Seems APIGateway automatically converts to lowercase\n Object.keys(event.headers).forEach((k) => {\n let lowerK = k.toLowerCase();\n if (!event.headers[lowerK]) {\n event.headers[lowerK] = event.headers[k];\n }\n });\n try {\n // Parse the request body if present and create a typed event object\n const eventWithType: APIGatewayProxyEventPika<TRequestBody> = {\n ...(event as any),\n body: event.body ? JSON.parse(event.body) : undefined\n };\n\n // Call the handler with the typed event\n response = await fn(eventWithType, context);\n } catch (err) {\n // Capture any errors that occur during processing\n error = err;\n }\n\n // Handle errors by returning an appropriate error response\n if (error) {\n console.error(error);\n\n // Handle HttpStatusError specifically (has required statusCode property)\n if (error instanceof HttpStatusError) {\n return toResponse(error.message, error.statusCode);\n }\n\n // Handle other HttpError types (has optional statusCode property)\n const httpError = error as HttpError;\n const statusCode = httpError.statusCode || 500;\n return toResponse(typeof error === 'string' ? error : error.message, statusCode);\n }\n\n // Return resource not found if the response is undefined\n if (response === undefined) {\n return toResponse(\n {\n message: 'Resource not found',\n code: 'RESOURCE_NOT_FOUND'\n },\n 404\n );\n }\n\n // Either return the structured response directly or wrap the result in a standard response\n return isObjectResponse(response) ? response : toResponse(response, 200);\n };\n}\n\n/**\n * Creates a standardized API Gateway response object.\n * Handles both string and non-string body types by automatically stringifying as needed.\n *\n * @template T - The type of the response body\n * @param body - The response body to send\n * @param statusCode - The HTTP status code (defaults to 200 OK)\n * @returns A properly formatted API Gateway response object\n */\nexport function toResponse<T>(body: T, statusCode = 200): APIGatewayProxyStructuredResultV2 {\n return {\n body: typeof body === 'string' ? body : JSON.stringify(body),\n statusCode\n };\n}\n\n/**\n * Type definition for Lambda Function URL events with additional IAM authorization details.\n * Extends the standard API Gateway event with specific requestContext properties for\n * Function URL integration patterns.\n *\n * @template T - The request body type\n */\nexport type LambdaFunctionUrlProxyEventPika<T = never> = APIGatewayProxyEventPika<T> & {\n requestContext: {\n authorizer?: {\n iam: {\n cognitoIdentity?: string;\n cognitoIdentityId?: string;\n userId?: string;\n user?: string;\n callerId?: string;\n caller?: string;\n accessKey?: string;\n principalOrgId?: string;\n accountId?: string;\n userArn?: string;\n [key: string]: any;\n };\n };\n identity?: {\n cognitoIdentity?: string;\n cognitoIdentityId?: string;\n user?: string;\n userId?: string;\n caller?: string;\n callerId?: string;\n accessKey?: string;\n principalOrgId?: string;\n accountId?: string;\n userArn?: string;\n [key: string]: any;\n };\n };\n};\n\n/**\n * Converts a Lambda Function URL event into a standardized API Gateway event.\n * This function ensures that IAM authorization details are properly mapped\n * from the authorizer to the identity property for consistent access patterns.\n *\n * Also, parses the body string into the generic type T if it exists and is a string\n *\n * This exists because the Lambda Function URL event has a different structure\n * than the API Gateway event and we almost never use Lambdas that are Function URL based\n * and so it's easier to just convert the event to a standard API Gateway event than\n * to handle the different event types.\n *\n * @template T - The request body type\n * @param event - The Lambda Function URL event to convert\n * @returns A standardized API Gateway event\n */\nexport function convertFunctionUrlEventToStandardApiGatewayEvent<T>(event: LambdaFunctionUrlProxyEventPika<T>): APIGatewayProxyEventPika<T> {\n if (event.requestContext.identity == null && event.requestContext.authorizer?.iam != null) {\n event.requestContext.identity = event.requestContext.authorizer.iam;\n event.requestContext.authorizer.iam.cognitoIdentityId = event.headers['cognito-identity-id'];\n event.requestContext.authorizer.iam.user = event.requestContext.authorizer.iam.userId;\n event.requestContext.authorizer.iam.caller = event.requestContext.authorizer.iam.callerId;\n }\n\n // Parse the body string into the generic type T if it exists and is a string\n if (event.body && typeof event.body === 'string') {\n try {\n // If content-type is not application/json, don't attempt to parse\n const contentType = event.headers['content-type'] || event.headers['Content-Type'];\n if (contentType && contentType.includes('application/json')) {\n event.body = JSON.parse(event.body) as T;\n }\n } catch (error) {\n console.error('Error parsing request body as JSON:', {\n body: event.body,\n errorMessage: error instanceof Error ? error.message : String(error),\n errorStack: error instanceof Error ? error.stack : undefined\n });\n throw error;\n }\n }\n\n return event;\n}\n"]}
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
// src/util/http-status-error.ts
|
|
2
|
+
var HttpStatusError = class extends Error {
|
|
3
|
+
constructor(message, statusCode) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.statusCode = statusCode;
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
|
|
1
9
|
// src/util/api-gateway-utils.ts
|
|
2
10
|
function isObjectResponse(data) {
|
|
3
11
|
return data !== null && data !== void 0 && typeof data === "object" && ("statusCode" in data || "body" in data);
|
|
@@ -23,7 +31,12 @@ function apiGatewayFunctionDecorator(fn) {
|
|
|
23
31
|
}
|
|
24
32
|
if (error) {
|
|
25
33
|
console.error(error);
|
|
26
|
-
|
|
34
|
+
if (error instanceof HttpStatusError) {
|
|
35
|
+
return toResponse(error.message, error.statusCode);
|
|
36
|
+
}
|
|
37
|
+
const httpError = error;
|
|
38
|
+
const statusCode = httpError.statusCode || 500;
|
|
39
|
+
return toResponse(typeof error === "string" ? error : error.message, statusCode);
|
|
27
40
|
}
|
|
28
41
|
if (response === void 0) {
|
|
29
42
|
return toResponse(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/util/api-gateway-utils.ts"],"names":[],"mappings":"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","file":"api-gateway-utils.mjs","sourcesContent":["/**\n * Utility functions and types for AWS API Gateway Lambda integration.\n * This module provides type-safe wrappers and helpers for handling\n * API Gateway events and responses in AWS Lambda functions.\n */\nimport type {\n APIGatewayEventRequestContextV2,\n APIGatewayProxyEventV2WithRequestContext,\n APIGatewayProxyHandlerV2,\n APIGatewayProxyResultV2,\n APIGatewayProxyStructuredResultV2,\n Context\n} from 'aws-lambda';\n\n/**\n * Extends the standard Error interface to include an optional HTTP status code.\n * This allows for standardized error handling with appropriate HTTP responses.\n */\nexport interface HttpError extends Error {\n statusCode?: number;\n}\n\n/**\n * A type that enhances the standard API Gateway event by replacing the body property\n * with a strongly-typed version rather than the default string representation.\n *\n * @template TRequestBody - The type of the request body after parsing\n * @template TRequestContext - The type of the request context\n */\ninterface APIGatewayProxyEventPikaWithRequestContext<TRequestBody, TRequestContext> extends Omit<APIGatewayProxyEventV2WithRequestContext<TRequestContext>, 'body'> {\n body: TRequestBody;\n}\n\n/**\n * A specialized API Gateway event type that includes:\n * 1. A strongly-typed request body\n * 2. The standard API Gateway request context\n * 3. Additional path and httpMethod properties for routing\n *\n * @template TRequestBody - The type of the parsed request body (defaults to never if not provided)\n */\nexport type APIGatewayProxyEventPika<TRequestBody = never> = APIGatewayProxyEventPikaWithRequestContext<TRequestBody, APIGatewayEventRequestContextV2> & {\n path: string;\n httpMethod: string;\n resource: string;\n};\n\n/**\n * A generic handler type for AWS Lambda functions.\n *\n * @template TEvent - The event type (input) for the handler\n * @template TResult - The result type (output) returned by the handler\n * @returns Either void or a Promise containing the result\n */\nexport type HandlerPika<TEvent = unknown, TResult = unknown> = (event: TEvent, context: Context) => void | Promise<TResult>;\n\n/**\n * A specialized handler type for API Gateway Lambda integrations with typed request and response.\n *\n * @template B - The request body type (defaults to never if not provided)\n * @template T - The response type (defaults to never if not provided)\n */\nexport type APIGatewayProxyHandlerPika<B = never, T = never> = HandlerPika<APIGatewayProxyEventPika<B>, APIGatewayProxyResultV2<T>>;\n\n/**\n * Type guard function that determines if the provided data is a structured API Gateway response.\n * A structured response must be an object containing either 'statusCode' or 'body' properties.\n *\n * @template TResponse - The expected response type\n * @param data - The data to check\n * @returns A type predicate indicating if the data is a structured API Gateway response\n */\nfunction isObjectResponse<TResponse>(data: undefined | void | APIGatewayProxyResultV2<TResponse>): data is APIGatewayProxyStructuredResultV2 {\n return data !== null && data !== undefined && typeof data === 'object' && ('statusCode' in data || 'body' in data);\n}\n\n/**\n * A higher-order function that wraps a typed Lambda handler to provide:\n * 1. Automatic JSON parsing of the request body\n * 2. Error handling with appropriate status codes\n * 3. Consistent response formatting\n *\n * @template TRequestBody - The expected type of the request body after parsing\n * @template TResponse - The expected type of the response\n * @param fn - The Lambda handler function to wrap\n * @returns A standard API Gateway Lambda handler with error handling and type safety\n */\nexport function apiGatewayFunctionDecorator<TRequestBody, TResponse>(fn: APIGatewayProxyHandlerPika<TRequestBody, TResponse>): APIGatewayProxyHandlerV2<TResponse> {\n return async (event, context) => {\n let error: HttpError | undefined;\n let response: undefined | void | APIGatewayProxyResultV2<TResponse>;\n\n // Just in case, add another version of the headers with all lowercase keys;\n // helps when running locally. Seems APIGateway automatically converts to lowercase\n Object.keys(event.headers).forEach((k) => {\n let lowerK = k.toLowerCase();\n if (!event.headers[lowerK]) {\n event.headers[lowerK] = event.headers[k];\n }\n });\n try {\n // Parse the request body if present and create a typed event object\n const eventWithType: APIGatewayProxyEventPika<TRequestBody> = {\n ...(event as any),\n body: event.body ? JSON.parse(event.body) : undefined\n };\n\n // Call the handler with the typed event\n response = await fn(eventWithType, context);\n } catch (err) {\n // Capture any errors that occur during processing\n error = err as HttpError;\n }\n\n // Handle errors by returning an appropriate error response\n if (error) {\n console.error(error);\n return toResponse(typeof error === 'string' ? error : error.message, error.statusCode ?? 500);\n }\n\n // Return resource not found if the response is undefined\n if (response === undefined) {\n return toResponse(\n {\n message: 'Resource not found',\n code: 'RESOURCE_NOT_FOUND'\n },\n 404\n );\n }\n\n // Either return the structured response directly or wrap the result in a standard response\n return isObjectResponse(response) ? response : toResponse(response, 200);\n };\n}\n\n/**\n * Creates a standardized API Gateway response object.\n * Handles both string and non-string body types by automatically stringifying as needed.\n *\n * @template T - The type of the response body\n * @param body - The response body to send\n * @param statusCode - The HTTP status code (defaults to 200 OK)\n * @returns A properly formatted API Gateway response object\n */\nexport function toResponse<T>(body: T, statusCode = 200): APIGatewayProxyStructuredResultV2 {\n return {\n body: typeof body === 'string' ? body : JSON.stringify(body),\n statusCode\n };\n}\n\n/**\n * Type definition for Lambda Function URL events with additional IAM authorization details.\n * Extends the standard API Gateway event with specific requestContext properties for\n * Function URL integration patterns.\n *\n * @template T - The request body type\n */\nexport type LambdaFunctionUrlProxyEventPika<T = never> = APIGatewayProxyEventPika<T> & {\n requestContext: {\n authorizer?: {\n iam: {\n cognitoIdentity?: string;\n cognitoIdentityId?: string;\n userId?: string;\n user?: string;\n callerId?: string;\n caller?: string;\n accessKey?: string;\n principalOrgId?: string;\n accountId?: string;\n userArn?: string;\n [key: string]: any;\n };\n };\n identity?: {\n cognitoIdentity?: string;\n cognitoIdentityId?: string;\n user?: string;\n userId?: string;\n caller?: string;\n callerId?: string;\n accessKey?: string;\n principalOrgId?: string;\n accountId?: string;\n userArn?: string;\n [key: string]: any;\n };\n };\n};\n\n/**\n * Converts a Lambda Function URL event into a standardized API Gateway event.\n * This function ensures that IAM authorization details are properly mapped\n * from the authorizer to the identity property for consistent access patterns.\n *\n * Also, parses the body string into the generic type T if it exists and is a string\n *\n * This exists because the Lambda Function URL event has a different structure\n * than the API Gateway event and we almost never use Lambdas that are Function URL based\n * and so it's easier to just convert the event to a standard API Gateway event than\n * to handle the different event types.\n *\n * @template T - The request body type\n * @param event - The Lambda Function URL event to convert\n * @returns A standardized API Gateway event\n */\nexport function convertFunctionUrlEventToStandardApiGatewayEvent<T>(event: LambdaFunctionUrlProxyEventPika<T>): APIGatewayProxyEventPika<T> {\n if (event.requestContext.identity == null && event.requestContext.authorizer?.iam != null) {\n event.requestContext.identity = event.requestContext.authorizer.iam;\n event.requestContext.authorizer.iam.cognitoIdentityId = event.headers['cognito-identity-id'];\n event.requestContext.authorizer.iam.user = event.requestContext.authorizer.iam.userId;\n event.requestContext.authorizer.iam.caller = event.requestContext.authorizer.iam.callerId;\n }\n\n // Parse the body string into the generic type T if it exists and is a string\n if (event.body && typeof event.body === 'string') {\n try {\n // If content-type is not application/json, don't attempt to parse\n const contentType = event.headers['content-type'] || event.headers['Content-Type'];\n if (contentType && contentType.includes('application/json')) {\n event.body = JSON.parse(event.body) as T;\n }\n } catch (error) {\n console.error('Error parsing request body as JSON:', {\n body: event.body,\n errorMessage: error instanceof Error ? error.message : String(error),\n errorStack: error instanceof Error ? error.stack : undefined\n });\n throw error;\n }\n }\n\n return event;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/util/http-status-error.ts","../../src/util/api-gateway-utils.ts"],"names":[],"mappings":"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","file":"api-gateway-utils.mjs","sourcesContent":["/**\n * Throw this error to return a specific HTTP status code from an API Gateway Lambda function.\n */\nexport class HttpStatusError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number\n ) {\n super(message);\n }\n}\n","/**\n * Utility functions and types for AWS API Gateway Lambda integration.\n * This module provides type-safe wrappers and helpers for handling\n * API Gateway events and responses in AWS Lambda functions.\n */\nimport type {\n APIGatewayEventRequestContextV2,\n APIGatewayProxyEventV2WithRequestContext,\n APIGatewayProxyHandlerV2,\n APIGatewayProxyResultV2,\n APIGatewayProxyStructuredResultV2,\n Context\n} from 'aws-lambda';\nimport { HttpStatusError } from './http-status-error';\n\n/**\n * Extends the standard Error interface to include an optional HTTP status code.\n * This allows for standardized error handling with appropriate HTTP responses.\n */\nexport interface HttpError extends Error {\n statusCode?: number;\n}\n\n/**\n * A type that enhances the standard API Gateway event by replacing the body property\n * with a strongly-typed version rather than the default string representation.\n *\n * @template TRequestBody - The type of the request body after parsing\n * @template TRequestContext - The type of the request context\n */\ninterface APIGatewayProxyEventPikaWithRequestContext<TRequestBody, TRequestContext> extends Omit<APIGatewayProxyEventV2WithRequestContext<TRequestContext>, 'body'> {\n body: TRequestBody;\n}\n\n/**\n * A specialized API Gateway event type that includes:\n * 1. A strongly-typed request body\n * 2. The standard API Gateway request context\n * 3. Additional path and httpMethod properties for routing\n *\n * @template TRequestBody - The type of the parsed request body (defaults to never if not provided)\n */\nexport type APIGatewayProxyEventPika<TRequestBody = never> = APIGatewayProxyEventPikaWithRequestContext<TRequestBody, APIGatewayEventRequestContextV2> & {\n path: string;\n httpMethod: string;\n resource: string;\n};\n\n/**\n * A generic handler type for AWS Lambda functions.\n *\n * @template TEvent - The event type (input) for the handler\n * @template TResult - The result type (output) returned by the handler\n * @returns Either void or a Promise containing the result\n */\nexport type HandlerPika<TEvent = unknown, TResult = unknown> = (event: TEvent, context: Context) => void | Promise<TResult>;\n\n/**\n * A specialized handler type for API Gateway Lambda integrations with typed request and response.\n *\n * @template B - The request body type (defaults to never if not provided)\n * @template T - The response type (defaults to never if not provided)\n */\nexport type APIGatewayProxyHandlerPika<B = never, T = never> = HandlerPika<APIGatewayProxyEventPika<B>, APIGatewayProxyResultV2<T>>;\n\n/**\n * Type guard function that determines if the provided data is a structured API Gateway response.\n * A structured response must be an object containing either 'statusCode' or 'body' properties.\n *\n * @template TResponse - The expected response type\n * @param data - The data to check\n * @returns A type predicate indicating if the data is a structured API Gateway response\n */\nfunction isObjectResponse<TResponse>(data: undefined | void | APIGatewayProxyResultV2<TResponse>): data is APIGatewayProxyStructuredResultV2 {\n return data !== null && data !== undefined && typeof data === 'object' && ('statusCode' in data || 'body' in data);\n}\n\n/**\n * A higher-order function that wraps a typed Lambda handler to provide:\n * 1. Automatic JSON parsing of the request body\n * 2. Error handling with appropriate status codes\n * 3. Consistent response formatting\n *\n * @template TRequestBody - The expected type of the request body after parsing\n * @template TResponse - The expected type of the response\n * @param fn - The Lambda handler function to wrap\n * @returns A standard API Gateway Lambda handler with error handling and type safety\n */\nexport function apiGatewayFunctionDecorator<TRequestBody, TResponse>(fn: APIGatewayProxyHandlerPika<TRequestBody, TResponse>): APIGatewayProxyHandlerV2<TResponse> {\n return async (event, context) => {\n let error: any; // Use 'any' to preserve original error type for instanceof checks\n let response: undefined | void | APIGatewayProxyResultV2<TResponse>;\n\n // Just in case, add another version of the headers with all lowercase keys;\n // helps when running locally. Seems APIGateway automatically converts to lowercase\n Object.keys(event.headers).forEach((k) => {\n let lowerK = k.toLowerCase();\n if (!event.headers[lowerK]) {\n event.headers[lowerK] = event.headers[k];\n }\n });\n try {\n // Parse the request body if present and create a typed event object\n const eventWithType: APIGatewayProxyEventPika<TRequestBody> = {\n ...(event as any),\n body: event.body ? JSON.parse(event.body) : undefined\n };\n\n // Call the handler with the typed event\n response = await fn(eventWithType, context);\n } catch (err) {\n // Capture any errors that occur during processing\n error = err;\n }\n\n // Handle errors by returning an appropriate error response\n if (error) {\n console.error(error);\n\n // Handle HttpStatusError specifically (has required statusCode property)\n if (error instanceof HttpStatusError) {\n return toResponse(error.message, error.statusCode);\n }\n\n // Handle other HttpError types (has optional statusCode property)\n const httpError = error as HttpError;\n const statusCode = httpError.statusCode || 500;\n return toResponse(typeof error === 'string' ? error : error.message, statusCode);\n }\n\n // Return resource not found if the response is undefined\n if (response === undefined) {\n return toResponse(\n {\n message: 'Resource not found',\n code: 'RESOURCE_NOT_FOUND'\n },\n 404\n );\n }\n\n // Either return the structured response directly or wrap the result in a standard response\n return isObjectResponse(response) ? response : toResponse(response, 200);\n };\n}\n\n/**\n * Creates a standardized API Gateway response object.\n * Handles both string and non-string body types by automatically stringifying as needed.\n *\n * @template T - The type of the response body\n * @param body - The response body to send\n * @param statusCode - The HTTP status code (defaults to 200 OK)\n * @returns A properly formatted API Gateway response object\n */\nexport function toResponse<T>(body: T, statusCode = 200): APIGatewayProxyStructuredResultV2 {\n return {\n body: typeof body === 'string' ? body : JSON.stringify(body),\n statusCode\n };\n}\n\n/**\n * Type definition for Lambda Function URL events with additional IAM authorization details.\n * Extends the standard API Gateway event with specific requestContext properties for\n * Function URL integration patterns.\n *\n * @template T - The request body type\n */\nexport type LambdaFunctionUrlProxyEventPika<T = never> = APIGatewayProxyEventPika<T> & {\n requestContext: {\n authorizer?: {\n iam: {\n cognitoIdentity?: string;\n cognitoIdentityId?: string;\n userId?: string;\n user?: string;\n callerId?: string;\n caller?: string;\n accessKey?: string;\n principalOrgId?: string;\n accountId?: string;\n userArn?: string;\n [key: string]: any;\n };\n };\n identity?: {\n cognitoIdentity?: string;\n cognitoIdentityId?: string;\n user?: string;\n userId?: string;\n caller?: string;\n callerId?: string;\n accessKey?: string;\n principalOrgId?: string;\n accountId?: string;\n userArn?: string;\n [key: string]: any;\n };\n };\n};\n\n/**\n * Converts a Lambda Function URL event into a standardized API Gateway event.\n * This function ensures that IAM authorization details are properly mapped\n * from the authorizer to the identity property for consistent access patterns.\n *\n * Also, parses the body string into the generic type T if it exists and is a string\n *\n * This exists because the Lambda Function URL event has a different structure\n * than the API Gateway event and we almost never use Lambdas that are Function URL based\n * and so it's easier to just convert the event to a standard API Gateway event than\n * to handle the different event types.\n *\n * @template T - The request body type\n * @param event - The Lambda Function URL event to convert\n * @returns A standardized API Gateway event\n */\nexport function convertFunctionUrlEventToStandardApiGatewayEvent<T>(event: LambdaFunctionUrlProxyEventPika<T>): APIGatewayProxyEventPika<T> {\n if (event.requestContext.identity == null && event.requestContext.authorizer?.iam != null) {\n event.requestContext.identity = event.requestContext.authorizer.iam;\n event.requestContext.authorizer.iam.cognitoIdentityId = event.headers['cognito-identity-id'];\n event.requestContext.authorizer.iam.user = event.requestContext.authorizer.iam.userId;\n event.requestContext.authorizer.iam.caller = event.requestContext.authorizer.iam.callerId;\n }\n\n // Parse the body string into the generic type T if it exists and is a string\n if (event.body && typeof event.body === 'string') {\n try {\n // If content-type is not application/json, don't attempt to parse\n const contentType = event.headers['content-type'] || event.headers['Content-Type'];\n if (contentType && contentType.includes('application/json')) {\n event.body = JSON.parse(event.body) as T;\n }\n } catch (error) {\n console.error('Error parsing request body as JSON:', {\n body: event.body,\n errorMessage: error instanceof Error ? error.message : String(error),\n errorStack: error instanceof Error ? error.stack : undefined\n });\n throw error;\n }\n }\n\n return event;\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/util/http-status-error.ts
|
|
4
|
+
var HttpStatusError = class extends Error {
|
|
5
|
+
constructor(message, statusCode) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.statusCode = statusCode;
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// src/util/bad-request-error.ts
|
|
12
|
+
var BadRequestError = class extends HttpStatusError {
|
|
13
|
+
constructor(message) {
|
|
14
|
+
super(message, 400);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
exports.BadRequestError = BadRequestError;
|
|
19
|
+
//# sourceMappingURL=bad-request-error.js.map
|
|
20
|
+
//# sourceMappingURL=bad-request-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/util/http-status-error.ts","../../src/util/bad-request-error.ts"],"names":[],"mappings":";;;AAGO,IAAM,eAAA,GAAN,cAA8B,KAAM,CAAA;AAAA,EACvC,WAAA,CACI,SACgB,UAClB,EAAA;AACE,IAAA,KAAA,CAAM,OAAO,CAAA;AAFG,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AAAA;AAIxB,CAAA;;;ACRa,IAAA,eAAA,GAAN,cAA8B,eAAgB,CAAA;AAAA,EACjD,YAAY,OAAiB,EAAA;AACzB,IAAA,KAAA,CAAM,SAAS,GAAG,CAAA;AAAA;AAE1B","file":"bad-request-error.js","sourcesContent":["/**\n * Throw this error to return a specific HTTP status code from an API Gateway Lambda function.\n */\nexport class HttpStatusError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number\n ) {\n super(message);\n }\n}\n","import { HttpStatusError } from './http-status-error';\n\nexport class BadRequestError extends HttpStatusError {\n constructor(message: string) {\n super(message, 400);\n }\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// src/util/http-status-error.ts
|
|
2
|
+
var HttpStatusError = class extends Error {
|
|
3
|
+
constructor(message, statusCode) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.statusCode = statusCode;
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
// src/util/bad-request-error.ts
|
|
10
|
+
var BadRequestError = class extends HttpStatusError {
|
|
11
|
+
constructor(message) {
|
|
12
|
+
super(message, 400);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export { BadRequestError };
|
|
17
|
+
//# sourceMappingURL=bad-request-error.mjs.map
|
|
18
|
+
//# sourceMappingURL=bad-request-error.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/util/http-status-error.ts","../../src/util/bad-request-error.ts"],"names":[],"mappings":";AAGO,IAAM,eAAA,GAAN,cAA8B,KAAM,CAAA;AAAA,EACvC,WAAA,CACI,SACgB,UAClB,EAAA;AACE,IAAA,KAAA,CAAM,OAAO,CAAA;AAFG,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AAAA;AAIxB,CAAA;;;ACRa,IAAA,eAAA,GAAN,cAA8B,eAAgB,CAAA;AAAA,EACjD,YAAY,OAAiB,EAAA;AACzB,IAAA,KAAA,CAAM,SAAS,GAAG,CAAA;AAAA;AAE1B","file":"bad-request-error.mjs","sourcesContent":["/**\n * Throw this error to return a specific HTTP status code from an API Gateway Lambda function.\n */\nexport class HttpStatusError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number\n ) {\n super(message);\n }\n}\n","import { HttpStatusError } from './http-status-error';\n\nexport class BadRequestError extends HttpStatusError {\n constructor(message: string) {\n super(message, 400);\n }\n}\n"]}
|
package/dist/util/bedrock.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BedrockActionGroupLambdaEvent, BedrockActionGroupLambdaResponse, Parameter } from '../types/chatbot/bedrock.mjs';
|
|
2
2
|
import { SessionDataWithChatUserCustomDataSpreadIn, RecordOrUndef } from '../types/chatbot/chatbot-types.mjs';
|
|
3
3
|
import '@aws-sdk/client-bedrock-agent-runtime';
|
|
4
|
+
import '@aws-sdk/client-bedrock-agentcore';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Handles an error and returns a BedrockLambdaResponse object.
|
package/dist/util/bedrock.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BedrockActionGroupLambdaEvent, BedrockActionGroupLambdaResponse, Parameter } from '../types/chatbot/bedrock.js';
|
|
2
2
|
import { SessionDataWithChatUserCustomDataSpreadIn, RecordOrUndef } from '../types/chatbot/chatbot-types.js';
|
|
3
3
|
import '@aws-sdk/client-bedrock-agent-runtime';
|
|
4
|
+
import '@aws-sdk/client-bedrock-agentcore';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Handles an error and returns a BedrockLambdaResponse object.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/util/http-status-error.ts
|
|
4
|
+
var HttpStatusError = class extends Error {
|
|
5
|
+
constructor(message, statusCode) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.statusCode = statusCode;
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// src/util/forbidden-error.ts
|
|
12
|
+
var ForbiddenError = class extends HttpStatusError {
|
|
13
|
+
constructor(message) {
|
|
14
|
+
super(message, 403);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
exports.ForbiddenError = ForbiddenError;
|
|
19
|
+
//# sourceMappingURL=forbidden-error.js.map
|
|
20
|
+
//# sourceMappingURL=forbidden-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/util/http-status-error.ts","../../src/util/forbidden-error.ts"],"names":[],"mappings":";;;AAGO,IAAM,eAAA,GAAN,cAA8B,KAAM,CAAA;AAAA,EACvC,WAAA,CACI,SACgB,UAClB,EAAA;AACE,IAAA,KAAA,CAAM,OAAO,CAAA;AAFG,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AAAA;AAIxB,CAAA;;;ACRa,IAAA,cAAA,GAAN,cAA6B,eAAgB,CAAA;AAAA,EAChD,YAAY,OAAiB,EAAA;AACzB,IAAA,KAAA,CAAM,SAAS,GAAG,CAAA;AAAA;AAE1B","file":"forbidden-error.js","sourcesContent":["/**\n * Throw this error to return a specific HTTP status code from an API Gateway Lambda function.\n */\nexport class HttpStatusError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number\n ) {\n super(message);\n }\n}\n","import { HttpStatusError } from './http-status-error';\n\nexport class ForbiddenError extends HttpStatusError {\n constructor(message: string) {\n super(message, 403);\n }\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// src/util/http-status-error.ts
|
|
2
|
+
var HttpStatusError = class extends Error {
|
|
3
|
+
constructor(message, statusCode) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.statusCode = statusCode;
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
// src/util/forbidden-error.ts
|
|
10
|
+
var ForbiddenError = class extends HttpStatusError {
|
|
11
|
+
constructor(message) {
|
|
12
|
+
super(message, 403);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export { ForbiddenError };
|
|
17
|
+
//# sourceMappingURL=forbidden-error.mjs.map
|
|
18
|
+
//# sourceMappingURL=forbidden-error.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/util/http-status-error.ts","../../src/util/forbidden-error.ts"],"names":[],"mappings":";AAGO,IAAM,eAAA,GAAN,cAA8B,KAAM,CAAA;AAAA,EACvC,WAAA,CACI,SACgB,UAClB,EAAA;AACE,IAAA,KAAA,CAAM,OAAO,CAAA;AAFG,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AAAA;AAIxB,CAAA;;;ACRa,IAAA,cAAA,GAAN,cAA6B,eAAgB,CAAA;AAAA,EAChD,YAAY,OAAiB,EAAA;AACzB,IAAA,KAAA,CAAM,SAAS,GAAG,CAAA;AAAA;AAE1B","file":"forbidden-error.mjs","sourcesContent":["/**\n * Throw this error to return a specific HTTP status code from an API Gateway Lambda function.\n */\nexport class HttpStatusError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number\n ) {\n super(message);\n }\n}\n","import { HttpStatusError } from './http-status-error';\n\nexport class ForbiddenError extends HttpStatusError {\n constructor(message: string) {\n super(message, 403);\n }\n}\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { InstructionAssistanceConfig, TagsChatAppOverridableFeature, AgentInstructionChatAppOverridableFeature, TagDefinition, TagDefinitionWidget } from '../types/chatbot/chatbot-types.mjs';
|
|
2
2
|
import '@aws-sdk/client-bedrock-agent-runtime';
|
|
3
|
+
import '@aws-sdk/client-bedrock-agentcore';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* IMPORTANT!!!!!!!!!!!!!!!!!!!!!!
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { InstructionAssistanceConfig, TagsChatAppOverridableFeature, AgentInstructionChatAppOverridableFeature, TagDefinition, TagDefinitionWidget } from '../types/chatbot/chatbot-types.js';
|
|
2
2
|
import '@aws-sdk/client-bedrock-agent-runtime';
|
|
3
|
+
import '@aws-sdk/client-bedrock-agentcore';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* IMPORTANT!!!!!!!!!!!!!!!!!!!!!!
|
package/dist/util/jwt.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { RecordOrUndef, SimpleAuthenticatedUser } from '../types/chatbot/chatbot-types.mjs';
|
|
2
2
|
import '@aws-sdk/client-bedrock-agent-runtime';
|
|
3
|
+
import '@aws-sdk/client-bedrock-agentcore';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Converts a payload containing a userId and optional customUserData into a JWT string.
|
package/dist/util/jwt.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { RecordOrUndef, SimpleAuthenticatedUser } from '../types/chatbot/chatbot-types.js';
|
|
2
2
|
import '@aws-sdk/client-bedrock-agent-runtime';
|
|
3
|
+
import '@aws-sdk/client-bedrock-agentcore';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Converts a payload containing a userId and optional customUserData into a JWT string.
|
|
@@ -1,4 +1,44 @@
|
|
|
1
|
+
import { SiteFeatures, ChatApp, AuthenticatedUser, RecordOrUndef, ChatAppOverridableFeatures, AccessRules, ChatUser } from '../types/chatbot/chatbot-types.mjs';
|
|
2
|
+
import '@aws-sdk/client-bedrock-agent-runtime';
|
|
3
|
+
import '@aws-sdk/client-bedrock-agentcore';
|
|
4
|
+
|
|
1
5
|
declare function gunzipBase64EncodedString(base64EncodedString: string): string;
|
|
2
6
|
declare function gzipAndBase64EncodeString(string: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* Compute what features the user is and isn't allowed to use for this chat app.
|
|
9
|
+
*
|
|
10
|
+
* Feature hierarchy (in order of precedence):
|
|
11
|
+
* 1. Site level (<root>/pika-config.ts) - Controls ultimate availability
|
|
12
|
+
* 2. Chat app level (chatApp.features) - Can override site settings
|
|
13
|
+
* 3. Admin override level (chatApp.override.features) - Can override chat app settings
|
|
14
|
+
*
|
|
15
|
+
* Note that we always return siteAdmin: { websiteEnabled: false } because we only check that for real when they try to access the admin page itself.
|
|
16
|
+
*
|
|
17
|
+
* Override rules:
|
|
18
|
+
* - Site level controls whether a feature can be used at all
|
|
19
|
+
* - Chat apps can override site level (but only to restrict)
|
|
20
|
+
* - Admins can override chat app level completely (but cannot enable features disabled at site level)
|
|
21
|
+
* - When overriding, complete feature configuration must be provided (no merging)
|
|
22
|
+
*/
|
|
23
|
+
declare function getOverridableFeatures(siteFeatures: SiteFeatures, chatApp: ChatApp, user: AuthenticatedUser<RecordOrUndef, RecordOrUndef>): ChatAppOverridableFeatures;
|
|
24
|
+
/**
|
|
25
|
+
* Generic function to check if a user has access to a feature based on user types and roles.
|
|
26
|
+
* This implements the same logic used in get for checking user access rules.
|
|
27
|
+
*
|
|
28
|
+
* **Access Control Logic:**
|
|
29
|
+
* - If the feature is disabled (`enabled: false`), no access regardless of other rules
|
|
30
|
+
* - If no userTypes or userRoles are specified, no access is granted (secure by default)
|
|
31
|
+
* - If multiple userTypes are provided, a user need only have one of them to have access (OR logic)
|
|
32
|
+
* - If multiple userRoles are provided, a user need only have one of them to have access (OR logic)
|
|
33
|
+
* - If both userTypes and userRoles are provided, the `applyRulesAs` setting determines how they're combined:
|
|
34
|
+
* - `'and'` (default): User must match a userType AND have a userRole
|
|
35
|
+
* - `'or'`: User must match a userType OR have a userRole
|
|
36
|
+
*
|
|
37
|
+
* @param user - The authenticated user to check access for
|
|
38
|
+
* @param feature - The feature configuration with user access rules
|
|
39
|
+
* @returns Whether the user has access to the feature
|
|
40
|
+
*/
|
|
41
|
+
declare function checkUserAccessToFeature(user: AuthenticatedUser<RecordOrUndef, RecordOrUndef>, feature: AccessRules): boolean;
|
|
42
|
+
declare function getEntityIdForUser(user: ChatUser<RecordOrUndef>, overrideDataForThisChatApp: RecordOrUndef, entityAttributeName?: string): string | undefined;
|
|
3
43
|
|
|
4
|
-
export { gunzipBase64EncodedString, gzipAndBase64EncodeString };
|
|
44
|
+
export { checkUserAccessToFeature, getEntityIdForUser, getOverridableFeatures, gunzipBase64EncodedString, gzipAndBase64EncodeString };
|
|
@@ -1,4 +1,44 @@
|
|
|
1
|
+
import { SiteFeatures, ChatApp, AuthenticatedUser, RecordOrUndef, ChatAppOverridableFeatures, AccessRules, ChatUser } from '../types/chatbot/chatbot-types.js';
|
|
2
|
+
import '@aws-sdk/client-bedrock-agent-runtime';
|
|
3
|
+
import '@aws-sdk/client-bedrock-agentcore';
|
|
4
|
+
|
|
1
5
|
declare function gunzipBase64EncodedString(base64EncodedString: string): string;
|
|
2
6
|
declare function gzipAndBase64EncodeString(string: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* Compute what features the user is and isn't allowed to use for this chat app.
|
|
9
|
+
*
|
|
10
|
+
* Feature hierarchy (in order of precedence):
|
|
11
|
+
* 1. Site level (<root>/pika-config.ts) - Controls ultimate availability
|
|
12
|
+
* 2. Chat app level (chatApp.features) - Can override site settings
|
|
13
|
+
* 3. Admin override level (chatApp.override.features) - Can override chat app settings
|
|
14
|
+
*
|
|
15
|
+
* Note that we always return siteAdmin: { websiteEnabled: false } because we only check that for real when they try to access the admin page itself.
|
|
16
|
+
*
|
|
17
|
+
* Override rules:
|
|
18
|
+
* - Site level controls whether a feature can be used at all
|
|
19
|
+
* - Chat apps can override site level (but only to restrict)
|
|
20
|
+
* - Admins can override chat app level completely (but cannot enable features disabled at site level)
|
|
21
|
+
* - When overriding, complete feature configuration must be provided (no merging)
|
|
22
|
+
*/
|
|
23
|
+
declare function getOverridableFeatures(siteFeatures: SiteFeatures, chatApp: ChatApp, user: AuthenticatedUser<RecordOrUndef, RecordOrUndef>): ChatAppOverridableFeatures;
|
|
24
|
+
/**
|
|
25
|
+
* Generic function to check if a user has access to a feature based on user types and roles.
|
|
26
|
+
* This implements the same logic used in get for checking user access rules.
|
|
27
|
+
*
|
|
28
|
+
* **Access Control Logic:**
|
|
29
|
+
* - If the feature is disabled (`enabled: false`), no access regardless of other rules
|
|
30
|
+
* - If no userTypes or userRoles are specified, no access is granted (secure by default)
|
|
31
|
+
* - If multiple userTypes are provided, a user need only have one of them to have access (OR logic)
|
|
32
|
+
* - If multiple userRoles are provided, a user need only have one of them to have access (OR logic)
|
|
33
|
+
* - If both userTypes and userRoles are provided, the `applyRulesAs` setting determines how they're combined:
|
|
34
|
+
* - `'and'` (default): User must match a userType AND have a userRole
|
|
35
|
+
* - `'or'`: User must match a userType OR have a userRole
|
|
36
|
+
*
|
|
37
|
+
* @param user - The authenticated user to check access for
|
|
38
|
+
* @param feature - The feature configuration with user access rules
|
|
39
|
+
* @returns Whether the user has access to the feature
|
|
40
|
+
*/
|
|
41
|
+
declare function checkUserAccessToFeature(user: AuthenticatedUser<RecordOrUndef, RecordOrUndef>, feature: AccessRules): boolean;
|
|
42
|
+
declare function getEntityIdForUser(user: ChatUser<RecordOrUndef>, overrideDataForThisChatApp: RecordOrUndef, entityAttributeName?: string): string | undefined;
|
|
3
43
|
|
|
4
|
-
export { gunzipBase64EncodedString, gzipAndBase64EncodeString };
|
|
44
|
+
export { checkUserAccessToFeature, getEntityIdForUser, getOverridableFeatures, gunzipBase64EncodedString, gzipAndBase64EncodeString };
|