@venturekit/runtime 0.0.0-dev.20260312012510 → 0.0.0-dev.20260329102450
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/README.md +1 -1
- package/dist/config/env.d.ts +62 -0
- package/dist/config/env.d.ts.map +1 -0
- package/dist/config/env.js +98 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/secrets.d.ts +67 -0
- package/dist/config/secrets.d.ts.map +1 -0
- package/dist/config/secrets.js +132 -0
- package/dist/config/secrets.js.map +1 -0
- package/dist/handler/adapter.d.ts.map +1 -0
- package/dist/{adapter.js → handler/adapter.js} +5 -44
- package/dist/handler/adapter.js.map +1 -0
- package/dist/{context.d.ts → handler/context.d.ts} +44 -3
- package/dist/handler/context.d.ts.map +1 -0
- package/dist/{context.js → handler/context.js} +9 -9
- package/dist/handler/context.js.map +1 -0
- package/dist/handler/errors.d.ts.map +1 -0
- package/dist/{errors.js → handler/errors.js} +11 -25
- package/dist/handler/errors.js.map +1 -0
- package/dist/{handler.d.ts → handler/handler.d.ts} +36 -3
- package/dist/handler/handler.d.ts.map +1 -0
- package/dist/{handler.js → handler/handler.js} +59 -23
- package/dist/handler/handler.js.map +1 -0
- package/dist/handler/response.d.ts.map +1 -0
- package/dist/{response.js → handler/response.js} +9 -17
- package/dist/handler/response.js.map +1 -0
- package/dist/handler/task-handler.d.ts +192 -0
- package/dist/handler/task-handler.d.ts.map +1 -0
- package/dist/handler/task-handler.js +262 -0
- package/dist/handler/task-handler.js.map +1 -0
- package/dist/index.d.ts +33 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -48
- package/dist/index.js.map +1 -1
- package/dist/{logger.d.ts → logging/logger.d.ts} +1 -1
- package/dist/logging/logger.d.ts.map +1 -0
- package/dist/{logger.js → logging/logger.js} +8 -16
- package/dist/logging/logger.js.map +1 -0
- package/dist/logging/tracing.d.ts +51 -0
- package/dist/logging/tracing.d.ts.map +1 -0
- package/dist/logging/tracing.js +77 -0
- package/dist/logging/tracing.js.map +1 -0
- package/dist/middleware/middleware.d.ts +120 -0
- package/dist/middleware/middleware.d.ts.map +1 -0
- package/dist/middleware/middleware.js +270 -0
- package/dist/middleware/middleware.js.map +1 -0
- package/dist/middleware/rate-limit-store.d.ts +153 -0
- package/dist/middleware/rate-limit-store.d.ts.map +1 -0
- package/dist/middleware/rate-limit-store.js +182 -0
- package/dist/middleware/rate-limit-store.js.map +1 -0
- package/dist/openapi/openapi.d.ts +147 -0
- package/dist/openapi/openapi.d.ts.map +1 -0
- package/dist/openapi/openapi.js +235 -0
- package/dist/openapi/openapi.js.map +1 -0
- package/dist/openapi.d.ts +10 -0
- package/dist/openapi.d.ts.map +1 -0
- package/dist/openapi.js +9 -0
- package/dist/openapi.js.map +1 -0
- package/dist/patterns/circuit-breaker.d.ts +78 -0
- package/dist/patterns/circuit-breaker.d.ts.map +1 -0
- package/dist/patterns/circuit-breaker.js +113 -0
- package/dist/patterns/circuit-breaker.js.map +1 -0
- package/dist/patterns/idempotency.d.ts +175 -0
- package/dist/patterns/idempotency.d.ts.map +1 -0
- package/dist/patterns/idempotency.js +305 -0
- package/dist/patterns/idempotency.js.map +1 -0
- package/dist/patterns/invoke.d.ts +279 -0
- package/dist/patterns/invoke.d.ts.map +1 -0
- package/dist/patterns/invoke.js +581 -0
- package/dist/patterns/invoke.js.map +1 -0
- package/dist/patterns/saga.d.ts +391 -0
- package/dist/patterns/saga.d.ts.map +1 -0
- package/dist/patterns/saga.js +556 -0
- package/dist/patterns/saga.js.map +1 -0
- package/dist/patterns.d.ts +17 -0
- package/dist/patterns.d.ts.map +1 -0
- package/dist/patterns.js +17 -0
- package/dist/patterns.js.map +1 -0
- package/dist/rate-limit.d.ts +16 -0
- package/dist/rate-limit.d.ts.map +1 -0
- package/dist/rate-limit.js +15 -0
- package/dist/rate-limit.js.map +1 -0
- package/dist/secrets.d.ts +11 -0
- package/dist/secrets.d.ts.map +1 -0
- package/dist/secrets.js +10 -0
- package/dist/secrets.js.map +1 -0
- package/dist/testing/test-utils.d.ts +99 -0
- package/dist/testing/test-utils.d.ts.map +1 -0
- package/dist/testing/test-utils.js +153 -0
- package/dist/testing/test-utils.js.map +1 -0
- package/dist/testing.d.ts +10 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +9 -0
- package/dist/testing.js.map +1 -0
- package/dist/ws/ws.d.ts +139 -0
- package/dist/ws/ws.d.ts.map +1 -0
- package/dist/ws/ws.js +294 -0
- package/dist/ws/ws.js.map +1 -0
- package/dist/ws.d.ts +5 -133
- package/dist/ws.d.ts.map +1 -1
- package/dist/ws.js +4 -291
- package/dist/ws.js.map +1 -1
- package/package.json +47 -5
- package/dist/adapter.d.ts.map +0 -1
- package/dist/adapter.js.map +0 -1
- package/dist/context.d.ts.map +0 -1
- package/dist/context.js.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js.map +0 -1
- package/dist/handler.d.ts.map +0 -1
- package/dist/handler.js.map +0 -1
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js.map +0 -1
- package/dist/middleware.d.ts +0 -47
- package/dist/middleware.d.ts.map +0 -1
- package/dist/middleware.js +0 -147
- package/dist/middleware.js.map +0 -1
- package/dist/response.d.ts.map +0 -1
- package/dist/response.js.map +0 -1
- /package/dist/{adapter.d.ts → handler/adapter.d.ts} +0 -0
- /package/dist/{errors.d.ts → handler/errors.d.ts} +0 -0
- /package/dist/{response.d.ts → handler/response.d.ts} +0 -0
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* VentureKit Runtime Errors
|
|
4
3
|
*
|
|
5
4
|
* Standardized error types for consistent error handling across handlers.
|
|
6
5
|
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.ServiceUnavailableError = exports.InternalError = exports.RateLimitError = exports.ValidationError = exports.ConflictError = exports.NotFoundError = exports.ForbiddenError = exports.UnauthorizedError = exports.BadRequestError = exports.VentureError = void 0;
|
|
9
|
-
exports.isVentureError = isVentureError;
|
|
10
6
|
/**
|
|
11
7
|
* Base error class for all VentureKit errors
|
|
12
8
|
*/
|
|
13
|
-
class VentureError extends Error {
|
|
9
|
+
export class VentureError extends Error {
|
|
14
10
|
code;
|
|
15
11
|
statusCode;
|
|
16
12
|
details;
|
|
@@ -31,62 +27,56 @@ class VentureError extends Error {
|
|
|
31
27
|
};
|
|
32
28
|
}
|
|
33
29
|
}
|
|
34
|
-
exports.VentureError = VentureError;
|
|
35
30
|
/**
|
|
36
31
|
* 400 Bad Request - Invalid input
|
|
37
32
|
*/
|
|
38
|
-
class BadRequestError extends VentureError {
|
|
33
|
+
export class BadRequestError extends VentureError {
|
|
39
34
|
constructor(message, details) {
|
|
40
35
|
super('BAD_REQUEST', message, 400, details);
|
|
41
36
|
this.name = 'BadRequestError';
|
|
42
37
|
}
|
|
43
38
|
}
|
|
44
|
-
exports.BadRequestError = BadRequestError;
|
|
45
39
|
/**
|
|
46
40
|
* 401 Unauthorized - Missing or invalid authentication
|
|
47
41
|
*/
|
|
48
|
-
class UnauthorizedError extends VentureError {
|
|
42
|
+
export class UnauthorizedError extends VentureError {
|
|
49
43
|
constructor(message = 'Authentication required') {
|
|
50
44
|
super('UNAUTHORIZED', message, 401);
|
|
51
45
|
this.name = 'UnauthorizedError';
|
|
52
46
|
}
|
|
53
47
|
}
|
|
54
|
-
exports.UnauthorizedError = UnauthorizedError;
|
|
55
48
|
/**
|
|
56
49
|
* 403 Forbidden - Authenticated but not allowed
|
|
57
50
|
*/
|
|
58
|
-
class ForbiddenError extends VentureError {
|
|
51
|
+
export class ForbiddenError extends VentureError {
|
|
59
52
|
constructor(message = 'Access denied') {
|
|
60
53
|
super('FORBIDDEN', message, 403);
|
|
61
54
|
this.name = 'ForbiddenError';
|
|
62
55
|
}
|
|
63
56
|
}
|
|
64
|
-
exports.ForbiddenError = ForbiddenError;
|
|
65
57
|
/**
|
|
66
58
|
* 404 Not Found - Resource doesn't exist
|
|
67
59
|
*/
|
|
68
|
-
class NotFoundError extends VentureError {
|
|
60
|
+
export class NotFoundError extends VentureError {
|
|
69
61
|
constructor(resource, id) {
|
|
70
62
|
const message = id ? `${resource} '${id}' not found` : `${resource} not found`;
|
|
71
63
|
super('NOT_FOUND', message, 404, { resource, id });
|
|
72
64
|
this.name = 'NotFoundError';
|
|
73
65
|
}
|
|
74
66
|
}
|
|
75
|
-
exports.NotFoundError = NotFoundError;
|
|
76
67
|
/**
|
|
77
68
|
* 409 Conflict - Resource already exists or state conflict
|
|
78
69
|
*/
|
|
79
|
-
class ConflictError extends VentureError {
|
|
70
|
+
export class ConflictError extends VentureError {
|
|
80
71
|
constructor(message, details) {
|
|
81
72
|
super('CONFLICT', message, 409, details);
|
|
82
73
|
this.name = 'ConflictError';
|
|
83
74
|
}
|
|
84
75
|
}
|
|
85
|
-
exports.ConflictError = ConflictError;
|
|
86
76
|
/**
|
|
87
77
|
* 422 Unprocessable Entity - Validation failed
|
|
88
78
|
*/
|
|
89
|
-
class ValidationError extends VentureError {
|
|
79
|
+
export class ValidationError extends VentureError {
|
|
90
80
|
fieldErrors;
|
|
91
81
|
constructor(message, fieldErrors) {
|
|
92
82
|
super('VALIDATION_ERROR', message, 422, { fields: fieldErrors });
|
|
@@ -94,41 +84,37 @@ class ValidationError extends VentureError {
|
|
|
94
84
|
this.name = 'ValidationError';
|
|
95
85
|
}
|
|
96
86
|
}
|
|
97
|
-
exports.ValidationError = ValidationError;
|
|
98
87
|
/**
|
|
99
88
|
* 429 Too Many Requests - Rate limited
|
|
100
89
|
*/
|
|
101
|
-
class RateLimitError extends VentureError {
|
|
90
|
+
export class RateLimitError extends VentureError {
|
|
102
91
|
constructor(retryAfterSec) {
|
|
103
92
|
super('RATE_LIMITED', 'Too many requests', 429, retryAfterSec ? { retryAfterSec } : undefined);
|
|
104
93
|
this.name = 'RateLimitError';
|
|
105
94
|
}
|
|
106
95
|
}
|
|
107
|
-
exports.RateLimitError = RateLimitError;
|
|
108
96
|
/**
|
|
109
97
|
* 500 Internal Server Error - Unexpected error
|
|
110
98
|
*/
|
|
111
|
-
class InternalError extends VentureError {
|
|
99
|
+
export class InternalError extends VentureError {
|
|
112
100
|
constructor(message = 'Internal server error') {
|
|
113
101
|
super('INTERNAL_ERROR', message, 500);
|
|
114
102
|
this.name = 'InternalError';
|
|
115
103
|
}
|
|
116
104
|
}
|
|
117
|
-
exports.InternalError = InternalError;
|
|
118
105
|
/**
|
|
119
106
|
* 503 Service Unavailable - Dependency failure
|
|
120
107
|
*/
|
|
121
|
-
class ServiceUnavailableError extends VentureError {
|
|
108
|
+
export class ServiceUnavailableError extends VentureError {
|
|
122
109
|
constructor(service) {
|
|
123
110
|
super('SERVICE_UNAVAILABLE', `${service} is currently unavailable`, 503, { service });
|
|
124
111
|
this.name = 'ServiceUnavailableError';
|
|
125
112
|
}
|
|
126
113
|
}
|
|
127
|
-
exports.ServiceUnavailableError = ServiceUnavailableError;
|
|
128
114
|
/**
|
|
129
115
|
* Check if an error is a VentureError
|
|
130
116
|
*/
|
|
131
|
-
function isVentureError(error) {
|
|
117
|
+
export function isVentureError(error) {
|
|
132
118
|
return error instanceof VentureError;
|
|
133
119
|
}
|
|
134
120
|
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/handler/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,OAAO,YAAa,SAAQ,KAAK;IAEnB;IAEA;IACA;IAJlB,YACkB,IAAY,EAC5B,OAAe,EACC,aAAqB,GAAG,EACxB,OAAiC;QAEjD,KAAK,CAAC,OAAO,CAAC,CAAC;QALC,SAAI,GAAJ,IAAI,CAAQ;QAEZ,eAAU,GAAV,UAAU,CAAc;QACxB,YAAO,GAAP,OAAO,CAA0B;QAGjD,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;IAED,MAAM;QACJ,OAAO;YACL,KAAK,EAAE;gBACL,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;aAC/C;SACF,CAAC;IACJ,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,YAAY;IAC/C,YAAY,OAAe,EAAE,OAAiC;QAC5D,KAAK,CAAC,aAAa,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,iBAAkB,SAAQ,YAAY;IACjD,YAAY,UAAkB,yBAAyB;QACrD,KAAK,CAAC,cAAc,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,cAAe,SAAQ,YAAY;IAC9C,YAAY,UAAkB,eAAe;QAC3C,KAAK,CAAC,WAAW,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,YAAY;IAC7C,YAAY,QAAgB,EAAE,EAAW;QACvC,MAAM,OAAO,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,QAAQ,YAAY,CAAC;QAC/E,KAAK,CAAC,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;QACnD,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,YAAY;IAC7C,YAAY,OAAe,EAAE,OAAiC;QAC5D,KAAK,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,YAAY;IAG7B;IAFlB,YACE,OAAe,EACC,WAAqC;QAErD,KAAK,CAAC,kBAAkB,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;QAFjD,gBAAW,GAAX,WAAW,CAA0B;QAGrD,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,cAAe,SAAQ,YAAY;IAC9C,YAAY,aAAsB;QAChC,KAAK,CAAC,cAAc,EAAE,mBAAmB,EAAE,GAAG,EAC5C,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,SAAS,CAC9C,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,YAAY;IAC7C,YAAY,UAAkB,uBAAuB;QACnD,KAAK,CAAC,gBAAgB,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,uBAAwB,SAAQ,YAAY;IACvD,YAAY,OAAe;QACzB,KAAK,CAAC,qBAAqB,EAAE,GAAG,OAAO,2BAA2B,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QACtF,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,KAAK,YAAY,YAAY,CAAC;AACvC,CAAC"}
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { APIGatewayProxyEventV2, APIGatewayProxyResultV2, Context } from 'aws-lambda';
|
|
10
10
|
import { RequestContext } from './context.js';
|
|
11
|
-
import { Logger } from '
|
|
12
|
-
import { Middleware } from '
|
|
11
|
+
import { Logger } from '../logging/logger.js';
|
|
12
|
+
import { Middleware } from '../middleware/middleware.js';
|
|
13
13
|
/**
|
|
14
14
|
* Handler function signature
|
|
15
15
|
*/
|
|
@@ -18,10 +18,27 @@ export type HandlerFn<TBody = unknown, TResult = unknown> = (body: TBody, ctx: R
|
|
|
18
18
|
* HTTP Status codes
|
|
19
19
|
*/
|
|
20
20
|
export type StatusCode = 200 | 201 | 204;
|
|
21
|
+
/**
|
|
22
|
+
* Zod-like schema interface (compatible with Zod without hard dependency)
|
|
23
|
+
*/
|
|
24
|
+
export interface ZodLikeSchema<T = unknown> {
|
|
25
|
+
safeParse(data: unknown): {
|
|
26
|
+
success: true;
|
|
27
|
+
data: T;
|
|
28
|
+
} | {
|
|
29
|
+
success: false;
|
|
30
|
+
error: {
|
|
31
|
+
issues: Array<{
|
|
32
|
+
path: (string | number)[];
|
|
33
|
+
message: string;
|
|
34
|
+
}>;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
}
|
|
21
38
|
/**
|
|
22
39
|
* Handler configuration
|
|
23
40
|
*/
|
|
24
|
-
export interface HandlerConfig {
|
|
41
|
+
export interface HandlerConfig<TBody = unknown, TQuery = unknown, TParams = unknown> {
|
|
25
42
|
/**
|
|
26
43
|
* Required OAuth scopes
|
|
27
44
|
* - Empty array or undefined = public endpoint (no auth)
|
|
@@ -46,6 +63,22 @@ export interface HandlerConfig {
|
|
|
46
63
|
* Requires @venturekit/data to be installed.
|
|
47
64
|
*/
|
|
48
65
|
transactional?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Zod schema for request body validation.
|
|
68
|
+
* If provided, the body is parsed and validated before the handler runs.
|
|
69
|
+
* On failure, a 422 ValidationError is thrown with structured field errors.
|
|
70
|
+
*/
|
|
71
|
+
body?: ZodLikeSchema<TBody>;
|
|
72
|
+
/**
|
|
73
|
+
* Zod schema for query parameter validation.
|
|
74
|
+
* Query params are extracted from the event and validated.
|
|
75
|
+
*/
|
|
76
|
+
query?: ZodLikeSchema<TQuery>;
|
|
77
|
+
/**
|
|
78
|
+
* Zod schema for path parameter validation.
|
|
79
|
+
* Path params are extracted from the event and validated.
|
|
80
|
+
*/
|
|
81
|
+
params?: ZodLikeSchema<TParams>;
|
|
49
82
|
}
|
|
50
83
|
/**
|
|
51
84
|
* VentureKit unified handler
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/handler/handler.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC3F,OAAO,EAAE,cAAc,EAAgB,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAgB,MAAM,sBAAsB,CAAC;AAE5D,OAAO,EAAW,UAAU,EAA8C,MAAM,6BAA6B,CAAC;AAG9G;;GAEG;AACH,MAAM,MAAM,SAAS,CAAC,KAAK,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,CAC1D,IAAI,EAAE,KAAK,EACX,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,KACX,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAEzC;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,OAAO;IACxC,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG;QAAE,OAAO,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,CAAC,CAAA;KAAE,GAAG;QAAE,OAAO,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE;YAAE,MAAM,EAAE,KAAK,CAAC;gBAAE,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;gBAAC,OAAO,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,CAAA;KAAE,CAAC;CACrJ;AAED;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO;IACjF;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB;;;;OAIG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;IAEpB,iCAAiC;IACjC,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC;IAE1B,gBAAgB;IAChB,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAE/C;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;;OAIG;IACH,IAAI,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IAE5B;;;OAGG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAE9B;;;OAGG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;CACjC;AAoDD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,OAAO,CAAC,KAAK,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,EACxD,EAAE,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,EAC7B,MAAM,GAAE,aAAkB,GACzB,CAAC,KAAK,EAAE,sBAAsB,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,uBAAuB,CAAC,CAgHvF"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* VentureKit Handler
|
|
4
3
|
*
|
|
@@ -7,13 +6,11 @@
|
|
|
7
6
|
* - With scopes = authenticated + scope check
|
|
8
7
|
* - Status code auto-detected from HTTP method or explicitly set
|
|
9
8
|
*/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const middleware_js_1 = require("./middleware.js");
|
|
16
|
-
const errors_js_1 = require("./errors.js");
|
|
9
|
+
import { buildContext } from './context.js';
|
|
10
|
+
import { createLogger } from '../logging/logger.js';
|
|
11
|
+
import { success, created, noContent, errorResponse } from './response.js';
|
|
12
|
+
import { compose, loggingMiddleware, errorBoundaryMiddleware } from '../middleware/middleware.js';
|
|
13
|
+
import { UnauthorizedError, ForbiddenError, ValidationError } from './errors.js';
|
|
17
14
|
/**
|
|
18
15
|
* Parse request body
|
|
19
16
|
*/
|
|
@@ -45,6 +42,20 @@ function getStatusCode(method, explicit) {
|
|
|
45
42
|
return 200;
|
|
46
43
|
}
|
|
47
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Convert Zod-like issues to a ValidationError
|
|
47
|
+
*/
|
|
48
|
+
function zodToValidationError(source, issues) {
|
|
49
|
+
const fieldErrors = {};
|
|
50
|
+
for (const issue of issues) {
|
|
51
|
+
const field = issue.path.length > 0 ? issue.path.join('.') : source;
|
|
52
|
+
if (!fieldErrors[field]) {
|
|
53
|
+
fieldErrors[field] = [];
|
|
54
|
+
}
|
|
55
|
+
fieldErrors[field].push(issue.message);
|
|
56
|
+
}
|
|
57
|
+
return new ValidationError(`Validation failed on ${source}`, fieldErrors);
|
|
58
|
+
}
|
|
48
59
|
/**
|
|
49
60
|
* VentureKit unified handler
|
|
50
61
|
*
|
|
@@ -66,39 +77,64 @@ function getStatusCode(method, explicit) {
|
|
|
66
77
|
* }, { scopes: ['projects.write'] });
|
|
67
78
|
* ```
|
|
68
79
|
*/
|
|
69
|
-
function handler(fn, config = {}) {
|
|
80
|
+
export function handler(fn, config = {}) {
|
|
70
81
|
const { scopes = [], status, middleware = [], logLevel = 'info', } = config;
|
|
71
82
|
const requiresAuth = scopes.length > 0;
|
|
72
|
-
const logger =
|
|
83
|
+
const logger = createLogger({ minLevel: logLevel });
|
|
73
84
|
// Build middleware stack
|
|
74
85
|
const middlewareStack = [
|
|
75
86
|
// Error boundary (outermost)
|
|
76
|
-
|
|
87
|
+
errorBoundaryMiddleware((error, ctx) => errorResponse(error, { requestId: ctx.requestId })),
|
|
77
88
|
// Logging
|
|
78
|
-
|
|
89
|
+
loggingMiddleware(logger),
|
|
79
90
|
// Custom middleware
|
|
80
91
|
...middleware,
|
|
81
92
|
];
|
|
82
|
-
const composedMiddleware =
|
|
93
|
+
const composedMiddleware = compose(middlewareStack);
|
|
83
94
|
return async (event, _context) => {
|
|
84
95
|
// Build request context
|
|
85
|
-
const ctx =
|
|
96
|
+
const ctx = buildContext(event, { supportedLocales: ['en'], defaultLocale: 'en' });
|
|
86
97
|
logger.setContext(ctx);
|
|
87
98
|
// Run through middleware and handler
|
|
88
99
|
return composedMiddleware(ctx, async () => {
|
|
89
100
|
// Auth check (only if scopes provided)
|
|
90
101
|
if (requiresAuth) {
|
|
91
102
|
if (!ctx.user) {
|
|
92
|
-
throw new
|
|
103
|
+
throw new UnauthorizedError();
|
|
93
104
|
}
|
|
94
105
|
// Scope check
|
|
95
106
|
const hasAllScopes = scopes.every(scope => ctx.user.scopes.includes(scope));
|
|
96
107
|
if (!hasAllScopes) {
|
|
97
|
-
throw new
|
|
108
|
+
throw new ForbiddenError('Insufficient permissions');
|
|
98
109
|
}
|
|
99
110
|
}
|
|
100
111
|
// Parse body
|
|
101
|
-
|
|
112
|
+
let body = parseBody(event);
|
|
113
|
+
// Validate body with Zod schema if provided
|
|
114
|
+
if (config.body) {
|
|
115
|
+
const result = config.body.safeParse(body);
|
|
116
|
+
if (!result.success) {
|
|
117
|
+
throw zodToValidationError('body', result.error.issues);
|
|
118
|
+
}
|
|
119
|
+
body = result.data;
|
|
120
|
+
}
|
|
121
|
+
// Validate query params with Zod schema if provided
|
|
122
|
+
if (config.query) {
|
|
123
|
+
const rawQuery = event.queryStringParameters || {};
|
|
124
|
+
const result = config.query.safeParse(rawQuery);
|
|
125
|
+
if (!result.success) {
|
|
126
|
+
throw zodToValidationError('query', result.error.issues);
|
|
127
|
+
}
|
|
128
|
+
ctx.queryParams = result.data;
|
|
129
|
+
}
|
|
130
|
+
// Validate path params with Zod schema if provided
|
|
131
|
+
if (config.params) {
|
|
132
|
+
const rawParams = event.pathParameters || {};
|
|
133
|
+
const result = config.params.safeParse(rawParams);
|
|
134
|
+
if (!result.success) {
|
|
135
|
+
throw zodToValidationError('params', result.error.issues);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
102
138
|
// Transaction support
|
|
103
139
|
if (config.transactional) {
|
|
104
140
|
const data = await import('@venturekit/data');
|
|
@@ -109,13 +145,13 @@ function handler(fn, config = {}) {
|
|
|
109
145
|
await tx.commit();
|
|
110
146
|
const statusCode = getStatusCode(event.requestContext.http.method, status);
|
|
111
147
|
if (statusCode === 204) {
|
|
112
|
-
return
|
|
148
|
+
return noContent({ requestId: ctx.requestId });
|
|
113
149
|
}
|
|
114
150
|
else if (statusCode === 201) {
|
|
115
|
-
return
|
|
151
|
+
return created(result, { requestId: ctx.requestId });
|
|
116
152
|
}
|
|
117
153
|
else {
|
|
118
|
-
return
|
|
154
|
+
return success(result, { requestId: ctx.requestId });
|
|
119
155
|
}
|
|
120
156
|
}
|
|
121
157
|
catch (txError) {
|
|
@@ -129,13 +165,13 @@ function handler(fn, config = {}) {
|
|
|
129
165
|
const statusCode = getStatusCode(event.requestContext.http.method, status);
|
|
130
166
|
// Return response based on status
|
|
131
167
|
if (statusCode === 204) {
|
|
132
|
-
return
|
|
168
|
+
return noContent({ requestId: ctx.requestId });
|
|
133
169
|
}
|
|
134
170
|
else if (statusCode === 201) {
|
|
135
|
-
return
|
|
171
|
+
return created(result, { requestId: ctx.requestId });
|
|
136
172
|
}
|
|
137
173
|
else {
|
|
138
|
-
return
|
|
174
|
+
return success(result, { requestId: ctx.requestId });
|
|
139
175
|
}
|
|
140
176
|
});
|
|
141
177
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/handler/handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../src/handler/response.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAiC,MAAM,aAAa,CAAC;AAE1E;;GAEG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC1C,IAAI,EAAE,CAAC,CAAC;IACR,IAAI,CAAC,EAAE;QACL,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE;YACX,IAAI,EAAE,MAAM,CAAC;YACb,QAAQ,EAAE,MAAM,CAAC;YACjB,KAAK,EAAE,MAAM,CAAC;YACd,UAAU,EAAE,MAAM,CAAC;SACpB,CAAC;KACH,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACnC,CAAC;IACF,IAAI,CAAC,EAAE;QACL,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,CAAC,EACvB,IAAI,EAAE,CAAC,EACP,OAAO,GAAE;IACP,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACf,GACL,uBAAuB,CAqBzB;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,CAAC,EACvB,IAAI,EAAE,CAAC,EACP,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACrE,uBAAuB,CAEzB;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,uBAAuB,CAMvF;AAED;;GAEG;AACH,wBAAgB,KAAK,CACnB,GAAG,EAAE,YAAY,EACjB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACnC,uBAAuB,CAwBzB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GACvD,uBAAuB,CAczB;AAED;;GAEG;AACH,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,OAAe,GACzB,uBAAuB,CAQzB"}
|
|
@@ -1,21 +1,13 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* VentureKit Response Utilities
|
|
4
3
|
*
|
|
5
4
|
* Standardized response formatting for API Gateway.
|
|
6
5
|
*/
|
|
7
|
-
|
|
8
|
-
exports.success = success;
|
|
9
|
-
exports.created = created;
|
|
10
|
-
exports.noContent = noContent;
|
|
11
|
-
exports.error = error;
|
|
12
|
-
exports.errorResponse = errorResponse;
|
|
13
|
-
exports.redirect = redirect;
|
|
14
|
-
const errors_js_1 = require("./errors.js");
|
|
6
|
+
import { isVentureError, InternalError } from './errors.js';
|
|
15
7
|
/**
|
|
16
8
|
* Create a success response
|
|
17
9
|
*/
|
|
18
|
-
function success(data, options = {}) {
|
|
10
|
+
export function success(data, options = {}) {
|
|
19
11
|
const { statusCode = 200, headers = {}, requestId } = options;
|
|
20
12
|
const body = {
|
|
21
13
|
data,
|
|
@@ -38,13 +30,13 @@ function success(data, options = {}) {
|
|
|
38
30
|
/**
|
|
39
31
|
* Create a created response (201)
|
|
40
32
|
*/
|
|
41
|
-
function created(data, options = {}) {
|
|
33
|
+
export function created(data, options = {}) {
|
|
42
34
|
return success(data, { ...options, statusCode: 201 });
|
|
43
35
|
}
|
|
44
36
|
/**
|
|
45
37
|
* Create a no content response (204)
|
|
46
38
|
*/
|
|
47
|
-
function noContent(options = {}) {
|
|
39
|
+
export function noContent(options = {}) {
|
|
48
40
|
return {
|
|
49
41
|
statusCode: 204,
|
|
50
42
|
body: '',
|
|
@@ -54,7 +46,7 @@ function noContent(options = {}) {
|
|
|
54
46
|
/**
|
|
55
47
|
* Create an error response from a VentureError
|
|
56
48
|
*/
|
|
57
|
-
function error(err, options = {}) {
|
|
49
|
+
export function error(err, options = {}) {
|
|
58
50
|
const { requestId } = options;
|
|
59
51
|
const body = {
|
|
60
52
|
error: {
|
|
@@ -80,9 +72,9 @@ function error(err, options = {}) {
|
|
|
80
72
|
/**
|
|
81
73
|
* Convert any error to an API Gateway response
|
|
82
74
|
*/
|
|
83
|
-
function errorResponse(err, options = {}) {
|
|
75
|
+
export function errorResponse(err, options = {}) {
|
|
84
76
|
const { requestId, logError = true } = options;
|
|
85
|
-
if (
|
|
77
|
+
if (isVentureError(err)) {
|
|
86
78
|
return error(err, { requestId });
|
|
87
79
|
}
|
|
88
80
|
// Log unexpected errors
|
|
@@ -90,12 +82,12 @@ function errorResponse(err, options = {}) {
|
|
|
90
82
|
console.error('Unexpected error:', err);
|
|
91
83
|
}
|
|
92
84
|
// Wrap in InternalError for consistent response
|
|
93
|
-
return error(new
|
|
85
|
+
return error(new InternalError(), { requestId });
|
|
94
86
|
}
|
|
95
87
|
/**
|
|
96
88
|
* Create a redirect response
|
|
97
89
|
*/
|
|
98
|
-
function redirect(location, permanent = false) {
|
|
90
|
+
export function redirect(location, permanent = false) {
|
|
99
91
|
return {
|
|
100
92
|
statusCode: permanent ? 301 : 302,
|
|
101
93
|
headers: {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response.js","sourceRoot":"","sources":["../../src/handler/response.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VentureKit Task Handler
|
|
3
|
+
*
|
|
4
|
+
* Unified handler for non-HTTP Lambda functions:
|
|
5
|
+
* - Standalone functions (src/functions/)
|
|
6
|
+
* - Queue consumers (src/queues/)
|
|
7
|
+
* - Scheduled tasks / cron handlers (src/crons/)
|
|
8
|
+
*
|
|
9
|
+
* Provides the same developer experience as handler() for routes:
|
|
10
|
+
* - Middleware pipeline
|
|
11
|
+
* - Structured logging
|
|
12
|
+
* - Error handling with structured responses
|
|
13
|
+
* - Transaction support (auto-commit / auto-rollback)
|
|
14
|
+
* - Input validation (Zod schemas)
|
|
15
|
+
* - Automatic trace context propagation
|
|
16
|
+
*
|
|
17
|
+
* ## Retry Architecture (Two Layers)
|
|
18
|
+
*
|
|
19
|
+
* **Layer 1 — Infrastructure retries (managed by AWS, outside your code):**
|
|
20
|
+
* - SQS queues: failed invocations return the message to the queue after
|
|
21
|
+
* `visibilityTimeout`. After `maxReceiveCount` failures → dead-letter queue.
|
|
22
|
+
* - EventBridge crons: 2 automatic retries with exponential backoff.
|
|
23
|
+
* - Async Lambda invocations: 2 automatic retries by default.
|
|
24
|
+
*
|
|
25
|
+
* **Layer 2 — Application retries (managed by taskHandler, inside one invocation):**
|
|
26
|
+
* - `retries: N` retries the handler within a single Lambda invocation.
|
|
27
|
+
* - Useful for transient errors (network blips, DB connection resets, throttles).
|
|
28
|
+
* - Uses exponential backoff: `retryDelayMs * 2^attempt`.
|
|
29
|
+
* - Validation errors (TaskValidationError) are never retried.
|
|
30
|
+
*
|
|
31
|
+
* The two layers are complementary: application retries handle transient glitches
|
|
32
|
+
* before the function fails. If all application retries are exhausted, the error
|
|
33
|
+
* propagates to the infrastructure layer (SQS visibility timeout / DLQ, etc.).
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* import { taskHandler } from '@venturekit/runtime';
|
|
38
|
+
*
|
|
39
|
+
* export const main = taskHandler<MyEvent, MyResult>(
|
|
40
|
+
* async (event, ctx, logger) => {
|
|
41
|
+
* logger.info('Processing', { event });
|
|
42
|
+
* return { processed: true };
|
|
43
|
+
* },
|
|
44
|
+
* { timeout: 30_000 },
|
|
45
|
+
* );
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
import type { Context } from 'aws-lambda';
|
|
49
|
+
import type { BaseContext } from './context.js';
|
|
50
|
+
import type { Middleware } from '../middleware/middleware.js';
|
|
51
|
+
import { Logger } from '../logging/logger.js';
|
|
52
|
+
/**
|
|
53
|
+
* Context for task (non-HTTP) handlers.
|
|
54
|
+
* Extends BaseContext so middleware written against BaseContext works here too.
|
|
55
|
+
*/
|
|
56
|
+
export interface TaskContext extends BaseContext {
|
|
57
|
+
/** Lambda function name */
|
|
58
|
+
functionName: string;
|
|
59
|
+
/** Remaining time in ms before Lambda timeout */
|
|
60
|
+
getRemainingTimeInMillis: () => number;
|
|
61
|
+
/** Raw Lambda context */
|
|
62
|
+
rawContext: Context;
|
|
63
|
+
/** The raw event payload (available to middleware) */
|
|
64
|
+
event: unknown;
|
|
65
|
+
/** Logger instance (available to middleware) */
|
|
66
|
+
logger: Logger;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Task handler function signature.
|
|
70
|
+
*/
|
|
71
|
+
export type TaskHandlerFn<TEvent = unknown, TResult = unknown> = (event: TEvent, ctx: TaskContext, logger: Logger) => Promise<TResult>;
|
|
72
|
+
/**
|
|
73
|
+
* Zod-like schema interface (compatible with Zod without hard dependency)
|
|
74
|
+
*/
|
|
75
|
+
interface ZodLikeSchema<T = unknown> {
|
|
76
|
+
safeParse(data: unknown): {
|
|
77
|
+
success: true;
|
|
78
|
+
data: T;
|
|
79
|
+
} | {
|
|
80
|
+
success: false;
|
|
81
|
+
error: {
|
|
82
|
+
issues: Array<{
|
|
83
|
+
path: (string | number)[];
|
|
84
|
+
message: string;
|
|
85
|
+
}>;
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Task handler configuration.
|
|
91
|
+
*/
|
|
92
|
+
export interface TaskHandlerConfig<TEvent = unknown> {
|
|
93
|
+
/** Custom middleware to apply (same Middleware type as HTTP handlers) */
|
|
94
|
+
middleware?: Middleware<TaskContext>[];
|
|
95
|
+
/** Log level (default: 'info') */
|
|
96
|
+
logLevel?: 'debug' | 'info' | 'warn' | 'error';
|
|
97
|
+
/**
|
|
98
|
+
* Wrap execution in a database transaction.
|
|
99
|
+
* Requires @venturekit/data. Auto-commits on success, rolls back on error.
|
|
100
|
+
*/
|
|
101
|
+
transactional?: boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Zod schema for event validation.
|
|
104
|
+
* If provided, the event payload is validated before the handler runs.
|
|
105
|
+
* On failure, an error is thrown with structured validation details.
|
|
106
|
+
*/
|
|
107
|
+
event?: ZodLikeSchema<TEvent>;
|
|
108
|
+
/**
|
|
109
|
+
* Timeout in milliseconds. If the handler exceeds this, an error is thrown.
|
|
110
|
+
* By default, no timeout is enforced (Lambda's own timeout applies).
|
|
111
|
+
*/
|
|
112
|
+
timeout?: number;
|
|
113
|
+
/**
|
|
114
|
+
* Maximum number of application-level retries within a single Lambda invocation
|
|
115
|
+
* (default: 0 = no retry). Only retries on non-validation errors.
|
|
116
|
+
*
|
|
117
|
+
* This is separate from infrastructure retries (SQS re-delivery, EventBridge
|
|
118
|
+
* retry policy) which happen outside your code when the Lambda returns an error.
|
|
119
|
+
*
|
|
120
|
+
* Recommended: use 1–3 for transient errors (network, throttle).
|
|
121
|
+
* Do NOT set high values for queue consumers — let the message return
|
|
122
|
+
* to the queue instead so other consumers can pick it up.
|
|
123
|
+
*/
|
|
124
|
+
retries?: number;
|
|
125
|
+
/**
|
|
126
|
+
* Initial delay in ms between retries (default: 1000).
|
|
127
|
+
* Doubles on each subsequent retry (exponential backoff).
|
|
128
|
+
*/
|
|
129
|
+
retryDelayMs?: number;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* VentureKit task handler for non-HTTP Lambda functions.
|
|
133
|
+
*
|
|
134
|
+
* Provides middleware, logging, validation, transactions, and error handling
|
|
135
|
+
* for standalone functions, queue consumers, and scheduled tasks.
|
|
136
|
+
*
|
|
137
|
+
* @example Basic usage
|
|
138
|
+
* ```typescript
|
|
139
|
+
* export const main = taskHandler<MyEvent, MyResult>(async (event, ctx, logger) => {
|
|
140
|
+
* logger.info('Processing event', { event });
|
|
141
|
+
* return { processed: true };
|
|
142
|
+
* });
|
|
143
|
+
* ```
|
|
144
|
+
*
|
|
145
|
+
* @example With validation and transactions
|
|
146
|
+
* ```typescript
|
|
147
|
+
* export const main = taskHandler<OrderEvent, OrderResult>(
|
|
148
|
+
* async (event, ctx, logger) => {
|
|
149
|
+
* const result = await ctx.tx!.query('INSERT INTO orders ...');
|
|
150
|
+
* return { orderId: result.id };
|
|
151
|
+
* },
|
|
152
|
+
* {
|
|
153
|
+
* event: OrderEventSchema,
|
|
154
|
+
* transactional: true,
|
|
155
|
+
* retries: 2,
|
|
156
|
+
* },
|
|
157
|
+
* );
|
|
158
|
+
* ```
|
|
159
|
+
*
|
|
160
|
+
* @example With middleware (same Middleware type as HTTP handlers)
|
|
161
|
+
* ```typescript
|
|
162
|
+
* export const main = taskHandler(
|
|
163
|
+
* async (event, ctx, logger) => { ... },
|
|
164
|
+
* {
|
|
165
|
+
* middleware: [
|
|
166
|
+
* { name: 'audit', fn: async (ctx, next) => {
|
|
167
|
+
* ctx.logger.info('Audit: start');
|
|
168
|
+
* const result = await next();
|
|
169
|
+
* ctx.logger.info('Audit: done');
|
|
170
|
+
* return result;
|
|
171
|
+
* }},
|
|
172
|
+
* ],
|
|
173
|
+
* },
|
|
174
|
+
* );
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
export declare function taskHandler<TEvent = unknown, TResult = unknown>(fn: TaskHandlerFn<TEvent, TResult>, config?: TaskHandlerConfig<TEvent>): (event: TEvent, context: Context) => Promise<TResult>;
|
|
178
|
+
/**
|
|
179
|
+
* Validation error for task events.
|
|
180
|
+
*/
|
|
181
|
+
export declare class TaskValidationError extends Error {
|
|
182
|
+
readonly issues: Array<{
|
|
183
|
+
path: (string | number)[];
|
|
184
|
+
message: string;
|
|
185
|
+
}>;
|
|
186
|
+
constructor(message: string, issues: Array<{
|
|
187
|
+
path: (string | number)[];
|
|
188
|
+
message: string;
|
|
189
|
+
}>);
|
|
190
|
+
}
|
|
191
|
+
export {};
|
|
192
|
+
//# sourceMappingURL=task-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-handler.d.ts","sourceRoot":"","sources":["../../src/handler/task-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAe,MAAM,cAAc,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAgB,MAAM,sBAAsB,CAAC;AAG5D;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC9C,2BAA2B;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,wBAAwB,EAAE,MAAM,MAAM,CAAC;IACvC,yBAAyB;IACzB,UAAU,EAAE,OAAO,CAAC;IACpB,sDAAsD;IACtD,KAAK,EAAE,OAAO,CAAC;IACf,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,CAC/D,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,MAAM,KACX,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB;;GAEG;AACH,UAAU,aAAa,CAAC,CAAC,GAAG,OAAO;IACjC,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG;QAAE,OAAO,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,CAAC,CAAA;KAAE,GAAG;QAAE,OAAO,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE;YAAE,MAAM,EAAE,KAAK,CAAC;gBAAE,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;gBAAC,OAAO,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,CAAA;KAAE,CAAC;CACrJ;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB,CAAC,MAAM,GAAG,OAAO;IACjD,yEAAyE;IACzE,UAAU,CAAC,EAAE,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;IACvC,kCAAkC;IAClC,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAC/C;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC9B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA4CD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,wBAAgB,WAAW,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,EAC7D,EAAE,EAAE,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,MAAM,GAAE,iBAAiB,CAAC,MAAM,CAAM,GACrC,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAmJvD;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,SAAgB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;gBAG5E,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAMhE"}
|