@pikku/lambda 0.12.2 → 0.12.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/handler-factories.d.ts +17 -0
  3. package/dist/handler-factories.js +91 -0
  4. package/dist/handler-factories.js.map +1 -0
  5. package/dist/http/index.d.ts +3 -0
  6. package/dist/http/index.js +3 -0
  7. package/dist/http/index.js.map +1 -1
  8. package/dist/http/request-converter-v2.d.ts +2 -0
  9. package/dist/http/request-converter-v2.js +25 -0
  10. package/dist/http/request-converter-v2.js.map +1 -0
  11. package/dist/http/response-converter-v2.d.ts +2 -0
  12. package/dist/http/response-converter-v2.js +31 -0
  13. package/dist/http/response-converter-v2.js.map +1 -0
  14. package/dist/http/run-fetch-v2.d.ts +2 -0
  15. package/dist/http/run-fetch-v2.js +25 -0
  16. package/dist/http/run-fetch-v2.js.map +1 -0
  17. package/dist/http/run-fetch.js +1 -1
  18. package/dist/index.d.ts +4 -0
  19. package/dist/index.js +4 -0
  20. package/dist/index.js.map +1 -1
  21. package/dist/lambda-deployment-service.d.ts +14 -0
  22. package/dist/lambda-deployment-service.js +89 -0
  23. package/dist/lambda-deployment-service.js.map +1 -0
  24. package/dist/queue/sqs-worker.js +1 -1
  25. package/dist/queue/sqs-worker.js.map +1 -1
  26. package/dist/scheduled/index.d.ts +1 -0
  27. package/dist/scheduled/index.js +2 -0
  28. package/dist/scheduled/index.js.map +1 -0
  29. package/dist/scheduled/run-scheduled.d.ts +2 -0
  30. package/dist/scheduled/run-scheduled.js +14 -0
  31. package/dist/scheduled/run-scheduled.js.map +1 -0
  32. package/dist/sqs-queue-service.d.ts +10 -0
  33. package/dist/sqs-queue-service.js +52 -0
  34. package/dist/sqs-queue-service.js.map +1 -0
  35. package/dist/websocket/utils.d.ts +1 -1
  36. package/package.json +12 -6
  37. package/src/handler-factories.ts +165 -0
  38. package/src/http/index.ts +3 -0
  39. package/src/http/request-converter-v2.ts +36 -0
  40. package/src/http/response-converter-v2.ts +40 -0
  41. package/src/http/run-fetch-v2.ts +42 -0
  42. package/src/http/run-fetch.ts +1 -1
  43. package/src/index.test.ts +13 -0
  44. package/src/index.ts +4 -0
  45. package/src/lambda-deployment-service.ts +134 -0
  46. package/src/queue/sqs-worker.ts +1 -1
  47. package/src/scheduled/index.ts +1 -0
  48. package/src/scheduled/run-scheduled.ts +30 -0
  49. package/src/sqs-queue-service.ts +91 -0
  50. package/src/websocket/lambda-eventhub-service.ts +3 -3
  51. package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,40 @@
1
+ ## 0.12.4
2
+
3
+ ### Patch Changes
4
+
5
+ - 41ce2cb: Upgrade to TypeScript 6 and raise the minimum Node.js version to 22.
6
+
7
+ All packages now build against `typescript@^6.0.3` and declare `engines.node >= 22`. Internal tooling (`ts-json-schema-generator`, `zod-to-ts`) was bumped to TypeScript 6-compatible releases.
8
+
9
+ - Updated dependencies [41ce2cb]
10
+ - @pikku/core@0.12.44
11
+
1
12
  ## 0.12.0
2
13
 
14
+ ## 0.12.3
15
+
16
+ ### Patch Changes
17
+
18
+ - e3142ad: Fix OPTIONS method comparison to use uppercase, matching the Fetch API Request.method convention. Previously the CORS preflight handler was dead code.
19
+ - 87433f0: Replace full SQS event logging with message count to prevent sensitive data leaking into CloudWatch logs.
20
+ - Updated dependencies [e412b4d]
21
+ - Updated dependencies [53dc8c8]
22
+ - Updated dependencies [0a1cc51]
23
+ - Updated dependencies [0a1cc51]
24
+ - Updated dependencies [0a1cc51]
25
+ - Updated dependencies [0a1cc51]
26
+ - Updated dependencies [0a1cc51]
27
+ - Updated dependencies [0a1cc51]
28
+ - Updated dependencies [0a1cc51]
29
+ - Updated dependencies [0a1cc51]
30
+ - Updated dependencies [0a1cc51]
31
+ - Updated dependencies [8b9b2e9]
32
+ - Updated dependencies [8b9b2e9]
33
+ - Updated dependencies [b973d44]
34
+ - Updated dependencies [8b9b2e9]
35
+ - Updated dependencies [8b9b2e9]
36
+ - @pikku/core@0.12.9
37
+
3
38
  ## 0.12.2
4
39
 
5
40
  ### Patch Changes
@@ -0,0 +1,17 @@
1
+ import { LocalVariablesService } from '@pikku/core/services';
2
+ import type { CoreSingletonServices } from '@pikku/core';
3
+ import type { APIGatewayEvent, APIGatewayProxyEventV2 } from 'aws-lambda';
4
+ export interface LambdaServiceFactories {
5
+ createConfig: (variables: LocalVariablesService, ...args: unknown[]) => Promise<unknown>;
6
+ createSingletonServices: (config: unknown, existingServices?: Partial<Record<string, unknown>>) => Promise<CoreSingletonServices>;
7
+ createPlatformServices?: () => Record<string, unknown> | Promise<Record<string, unknown>>;
8
+ }
9
+ export declare function createLambdaHandler(factories: LambdaServiceFactories, handlerTypes: string[]): Record<string, unknown>;
10
+ export declare function createLambdaWorkerHandler(factories: LambdaServiceFactories): {
11
+ handler(event: APIGatewayProxyEventV2): Promise<import("aws-lambda").APIGatewayProxyStructuredResultV2>;
12
+ };
13
+ export declare function createLambdaWebSocketHandler(factories: LambdaServiceFactories): {
14
+ connect(event: APIGatewayEvent): Promise<import("aws-lambda").APIGatewayProxyResult>;
15
+ disconnect(event: APIGatewayEvent): Promise<import("aws-lambda").APIGatewayProxyResult>;
16
+ default(event: APIGatewayEvent): Promise<import("aws-lambda").APIGatewayProxyResult>;
17
+ };
@@ -0,0 +1,91 @@
1
+ import { LocalVariablesService, LocalSecretService } from '@pikku/core/services';
2
+ import { runFetchV2 } from './http/run-fetch-v2.js';
3
+ import { runSQSQueueWorker } from './queue/sqs-worker.js';
4
+ import { runLambdaScheduled } from './scheduled/run-scheduled.js';
5
+ let cachedServices = null;
6
+ async function setupServices(factories) {
7
+ if (cachedServices)
8
+ return cachedServices;
9
+ const variables = new LocalVariablesService(process.env);
10
+ const config = await factories.createConfig(variables);
11
+ const secrets = new LocalSecretService(variables);
12
+ const platformServices = factories.createPlatformServices
13
+ ? await factories.createPlatformServices()
14
+ : {};
15
+ cachedServices = await factories.createSingletonServices(config, {
16
+ variables,
17
+ secrets,
18
+ ...platformServices,
19
+ });
20
+ return cachedServices;
21
+ }
22
+ export function createLambdaHandler(factories, handlerTypes) {
23
+ const result = {};
24
+ if (handlerTypes.includes('fetch')) {
25
+ result.handler = async (event) => {
26
+ await setupServices(factories);
27
+ return runFetchV2(event);
28
+ };
29
+ }
30
+ if (handlerTypes.includes('queue')) {
31
+ result.queue = async (event) => {
32
+ const services = await setupServices(factories);
33
+ return runSQSQueueWorker(services.logger, event);
34
+ };
35
+ }
36
+ if (handlerTypes.includes('scheduled')) {
37
+ result.scheduled = async (event) => {
38
+ await setupServices(factories);
39
+ return runLambdaScheduled(event);
40
+ };
41
+ }
42
+ if (!handlerTypes.includes('fetch')) {
43
+ const activeHandlers = handlerTypes.join(', ');
44
+ result.handler = async () => ({
45
+ statusCode: 200,
46
+ body: `Lambda active (handlers: ${activeHandlers})`,
47
+ });
48
+ }
49
+ return result;
50
+ }
51
+ export function createLambdaWorkerHandler(factories) {
52
+ return {
53
+ async handler(event) {
54
+ await setupServices(factories);
55
+ return runFetchV2(event);
56
+ },
57
+ };
58
+ }
59
+ export function createLambdaWebSocketHandler(factories) {
60
+ const getChannelStore = () => {
61
+ if (!cachedServices) {
62
+ throw new Error('Services not initialized for WebSocket handler');
63
+ }
64
+ const channelStore = cachedServices
65
+ .channelStore;
66
+ if (!channelStore) {
67
+ throw new Error('channelStore not found in singleton services. Ensure it is configured for channel units.');
68
+ }
69
+ return channelStore;
70
+ };
71
+ return {
72
+ async connect(event) {
73
+ await setupServices(factories);
74
+ const { connectWebsocket } = await import('./websocket/index.js');
75
+ return connectWebsocket(event, { channelStore: getChannelStore() });
76
+ },
77
+ async disconnect(event) {
78
+ await setupServices(factories);
79
+ const { disconnectWebsocket } = await import('./websocket/index.js');
80
+ return disconnectWebsocket(event, { channelStore: getChannelStore() });
81
+ },
82
+ async default(event) {
83
+ await setupServices(factories);
84
+ const { processWebsocketMessage } = await import('./websocket/index.js');
85
+ return processWebsocketMessage(event, {
86
+ channelStore: getChannelStore(),
87
+ });
88
+ },
89
+ };
90
+ }
91
+ //# sourceMappingURL=handler-factories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler-factories.js","sourceRoot":"","sources":["../src/handler-factories.ts"],"names":[],"mappings":"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"}
@@ -1 +1,4 @@
1
1
  export * from './run-fetch.js';
2
+ export * from './run-fetch-v2.js';
3
+ export { lambdaV2EventToRequest } from './request-converter-v2.js';
4
+ export { responseToLambdaV2Result } from './response-converter-v2.js';
@@ -1,2 +1,5 @@
1
1
  export * from './run-fetch.js';
2
+ export * from './run-fetch-v2.js';
3
+ export { lambdaV2EventToRequest } from './request-converter-v2.js';
4
+ export { responseToLambdaV2Result } from './response-converter-v2.js';
2
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,mBAAmB,CAAA;AACjC,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAA;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAA"}
@@ -0,0 +1,2 @@
1
+ import type { APIGatewayProxyEventV2 } from 'aws-lambda';
2
+ export declare const lambdaV2EventToRequest: (event: APIGatewayProxyEventV2) => Request;
@@ -0,0 +1,25 @@
1
+ export const lambdaV2EventToRequest = (event) => {
2
+ const host = event.headers?.host ?? event.requestContext?.domainName ?? 'localhost';
3
+ const url = new URL(event.rawPath, `https://${host}`);
4
+ if (event.rawQueryString) {
5
+ url.search = `?${event.rawQueryString}`;
6
+ }
7
+ const body = event.body && event.isBase64Encoded
8
+ ? Buffer.from(event.body, 'base64')
9
+ : event.body || undefined;
10
+ const method = event.requestContext?.http?.method || 'GET';
11
+ const headers = {};
12
+ if (event.headers) {
13
+ for (const [key, value] of Object.entries(event.headers)) {
14
+ if (value != null) {
15
+ headers[key] = value;
16
+ }
17
+ }
18
+ }
19
+ return new Request(url.toString(), {
20
+ method,
21
+ headers,
22
+ body: ['GET', 'HEAD'].includes(method.toUpperCase()) ? undefined : body,
23
+ });
24
+ };
25
+ //# sourceMappingURL=request-converter-v2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-converter-v2.js","sourceRoot":"","sources":["../../src/http/request-converter-v2.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,KAA6B,EACpB,EAAE;IACX,MAAM,IAAI,GACR,KAAK,CAAC,OAAO,EAAE,IAAI,IAAI,KAAK,CAAC,cAAc,EAAE,UAAU,IAAI,WAAW,CAAA;IACxE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,WAAW,IAAI,EAAE,CAAC,CAAA;IAErD,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;QAEzB,GAAG,CAAC,MAAM,GAAG,IAAI,KAAK,CAAC,cAAc,EAAE,CAAA;IACzC,CAAC;IAED,MAAM,IAAI,GACR,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,eAAe;QACjC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC;QACnC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,SAAS,CAAA;IAE7B,MAAM,MAAM,GAAG,KAAK,CAAC,cAAc,EAAE,IAAI,EAAE,MAAM,IAAI,KAAK,CAAA;IAE1D,MAAM,OAAO,GAA2B,EAAE,CAAA;IAC1C,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YACzD,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;gBAClB,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;QACjC,MAAM;QACN,OAAO;QACP,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;KACxE,CAAC,CAAA;AACJ,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ import type { APIGatewayProxyStructuredResultV2 } from 'aws-lambda';
2
+ export declare const responseToLambdaV2Result: (response: Response) => Promise<APIGatewayProxyStructuredResultV2>;
@@ -0,0 +1,31 @@
1
+ export const responseToLambdaV2Result = async (response) => {
2
+ const cookies = response.headers.getSetCookie
3
+ ? response.headers.getSetCookie()
4
+ : [];
5
+ const headers = {};
6
+ response.headers.forEach((value, key) => {
7
+ if (key.toLowerCase() === 'set-cookie' && cookies.length > 0)
8
+ return;
9
+ headers[key.toLowerCase()] = value;
10
+ });
11
+ let body;
12
+ let isBase64Encoded = false;
13
+ const contentType = response.headers.get('content-type') || '';
14
+ const isBinary = !/^text\/|application\/(json|javascript|xml)/.test(contentType);
15
+ const buffer = Buffer.from(await response.arrayBuffer());
16
+ if (isBinary) {
17
+ body = buffer.toString('base64');
18
+ isBase64Encoded = true;
19
+ }
20
+ else {
21
+ body = buffer.toString('utf-8');
22
+ }
23
+ return {
24
+ statusCode: response.status,
25
+ headers,
26
+ body,
27
+ isBase64Encoded,
28
+ ...(cookies.length > 0 ? { cookies } : {}),
29
+ };
30
+ };
31
+ //# sourceMappingURL=response-converter-v2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-converter-v2.js","sourceRoot":"","sources":["../../src/http/response-converter-v2.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,EAC3C,QAAkB,EAC0B,EAAE;IAE9C,MAAM,OAAO,GAAa,QAAQ,CAAC,OAAO,CAAC,YAAY;QACrD,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE;QACjC,CAAC,CAAC,EAAE,CAAA;IAEN,MAAM,OAAO,GAA2B,EAAE,CAAA;IAC1C,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACtC,IAAI,GAAG,CAAC,WAAW,EAAE,KAAK,YAAY,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,OAAM;QACpE,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,GAAG,KAAK,CAAA;IACpC,CAAC,CAAC,CAAA;IAEF,IAAI,IAAY,CAAA;IAChB,IAAI,eAAe,GAAG,KAAK,CAAA;IAE3B,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAA;IAC9D,MAAM,QAAQ,GAAG,CAAC,4CAA4C,CAAC,IAAI,CACjE,WAAW,CACZ,CAAA;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAA;IACxD,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QAChC,eAAe,GAAG,IAAI,CAAA;IACxB,CAAC;SAAM,CAAC;QACN,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;IACjC,CAAC;IAED,OAAO;QACL,UAAU,EAAE,QAAQ,CAAC,MAAM;QAC3B,OAAO;QACP,IAAI;QACJ,eAAe;QACf,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC3C,CAAA;AACH,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ import type { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2 } from 'aws-lambda';
2
+ export declare const runFetchV2: (event: APIGatewayProxyEventV2) => Promise<APIGatewayProxyStructuredResultV2>;
@@ -0,0 +1,25 @@
1
+ import { PikkuFetchHTTPResponse, fetchData } from '@pikku/core/http';
2
+ import { responseToLambdaV2Result } from './response-converter-v2.js';
3
+ import { lambdaV2EventToRequest } from './request-converter-v2.js';
4
+ export const runFetchV2 = async (event) => {
5
+ const request = lambdaV2EventToRequest(event);
6
+ const response = new PikkuFetchHTTPResponse();
7
+ if (request.method === 'OPTIONS') {
8
+ response.header('Access-Control-Allow-Origin', request.headers.get('origin') || '*');
9
+ response.header('Access-Control-Allow-Headers', 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent');
10
+ response.header('Access-Control-Allow-Methods', 'OPTIONS,DELETE,GET,HEAD,PATCH,POST,PUT');
11
+ response.status(200);
12
+ return responseToLambdaV2Result(response.toResponse());
13
+ }
14
+ try {
15
+ await fetchData(request, response);
16
+ }
17
+ catch (err) {
18
+ console.error('fetchData error:', err);
19
+ response.status(500);
20
+ response.header('content-type', 'application/json');
21
+ response.json({ error: 'Internal Server Error' });
22
+ }
23
+ return responseToLambdaV2Result(response.toResponse());
24
+ };
25
+ //# sourceMappingURL=run-fetch-v2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-fetch-v2.js","sourceRoot":"","sources":["../../src/http/run-fetch-v2.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAKpE,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAA;AAElE,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAC7B,KAA6B,EACe,EAAE;IAC9C,MAAM,OAAO,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAA;IAC7C,MAAM,QAAQ,GAAG,IAAI,sBAAsB,EAAE,CAAA;IAE7C,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACjC,QAAQ,CAAC,MAAM,CACb,6BAA6B,EAC7B,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,GAAG,CACrC,CAAA;QACD,QAAQ,CAAC,MAAM,CACb,8BAA8B,EAC9B,uFAAuF,CACxF,CAAA;QACD,QAAQ,CAAC,MAAM,CACb,8BAA8B,EAC9B,wCAAwC,CACzC,CAAA;QACD,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACpB,OAAO,wBAAwB,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAA;IACxD,CAAC;IAED,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;IACpC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAA;QACtC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACpB,QAAQ,CAAC,MAAM,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;QACnD,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC,CAAA;IACnD,CAAC;IAED,OAAO,wBAAwB,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAA;AACxD,CAAC,CAAA"}
@@ -4,7 +4,7 @@ import { lambdaEventToRequest } from '../request-converter.js';
4
4
  export const runFetch = async (event) => {
5
5
  const request = lambdaEventToRequest(event);
6
6
  const response = new PikkuFetchHTTPResponse();
7
- if (request.method === 'options') {
7
+ if (request.method === 'OPTIONS') {
8
8
  response.header('Access-Control-Allow-Headers', 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent');
9
9
  response.header('Access-Control-Allow-Methods', 'OPTIONS,DELETE,GET,HEAD,PATCH,POST,PUT');
10
10
  response.status(200);
package/dist/index.d.ts CHANGED
@@ -1,3 +1,7 @@
1
1
  export * from './http/index.js';
2
2
  export * from './websocket/index.js';
3
3
  export * from './queue/index.js';
4
+ export * from './scheduled/index.js';
5
+ export * from './handler-factories.js';
6
+ export { SQSQueueService } from './sqs-queue-service.js';
7
+ export { LambdaDeploymentService } from './lambda-deployment-service.js';
package/dist/index.js CHANGED
@@ -1,4 +1,8 @@
1
1
  export * from './http/index.js';
2
2
  export * from './websocket/index.js';
3
3
  export * from './queue/index.js';
4
+ export * from './scheduled/index.js';
5
+ export * from './handler-factories.js';
6
+ export { SQSQueueService } from './sqs-queue-service.js';
7
+ export { LambdaDeploymentService } from './lambda-deployment-service.js';
4
8
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,sBAAsB,CAAA;AACpC,cAAc,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,sBAAsB,CAAA;AACpC,cAAc,kBAAkB,CAAA;AAChC,cAAc,sBAAsB,CAAA;AACpC,cAAc,wBAAwB,CAAA;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAA"}
@@ -0,0 +1,14 @@
1
+ import type { DeploymentService, DeploymentConfig } from '@pikku/core/services';
2
+ import type { JWTService } from '@pikku/core/services';
3
+ import type { SecretService } from '@pikku/core/services';
4
+ export declare class LambdaDeploymentService implements DeploymentService {
5
+ private jwt;
6
+ private secrets;
7
+ private client;
8
+ private bindings;
9
+ constructor(jwt: JWTService | undefined, secrets: SecretService, functionBindings: Record<string, string>);
10
+ init(): Promise<void>;
11
+ start(_config: DeploymentConfig): Promise<void>;
12
+ stop(): Promise<void>;
13
+ invoke(funcName: string, data: unknown, session?: unknown, traceId?: string): Promise<unknown>;
14
+ }
@@ -0,0 +1,89 @@
1
+ import { LambdaClient, InvokeCommand } from '@aws-sdk/client-lambda';
2
+ import { encryptJSON } from '@pikku/core/crypto-utils';
3
+ export class LambdaDeploymentService {
4
+ jwt;
5
+ secrets;
6
+ client;
7
+ bindings;
8
+ constructor(jwt, secrets, functionBindings) {
9
+ this.jwt = jwt;
10
+ this.secrets = secrets;
11
+ this.client = new LambdaClient({});
12
+ this.bindings = new Map(Object.entries(functionBindings));
13
+ }
14
+ async init() { }
15
+ async start(_config) { }
16
+ async stop() { }
17
+ async invoke(funcName, data, session, traceId) {
18
+ const lambdaFunctionName = this.bindings.get(funcName);
19
+ if (!lambdaFunctionName) {
20
+ throw new Error(`No Lambda binding for function '${funcName}'. ` +
21
+ `Available bindings: ${[...this.bindings.keys()].join(', ')}`);
22
+ }
23
+ const headers = {
24
+ 'content-type': 'application/json',
25
+ ...(traceId && { 'x-request-id': traceId }),
26
+ };
27
+ let secret;
28
+ try {
29
+ secret = await this.secrets.getSecret('PIKKU_REMOTE_SECRET');
30
+ }
31
+ catch { }
32
+ if (secret && this.jwt) {
33
+ const sessionEnc = session
34
+ ? await encryptJSON(secret, { session })
35
+ : undefined;
36
+ const token = await this.jwt.encode({ value: 5, unit: 'minute' }, {
37
+ aud: 'pikku-remote',
38
+ fn: funcName,
39
+ iat: Math.floor(Date.now() / 1000),
40
+ session: sessionEnc,
41
+ });
42
+ headers.authorization = `Bearer ${token}`;
43
+ }
44
+ const rpcPath = `/remote/rpc/${encodeURIComponent(funcName)}`;
45
+ const apiGatewayEvent = {
46
+ httpMethod: 'POST',
47
+ path: rpcPath,
48
+ headers,
49
+ body: JSON.stringify({ data }),
50
+ isBase64Encoded: false,
51
+ queryStringParameters: null,
52
+ pathParameters: null,
53
+ stageVariables: null,
54
+ requestContext: {
55
+ httpMethod: 'POST',
56
+ path: rpcPath,
57
+ stage: 'prod',
58
+ requestId: crypto.randomUUID(),
59
+ identity: {},
60
+ },
61
+ resource: rpcPath,
62
+ };
63
+ const response = await this.client.send(new InvokeCommand({
64
+ FunctionName: lambdaFunctionName,
65
+ Payload: JSON.stringify(apiGatewayEvent),
66
+ }));
67
+ if (response.FunctionError) {
68
+ const errorPayload = response.Payload
69
+ ? new TextDecoder().decode(response.Payload)
70
+ : 'Unknown error';
71
+ throw new Error(`Remote RPC call to '${funcName}' failed: Lambda error: ${errorPayload}`);
72
+ }
73
+ if (!response.Payload) {
74
+ throw new Error(`Remote RPC call to '${funcName}' returned no payload`);
75
+ }
76
+ const lambdaResult = JSON.parse(new TextDecoder().decode(response.Payload));
77
+ if (lambdaResult.statusCode && lambdaResult.statusCode >= 400) {
78
+ throw new Error(`Remote RPC call to '${funcName}' failed: ${lambdaResult.statusCode} ${lambdaResult.body}`);
79
+ }
80
+ const body = lambdaResult.body;
81
+ try {
82
+ return JSON.parse(body);
83
+ }
84
+ catch {
85
+ return body;
86
+ }
87
+ }
88
+ }
89
+ //# sourceMappingURL=lambda-deployment-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lambda-deployment-service.js","sourceRoot":"","sources":["../src/lambda-deployment-service.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAIpE,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAEtD,MAAM,OAAO,uBAAuB;IAKxB;IACA;IALF,MAAM,CAAc;IACpB,QAAQ,CAAqB;IAErC,YACU,GAA2B,EAC3B,OAAsB,EAC9B,gBAAwC;QAFhC,QAAG,GAAH,GAAG,CAAwB;QAC3B,YAAO,GAAP,OAAO,CAAe;QAG9B,IAAI,CAAC,MAAM,GAAG,IAAI,YAAY,CAAC,EAAE,CAAC,CAAA;QAClC,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAA;IAC3D,CAAC;IAED,KAAK,CAAC,IAAI,KAAmB,CAAC;IAC9B,KAAK,CAAC,KAAK,CAAC,OAAyB,IAAkB,CAAC;IACxD,KAAK,CAAC,IAAI,KAAmB,CAAC;IAE9B,KAAK,CAAC,MAAM,CACV,QAAgB,EAChB,IAAa,EACb,OAAiB,EACjB,OAAgB;QAEhB,MAAM,kBAAkB,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACtD,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CACb,mCAAmC,QAAQ,KAAK;gBAC9C,uBAAuB,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAChE,CAAA;QACH,CAAC;QAED,MAAM,OAAO,GAA2B;YACtC,cAAc,EAAE,kBAAkB;YAClC,GAAG,CAAC,OAAO,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC;SAC5C,CAAA;QAGD,IAAI,MAA0B,CAAA;QAC9B,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAA;QAC9D,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QAEV,IAAI,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,MAAM,UAAU,GAAG,OAAO;gBACxB,CAAC,CAAC,MAAM,WAAW,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC;gBACxC,CAAC,CAAC,SAAS,CAAA;YACb,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,CACjC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAC5B;gBACE,GAAG,EAAE,cAAc;gBACnB,EAAE,EAAE,QAAQ;gBACZ,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;gBAClC,OAAO,EAAE,UAAU;aACpB,CACF,CAAA;YACD,OAAO,CAAC,aAAa,GAAG,UAAU,KAAK,EAAE,CAAA;QAC3C,CAAC;QAGD,MAAM,OAAO,GAAG,eAAe,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAA;QAC7D,MAAM,eAAe,GAAG;YACtB,UAAU,EAAE,MAAM;YAClB,IAAI,EAAE,OAAO;YACb,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC;YAC9B,eAAe,EAAE,KAAK;YACtB,qBAAqB,EAAE,IAAI;YAC3B,cAAc,EAAE,IAAI;YACpB,cAAc,EAAE,IAAI;YACpB,cAAc,EAAE;gBACd,UAAU,EAAE,MAAM;gBAClB,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,MAAM;gBACb,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE;gBAC9B,QAAQ,EAAE,EAAE;aACb;YACD,QAAQ,EAAE,OAAO;SAClB,CAAA;QAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CACrC,IAAI,aAAa,CAAC;YAChB,YAAY,EAAE,kBAAkB;YAChC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC;SACzC,CAAC,CACH,CAAA;QAED,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;YAC3B,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO;gBACnC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAC5C,CAAC,CAAC,eAAe,CAAA;YACnB,MAAM,IAAI,KAAK,CACb,uBAAuB,QAAQ,2BAA2B,YAAY,EAAE,CACzE,CAAA;QACH,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,uBAAuB,QAAQ,uBAAuB,CAAC,CAAA;QACzE,CAAC;QAGD,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAA;QAE3E,IAAI,YAAY,CAAC,UAAU,IAAI,YAAY,CAAC,UAAU,IAAI,GAAG,EAAE,CAAC;YAC9D,MAAM,IAAI,KAAK,CACb,uBAAuB,QAAQ,aAAa,YAAY,CAAC,UAAU,IAAI,YAAY,CAAC,IAAI,EAAE,CAC3F,CAAA;QACH,CAAC;QAGD,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAA;QAC9B,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;CACF"}
@@ -34,7 +34,7 @@ export function mapSQSRecordToQueueJob(record, maxAttempts) {
34
34
  return job;
35
35
  }
36
36
  export const runSQSQueueWorker = async (logger, event) => {
37
- console.log(JSON.stringify(event, null, 2));
37
+ logger.info(`Processing ${event.Records.length} SQS messages`);
38
38
  const jobs = event.Records.map(mapSQSRecordToQueueJob);
39
39
  const results = await Promise.allSettled(jobs.map(async (job) => {
40
40
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"sqs-worker.js","sourceRoot":"","sources":["../../src/queue/sqs-worker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sqs-worker.js","sourceRoot":"","sources":["../../src/queue/sqs-worker.ts"],"names":[],"mappings":"AACA,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,mBAAmB,CAAA;AAO1B,MAAM,UAAU,sBAAsB,CACpC,MAAiB,EACjB,WAAoB;IAEpB,IAAI,IAAS,CAAA;IAEb,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,GAAG,MAAM,CAAC,IAAI,CAAA;IACpB,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;IAC5D,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAG,CAAA;IAEzD,MAAM,GAAG,GAAa;QACpB,SAAS;QACT,IAAI;QACJ,EAAE,EAAE,MAAM,CAAC,SAAS;QACpB,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,QAA0B;QAC9C,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;YACf,WAAW,EAAE,IAAI,IAAI,EAAE;YACvB,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,uBAAuB,CAAC,GAAG,CAAC;YACrE,WAAW;YACX,MAAM,EAAE,SAAS;YACjB,QAAQ,EAAE,CAAC;YACX,SAAS,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;YAC9D,WAAW,EAAE,SAAS;YACtB,QAAQ,EAAE,SAAS;YACnB,KAAK,EAAE,SAAS;SACjB,CAAC;QACF,iBAAiB,EAAE,KAAK,IAAI,EAAE;YAC5B,MAAM,IAAI,KAAK,CACb,mEAAmE,CACpE,CAAA;QACH,CAAC;KACF,CAAA;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAKD,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EACpC,MAAc,EACd,KAAe,EACY,EAAE;IAC7B,MAAM,CAAC,IAAI,CAAC,cAAc,KAAK,CAAC,OAAO,CAAC,MAAM,eAAe,CAAC,CAAA;IAC9D,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAA;IAGtD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CACtC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACrB,IAAI,CAAC;YACH,OAAO,MAAM,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC,CAAA;QACnC,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,IAAI,KAAK,YAAY,mBAAmB,EAAE,CAAC;gBAEzC,MAAM,KAAK,CAAA;YACb,CAAC;iBAAM,IAAI,KAAK,YAAY,sBAAsB,EAAE,CAAC;gBAEnD,MAAM,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,EAAE,eAAe,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;gBAC5D,OAAM;YACR,CAAC;YACD,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC,CAAC,CACH,CAAA;IAGD,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;QAChC,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YACjC,MAAM,CAAC,KAAK,CACV,iCAAiC,IAAI,CAAC,KAAK,CAAE,CAAC,EAAE,GAAG,EACnD,MAAM,CAAC,MAAM,CACd,CAAA;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,OAAO;QACL,iBAAiB,EAAE,OAAO;aACvB,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;YACvB,MAAM;YACN,cAAc,EAAE,IAAI,CAAC,KAAK,CAAE,CAAC,EAAE,IAAI,WAAW,KAAK,EAAE;SACtD,CAAC,CAAC;aACF,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,UAAU,CAAC;aACpD,GAAG,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC;KACrD,CAAA;AACH,CAAC,CAAA"}
@@ -0,0 +1 @@
1
+ export { runLambdaScheduled } from './run-scheduled.js';
@@ -0,0 +1,2 @@
1
+ export { runLambdaScheduled } from './run-scheduled.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scheduled/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA"}
@@ -0,0 +1,2 @@
1
+ import type { ScheduledEvent } from 'aws-lambda';
2
+ export declare const runLambdaScheduled: (_event: ScheduledEvent) => Promise<void>;
@@ -0,0 +1,14 @@
1
+ import { runScheduledTask, getScheduledTasks } from '@pikku/core/scheduler';
2
+ export const runLambdaScheduled = async (_event) => {
3
+ const scheduledTasks = getScheduledTasks();
4
+ for (const [name] of scheduledTasks) {
5
+ const traceId = `cron-${crypto.randomUUID()}`;
6
+ try {
7
+ await runScheduledTask({ name, traceId });
8
+ }
9
+ catch (err) {
10
+ console.error(`Scheduled task '${name}' (traceId: ${traceId}) failed:`, err);
11
+ }
12
+ }
13
+ };
14
+ //# sourceMappingURL=run-scheduled.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-scheduled.js","sourceRoot":"","sources":["../../src/scheduled/run-scheduled.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAE3E,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,EACrC,MAAsB,EACP,EAAE;IACjB,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAA;IAI1C,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,cAAc,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,QAAQ,MAAM,CAAC,UAAU,EAAE,EAAE,CAAA;QAC7C,IAAI,CAAC;YACH,MAAM,gBAAgB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;QAC3C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CACX,mBAAmB,IAAI,eAAe,OAAO,WAAW,EACxD,GAAG,CACJ,CAAA;QACH,CAAC;IACH,CAAC;AACH,CAAC,CAAA"}
@@ -0,0 +1,10 @@
1
+ import type { QueueService, QueueJob, JobOptions } from '@pikku/core/queue';
2
+ export declare class SQSQueueService implements QueueService {
3
+ private queueUrlMap?;
4
+ readonly supportsResults = false;
5
+ private client;
6
+ constructor(queueUrlMap?: Record<string, string> | undefined);
7
+ add<T>(queueName: string, data: T, options?: JobOptions): Promise<string>;
8
+ getJob<T, R>(_queueName: string, _jobId: string): Promise<QueueJob<T, R> | null>;
9
+ private resolveQueueUrl;
10
+ }
@@ -0,0 +1,52 @@
1
+ import { SQSClient, SendMessageCommand } from '@aws-sdk/client-sqs';
2
+ export class SQSQueueService {
3
+ queueUrlMap;
4
+ supportsResults = false;
5
+ client;
6
+ constructor(queueUrlMap) {
7
+ this.queueUrlMap = queueUrlMap;
8
+ this.client = new SQSClient({});
9
+ }
10
+ async add(queueName, data, options) {
11
+ const queueUrl = this.resolveQueueUrl(queueName);
12
+ const messageId = crypto.randomUUID();
13
+ const message = {
14
+ id: messageId,
15
+ queueName,
16
+ data,
17
+ pikkuUserId: options?.pikkuUserId,
18
+ };
19
+ const result = await this.client.send(new SendMessageCommand({
20
+ QueueUrl: queueUrl,
21
+ MessageBody: JSON.stringify(message),
22
+ DelaySeconds: options?.delay
23
+ ? Math.min(Math.ceil(options.delay / 1000), 900)
24
+ : undefined,
25
+ }));
26
+ return result.MessageId ?? messageId;
27
+ }
28
+ async getJob(_queueName, _jobId) {
29
+ throw new Error('SQSQueueService does not support getJob(). ' +
30
+ 'SQS is fire-and-forget. ' +
31
+ 'Use BullMQ or PgBoss if you need job result tracking.');
32
+ }
33
+ resolveQueueUrl(queueName) {
34
+ if (this.queueUrlMap?.[queueName]) {
35
+ return this.queueUrlMap[queueName];
36
+ }
37
+ const envKey = `SQS_QUEUE_URL_${toScreamingSnake(queueName)}`;
38
+ const url = process.env[envKey];
39
+ if (!url) {
40
+ throw new Error(`SQS queue URL not found for queue "${queueName}". ` +
41
+ `Set environment variable ${envKey} or pass queueUrlMap to constructor.`);
42
+ }
43
+ return url;
44
+ }
45
+ }
46
+ function toScreamingSnake(name) {
47
+ return name
48
+ .replace(/([a-z0-9])([A-Z])/g, '$1_$2')
49
+ .replace(/-/g, '_')
50
+ .toUpperCase();
51
+ }
52
+ //# sourceMappingURL=sqs-queue-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqs-queue-service.js","sourceRoot":"","sources":["../src/sqs-queue-service.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAGnE,MAAM,OAAO,eAAe;IAIN;IAHX,eAAe,GAAG,KAAK,CAAA;IACxB,MAAM,CAAW;IAEzB,YAAoB,WAAoC;QAApC,gBAAW,GAAX,WAAW,CAAyB;QACtD,IAAI,CAAC,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,CAAC,CAAA;IACjC,CAAC;IAED,KAAK,CAAC,GAAG,CACP,SAAiB,EACjB,IAAO,EACP,OAAoB;QAEpB,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAA;QAChD,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,EAAE,CAAA;QAErC,MAAM,OAAO,GAAG;YACd,EAAE,EAAE,SAAS;YACb,SAAS;YACT,IAAI;YACJ,WAAW,EAAE,OAAO,EAAE,WAAW;SAClC,CAAA;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CACnC,IAAI,kBAAkB,CAAC;YACrB,QAAQ,EAAE,QAAQ;YAClB,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;YACpC,YAAY,EAAE,OAAO,EAAE,KAAK;gBAC1B,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC;gBAChD,CAAC,CAAC,SAAS;SACd,CAAC,CACH,CAAA;QAED,OAAO,MAAM,CAAC,SAAS,IAAI,SAAS,CAAA;IACtC,CAAC;IAED,KAAK,CAAC,MAAM,CACV,UAAkB,EAClB,MAAc;QAEd,MAAM,IAAI,KAAK,CACb,6CAA6C;YAC3C,0BAA0B;YAC1B,uDAAuD,CAC1D,CAAA;IACH,CAAC;IASO,eAAe,CAAC,SAAiB;QACvC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAA;QACpC,CAAC;QAED,MAAM,MAAM,GAAG,iBAAiB,gBAAgB,CAAC,SAAS,CAAC,EAAE,CAAA;QAC7D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QAE/B,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CACb,sCAAsC,SAAS,KAAK;gBAClD,4BAA4B,MAAM,sCAAsC,CAC3E,CAAA;QACH,CAAC;QAED,OAAO,GAAG,CAAA;IACZ,CAAC;CACF;AAED,SAAS,gBAAgB,CAAC,IAAY;IACpC,OAAO,IAAI;SACR,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;SACtC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC;SAClB,WAAW,EAAE,CAAA;AAClB,CAAC"}
@@ -9,5 +9,5 @@ export declare const getServerlessDependencies: (channelStore: ChannelStore, eve
9
9
  channelId: string;
10
10
  callbackAPI: ApiGatewayManagementApiClient;
11
11
  channelHandlerFactory: import("@pikku/core/channel").PikkuChannelHandlerFactory;
12
- channelStore: ChannelStore<unknown, unknown, import("@pikku/core").CoreUserSession, import("@pikku/core/channel").Channel<unknown, unknown>>;
12
+ channelStore: ChannelStore<unknown, unknown, import("@pikku/core/channel").Channel<unknown, unknown>>;
13
13
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/lambda",
3
- "version": "0.12.2",
3
+ "version": "0.12.4",
4
4
  "license": "MIT",
5
5
  "author": "yasser.fadl@gmail.com",
6
6
  "module": "dist/index.js",
@@ -13,25 +13,31 @@
13
13
  "release": "npm run build && npm test",
14
14
  "test": "bash run-tests.sh",
15
15
  "test:watch": "bash run-tests.sh --watch",
16
- "test:coverage": "bash run-tests.sh --coverage"
16
+ "test:coverage": "bash run-tests.sh --coverage",
17
+ "prepublishOnly": "yarn build"
17
18
  },
18
19
  "exports": {
19
20
  ".": "./dist/index.js",
20
21
  "./http": "./dist/http/index.js",
21
22
  "./websocket": "./dist/websocket/index.js",
22
- "./queue": "./dist/queue/index.js"
23
+ "./queue": "./dist/queue/index.js",
24
+ "./scheduled": "./dist/scheduled/index.js"
23
25
  },
24
26
  "peerDependencies": {
25
27
  "@aws-sdk/client-apigatewaymanagementapi": "^3.713.0",
26
- "@pikku/core": "^0.12.2",
28
+ "@aws-sdk/client-lambda": "^3.713.0",
29
+ "@aws-sdk/client-sqs": "^3.713.0",
30
+ "@pikku/core": "^0.12.44",
27
31
  "@types/aws-lambda": "^8.10.161"
28
32
  },
29
33
  "devDependencies": {
30
34
  "@aws-sdk/client-apigatewaymanagementapi": "^3.1000.0",
35
+ "@aws-sdk/client-lambda": "^3.1000.0",
36
+ "@aws-sdk/client-sqs": "^3.1000.0",
31
37
  "@types/aws-lambda": "^8.10.161",
32
- "typescript": "^5.9.3"
38
+ "typescript": "^6.0.3"
33
39
  },
34
40
  "engines": {
35
- "node": ">=18"
41
+ "node": ">=22"
36
42
  }
37
43
  }