@spytecgps/lambda-utils 2.4.0 → 3.0.1

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.
@@ -7,6 +7,7 @@ export type EnvConfigsParam<T> = {
7
7
  [k: string]: DeepPartial<T>;
8
8
  };
9
9
  export declare const getEnvKey: () => Env;
10
+ export declare const isOffline: () => boolean;
10
11
  export declare const isLocal: () => boolean;
11
12
  export declare const isTest: () => boolean;
12
13
  export declare const isDev: () => boolean;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,6 @@
1
- export * from './wrappers';
1
+ export * from './config';
2
2
  export * from './errors';
3
- export * from './validation';
4
- export * from './types';
5
3
  export * from './middleware';
4
+ export * from './types';
6
5
  export * from './utils';
7
- export * from './config';
6
+ export * from './validation';
package/dist/index.js CHANGED
@@ -1 +1,653 @@
1
- import{logger as e,withRequest as r}from"@spytecgps/sdk-logger";import t from"dayjs";import s from"dayjs/plugin/timezone";import o from"dayjs/plugin/utc";import*as a from"joi";import*as n from"qs";import i from"@middy/core";export{default as httpErrorHandler}from"@middy/http-error-handler";import l from"@middy/http-response-serializer";export{default as httpResponseSerializer}from"@middy/http-response-serializer";export{default as sqsJsonBodyParser}from"@middy/sqs-json-body-parser";import c from"deepmerge";export{default as merge}from"deepmerge";import d from"@middy/input-output-logger";import{LambdaClient as u,InvokeCommand as p}from"@aws-sdk/client-lambda";t.extend(o),t.extend(s);const m=a.extend((e=>({type:"object",base:e.object(),messages:{"json.valid":"must be valid JSON"},coerce(e){try{return{value:JSON.parse(e)}}catch(e){return null}},validate:(e,r)=>e?{value:e}:{value:e,errors:r.error("json.valid")}}))),v=a.extend((e=>({type:"object",base:e.object(),coerce:e=>({value:n.parse(e)})}))),g=a.string().regex(/^\d{15,16}$/).message("Invalid IMEI"),h=a.string().regex(/^[0-9A-Za-z]{18,22}$/).message("Invalid ICCID"),y=a.extend((e=>({type:"imei",messages:"Invalid IMEI",base:e.string().regex(/^\d{15,16}$/)})),(e=>({type:"iccid",messages:"Invalid ICCID",base:e.string().regex(/^[0-9A-Za-z]{18,22}$/)})),(e=>({type:"urlEncodedObject",base:e.object(),coerce:e=>({value:n.parse(e)})})),(e=>({type:"jsonObject",base:e.object(),coerce(e){try{return{value:JSON.parse(e)}}catch(e){return null}},validate:(e,r)=>e?{value:e}:{value:e,errors:r.error("json.valid")}})),(e=>({type:"delimitedArray",base:e.array().default([]),coerce:e=>({value:e.split?e.split(","):e})})),(e=>({type:"queryStringParameters",messages:"Missing query parameters",base:e.object().required()})),(e=>({type:"date",base:e.date(),prepare(e,r){try{const r=t.tz(e,"UTC");if(r.isValid())return{value:r.toDate()}}catch(e){return r.error("any.invalid")}}})),(e=>({type:"jsonArray",base:e.array(),coerce(e){try{return{value:JSON.parse(e)}}catch(e){return{value:null}}},validate:(e,r)=>Array.isArray(e)?{value:e}:{value:e,errors:r.error("jsonArray.schema")}})),(e=>({type:"base64ThenUriEncodedObject",base:e.object(),coerce(e){try{const r=decodeURIComponent(Buffer.from(e,"base64").toString());return{value:JSON.parse(r)}}catch(e){return null}},validate:(e,r)=>e?{value:e}:{value:e,errors:r.error("json.valid")}})));class b extends Error{}class f extends b{code=400;statusCode=400;name="BadRequestError"}class w extends Error{code;statusCode}class C extends b{code=409;statusCode=409;name="ConflictError"}class E extends b{code=403;statusCode=403;name="ForbiddenError"}class x extends b{code=404;statusCode=404;name="NotFoundError"}class A extends b{code=401;statusCode=401;name="UnauthorizedError"}const q=({scope:e,type:r}={})=>a.object({clientId:a.number(),resources:m.object({}),scope:e?a.string().pattern(new RegExp(`${e}`)).error((()=>new A(`missing scope ${e}`))):a.optional(),type:r?a.any().valid(r).error((()=>new A(`missing user type ${r}`))):a.optional(),enterprise:a.boolean().default(!1),maintenanceModule:a.boolean().default(!1),billingMethod:a.string().optional(),customerSegment:a.string().optional(),securityGroupTagId:a.number().optional().allow(null),securityRole:a.string().optional().allow(null)}),I=a.object({authorizer:q()}),N=(e={})=>a.object({authorizer:q(e)}),S=(r,t,s)=>{if(!t)return e.warn("skipping validation"),r;const{error:o,value:a}=t.validate(r,{allowUnknown:s?.allowUnknown||!0,errors:{label:"key",wrap:{label:!1}}});if(o)throw e.error({error:o},"Validation error"),o.isJoi?new f(o.message):o;return a},j=y.object({requestContext:N()}),O={"Content-Type":"application/json","Access-Control-Allow-Origin":"*","Access-Control-Allow-Credentials":!0},R=(e,r,t)=>({success:e<400,message:r,result:t||void 0}),_=({statusCode:e=200,message:r="ok",data:t,headers:s={},rawResult:o=!1,stringifyBody:a=!0})=>{const n=o?t:R(e,r,t),i=a?n&&JSON.stringify(n):t;return{headers:{...O,...s},statusCode:e,body:i}},z=async({event:t,context:s,schema:o,handler:a})=>{t&&s&&r(t,s);try{const e=S(t,o),r=await a(e);return _(r)}catch(r){return e.error({err:r,event:(n=t,{resource:n.resource,httpMethod:n.httpMethod,queryStringParameters:n.queryStringParameters,pathParameters:n.pathParameters,body:n.body})},"apiGatewayWrapper - caught error"),_({statusCode:r.code||500,message:r.message||"Error"})}var n};const T=async({event:t,context:s,schema:o,handler:a,singleHandler:n,mode:i="serial"})=>{t&&s&&r(t,s);try{const e=S(t,o);await async function(e,r,t,s){if(!r&&!t)throw new Error("handler or singleHandler not defined");if(r)await r(e);else if(t){const r=e.Records;if("serial"===s)for(const e of r)await t(e);else"parallel"===s&&await Promise.all(r.map((e=>t(e))))}}(e,a,n,i)}catch(r){throw e.error({err:r,event:(l=t,(l.Records||[]).map((e=>({messageId:e.messageId,body:e.body,messageAttributes:e.messageAttributes}))))},"sqsEventWrapper - caught error"),r}var l},P=async({event:t,context:s,schema:o,handler:a,singleHandler:n,mode:i="serial"})=>{t&&s&&r(t,s);try{const e=S(t,o);return await(async(e,r,t,s)=>{if(!r&&!t)throw new Error("handler or singleHandler not defined");if(r)return await r(e);if(t){const r=e.Records;if("serial"===s){const e=[];for(const s of r){const r=await t(s);e.push(r)}return e}if("parallel"===s)return await Promise.all(r.map((e=>t(e))))}})(e,a,n,i)}catch(r){throw e.error({err:r,event:(l=t,(l.Records||[]).map((e=>({messageId:e.messageId,body:e.body,messageAttributes:e.messageAttributes}))))},"sqsEventWrapper - caught error"),r}var l},M=()=>"test"===process.env.NODE_ENV?"test":process.env.IS_OFFLINE&&"dev"===process.env.STAGE?"local":process.env.STAGE??process.env.NODE_ENV??"dev",H=()=>"local"===M(),$=()=>"test"===M(),k=()=>"dev"===M(),G=()=>"prod"===M(),W=e=>{const r=e.base,t=e[M()]??{};return c(r,t)},J="_X_AMZN_TRACE_ID",U="x-correlation-",B=`${U}id`,F=`${U}trace-id`,D={before:async({event:r,context:t})=>{const s={awsRequestId:t?.awsRequestId},o=r?.requestContext?.requestId;o&&(s.apiRequestId=o),r.headers&&Object.keys(r.headers).forEach((e=>{e.toLowerCase().startsWith(U)&&(s[e]=r.headers[e])})),process.env[J]&&(s[F]=process.env[J]),s[B]||(s[B]=t.awsRequestId),e.setHapnContext(s)}},V=d({omitPaths:["event.multiValueHeaders","event.multiValueQueryStringParameters","event.resource","event.httpMethod","event.headers","event.stageVariables","event.requestContext.resourceId","event.requestContext.resourcePath","event.requestContext.httpMethod","event.requestContext.extendedRequestId","event.requestContext.requestTime","event.requestContext.path","event.requestContext.accountId","event.requestContext.protocol","event.requestContext.stage","event.requestContext.domainPrefix","event.requestContext.requestTimeEpoch","event.requestContext.apiId","event.requestContext.domainName","event.requestContext.identity","event.isBase64Encoded","event.body","response.body","response.headers"],logger:r=>{const t=r?.event?"event":"response";e.info(r.event??r.response,t)}}),L=({schema:r,allowUnknown:t=!0})=>({before:s=>{const{error:o,value:a}=r.validate(s.event,{allowUnknown:t,errors:{label:"key",wrap:{label:!1}}});if(o)throw e.error("Validation error",{error:o}),o.isJoi?new f(o.message):o;s.event=a}}),Z={isWarmingUp:e=>"serverless-plugin-warmup"===e.source},Q=(e={})=>{const r={...Z,...e};return{before:e=>{if(r.isWarmingUp(e.event))return"warmup"}}},X=[Q(),D,H()||$()?void 0:V].filter(Boolean),K=[l({serializers:[{regex:/^application\/xml$/,serializer:({body:e})=>`<message>${e}</message>`},{regex:/^application\/json$/,serializer:({body:e})=>JSON.stringify(e)},{regex:/^text\/plain$/,serializer:({body:e})=>e}],default:"application/json"}),{after:e=>{e.response=_(e.response)},onError:r=>{e.error(r.error,"Request failed"),r.response=_({statusCode:r.error.code||500,message:r.error.message||"Error"})}},(({authFunctionName:r="spytec-web-api-auth-prod-AuthorizerFunction",enabled:t=!!process.env.IS_OFFLINE}={})=>{const s=new u({region:process.env.AWS_REGION});return{before:async o=>{if(!t)return;const{event:a}=o,n=a.headers?.Authorization||a.headers?.authorization;if(!n||!n.startsWith("Bearer "))throw new Error("Authorization header is missing or invalid");const i={authorizationToken:n.slice(7)},l=new p({FunctionName:r,Payload:Buffer.from(JSON.stringify(i))});try{const e=await s.send(l),r=JSON.parse(Buffer.from(e.Payload).toString());if(r.errorMessage)throw new Error(r.errorMessage);a.requestContext.authorizer=r.context}catch(r){throw e.error("Error invoking auth function:",r),new Error("Authorization failed")}}}})()],Y=e=>i(e).use([...X]),ee=e=>i(e).use([...X,...K]);class re{collectionName;constructor(e){this.collectionName=e??`${process.env.AWS_LAMBDA_FUNCTION_NAME}-${process.env.AWS_LAMBDA_FUNCTION_VERSION}`,global.CACHE_STORAGE||(global.CACHE_STORAGE={}),global.CACHE_STORAGE[this.collectionName]||(global.CACHE_STORAGE[this.collectionName]=new Map)}set(e,r,t){const s=1e3*t+Date.now();global.CACHE_STORAGE[this.collectionName].set(e,{value:r,expire:s})}get(e){if(!e)throw new Error("key is required!");const r=global.CACHE_STORAGE[this.collectionName].get(e);return r?!r.expire||r.expire>Date.now()?r.value:this.remove(e):null}remove(e){global.CACHE_STORAGE[this.collectionName].get(e)&&global.CACHE_STORAGE[this.collectionName].delete(e)}}const te=async(e,r,t,s)=>{let o=r.get(t);return o||(o=await e(),r.set(t,o,s)),o},se=(e,r,t=new Error("Promise timed out"))=>{const s=new Promise(((e,s)=>{setTimeout((()=>{s(t)}),r)}));return Promise.race([e,s])};export{f as BadRequestError,w as BaseError,C as ConflictError,E as ForbiddenError,b as HttpError,re as LambdaCache,x as NotFoundError,y as SpytecJoi,A as UnauthorizedError,z as apiGatewayEventWrapper,K as apiGatewayMiddlewares,ee as apiGatewayMiddy,X as baseMiddlewares,_ as buildProxyResult,R as buildResponseBody,j as defaultApiSchema,q as getAuthorizerValidator,M as getEnvKey,N as getRequestContextValidator,h as iccidSchema,g as imeiSchema,k as isDev,H as isLocal,G as isProduction,$ as isTest,m as json,Y as middy,te as promiseWithCache,se as promiseWithTimeout,I as requestContextValidator,W as setupEnvConfig,T as sqsEventWrapper,P as sqsEventWrapperWithReturn,v as urlEncoded,S as validateEvent,L as validatorMiddleware,Q as warmupMiddleware};
1
+ 'use strict';
2
+
3
+ var merge = require('deepmerge');
4
+ var core = require('@middy/core');
5
+ var httpErrorHandler = require('@middy/http-error-handler');
6
+ var httpResponseSerializer = require('@middy/http-response-serializer');
7
+ var sqsJsonBodyParser = require('@middy/sqs-json-body-parser');
8
+ var inputOutputLogger = require('@middy/input-output-logger');
9
+ var clientLambda = require('@aws-sdk/client-lambda');
10
+ var dayjs = require('dayjs');
11
+ var timezone = require('dayjs/plugin/timezone');
12
+ var utc = require('dayjs/plugin/utc');
13
+ var Joi = require('joi');
14
+ var qs = require('qs');
15
+
16
+ function _interopNamespaceDefault(e) {
17
+ var n = Object.create(null);
18
+ if (e) {
19
+ Object.keys(e).forEach(function (k) {
20
+ if (k !== 'default') {
21
+ var d = Object.getOwnPropertyDescriptor(e, k);
22
+ Object.defineProperty(n, k, d.get ? d : {
23
+ enumerable: true,
24
+ get: function () { return e[k]; }
25
+ });
26
+ }
27
+ });
28
+ }
29
+ n.default = e;
30
+ return Object.freeze(n);
31
+ }
32
+
33
+ var Joi__namespace = /*#__PURE__*/_interopNamespaceDefault(Joi);
34
+ var qs__namespace = /*#__PURE__*/_interopNamespaceDefault(qs);
35
+
36
+ const getEnvKey = () => {
37
+ if (process.env.NODE_ENV === 'test') {
38
+ return 'test';
39
+ }
40
+ if (isOffline() && process.env.STAGE === 'dev') {
41
+ return 'local';
42
+ }
43
+ return (process.env.STAGE ?? process.env.NODE_ENV ?? 'dev');
44
+ };
45
+ const isOffline = () => !!process.env.IS_OFFLINE;
46
+ const isLocal = () => getEnvKey() === 'local';
47
+ const isTest = () => getEnvKey() === 'test';
48
+ const isDev = () => getEnvKey() === 'dev';
49
+ const isProduction = () => getEnvKey() === 'prod';
50
+ const setupEnvConfig = (envConfigs) => {
51
+ const baseConfig = envConfigs['base'];
52
+ const envConfig = envConfigs[getEnvKey()] ?? {};
53
+ return merge(baseConfig, envConfig);
54
+ };
55
+
56
+ class HttpError extends Error {
57
+ }
58
+
59
+ class BadRequestError extends HttpError {
60
+ code = 400;
61
+ statusCode = 400;
62
+ name = 'BadRequestError';
63
+ }
64
+
65
+ class BaseError extends Error {
66
+ code;
67
+ statusCode;
68
+ }
69
+
70
+ class ConflictError extends HttpError {
71
+ code = 409;
72
+ statusCode = 409;
73
+ name = 'ConflictError';
74
+ }
75
+
76
+ class ForbiddenError extends HttpError {
77
+ code = 403;
78
+ statusCode = 403;
79
+ name = 'ForbiddenError';
80
+ }
81
+
82
+ class NotFoundError extends HttpError {
83
+ code = 404;
84
+ statusCode = 404;
85
+ name = 'NotFoundError';
86
+ }
87
+
88
+ class UnauthorizedError extends HttpError {
89
+ code = 401;
90
+ statusCode = 401;
91
+ name = 'UnauthorizedError';
92
+ }
93
+
94
+ const AMAZON_TRACE_ID = '_X_AMZN_TRACE_ID';
95
+ const CORRELATION_HEADER = 'x-correlation-';
96
+ const CORRELATION_ID = `${CORRELATION_HEADER}id`;
97
+ const CORRELATION_TRACE_ID = `${CORRELATION_HEADER}trace-id`;
98
+ const contextualLogger = ({ logger }) => {
99
+ const before = async ({ event, context }) => {
100
+ const ctx = {
101
+ awsRequestId: context?.awsRequestId,
102
+ };
103
+ // capture api gateway request ID
104
+ const apiRequestId = event?.requestContext?.requestId;
105
+ if (apiRequestId) {
106
+ ctx.apiRequestId = apiRequestId;
107
+ }
108
+ // capture any correlation headers sent from upstream callers
109
+ if (event.headers) {
110
+ Object.keys(event.headers).forEach((header) => {
111
+ if (header.toLowerCase().startsWith(CORRELATION_HEADER)) {
112
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
113
+ ctx[header] = event.headers[header];
114
+ }
115
+ });
116
+ }
117
+ // capture the xray trace id if its enabled
118
+ if (process.env[AMAZON_TRACE_ID]) {
119
+ ctx[CORRELATION_TRACE_ID] = process.env[AMAZON_TRACE_ID];
120
+ }
121
+ // set the correlation id if not already set by upstream callers
122
+ /* istanbul ignore next */
123
+ if (!ctx[CORRELATION_ID]) {
124
+ ctx[CORRELATION_ID] = context.awsRequestId;
125
+ }
126
+ logger.setHapnContext(ctx);
127
+ };
128
+ return {
129
+ before,
130
+ };
131
+ };
132
+
133
+ const ioLogger = ({ logger }) => inputOutputLogger({
134
+ omitPaths: [
135
+ 'event.multiValueHeaders',
136
+ 'event.multiValueQueryStringParameters',
137
+ 'event.resource',
138
+ 'event.httpMethod',
139
+ 'event.headers',
140
+ 'event.stageVariables',
141
+ 'event.requestContext.resourceId',
142
+ 'event.requestContext.resourcePath',
143
+ 'event.requestContext.httpMethod',
144
+ 'event.requestContext.extendedRequestId',
145
+ 'event.requestContext.requestTime',
146
+ 'event.requestContext.path',
147
+ 'event.requestContext.accountId',
148
+ 'event.requestContext.protocol',
149
+ 'event.requestContext.stage',
150
+ 'event.requestContext.domainPrefix',
151
+ 'event.requestContext.requestTimeEpoch',
152
+ 'event.requestContext.apiId',
153
+ 'event.requestContext.domainName',
154
+ 'event.requestContext.identity',
155
+ 'event.isBase64Encoded',
156
+ 'event.body',
157
+ 'response.body',
158
+ 'response.headers',
159
+ ],
160
+ logger: (req) => {
161
+ if (isLocal() || isTest()) {
162
+ return;
163
+ }
164
+ const message = req?.event ? 'event' : 'response';
165
+ logger.info(req.event ?? req.response, message);
166
+ },
167
+ });
168
+
169
+ const normalizerMiddleware = () => {
170
+ return {
171
+ before: async (request) => {
172
+ const event = request.event;
173
+ event.queryStringParameters = event.queryStringParameters || {};
174
+ event.pathParameters = event.pathParameters || {};
175
+ },
176
+ };
177
+ };
178
+
179
+ const offlineAuth = ({ authFunctionName = 'spytec-web-api-auth-prod-AuthorizerFunctionV4', enabled = isOffline(), logger, }) => {
180
+ const lambdaClient = new clientLambda.LambdaClient({ region: process.env.AWS_REGION });
181
+ return {
182
+ before: async (request) => {
183
+ if (!enabled)
184
+ return;
185
+ const { event } = request;
186
+ // Extract Bearer token from the Authorization header
187
+ const authHeader = event.headers?.Authorization || event.headers?.authorization;
188
+ if (!authHeader || !authHeader.startsWith('Bearer ')) {
189
+ // throw new Error('Authorization header is missing or invalid')
190
+ // if we can't extract the token, this is is a public route, ignore it
191
+ logger.warn('Authorization header is missing or invalid, skipping fake offline authorization');
192
+ return;
193
+ }
194
+ const token = authHeader.slice(7); // Remove 'Bearer ' prefix
195
+ // Prepare payload for the auth function
196
+ const payload = {
197
+ authorizationToken: token,
198
+ };
199
+ // Invoke the auth function manually
200
+ const command = new clientLambda.InvokeCommand({
201
+ FunctionName: authFunctionName,
202
+ Payload: Buffer.from(JSON.stringify(payload)),
203
+ });
204
+ try {
205
+ const response = await lambdaClient.send(command);
206
+ const responsePayload = JSON.parse(Buffer.from(response.Payload ?? '').toString());
207
+ if (responsePayload.errorMessage) {
208
+ throw new Error(responsePayload.errorMessage);
209
+ }
210
+ event.requestContext.authorizer = responsePayload.context;
211
+ }
212
+ catch (error) {
213
+ logger.error(error, 'Error invoking auth function');
214
+ throw new Error('Authorization failed');
215
+ }
216
+ },
217
+ };
218
+ };
219
+
220
+ const baseHeaders = {
221
+ 'Content-Type': 'application/json',
222
+ 'Access-Control-Allow-Origin': '*',
223
+ 'Access-Control-Allow-Credentials': true,
224
+ };
225
+ const buildResponseBody = (statusCode, message, data) => {
226
+ return {
227
+ success: statusCode < 400,
228
+ message,
229
+ result: typeof data !== 'undefined' ? data : undefined,
230
+ };
231
+ };
232
+ const buildProxyResult = ({ statusCode = 200, message = 'ok', data, headers = {}, multiValueHeaders = {}, rawResult = false, stringifyBody = true, }) => {
233
+ const resp = rawResult ? data : buildResponseBody(statusCode, message, data);
234
+ const body = stringifyBody ? resp && JSON.stringify(resp) : data;
235
+ return {
236
+ headers: { ...baseHeaders, ...headers },
237
+ multiValueHeaders,
238
+ statusCode,
239
+ body,
240
+ };
241
+ };
242
+
243
+ const responseWrapper = ({ logger }) => {
244
+ const responseWrapperMiddlewareAfter = (req) => {
245
+ req.response = buildProxyResult(req.response);
246
+ };
247
+ const responseWrapperMiddlewareError = (req) => {
248
+ const statusCode = req.error?.code ?? 500;
249
+ const errorMessage = req.error?.message || 'Error';
250
+ const loggerMethod = statusCode >= 500 ? 'error' : 'info';
251
+ logger[loggerMethod](req.error, 'Request failed');
252
+ req.response = buildProxyResult({
253
+ statusCode,
254
+ message: errorMessage,
255
+ });
256
+ };
257
+ return {
258
+ after: responseWrapperMiddlewareAfter,
259
+ onError: responseWrapperMiddlewareError,
260
+ };
261
+ };
262
+
263
+ const validator = ({ schema, allowUnknown = true, logger }) => {
264
+ const validatorMiddlewareBefore = (request) => {
265
+ const { error, value } = schema.validate(request.event, {
266
+ allowUnknown,
267
+ errors: {
268
+ label: 'key',
269
+ wrap: {
270
+ label: false,
271
+ },
272
+ },
273
+ });
274
+ if (error) {
275
+ logger.warn(error, 'Validation error');
276
+ throw error.isJoi ? new BadRequestError(error.message) : error;
277
+ }
278
+ request.event = value;
279
+ };
280
+ return {
281
+ before: validatorMiddlewareBefore,
282
+ };
283
+ };
284
+
285
+ /* eslint-disable @typescript-eslint/no-explicit-any */
286
+ const defaults = {
287
+ isWarmingUp: (event) => event.source === 'serverless-plugin-warmup',
288
+ };
289
+ const warmupMiddleware = (opt = {}) => {
290
+ const options = { ...defaults, ...opt };
291
+ const warmupMiddlewareBefore = (request) => {
292
+ if (options.isWarmingUp(request.event)) {
293
+ return 'warmup';
294
+ }
295
+ };
296
+ return {
297
+ before: warmupMiddlewareBefore,
298
+ };
299
+ };
300
+
301
+ // Function that returns base middlewares with required logger
302
+ const getBaseMiddlewares = ({ logger }) => [
303
+ warmupMiddleware(),
304
+ contextualLogger({ logger }),
305
+ ioLogger({ logger }),
306
+ ];
307
+ // Function that returns API Gateway middlewares with required logger
308
+ const getApiGatewayMiddlewares = ({ logger, offlineAuthEnabled = true }) => [
309
+ httpResponseSerializer({
310
+ serializers: [
311
+ {
312
+ regex: /^application\/xml$/,
313
+ serializer: ({ body }) => `<message>${body}</message>`,
314
+ },
315
+ {
316
+ regex: /^application\/json$/,
317
+ serializer: ({ body }) => JSON.stringify(body),
318
+ },
319
+ {
320
+ regex: /^text\/plain$/,
321
+ serializer: ({ body }) => body,
322
+ },
323
+ ],
324
+ default: 'application/json',
325
+ }),
326
+ responseWrapper({ logger }),
327
+ offlineAuth({ logger, enabled: offlineAuthEnabled }),
328
+ normalizerMiddleware(),
329
+ ];
330
+
331
+ class LambdaCache {
332
+ collectionName;
333
+ /**
334
+ * @param {String} collectionName (not required) - The collection key used to store the cache values.
335
+ * If not provide default collection name uses :
336
+ * ${process.env.AWS_LAMBDA_FUNCTION_NAME}-${process.env.AWS_LAMBDA_FUNCTION_VERSION}
337
+ * */
338
+ constructor(collectionName) {
339
+ this.collectionName =
340
+ collectionName ?? `${process.env.AWS_LAMBDA_FUNCTION_NAME}-${process.env.AWS_LAMBDA_FUNCTION_VERSION}`;
341
+ if (!global['CACHE_STORAGE']) {
342
+ global['CACHE_STORAGE'] = {};
343
+ }
344
+ if (!global['CACHE_STORAGE'][this.collectionName]) {
345
+ global['CACHE_STORAGE'][this.collectionName] = new Map();
346
+ }
347
+ }
348
+ /**
349
+ * @param {String} key (required) - cache key
350
+ * @param {Object} value (required) - cache value
351
+ * @param {Number} expire (required) - cache expiration time (seconds)
352
+ * */
353
+ set(key, value, ttl) {
354
+ const expire = 1000 * ttl + Date.now();
355
+ global['CACHE_STORAGE'][this.collectionName].set(key, { value, expire });
356
+ }
357
+ /**
358
+ * @param {String} key (required) - cache key to get
359
+ * */
360
+ get(key) {
361
+ if (!key) {
362
+ throw new Error('key is required!');
363
+ }
364
+ const record = global['CACHE_STORAGE'][this.collectionName].get(key);
365
+ if (!record) {
366
+ return null;
367
+ }
368
+ if (!record.expire || record.expire > Date.now()) {
369
+ return record.value;
370
+ }
371
+ else {
372
+ return this.remove(key);
373
+ }
374
+ }
375
+ /**
376
+ * @param {String} key (required) - cache key to remove
377
+ * */
378
+ remove(key) {
379
+ const record = global['CACHE_STORAGE'][this.collectionName].get(key);
380
+ if (!record) {
381
+ return;
382
+ }
383
+ global['CACHE_STORAGE'][this.collectionName].delete(key);
384
+ }
385
+ }
386
+
387
+ const promiseWithCache = async (promise, cacheInstance, cacheKey, ttl) => {
388
+ let instance = cacheInstance.get(cacheKey);
389
+ if (!instance) {
390
+ instance = await promise();
391
+ cacheInstance.set(cacheKey, instance, ttl);
392
+ }
393
+ return instance;
394
+ };
395
+
396
+ const promiseWithTimeout = (promise, ms, timeoutError = new Error('Promise timed out')) => {
397
+ // create a promise that rejects in milliseconds
398
+ const timeout = new Promise((_, reject) => {
399
+ setTimeout(() => {
400
+ reject(timeoutError);
401
+ }, ms);
402
+ });
403
+ // returns a race between timeout and the passed promise
404
+ return Promise.race([promise, timeout]);
405
+ //Adding comment to test
406
+ };
407
+
408
+ dayjs.extend(utc);
409
+ dayjs.extend(timezone);
410
+ const json = Joi__namespace.extend((joi) => {
411
+ return {
412
+ type: 'object',
413
+ base: joi.object(),
414
+ messages: {
415
+ 'json.valid': 'must be valid JSON',
416
+ },
417
+ coerce(value) {
418
+ try {
419
+ return { value: JSON.parse(value) };
420
+ }
421
+ catch (err) {
422
+ return null;
423
+ }
424
+ },
425
+ validate(value, helpers) {
426
+ if (!value) {
427
+ return { value, errors: helpers.error('json.valid') };
428
+ }
429
+ return { value };
430
+ },
431
+ };
432
+ });
433
+ const urlEncoded = Joi__namespace.extend((joi) => {
434
+ return {
435
+ type: 'object',
436
+ base: joi.object(),
437
+ coerce(value) {
438
+ return { value: qs__namespace.parse(value) };
439
+ },
440
+ };
441
+ });
442
+ const imeiSchema = Joi__namespace.string()
443
+ .regex(/^\d{15,16}$/)
444
+ .message('Invalid IMEI');
445
+ const iccidSchema = Joi__namespace.string()
446
+ .regex(/^[0-9A-Za-z]{18,22}$/)
447
+ .message('Invalid ICCID');
448
+ const SpytecJoi = Joi__namespace.extend((joi) => ({
449
+ type: 'imei',
450
+ messages: 'Invalid IMEI',
451
+ base: joi.string().regex(/^\d{15,16}$/),
452
+ }), (joi) => ({
453
+ type: 'iccid',
454
+ messages: 'Invalid ICCID',
455
+ base: joi.string().regex(/^[0-9A-Za-z]{18,22}$/),
456
+ }), (joi) => ({
457
+ type: 'urlEncodedObject',
458
+ base: joi.object(),
459
+ coerce(value) {
460
+ return { value: qs__namespace.parse(value) };
461
+ },
462
+ }), (joi) => ({
463
+ type: 'jsonObject',
464
+ base: joi.object(),
465
+ coerce(value) {
466
+ try {
467
+ return { value: JSON.parse(value) };
468
+ }
469
+ catch (err) {
470
+ return null;
471
+ }
472
+ },
473
+ validate(value, helpers) {
474
+ if (!value) {
475
+ return { value, errors: helpers.error('json.valid') };
476
+ }
477
+ return { value };
478
+ },
479
+ }), (joi) => ({
480
+ type: 'delimitedArray',
481
+ base: joi.array().default([]),
482
+ coerce: (value) => ({
483
+ value: value.split ? value.split(',') : value,
484
+ }),
485
+ }), (joi) => ({
486
+ type: 'queryStringParameters',
487
+ messages: 'Missing query parameters',
488
+ base: joi.object().required(),
489
+ }), (joi) => ({
490
+ type: 'date',
491
+ base: joi.date(),
492
+ prepare(value, helpers) {
493
+ try {
494
+ const dayjsDate = dayjs.tz(value, 'UTC');
495
+ if (dayjsDate.isValid()) {
496
+ return { value: dayjsDate.toDate() };
497
+ }
498
+ }
499
+ catch (error) {
500
+ return helpers.error('any.invalid');
501
+ }
502
+ },
503
+ }), (joi) => ({
504
+ type: 'jsonArray',
505
+ base: joi.array(),
506
+ coerce(value) {
507
+ try {
508
+ return { value: JSON.parse(value) };
509
+ }
510
+ catch (err) {
511
+ return { value: null };
512
+ }
513
+ },
514
+ validate(value, helpers) {
515
+ if (!Array.isArray(value)) {
516
+ return { value, errors: helpers.error('jsonArray.schema') };
517
+ }
518
+ return { value };
519
+ },
520
+ }), (joi) => ({
521
+ type: 'base64ThenUriEncodedObject',
522
+ base: joi.object(),
523
+ coerce(value) {
524
+ try {
525
+ const decodedValue = decodeURIComponent(Buffer.from(value, 'base64').toString());
526
+ return { value: JSON.parse(decodedValue) };
527
+ }
528
+ catch (err) {
529
+ return null;
530
+ }
531
+ },
532
+ validate(value, helpers) {
533
+ if (!value) {
534
+ return { value, errors: helpers.error('json.valid') };
535
+ }
536
+ return { value };
537
+ },
538
+ }));
539
+
540
+ const getAuthorizerValidator = (params = {}) => {
541
+ return Joi__namespace.object({
542
+ clientId: Joi__namespace.number().greater(0).required(),
543
+ userId: Joi__namespace.string().guid( /*{ version: 'uuidv4' }*/).required(),
544
+ resources: json.object({}),
545
+ scope: Joi__namespace.string().optional(),
546
+ // .error(() => new UnauthorizedError(`missing scope ${scope}`))
547
+ type: Joi__namespace.string().optional(),
548
+ // .error(() => new UnauthorizedError(`missing user type ${type}`))
549
+ enterprise: Joi__namespace.boolean().default(false),
550
+ maintenanceModule: Joi__namespace.boolean().default(false),
551
+ billingMethod: Joi__namespace.string().optional(),
552
+ customerSegment: Joi__namespace.string().optional(),
553
+ securityGroupTagId: Joi__namespace.number().optional().allow(null),
554
+ securityRole: Joi__namespace.string().optional().allow(null),
555
+ ...params,
556
+ });
557
+ };
558
+ const getAuthorizerValidatorV4 = (params = {}) => {
559
+ return Joi__namespace.object({
560
+ clientId: Joi__namespace.number().greater(0).required(),
561
+ userId: Joi__namespace.string().guid( /*{ version: 'uuidv4' }*/).required(),
562
+ scope: Joi__namespace.string().optional(),
563
+ type: Joi__namespace.string().optional(),
564
+ ...params,
565
+ });
566
+ };
567
+ /**
568
+ * @deprecated
569
+ */
570
+ const requestContextValidator = Joi__namespace.object({
571
+ authorizer: getAuthorizerValidator(),
572
+ });
573
+ const getRequestContextValidator = (params = {}) => {
574
+ return Joi__namespace.object({
575
+ authorizer: getAuthorizerValidator(params),
576
+ });
577
+ };
578
+ const getRequestContextValidatorV4 = (params = {}) => {
579
+ return Joi__namespace.object({
580
+ authorizer: getAuthorizerValidatorV4(params),
581
+ });
582
+ };
583
+
584
+ /**
585
+ * @deprecated
586
+ */
587
+ const validateEvent = (event, schema, validateOptions) => {
588
+ if (!schema) {
589
+ console.warn(`skipping validation`);
590
+ return event;
591
+ }
592
+ const { error, value } = schema.validate(event, {
593
+ allowUnknown: validateOptions?.allowUnknown || true,
594
+ errors: {
595
+ label: 'key',
596
+ wrap: {
597
+ label: false,
598
+ },
599
+ },
600
+ });
601
+ if (error) {
602
+ console.error({ error }, 'Validation error');
603
+ throw error.isJoi ? new BadRequestError(error.message) : error;
604
+ }
605
+ return value;
606
+ };
607
+
608
+ const defaultApiSchema = SpytecJoi.object({
609
+ requestContext: getRequestContextValidator(),
610
+ });
611
+
612
+ exports.merge = merge;
613
+ exports.middy = core;
614
+ exports.httpErrorHandler = httpErrorHandler;
615
+ exports.httpResponseSerializer = httpResponseSerializer;
616
+ exports.sqsJsonBodyParser = sqsJsonBodyParser;
617
+ exports.BadRequestError = BadRequestError;
618
+ exports.BaseError = BaseError;
619
+ exports.ConflictError = ConflictError;
620
+ exports.ForbiddenError = ForbiddenError;
621
+ exports.HttpError = HttpError;
622
+ exports.LambdaCache = LambdaCache;
623
+ exports.NotFoundError = NotFoundError;
624
+ exports.SpytecJoi = SpytecJoi;
625
+ exports.UnauthorizedError = UnauthorizedError;
626
+ exports.contextualLogger = contextualLogger;
627
+ exports.defaultApiSchema = defaultApiSchema;
628
+ exports.getApiGatewayMiddlewares = getApiGatewayMiddlewares;
629
+ exports.getAuthorizerValidator = getAuthorizerValidator;
630
+ exports.getAuthorizerValidatorV4 = getAuthorizerValidatorV4;
631
+ exports.getBaseMiddlewares = getBaseMiddlewares;
632
+ exports.getEnvKey = getEnvKey;
633
+ exports.getRequestContextValidator = getRequestContextValidator;
634
+ exports.getRequestContextValidatorV4 = getRequestContextValidatorV4;
635
+ exports.iccidSchema = iccidSchema;
636
+ exports.imeiSchema = imeiSchema;
637
+ exports.ioLogger = ioLogger;
638
+ exports.isDev = isDev;
639
+ exports.isLocal = isLocal;
640
+ exports.isOffline = isOffline;
641
+ exports.isProduction = isProduction;
642
+ exports.isTest = isTest;
643
+ exports.json = json;
644
+ exports.offlineAuth = offlineAuth;
645
+ exports.promiseWithCache = promiseWithCache;
646
+ exports.promiseWithTimeout = promiseWithTimeout;
647
+ exports.requestContextValidator = requestContextValidator;
648
+ exports.responseWrapper = responseWrapper;
649
+ exports.setupEnvConfig = setupEnvConfig;
650
+ exports.urlEncoded = urlEncoded;
651
+ exports.validateEvent = validateEvent;
652
+ exports.validator = validator;
653
+ exports.warmupMiddleware = warmupMiddleware;
@@ -1,12 +1,11 @@
1
- export declare const contextualLogger: () => {
2
- before: ({ event, context }: {
3
- event: any;
4
- context: any;
5
- }) => Promise<void>;
6
- };
7
- export declare const contextualLoggerMiddleware: {
1
+ import { HapnLogger } from '@spytecgps/sdk-logger';
2
+ interface ContextualLoggerOptions {
3
+ logger: HapnLogger;
4
+ }
5
+ export declare const contextualLogger: ({ logger }: ContextualLoggerOptions) => {
8
6
  before: ({ event, context }: {
9
7
  event: any;
10
8
  context: any;
11
9
  }) => Promise<void>;
12
10
  };
11
+ export {};
@@ -1,8 +1,8 @@
1
1
  import { APIGatewayProxyResult } from 'aws-lambda';
2
- import { HandlerResponse } from '../types';
2
+ import { HandlerResponse } from '../../types';
3
3
  export declare const buildResponseBody: <T>(statusCode: number, message: string, data?: T) => {
4
4
  success: boolean;
5
5
  message: string;
6
6
  result: T | undefined;
7
7
  };
8
- export declare const buildProxyResult: <R>({ statusCode, message, data, headers, rawResult, stringifyBody, }: HandlerResponse<R>) => APIGatewayProxyResult;
8
+ export declare const buildProxyResult: <R>({ statusCode, message, data, headers, multiValueHeaders, rawResult, stringifyBody, }: HandlerResponse<R>) => APIGatewayProxyResult;
@@ -1,25 +1,33 @@
1
- import rawMiddy from '@middy/core';
1
+ import middy from '@middy/core';
2
2
  import httpErrorHandler from '@middy/http-error-handler';
3
3
  import httpResponseSerializer from '@middy/http-response-serializer';
4
4
  import sqsJsonBodyParser from '@middy/sqs-json-body-parser';
5
- import { Context as LambdaContext } from 'aws-lambda/handler';
6
- import { MiddyInputHandler } from './types';
7
- import { validatorMiddleware } from './validation';
5
+ import { HapnLogger } from '@spytecgps/sdk-logger';
6
+ import { contextualLogger } from './contextualLogger';
7
+ import { ioLogger } from './ioLogger';
8
+ import { offlineAuth } from './offlineAuthorizer';
9
+ import { responseWrapper } from './responseWrapper';
10
+ import { validator } from './validation';
8
11
  import { warmupMiddleware } from './warmup';
9
- declare const baseMiddlewares: ({
12
+ interface BaseMiddlewaresOptions {
13
+ logger: HapnLogger;
14
+ }
15
+ interface ApiGatewayMiddlewaresOptions {
16
+ logger: HapnLogger;
17
+ offlineAuthEnabled?: boolean;
18
+ }
19
+ declare const getBaseMiddlewares: ({ logger }: BaseMiddlewaresOptions) => ({
10
20
  before: ({ event, context }: {
11
21
  event: any;
12
22
  context: any;
13
23
  }) => Promise<void>;
14
- } | rawMiddy.MiddlewareObj<any, any, Error, LambdaContext> | {
24
+ } | middy.MiddlewareObj<any, any, Error, import("aws-lambda").Context> | {
15
25
  before: (request: any) => string;
16
26
  })[];
17
- declare const apiGatewayMiddlewares: (rawMiddy.MiddlewareObj<any, any, Error, LambdaContext> | {
27
+ declare const getApiGatewayMiddlewares: ({ logger, offlineAuthEnabled }: ApiGatewayMiddlewaresOptions) => (middy.MiddlewareObj<any, any, Error, import("aws-lambda").Context> | {
18
28
  before: (request: any) => Promise<void>;
19
29
  } | {
20
30
  after: (req: any) => void;
21
31
  onError: (req: any) => void;
22
32
  })[];
23
- declare const middy: <TEvent, TResult, TContext extends LambdaContext>(handler: MiddyInputHandler<TEvent, TResult, TContext>) => rawMiddy.MiddyfiedHandler<TEvent, TResult, Error, TContext>;
24
- declare const apiGatewayMiddy: <TEvent, TResult, TContext extends LambdaContext>(handler: MiddyInputHandler<TEvent, TResult, TContext>) => rawMiddy.MiddyfiedHandler<TEvent, TResult, Error, TContext>;
25
- export { apiGatewayMiddlewares, apiGatewayMiddy, baseMiddlewares, httpErrorHandler, httpResponseSerializer, middy, sqsJsonBodyParser, validatorMiddleware, warmupMiddleware, };
33
+ export { contextualLogger, getApiGatewayMiddlewares, getBaseMiddlewares, httpErrorHandler, httpResponseSerializer, ioLogger, middy, offlineAuth, responseWrapper, sqsJsonBodyParser, validator, warmupMiddleware, };
@@ -1 +1,6 @@
1
- export declare const ioLoggerMiddleware: import("@middy/core").MiddlewareObj<any, any, Error, import("aws-lambda").Context>;
1
+ import { HapnLogger } from '@spytecgps/sdk-logger';
2
+ interface IoLoggerOptions {
3
+ logger: HapnLogger;
4
+ }
5
+ export declare const ioLogger: ({ logger }: IoLoggerOptions) => import("@middy/core").MiddlewareObj<any, any, Error, import("aws-lambda").Context>;
6
+ export {};
@@ -0,0 +1,3 @@
1
+ export declare const normalizerMiddleware: () => {
2
+ before: (request: any) => Promise<void>;
3
+ };
@@ -1,8 +1,10 @@
1
- interface OfflineMiddlewareOptions {
1
+ import { HapnLogger } from '@spytecgps/sdk-logger';
2
+ interface OfflineAuthOptions {
2
3
  authFunctionName?: string;
3
4
  enabled?: boolean;
5
+ logger: HapnLogger;
4
6
  }
5
- export declare const offlineAuthMiddleware: ({ authFunctionName, enabled, }?: OfflineMiddlewareOptions) => {
7
+ export declare const offlineAuth: ({ authFunctionName, enabled, logger, }: OfflineAuthOptions) => {
6
8
  before: (request: any) => Promise<void>;
7
9
  };
8
10
  export {};
@@ -1,4 +1,9 @@
1
- export declare const responseWrapperMiddleware: () => {
1
+ import { HapnLogger } from '@spytecgps/sdk-logger';
2
+ interface ResponseWrapperOptions {
3
+ logger: HapnLogger;
4
+ }
5
+ export declare const responseWrapper: ({ logger }: ResponseWrapperOptions) => {
2
6
  after: (req: any) => void;
3
7
  onError: (req: any) => void;
4
8
  };
9
+ export {};
@@ -1,9 +1,11 @@
1
+ import { HapnLogger } from '@spytecgps/sdk-logger';
1
2
  import Joi from 'joi';
2
- interface ValidatorOpts {
3
+ interface ValidatorOptions {
3
4
  schema: Joi.Schema;
4
5
  allowUnknown?: boolean;
6
+ logger: HapnLogger;
5
7
  }
6
- export declare const validatorMiddleware: ({ schema, allowUnknown }: ValidatorOpts) => {
8
+ export declare const validator: ({ schema, allowUnknown, logger }: ValidatorOptions) => {
7
9
  before: (request: any) => void;
8
10
  };
9
11
  export {};
package/dist/types.d.ts CHANGED
@@ -46,6 +46,9 @@ export interface HandlerResponse<R> {
46
46
  headers?: {
47
47
  [header: string]: boolean | number | string;
48
48
  };
49
+ multiValueHeaders?: {
50
+ [header: string]: (boolean | number | string)[];
51
+ };
49
52
  isBase64Encoded?: boolean;
50
53
  message?: string;
51
54
  data?: R;
@@ -72,3 +75,12 @@ export type SQSWrapperArgsWithReturn<RecordType extends BaseRecord, T> = {
72
75
  singleHandler?: (record: RecordType) => T | Promise<T>;
73
76
  mode?: 'serial' | 'parallel';
74
77
  };
78
+ export interface SpytecAuthContextV4 {
79
+ type: AuthClass;
80
+ userId?: string;
81
+ clientId: number;
82
+ principalId: string;
83
+ scope?: string;
84
+ }
85
+ export type BaseAPIGatewayEventV4 = Omit<APIGatewayProxyEventBase<SpytecAuthContextV4>, 'pathParameters' | 'queryStringParameters' | 'body'>;
86
+ export type UserAPIHandlerV4<TEvent = APIGatewayProxyWithLambdaAuthorizerEvent<SpytecAuthContextV4>, TResult = any> = (event: TEvent, context: APIGatewayEventRequestContext, callback: Callback<TResult>) => void | Promise<TResult>;
@@ -1,14 +1,14 @@
1
1
  import { APIGatewayEventRequestContextWithAuthorizer } from 'aws-lambda/common/api-gateway';
2
2
  import * as Joi from 'joi';
3
- import { AuthClass, SpytecAuthContext } from '../types';
4
- interface GetAuthorizerValidatorParams {
5
- scope?: string;
6
- type?: AuthClass;
7
- }
8
- export declare const getAuthorizerValidator: ({ scope, type }?: GetAuthorizerValidatorParams) => Joi.ObjectSchema<SpytecAuthContext>;
3
+ import { SpytecAuthContext, SpytecAuthContextV4 } from '../types';
4
+ type GetAuthorizerValidatorParams = Partial<Record<keyof SpytecAuthContext, Joi.AnySchema>>;
5
+ type GetAuthorizerValidatorParamsV4 = Partial<Record<keyof SpytecAuthContextV4, Joi.AnySchema>>;
6
+ export declare const getAuthorizerValidator: (params?: GetAuthorizerValidatorParams) => Joi.ObjectSchema<SpytecAuthContext>;
7
+ export declare const getAuthorizerValidatorV4: (params?: GetAuthorizerValidatorParamsV4) => Joi.ObjectSchema<SpytecAuthContext>;
9
8
  /**
10
9
  * @deprecated
11
10
  */
12
11
  export declare const requestContextValidator: Joi.ObjectSchema<any>;
13
12
  export declare const getRequestContextValidator: (params?: GetAuthorizerValidatorParams) => Joi.ObjectSchema<APIGatewayEventRequestContextWithAuthorizer<SpytecAuthContext>>;
13
+ export declare const getRequestContextValidatorV4: (params?: GetAuthorizerValidatorParamsV4) => Joi.ObjectSchema<APIGatewayEventRequestContextWithAuthorizer<SpytecAuthContextV4>>;
14
14
  export {};
@@ -1,3 +1,6 @@
1
1
  import { ObjectSchema, ValidationOptions } from 'joi';
2
+ /**
3
+ * @deprecated
4
+ */
2
5
  declare const validateEvent: <T>(event: any, schema?: ObjectSchema<T>, validateOptions?: ValidationOptions) => T;
3
6
  export default validateEvent;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spytecgps/lambda-utils",
3
- "version": "2.4.0",
3
+ "version": "3.0.1",
4
4
  "description": "Lambda Utils",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -33,19 +33,22 @@
33
33
  "@middy/http-response-serializer": "^2.5.7",
34
34
  "@middy/input-output-logger": "^2.5.7",
35
35
  "@middy/sqs-json-body-parser": "^2.5.7",
36
- "@spytecgps/sdk-logger": "^2.0.6",
37
- "dayjs": "^1.11.11",
36
+ "dayjs": "^1.11.13",
38
37
  "deepmerge": "^4.3.1",
39
- "joi": "^17.13.0",
38
+ "joi": "^17.13.3",
40
39
  "qs": "^6.10.1"
41
40
  },
41
+ "peerDependencies": {
42
+ "@spytecgps/sdk-logger": "^2.0.18"
43
+ },
42
44
  "devDependencies": {
43
- "@aws-sdk/client-lambda": "^3.699.0",
44
- "@rollup/plugin-commonjs": "^23.0.2",
45
+ "@aws-sdk/client-lambda": "^3.731.1",
46
+ "@rollup/plugin-commonjs": "^28.0.2",
45
47
  "@rollup/plugin-json": "^6.1.0",
46
- "@rollup/plugin-node-resolve": "^15.0.1",
48
+ "@rollup/plugin-node-resolve": "^16.0.0",
47
49
  "@rollup/plugin-terser": "^0.4.4",
48
- "@rollup/plugin-typescript": "^9.0.2",
50
+ "@rollup/plugin-typescript": "^12.1.2",
51
+ "@spytecgps/sdk-logger": "^2.0.18",
49
52
  "@types/aws-lambda": "^8.10.76",
50
53
  "@types/jest": "^29.5.12",
51
54
  "@types/joi": "^17.2.3",
@@ -66,10 +69,9 @@
66
69
  "rollup": "^4.24.0",
67
70
  "rollup-plugin-peer-deps-external": "^2.2.4",
68
71
  "ts-jest": "^29.0.3",
69
- "ts-loader": "^9.5.1",
70
72
  "typescript": "^5.6.3"
71
73
  },
72
74
  "files": [
73
75
  "dist/**/*"
74
76
  ]
75
- }
77
+ }
@@ -1,2 +0,0 @@
1
- import { logger, withRequest } from '@spytecgps/sdk-logger';
2
- export { logger, withRequest };
@@ -1,4 +0,0 @@
1
- import { APIGatewayProxyResult } from 'aws-lambda';
2
- import { WrapperArgs } from '../types';
3
- declare const apiGatewayEventWrapper: <E, R>({ event, context, schema, handler, }: WrapperArgs<E, R>) => Promise<APIGatewayProxyResult>;
4
- export default apiGatewayEventWrapper;
@@ -1,5 +0,0 @@
1
- import apiGatewayEventWrapper from './apiGatewayEventWrapper';
2
- import sqsEventWrapper from './sqsEventWrapper';
3
- import sqsEventWrapperWithReturn from './sqsEventWrapperWithReturn';
4
- export { apiGatewayEventWrapper, sqsEventWrapper, sqsEventWrapperWithReturn };
5
- export * from './response';
@@ -1,3 +0,0 @@
1
- import { BaseRecord, SQSWrapperArgs } from '../types';
2
- declare const sqsEventWrapper: <RecordType extends BaseRecord>({ event, context, schema, handler, singleHandler, mode, }: SQSWrapperArgs<RecordType>) => Promise<void>;
3
- export default sqsEventWrapper;
@@ -1,3 +0,0 @@
1
- import { BaseRecord, SQSWrapperArgsWithReturn } from '../types';
2
- declare const sqsEventWrapper: <RecordType extends BaseRecord, T>({ event, context, schema, handler, singleHandler, mode, }: SQSWrapperArgsWithReturn<RecordType, T>) => Promise<T | T[]>;
3
- export default sqsEventWrapper;