@spytecgps/lambda-utils 2.0.2 → 2.0.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.
@@ -1,4 +1,4 @@
1
- import { HttpError } from './HttpError';
1
+ import HttpError from './HttpError';
2
2
  export default class BadRequestError extends HttpError {
3
3
  code: number;
4
4
  statusCode: number;
@@ -0,0 +1,4 @@
1
+ export default class BaseError extends Error {
2
+ code: 500;
3
+ statusCode: 500;
4
+ }
@@ -1,4 +1,4 @@
1
- import { HttpError } from './HttpError';
1
+ import HttpError from './HttpError';
2
2
  export default class ConflictError extends HttpError {
3
3
  code: number;
4
4
  statusCode: number;
@@ -1,4 +1,4 @@
1
- import { HttpError } from './HttpError';
1
+ import HttpError from './HttpError';
2
2
  export default class ForbiddenError extends HttpError {
3
3
  code: number;
4
4
  statusCode: number;
@@ -1,4 +1,4 @@
1
- export declare abstract class HttpError extends Error {
1
+ export default abstract class HttpError extends Error {
2
2
  abstract code: number;
3
3
  abstract statusCode: number;
4
4
  }
@@ -1,4 +1,4 @@
1
- import { HttpError } from './HttpError';
1
+ import HttpError from './HttpError';
2
2
  export default class NotFoundError extends HttpError {
3
3
  code: number;
4
4
  statusCode: number;
@@ -1,4 +1,4 @@
1
- import { HttpError } from './HttpError';
1
+ import HttpError from './HttpError';
2
2
  export default class UnauthorizedError extends HttpError {
3
3
  code: number;
4
4
  statusCode: number;
@@ -1,6 +1,8 @@
1
1
  import BadRequestError from './BadRequestError';
2
+ import BaseError from './BaseError';
2
3
  import ConflictError from './ConflictError';
3
4
  import ForbiddenError from './ForbiddenError';
5
+ import HttpError from './HttpError';
4
6
  import NotFoundError from './NotFoundError';
5
7
  import UnauthorizedError from './UnauthorizedError';
6
- export { BadRequestError, NotFoundError, UnauthorizedError, ForbiddenError, ConflictError };
8
+ export { BadRequestError, NotFoundError, UnauthorizedError, ForbiddenError, ConflictError, HttpError, BaseError };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- !function(e,r){"object"==typeof exports&&"object"==typeof module?module.exports=r():"function"==typeof define&&define.amd?define([],r):"object"==typeof exports?exports["lambda-utils"]=r():e["lambda-utils"]=r()}(global,(()=>(()=>{"use strict";var e={n:r=>{var t=r&&r.__esModule?()=>r.default:()=>r;return e.d(t,{a:t}),t},d:(r,t)=>{for(var a in t)e.o(t,a)&&!e.o(r,a)&&Object.defineProperty(r,a,{enumerable:!0,get:t[a]})},o:(e,r)=>Object.prototype.hasOwnProperty.call(e,r),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},r={};e.r(r),e.d(r,{BadRequestError:()=>x,ConflictError:()=>N,ForbiddenError:()=>_,LambdaCache:()=>Q,NotFoundError:()=>T,SpytecJoi:()=>v,UnauthorizedError:()=>w,apiGatewayEventWrapper:()=>I,apiGatewayMiddlewares:()=>Z,apiGatewayMiddy:()=>K,buildProxyResult:()=>O,buildResponseBody:()=>S,defaultApiSchema:()=>A,getAuthorizerValidator:()=>f,getRequestContextValidator:()=>E,httpErrorHandler:()=>$(),httpResponseSerializer:()=>G(),iccidSchema:()=>b,imeiSchema:()=>g,json:()=>m,logger:()=>a,middy:()=>X,promiseWithCache:()=>Y,promiseWithTimeout:()=>ee,requestContextValidator:()=>C,resetLogger:()=>o,sqsEventWrapper:()=>R,urlEncoded:()=>y,validateEvent:()=>j,validatorMiddleware:()=>V,withRequest:()=>t.withRequest});const t=require("@spytecgps/sdk-logger");let a=(0,t.createLogger)();const o=e=>(a=(0,t.createLogger)({base:e}),a),s=require("dayjs");var n=e.n(s);const i=require("dayjs/plugin/timezone");var l=e.n(i);const c=require("dayjs/plugin/utc");var d=e.n(c);const u=require("joi"),p=require("qs");n().extend(d()),n().extend(l());const m=u.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")}}))),y=u.extend((e=>({type:"object",base:e.object(),coerce:e=>({value:p.parse(e)})}))),g=u.string().regex(/^\d{15,16}$/).message("Invalid IMEI"),b=u.string().regex(/^[0-9A-Za-z]{18,22}$/).message("Invalid ICCID"),v=u.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:p.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=n().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 h extends Error{}class w extends h{code=401;statusCode=401;name="UnauthorizedError"}const f=({scope:e,type:r}={})=>u.object({clientId:u.number(),resources:m.object({}),scope:e?u.string().pattern(new RegExp(`${e}`)).error((()=>new w(`missing scope ${e}`))):u.optional(),type:r?u.any().valid(r).error((()=>new w(`missing user type ${r}`))):u.optional(),enterprise:u.boolean().default(!1),maintenanceModule:u.boolean().default(!1)}),C=u.object({authorizer:f()}),E=(e={})=>u.object({authorizer:f(e)});class x extends h{code=400;statusCode=400;name="BadRequestError"}const j=(e,r,t)=>{if(!r)return a.warn("skipping validation"),e;const{error:o,value:s}=r.validate(e,{allowUnknown:t?.allowUnknown||!0,errors:{label:"key",wrap:{label:!1}}});if(o)throw a.error({error:o},"Validation error"),o.isJoi?new x(o.message):o;return s},A=v.object({requestContext:E()}),q={"Content-Type":"application/json","Access-Control-Allow-Origin":"*","Access-Control-Allow-Credentials":!0},S=(e,r,t)=>({success:e<400,message:r,result:t||void 0}),O=({statusCode:e=200,message:r="ok",data:t,headers:a={},rawResult:o=!1,stringifyBody:s=!0})=>{const n=o?t:S(e,r,t),i=s?n&&JSON.stringify(n):t;return{headers:{...q,...a},statusCode:e,body:i}},I=async({event:e,context:r,schema:o,handler:s})=>{e&&r&&(0,t.withRequest)(e,r);try{const r=j(e,o),t=await s(r);return O(t)}catch(r){return a.error({err:r,event:(n=e,{resource:n.resource,httpMethod:n.httpMethod,queryStringParameters:n.queryStringParameters,pathParameters:n.pathParameters,body:n.body})},"apiGatewayWrapper - caught error"),O({statusCode:r.code||500,message:r.message||"Error"})}var n},R=async({event:e,context:r,schema:o,handler:s,singleHandler:n,mode:i="serial"})=>{e&&r&&(0,t.withRequest)(e,r);try{const r=j(e,o);await async function(e,r,t,a){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"===a)for(const e of r)await t(e);else"parallel"===a&&await Promise.all(r.map((e=>t(e))))}}(r,s,n,i)}catch(r){throw a.error({err:r,event:(l=e,(l.Records||[]).map((e=>({messageId:e.messageId,body:e.body,messageAttributes:e.messageAttributes}))))},"sqsEventWrapper - caught error"),r}var l};class N extends h{code=409;statusCode=409;name="ConflictError"}class _ extends h{code=403;statusCode=403;name="ForbiddenError"}class T extends h{code=404;statusCode=404;name="NotFoundError"}const z=require("@middy/core");var M=e.n(z);const P=require("@middy/http-error-handler");var $=e.n(P);const U=require("@middy/http-response-serializer");var G=e.n(U);const k="_X_AMZN_TRACE_ID",H="x-correlation-",J=`${H}id`,W=`${H}trace-id`,D=(()=>{const e={};return{before:async({event:r,context:t})=>{if(t&&(e.requestId=t?.awsRequestId,e.function=t.functionName),e.requestId||(e.requestId=r?.requestContext?.requestId),Object.prototype.hasOwnProperty.call(r,"headers")){const t=r;Object.keys(t).forEach((r=>{r.toLowerCase().startsWith(H)&&(e[r]=t[r])}))}process.env[k]&&(e[W]=process.env[k]),e[J]||(e[J]=t?.awsRequestId),e.contextUserId=r?.requestContext?.authorizer?.claims?.userId,e.contextUserEmail=r?.requestContext?.authorizer?.claims?.email,o(e)}}})(),B=require("@middy/input-output-logger"),L=e.n(B)()({logger:e=>{const r=e?.event?"event":"response";a.info(r,e)}}),V=({schema:e,allowUnknown:r=!0})=>({before:t=>{const{error:o,value:s}=e.validate(t.event,{allowUnknown:r,errors:{label:"key",wrap:{label:!1}}});if(o)throw a.error("Validation error",{error:o}),o.isJoi?new x(o.message):o;t.event=s}}),F=[D,L],Z=[G()({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"}),$()({logger:e=>a.error(e)}),{after:e=>{e.response=O(e.response)}}],X=e=>M()(e).use([...F]),K=e=>M()(e).use([...F,...Z]);class Q{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 a=1e3*t+Date.now();global.CACHE_STORAGE[this.collectionName].set(e,{value:r,expire:a})}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 Y=async(e,r,t,a)=>{let o=r.get(t);return o||(o=await e(),r.set(t,o,a)),o},ee=(e,r,t=new Error("Promise timed out"))=>{const a=new Promise(((e,a)=>{setTimeout((()=>{a(t)}),r)}));return Promise.race([e,a])};return r})()));
1
+ !function(e,r){"object"==typeof exports&&"object"==typeof module?module.exports=r():"function"==typeof define&&define.amd?define([],r):"object"==typeof exports?exports["lambda-utils"]=r():e["lambda-utils"]=r()}(global,(()=>(()=>{"use strict";var e={n:r=>{var t=r&&r.__esModule?()=>r.default:()=>r;return e.d(t,{a:t}),t},d:(r,t)=>{for(var a in t)e.o(t,a)&&!e.o(r,a)&&Object.defineProperty(r,a,{enumerable:!0,get:t[a]})},o:(e,r)=>Object.prototype.hasOwnProperty.call(e,r),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},r={};e.r(r),e.d(r,{BadRequestError:()=>x,BaseError:()=>N,ConflictError:()=>_,ForbiddenError:()=>T,HttpError:()=>h,LambdaCache:()=>Y,NotFoundError:()=>z,SpytecJoi:()=>v,UnauthorizedError:()=>w,apiGatewayEventWrapper:()=>I,apiGatewayMiddlewares:()=>X,apiGatewayMiddy:()=>Q,buildProxyResult:()=>O,buildResponseBody:()=>S,defaultApiSchema:()=>A,getAuthorizerValidator:()=>f,getRequestContextValidator:()=>C,httpErrorHandler:()=>U(),httpResponseSerializer:()=>H(),iccidSchema:()=>b,imeiSchema:()=>g,json:()=>m,logger:()=>a,middy:()=>K,promiseWithCache:()=>ee,promiseWithTimeout:()=>re,requestContextValidator:()=>E,resetLogger:()=>o,sqsEventWrapper:()=>R,urlEncoded:()=>y,validateEvent:()=>j,validatorMiddleware:()=>F,withRequest:()=>t.withRequest});const t=require("@spytecgps/sdk-logger");let a=(0,t.createLogger)();const o=e=>(a=(0,t.createLogger)({base:e}),a),s=require("dayjs");var n=e.n(s);const i=require("dayjs/plugin/timezone");var l=e.n(i);const c=require("dayjs/plugin/utc");var d=e.n(c);const u=require("joi"),p=require("qs");n().extend(d()),n().extend(l());const m=u.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")}}))),y=u.extend((e=>({type:"object",base:e.object(),coerce:e=>({value:p.parse(e)})}))),g=u.string().regex(/^\d{15,16}$/).message("Invalid IMEI"),b=u.string().regex(/^[0-9A-Za-z]{18,22}$/).message("Invalid ICCID"),v=u.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:p.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=n().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 h extends Error{}class w extends h{code=401;statusCode=401;name="UnauthorizedError"}const f=({scope:e,type:r}={})=>u.object({clientId:u.number(),resources:m.object({}),scope:e?u.string().pattern(new RegExp(`${e}`)).error((()=>new w(`missing scope ${e}`))):u.optional(),type:r?u.any().valid(r).error((()=>new w(`missing user type ${r}`))):u.optional(),enterprise:u.boolean().default(!1),maintenanceModule:u.boolean().default(!1)}),E=u.object({authorizer:f()}),C=(e={})=>u.object({authorizer:f(e)});class x extends h{code=400;statusCode=400;name="BadRequestError"}const j=(e,r,t)=>{if(!r)return a.warn("skipping validation"),e;const{error:o,value:s}=r.validate(e,{allowUnknown:t?.allowUnknown||!0,errors:{label:"key",wrap:{label:!1}}});if(o)throw a.error({error:o},"Validation error"),o.isJoi?new x(o.message):o;return s},A=v.object({requestContext:C()}),q={"Content-Type":"application/json","Access-Control-Allow-Origin":"*","Access-Control-Allow-Credentials":!0},S=(e,r,t)=>({success:e<400,message:r,result:t||void 0}),O=({statusCode:e=200,message:r="ok",data:t,headers:a={},rawResult:o=!1,stringifyBody:s=!0})=>{const n=o?t:S(e,r,t),i=s?n&&JSON.stringify(n):t;return{headers:{...q,...a},statusCode:e,body:i}},I=async({event:e,context:r,schema:o,handler:s})=>{e&&r&&(0,t.withRequest)(e,r);try{const r=j(e,o),t=await s(r);return O(t)}catch(r){return a.error({err:r,event:(n=e,{resource:n.resource,httpMethod:n.httpMethod,queryStringParameters:n.queryStringParameters,pathParameters:n.pathParameters,body:n.body})},"apiGatewayWrapper - caught error"),O({statusCode:r.code||500,message:r.message||"Error"})}var n},R=async({event:e,context:r,schema:o,handler:s,singleHandler:n,mode:i="serial"})=>{e&&r&&(0,t.withRequest)(e,r);try{const r=j(e,o);await async function(e,r,t,a){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"===a)for(const e of r)await t(e);else"parallel"===a&&await Promise.all(r.map((e=>t(e))))}}(r,s,n,i)}catch(r){throw a.error({err:r,event:(l=e,(l.Records||[]).map((e=>({messageId:e.messageId,body:e.body,messageAttributes:e.messageAttributes}))))},"sqsEventWrapper - caught error"),r}var l};class N extends Error{code;statusCode}class _ extends h{code=409;statusCode=409;name="ConflictError"}class T extends h{code=403;statusCode=403;name="ForbiddenError"}class z extends h{code=404;statusCode=404;name="NotFoundError"}const M=require("@middy/core");var P=e.n(M);const $=require("@middy/http-error-handler");var U=e.n($);const G=require("@middy/http-response-serializer");var H=e.n(G);const k="_X_AMZN_TRACE_ID",J="x-correlation-",W=`${J}id`,B=`${J}trace-id`,D=(()=>{const e={};return{before:async({event:r,context:t})=>{if(t&&(e.requestId=t?.awsRequestId,e.function=t.functionName),e.requestId||(e.requestId=r?.requestContext?.requestId),Object.prototype.hasOwnProperty.call(r,"headers")){const t=r;Object.keys(t).forEach((r=>{r.toLowerCase().startsWith(J)&&(e[r]=t[r])}))}process.env[k]&&(e[B]=process.env[k]),e[W]||(e[W]=t?.awsRequestId),e.contextUserId=r?.requestContext?.authorizer?.claims?.userId,e.contextUserEmail=r?.requestContext?.authorizer?.claims?.email,o(e)}}})(),L=require("@middy/input-output-logger"),V=e.n(L)()({logger:e=>{const r=e?.event?"event":"response";a.info(r,e)}}),F=({schema:e,allowUnknown:r=!0})=>({before:t=>{const{error:o,value:s}=e.validate(t.event,{allowUnknown:r,errors:{label:"key",wrap:{label:!1}}});if(o)throw a.error("Validation error",{error:o}),o.isJoi?new x(o.message):o;t.event=s}}),Z=[D,V],X=[H()({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"}),U()({logger:e=>a.error(e)}),{after:e=>{e.response=O(e.response)}}],K=e=>P()(e).use([...Z]),Q=e=>P()(e).use([...Z,...X]);class Y{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 a=1e3*t+Date.now();global.CACHE_STORAGE[this.collectionName].set(e,{value:r,expire:a})}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 ee=async(e,r,t,a)=>{let o=r.get(t);return o||(o=await e(),r.set(t,o,a)),o},re=(e,r,t=new Error("Promise timed out"))=>{const a=new Promise(((e,a)=>{setTimeout((()=>{a(t)}),r)}));return Promise.race([e,a])};return r})()));
package/dist/types.d.ts CHANGED
@@ -10,6 +10,7 @@ export interface SpytecAuthorizedResources {
10
10
  export type AuthClass = 'user' | 'client' | 'system';
11
11
  export type DevicesAccess = 'full' | 'limited';
12
12
  export type BoundariesAccess = 'full' | 'limited';
13
+ export type TasksAccess = 'full' | 'can_complete' | 'read_only' | 'no_access';
13
14
  export interface SpytecAuthContext {
14
15
  type: AuthClass;
15
16
  userId?: string;
@@ -22,6 +23,7 @@ export interface SpytecAuthContext {
22
23
  scope?: string;
23
24
  enterprise?: boolean;
24
25
  maintenanceModule?: boolean;
26
+ tasksAccess?: TasksAccess;
25
27
  }
26
28
  export type BaseAPIGatewayEvent = Omit<APIGatewayProxyEventBase<SpytecAuthContext>, 'pathParameters' | 'queryStringParameters' | 'body'>;
27
29
  export interface WrapperArgs<E, R> {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spytecgps/lambda-utils",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "description": "Lambda Utils",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",