@thisisagile/easy-service 17.16.0 → 17.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@ import { meta, tryTo } from "@thisisagile/easy";
3
3
  var route = (uri) => (subject) => {
4
4
  meta(subject).set("route", uri);
5
5
  };
6
- var toRoute = (endpoint, requires, verb, middleware) => tryTo(verb).is.defined().map((verb2) => ({ verb: verb2, endpoint, requires, middleware: middleware ?? [] })).orElse();
6
+ var toRoute = (endpoint, requires, verb, middleware, name = "") => tryTo(verb).is.defined().map((verb2) => ({ verb: verb2, name, endpoint, requires, middleware: middleware ?? [] })).orElse();
7
7
  var Router = class {
8
8
  constructor(resource) {
9
9
  this.resource = resource;
@@ -25,7 +25,8 @@ var Router = class {
25
25
  uc: v.get("uc")
26
26
  },
27
27
  v.get("verb"),
28
- v.get("middleware")
28
+ v.get("middleware"),
29
+ v.property.toString()
29
30
  )
30
31
  );
31
32
  }
@@ -36,4 +37,4 @@ export {
36
37
  route,
37
38
  routes
38
39
  };
39
- //# sourceMappingURL=chunk-FYPLZQRO.mjs.map
40
+ //# sourceMappingURL=chunk-B37TXK4C.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/resources/Route.ts"],"sourcesContent":["import { List, meta, Optional, tryTo, Uri, Scope, UseCase, Req } from '@thisisagile/easy';\nimport { Resource } from './Resource';\nimport { RequestHandler } from 'express';\nimport { Verb } from '../http/Verb';\n\nexport const route =\n (uri: Uri): ClassDecorator =>\n (subject: unknown): void => {\n meta(subject).set('route', uri);\n };\n\nexport type Endpoint<T = unknown> = (re: Req) => Promise<T | List<T>>;\nexport type RouteRequires = { token: boolean; labCoat: boolean; scope?: Scope; uc?: UseCase };\nexport type Route = { verb: Verb; name: string, endpoint: Endpoint; requires: RouteRequires; middleware: RequestHandler[] };\nexport type Routes = { route: Uri; middleware: RequestHandler[]; endpoints: List<Route> };\n\nconst toRoute = (endpoint: Endpoint, requires: RouteRequires, verb?: Verb, middleware?: RequestHandler[], name = ''): Optional<Route> =>\n tryTo(verb)\n .is.defined()\n .map(verb => ({ verb, name, endpoint, requires, middleware: middleware ?? [] }) as Route)\n .orElse();\n\nclass Router implements Routes {\n constructor(readonly resource: Resource) {}\n\n get route(): Uri {\n return meta(this.resource).get('route');\n }\n\n get middleware(): RequestHandler[] {\n return meta(this.resource).get<RequestHandler[]>('middleware') ?? [];\n }\n\n get endpoints(): List<Route> {\n return meta(this.resource)\n .properties('verb')\n .mapDefined(v =>\n toRoute(\n this.resource[v.property],\n {\n labCoat: v.get<boolean>('labCoat') ?? false,\n token: v.get<boolean>('token') ?? false,\n scope: v.get<Scope>('scope'),\n uc: v.get<UseCase>('uc'),\n },\n v.get<Verb>('verb'),\n v.get<RequestHandler[]>('middleware'),\n v.property.toString(),\n )\n );\n }\n}\n\nexport const routes = (resource: Resource): Routes => new Router(resource);\n"],"mappings":";AAAA,SAAe,MAAgB,aAAuC;AAK/D,IAAM,QACX,CAAC,QACD,CAAC,YAA2B;AAC1B,OAAK,OAAO,EAAE,IAAI,SAAS,GAAG;AAChC;AAOF,IAAM,UAAU,CAAC,UAAoB,UAAyB,MAAa,YAA+B,OAAO,OAC/G,MAAM,IAAI,EACP,GAAG,QAAQ,EACX,IAAI,CAAAA,WAAS,EAAE,MAAAA,OAAM,MAAM,UAAU,UAAU,YAAY,cAAc,CAAC,EAAE,EAAW,EACvF,OAAO;AAEZ,IAAM,SAAN,MAA+B;AAAA,EAC7B,YAAqB,UAAoB;AAApB;AAAA,EAAqB;AAAA,EAE1C,IAAI,QAAa;AACf,WAAO,KAAK,KAAK,QAAQ,EAAE,IAAI,OAAO;AAAA,EACxC;AAAA,EAEA,IAAI,aAA+B;AACjC,WAAO,KAAK,KAAK,QAAQ,EAAE,IAAsB,YAAY,KAAK,CAAC;AAAA,EACrE;AAAA,EAEA,IAAI,YAAyB;AAC3B,WAAO,KAAK,KAAK,QAAQ,EACtB,WAAW,MAAM,EACjB;AAAA,MAAW,OACV;AAAA,QACE,KAAK,SAAS,EAAE,QAAQ;AAAA,QACxB;AAAA,UACE,SAAS,EAAE,IAAa,SAAS,KAAK;AAAA,UACtC,OAAO,EAAE,IAAa,OAAO,KAAK;AAAA,UAClC,OAAO,EAAE,IAAW,OAAO;AAAA,UAC3B,IAAI,EAAE,IAAa,IAAI;AAAA,QACzB;AAAA,QACA,EAAE,IAAU,MAAM;AAAA,QAClB,EAAE,IAAsB,YAAY;AAAA,QACpC,EAAE,SAAS,SAAS;AAAA,MACtB;AAAA,IACF;AAAA,EACJ;AACF;AAEO,IAAM,SAAS,CAAC,aAA+B,IAAI,OAAO,QAAQ;","names":["verb"]}
@@ -6,7 +6,7 @@ import {
6
6
  } from "../chunk-W62PBGRF.mjs";
7
7
  import {
8
8
  route
9
- } from "../chunk-FYPLZQRO.mjs";
9
+ } from "../chunk-B37TXK4C.mjs";
10
10
  import {
11
11
  __decorateClass
12
12
  } from "../chunk-4N72FQFX.mjs";
package/dist/index.js CHANGED
@@ -66,7 +66,7 @@ var import_easy2 = require("@thisisagile/easy");
66
66
  var route = (uri2) => (subject) => {
67
67
  (0, import_easy2.meta)(subject).set("route", uri2);
68
68
  };
69
- var toRoute = (endpoint, requires2, verb, middleware) => (0, import_easy2.tryTo)(verb).is.defined().map((verb2) => ({ verb: verb2, endpoint, requires: requires2, middleware: middleware ?? [] })).orElse();
69
+ var toRoute = (endpoint, requires2, verb, middleware, name = "") => (0, import_easy2.tryTo)(verb).is.defined().map((verb2) => ({ verb: verb2, name, endpoint, requires: requires2, middleware: middleware ?? [] })).orElse();
70
70
  var Router = class {
71
71
  constructor(resource) {
72
72
  this.resource = resource;
@@ -88,7 +88,8 @@ var Router = class {
88
88
  uc: v.get("uc")
89
89
  },
90
90
  v.get("verb"),
91
- v.get("middleware")
91
+ v.get("middleware"),
92
+ v.property.toString()
92
93
  )
93
94
  );
94
95
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/health/HealthResource.ts","../src/health/HealthUri.ts","../src/resources/Route.ts","../src/http/Verb.ts","../src/http/OriginatedError.ts","../src/resources/Requires.ts","../src/resources/Service.ts","../src/security/Jwt.ts"],"sourcesContent":["export * from './health/HealthResource';\nexport * from './health/HealthUri';\nexport * from './http/OriginatedError';\nexport * from './http/Verb';\nexport * from './resources/AppProvider';\nexport * from './resources/Requires';\nexport * from './resources/Resource';\nexport * from './resources/Route';\nexport * from './resources/Service';\nexport * from './security/Jwt';\n","import { resolve, Json } from '@thisisagile/easy';\nimport { HealthUri } from './HealthUri';\nimport { Resource } from '../resources/Resource';\nimport { route } from '../resources/Route';\nimport { get } from '../http/Verb';\n\n@route(HealthUri.Health)\nexport class HealthResource implements Resource {\n @get()\n ok = (): Promise<Json> => resolve({ state: 'Service is healthy.' });\n}\n","import { EasyUri, uri } from '@thisisagile/easy';\n\nexport class HealthUri extends EasyUri {\n static readonly health = uri.segment('health');\n static readonly Health = new HealthUri([HealthUri.health]);\n}\n","import { List, meta, Optional, tryTo, Uri, Scope, UseCase, Req } from '@thisisagile/easy';\nimport { Resource } from './Resource';\nimport { RequestHandler } from 'express';\nimport { Verb } from '../http/Verb';\n\nexport const route =\n (uri: Uri): ClassDecorator =>\n (subject: unknown): void => {\n meta(subject).set('route', uri);\n };\n\nexport type Endpoint<T = unknown> = (re: Req) => Promise<T | List<T>>;\nexport type RouteRequires = { token: boolean; labCoat: boolean; scope?: Scope; uc?: UseCase };\nexport type Route = { verb: Verb; endpoint: Endpoint; requires: RouteRequires; middleware: RequestHandler[] };\nexport type Routes = { route: Uri; middleware: RequestHandler[]; endpoints: List<Route> };\n\nconst toRoute = (endpoint: Endpoint, requires: RouteRequires, verb?: Verb, middleware?: RequestHandler[]): Optional<Route> =>\n tryTo(verb)\n .is.defined()\n .map(verb => ({ verb, endpoint, requires, middleware: middleware ?? [] }) as Route)\n .orElse();\n\nclass Router implements Routes {\n constructor(readonly resource: Resource) {}\n\n get route(): Uri {\n return meta(this.resource).get('route');\n }\n\n get middleware(): RequestHandler[] {\n return meta(this.resource).get<RequestHandler[]>('middleware') ?? [];\n }\n\n get endpoints(): List<Route> {\n return meta(this.resource)\n .properties('verb')\n .mapDefined(v =>\n toRoute(\n this.resource[v.property],\n {\n labCoat: v.get<boolean>('labCoat') ?? false,\n token: v.get<boolean>('token') ?? false,\n scope: v.get<Scope>('scope'),\n uc: v.get<UseCase>('uc'),\n },\n v.get<Verb>('verb'),\n v.get<RequestHandler[]>('middleware')\n )\n );\n }\n}\n\nexport const routes = (resource: Resource): Routes => new Router(resource);\n","import { meta, CacheControl, ContentType, HttpStatus, HttpVerb } from '@thisisagile/easy';\n\nexport type VerbOptions = { onOk?: HttpStatus; onNotFound?: HttpStatus; onError?: HttpStatus; type?: ContentType; cache?: CacheControl };\nexport type Verb = { verb: HttpVerb; options: VerbOptions };\n\nexport const toVerbOptions = (options?: VerbOptions): Required<VerbOptions> => ({\n onOk: options?.onOk ?? HttpStatus.Ok,\n onNotFound: options?.onNotFound ?? HttpStatus.NotFound,\n onError: options?.onError ?? HttpStatus.BadRequest,\n type: options?.type ?? ContentType.Json,\n cache: options?.cache ?? CacheControl.disabled(),\n});\n\nconst toVerb =\n <T>(verb: HttpVerb, options?: VerbOptions): PropertyDecorator =>\n (subject: unknown, property: string | symbol): void => {\n meta(subject).property(property).set('verb', { verb, options });\n };\n\nexport const get = (options?: VerbOptions): PropertyDecorator => toVerb(HttpVerb.Get, options);\n\nexport const search = (options?: VerbOptions): PropertyDecorator => toVerb(HttpVerb.Get, { onNotFound: HttpStatus.Ok, ...options });\n\nexport const put = (options?: VerbOptions): PropertyDecorator => toVerb(HttpVerb.Put, options);\n\nexport const patch = (options?: VerbOptions): PropertyDecorator => toVerb(HttpVerb.Patch, options);\n\nexport const post = (options?: VerbOptions): PropertyDecorator => toVerb(HttpVerb.Post, { onOk: HttpStatus.Created, ...options });\n\nexport const del = (options?: VerbOptions): PropertyDecorator => toVerb(HttpVerb.Delete, { onOk: HttpStatus.NoContent, ...options });\n\nexport const stream = (options?: VerbOptions): PropertyDecorator => toVerb(HttpVerb.Get, { type: ContentType.Stream, ...options });\n","import { ErrorOrigin, isError } from '@thisisagile/easy';\nimport { VerbOptions } from './Verb';\n\nexport class OriginatedError extends Error {\n constructor(\n readonly origin: ErrorOrigin,\n readonly options?: VerbOptions\n ) {\n super();\n if (isError(origin)) this.stack = origin.stack;\n }\n}\n\nexport const isOriginatedError = (e?: unknown): e is OriginatedError => isError(e) && e instanceof OriginatedError;\n\nexport const toOriginatedError = (e: unknown, options?: VerbOptions): OriginatedError =>\n isOriginatedError(e) ? e : new OriginatedError(e as ErrorOrigin, options);\n","import { meta } from '@thisisagile/easy';\nimport { Scope, UseCase } from '@thisisagile/easy';\n\nexport class Requires {\n readonly labCoat =\n (): PropertyDecorator =>\n (subject: unknown, property: string | symbol): void => {\n meta(subject).property(property).set('labCoat', true);\n };\n\n readonly token =\n (): PropertyDecorator =>\n (subject: unknown, property: string | symbol): void => {\n meta(subject).property(property).set('token', true);\n };\n\n readonly scope =\n (scope: Scope): PropertyDecorator =>\n (subject: unknown, property: string | symbol): void => {\n meta(subject).property(property).set('token', true);\n meta(subject).property(property).set('scope', scope);\n };\n\n readonly useCase =\n (uc: UseCase): PropertyDecorator =>\n (subject: unknown, property: string | symbol): void => {\n meta(subject).property(property).set('token', true);\n meta(subject).property(property).set('uc', uc);\n };\n}\n\nexport const requires = new Requires();\n","import { AppProvider, Handler } from './AppProvider';\nimport { Constructor, Enum, List, toList, tryTo } from '@thisisagile/easy';\nimport { Resource } from './Resource';\n\nexport class Service extends Enum {\n protected port = 8080;\n\n constructor(\n readonly name: string,\n protected app: AppProvider,\n protected resources: List<Resource> = toList()\n ) {\n super(name);\n }\n\n pre = (): Handler[] => [];\n post = (): Handler[] => [];\n\n with(...resources: Constructor<Resource>[]): this {\n return tryTo(this).accept(t => t.resources.add(resources.map(r => new r()))).value;\n }\n\n atPort(port: number): this {\n return tryTo(this).accept(t => (t.port = port)).value;\n }\n\n start(message = `Service ${this.name} listening on port ${this.port} with ${this.resources.length} resources.`): void {\n tryTo(this)\n .accept(t => t.pre().forEach(h => this.app.use(h)))\n .accept(t => t.resources.forEach(r => this.app.route(this, r)))\n .accept(t => t.post().forEach(h => this.app.use(h)))\n .accept(t => t.app.listen(this.port, message));\n }\n}\n","import { Algorithm, sign, verify } from 'jsonwebtoken';\nimport { ctx, Json, OneOrMore, Optional, tryTo, Validatable, Jwt as JwtBase } from '@thisisagile/easy';\n\ninterface SignOptions {\n audience?: Optional<OneOrMore<string>>;\n issuer?: Optional<string>;\n}\nexport class Jwt extends JwtBase implements Validatable {\n static of = (a: { jwt: string }): Jwt => new Jwt(a.jwt);\n\n get isValid(): boolean {\n return (\n tryTo(() => ctx.env.get('tokenPublicKey') ?? '')\n .map(key => verify(this.value, key))\n .map(() => true)\n .orElse() ?? false\n );\n }\n\n static sign = (token: Json, options?: SignOptions): Jwt =>\n tryTo(() => ctx.env.get('tokenPrivateKey') ?? '')\n .is.not.empty()\n .map(key =>\n sign(token, key, {\n ...options,\n expiresIn: ctx.env.get('tokenExpiresIn') as any ?? '1h',\n keyid: ctx.env.get('tokenKeyid') ?? 'easy',\n algorithm: ctx.env.get('tokenAlgorithm', 'RS256') as Algorithm,\n })\n )\n .map(s => new Jwt(s)).value;\n}\n"],"mappings":"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","names":["import_easy","import_easy","uri","requires","verb","import_easy","import_easy","import_easy","import_easy","import_easy","JwtBase"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/health/HealthResource.ts","../src/health/HealthUri.ts","../src/resources/Route.ts","../src/http/Verb.ts","../src/http/OriginatedError.ts","../src/resources/Requires.ts","../src/resources/Service.ts","../src/security/Jwt.ts"],"sourcesContent":["export * from './health/HealthResource';\nexport * from './health/HealthUri';\nexport * from './http/OriginatedError';\nexport * from './http/Verb';\nexport * from './resources/AppProvider';\nexport * from './resources/Requires';\nexport * from './resources/Resource';\nexport * from './resources/Route';\nexport * from './resources/Service';\nexport * from './security/Jwt';\n","import { resolve, Json } from '@thisisagile/easy';\nimport { HealthUri } from './HealthUri';\nimport { Resource } from '../resources/Resource';\nimport { route } from '../resources/Route';\nimport { get } from '../http/Verb';\n\n@route(HealthUri.Health)\nexport class HealthResource implements Resource {\n @get()\n ok = (): Promise<Json> => resolve({ state: 'Service is healthy.' });\n}\n","import { EasyUri, uri } from '@thisisagile/easy';\n\nexport class HealthUri extends EasyUri {\n static readonly health = uri.segment('health');\n static readonly Health = new HealthUri([HealthUri.health]);\n}\n","import { List, meta, Optional, tryTo, Uri, Scope, UseCase, Req } from '@thisisagile/easy';\nimport { Resource } from './Resource';\nimport { RequestHandler } from 'express';\nimport { Verb } from '../http/Verb';\n\nexport const route =\n (uri: Uri): ClassDecorator =>\n (subject: unknown): void => {\n meta(subject).set('route', uri);\n };\n\nexport type Endpoint<T = unknown> = (re: Req) => Promise<T | List<T>>;\nexport type RouteRequires = { token: boolean; labCoat: boolean; scope?: Scope; uc?: UseCase };\nexport type Route = { verb: Verb; name: string, endpoint: Endpoint; requires: RouteRequires; middleware: RequestHandler[] };\nexport type Routes = { route: Uri; middleware: RequestHandler[]; endpoints: List<Route> };\n\nconst toRoute = (endpoint: Endpoint, requires: RouteRequires, verb?: Verb, middleware?: RequestHandler[], name = ''): Optional<Route> =>\n tryTo(verb)\n .is.defined()\n .map(verb => ({ verb, name, endpoint, requires, middleware: middleware ?? [] }) as Route)\n .orElse();\n\nclass Router implements Routes {\n constructor(readonly resource: Resource) {}\n\n get route(): Uri {\n return meta(this.resource).get('route');\n }\n\n get middleware(): RequestHandler[] {\n return meta(this.resource).get<RequestHandler[]>('middleware') ?? [];\n }\n\n get endpoints(): List<Route> {\n return meta(this.resource)\n .properties('verb')\n .mapDefined(v =>\n toRoute(\n this.resource[v.property],\n {\n labCoat: v.get<boolean>('labCoat') ?? false,\n token: v.get<boolean>('token') ?? false,\n scope: v.get<Scope>('scope'),\n uc: v.get<UseCase>('uc'),\n },\n v.get<Verb>('verb'),\n v.get<RequestHandler[]>('middleware'),\n v.property.toString(),\n )\n );\n }\n}\n\nexport const routes = (resource: Resource): Routes => new Router(resource);\n","import { meta, CacheControl, ContentType, HttpStatus, HttpVerb } from '@thisisagile/easy';\n\nexport type VerbOptions = { onOk?: HttpStatus; onNotFound?: HttpStatus; onError?: HttpStatus; type?: ContentType; cache?: CacheControl };\nexport type Verb = { verb: HttpVerb; options: VerbOptions };\n\nexport const toVerbOptions = (options?: VerbOptions): Required<VerbOptions> => ({\n onOk: options?.onOk ?? HttpStatus.Ok,\n onNotFound: options?.onNotFound ?? HttpStatus.NotFound,\n onError: options?.onError ?? HttpStatus.BadRequest,\n type: options?.type ?? ContentType.Json,\n cache: options?.cache ?? CacheControl.disabled(),\n});\n\nconst toVerb =\n <T>(verb: HttpVerb, options?: VerbOptions): PropertyDecorator =>\n (subject: unknown, property: string | symbol): void => {\n meta(subject).property(property).set('verb', { verb, options });\n };\n\nexport const get = (options?: VerbOptions): PropertyDecorator => toVerb(HttpVerb.Get, options);\n\nexport const search = (options?: VerbOptions): PropertyDecorator => toVerb(HttpVerb.Get, { onNotFound: HttpStatus.Ok, ...options });\n\nexport const put = (options?: VerbOptions): PropertyDecorator => toVerb(HttpVerb.Put, options);\n\nexport const patch = (options?: VerbOptions): PropertyDecorator => toVerb(HttpVerb.Patch, options);\n\nexport const post = (options?: VerbOptions): PropertyDecorator => toVerb(HttpVerb.Post, { onOk: HttpStatus.Created, ...options });\n\nexport const del = (options?: VerbOptions): PropertyDecorator => toVerb(HttpVerb.Delete, { onOk: HttpStatus.NoContent, ...options });\n\nexport const stream = (options?: VerbOptions): PropertyDecorator => toVerb(HttpVerb.Get, { type: ContentType.Stream, ...options });\n","import { ErrorOrigin, isError } from '@thisisagile/easy';\nimport { VerbOptions } from './Verb';\n\nexport class OriginatedError extends Error {\n constructor(\n readonly origin: ErrorOrigin,\n readonly options?: VerbOptions\n ) {\n super();\n if (isError(origin)) this.stack = origin.stack;\n }\n}\n\nexport const isOriginatedError = (e?: unknown): e is OriginatedError => isError(e) && e instanceof OriginatedError;\n\nexport const toOriginatedError = (e: unknown, options?: VerbOptions): OriginatedError =>\n isOriginatedError(e) ? e : new OriginatedError(e as ErrorOrigin, options);\n","import { meta } from '@thisisagile/easy';\nimport { Scope, UseCase } from '@thisisagile/easy';\n\nexport class Requires {\n readonly labCoat =\n (): PropertyDecorator =>\n (subject: unknown, property: string | symbol): void => {\n meta(subject).property(property).set('labCoat', true);\n };\n\n readonly token =\n (): PropertyDecorator =>\n (subject: unknown, property: string | symbol): void => {\n meta(subject).property(property).set('token', true);\n };\n\n readonly scope =\n (scope: Scope): PropertyDecorator =>\n (subject: unknown, property: string | symbol): void => {\n meta(subject).property(property).set('token', true);\n meta(subject).property(property).set('scope', scope);\n };\n\n readonly useCase =\n (uc: UseCase): PropertyDecorator =>\n (subject: unknown, property: string | symbol): void => {\n meta(subject).property(property).set('token', true);\n meta(subject).property(property).set('uc', uc);\n };\n}\n\nexport const requires = new Requires();\n","import { AppProvider, Handler } from './AppProvider';\nimport { Constructor, Enum, List, toList, tryTo } from '@thisisagile/easy';\nimport { Resource } from './Resource';\n\nexport class Service extends Enum {\n protected port = 8080;\n\n constructor(\n readonly name: string,\n protected app: AppProvider,\n protected resources: List<Resource> = toList()\n ) {\n super(name);\n }\n\n pre = (): Handler[] => [];\n post = (): Handler[] => [];\n\n with(...resources: Constructor<Resource>[]): this {\n return tryTo(this).accept(t => t.resources.add(resources.map(r => new r()))).value;\n }\n\n atPort(port: number): this {\n return tryTo(this).accept(t => (t.port = port)).value;\n }\n\n start(message = `Service ${this.name} listening on port ${this.port} with ${this.resources.length} resources.`): void {\n tryTo(this)\n .accept(t => t.pre().forEach(h => this.app.use(h)))\n .accept(t => t.resources.forEach(r => this.app.route(this, r)))\n .accept(t => t.post().forEach(h => this.app.use(h)))\n .accept(t => t.app.listen(this.port, message));\n }\n}\n","import { Algorithm, sign, verify } from 'jsonwebtoken';\nimport { ctx, Json, OneOrMore, Optional, tryTo, Validatable, Jwt as JwtBase } from '@thisisagile/easy';\n\ninterface SignOptions {\n audience?: Optional<OneOrMore<string>>;\n issuer?: Optional<string>;\n}\nexport class Jwt extends JwtBase implements Validatable {\n static of = (a: { jwt: string }): Jwt => new Jwt(a.jwt);\n\n get isValid(): boolean {\n return (\n tryTo(() => ctx.env.get('tokenPublicKey') ?? '')\n .map(key => verify(this.value, key))\n .map(() => true)\n .orElse() ?? false\n );\n }\n\n static sign = (token: Json, options?: SignOptions): Jwt =>\n tryTo(() => ctx.env.get('tokenPrivateKey') ?? '')\n .is.not.empty()\n .map(key =>\n sign(token, key, {\n ...options,\n expiresIn: ctx.env.get('tokenExpiresIn') as any ?? '1h',\n keyid: ctx.env.get('tokenKeyid') ?? 'easy',\n algorithm: ctx.env.get('tokenAlgorithm', 'RS256') as Algorithm,\n })\n )\n .map(s => new Jwt(s)).value;\n}\n"],"mappings":"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","names":["import_easy","import_easy","uri","requires","verb","import_easy","import_easy","import_easy","import_easy","import_easy","JwtBase"]}
@@ -12,6 +12,7 @@ export type RouteRequires = {
12
12
  };
13
13
  export type Route = {
14
14
  verb: Verb;
15
+ name: string;
15
16
  endpoint: Endpoint;
16
17
  requires: RouteRequires;
17
18
  middleware: RequestHandler[];
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  route,
3
3
  routes
4
- } from "../chunk-FYPLZQRO.mjs";
4
+ } from "../chunk-B37TXK4C.mjs";
5
5
  import "../chunk-4N72FQFX.mjs";
6
6
  export {
7
7
  route,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thisisagile/easy-service",
3
- "version": "17.16.0",
3
+ "version": "17.17.0",
4
4
  "description": "Straightforward library for building domain-driven microservice architectures",
5
5
  "author": "Sander Hoogendoorn",
6
6
  "license": "MIT",
@@ -37,7 +37,7 @@
37
37
  "@thisisagile/easy-test": "*"
38
38
  },
39
39
  "dependencies": {
40
- "@thisisagile/easy": "^17.16.0",
40
+ "@thisisagile/easy": "^17.17.0",
41
41
  "jsonwebtoken": "^9.0.2"
42
42
  }
43
43
  }
@@ -11,13 +11,13 @@ export const route =
11
11
 
12
12
  export type Endpoint<T = unknown> = (re: Req) => Promise<T | List<T>>;
13
13
  export type RouteRequires = { token: boolean; labCoat: boolean; scope?: Scope; uc?: UseCase };
14
- export type Route = { verb: Verb; endpoint: Endpoint; requires: RouteRequires; middleware: RequestHandler[] };
14
+ export type Route = { verb: Verb; name: string, endpoint: Endpoint; requires: RouteRequires; middleware: RequestHandler[] };
15
15
  export type Routes = { route: Uri; middleware: RequestHandler[]; endpoints: List<Route> };
16
16
 
17
- const toRoute = (endpoint: Endpoint, requires: RouteRequires, verb?: Verb, middleware?: RequestHandler[]): Optional<Route> =>
17
+ const toRoute = (endpoint: Endpoint, requires: RouteRequires, verb?: Verb, middleware?: RequestHandler[], name = ''): Optional<Route> =>
18
18
  tryTo(verb)
19
19
  .is.defined()
20
- .map(verb => ({ verb, endpoint, requires, middleware: middleware ?? [] }) as Route)
20
+ .map(verb => ({ verb, name, endpoint, requires, middleware: middleware ?? [] }) as Route)
21
21
  .orElse();
22
22
 
23
23
  class Router implements Routes {
@@ -44,7 +44,8 @@ class Router implements Routes {
44
44
  uc: v.get<UseCase>('uc'),
45
45
  },
46
46
  v.get<Verb>('verb'),
47
- v.get<RequestHandler[]>('middleware')
47
+ v.get<RequestHandler[]>('middleware'),
48
+ v.property.toString(),
48
49
  )
49
50
  );
50
51
  }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/resources/Route.ts"],"sourcesContent":["import { List, meta, Optional, tryTo, Uri, Scope, UseCase, Req } from '@thisisagile/easy';\nimport { Resource } from './Resource';\nimport { RequestHandler } from 'express';\nimport { Verb } from '../http/Verb';\n\nexport const route =\n (uri: Uri): ClassDecorator =>\n (subject: unknown): void => {\n meta(subject).set('route', uri);\n };\n\nexport type Endpoint<T = unknown> = (re: Req) => Promise<T | List<T>>;\nexport type RouteRequires = { token: boolean; labCoat: boolean; scope?: Scope; uc?: UseCase };\nexport type Route = { verb: Verb; endpoint: Endpoint; requires: RouteRequires; middleware: RequestHandler[] };\nexport type Routes = { route: Uri; middleware: RequestHandler[]; endpoints: List<Route> };\n\nconst toRoute = (endpoint: Endpoint, requires: RouteRequires, verb?: Verb, middleware?: RequestHandler[]): Optional<Route> =>\n tryTo(verb)\n .is.defined()\n .map(verb => ({ verb, endpoint, requires, middleware: middleware ?? [] }) as Route)\n .orElse();\n\nclass Router implements Routes {\n constructor(readonly resource: Resource) {}\n\n get route(): Uri {\n return meta(this.resource).get('route');\n }\n\n get middleware(): RequestHandler[] {\n return meta(this.resource).get<RequestHandler[]>('middleware') ?? [];\n }\n\n get endpoints(): List<Route> {\n return meta(this.resource)\n .properties('verb')\n .mapDefined(v =>\n toRoute(\n this.resource[v.property],\n {\n labCoat: v.get<boolean>('labCoat') ?? false,\n token: v.get<boolean>('token') ?? false,\n scope: v.get<Scope>('scope'),\n uc: v.get<UseCase>('uc'),\n },\n v.get<Verb>('verb'),\n v.get<RequestHandler[]>('middleware')\n )\n );\n }\n}\n\nexport const routes = (resource: Resource): Routes => new Router(resource);\n"],"mappings":";AAAA,SAAe,MAAgB,aAAuC;AAK/D,IAAM,QACX,CAAC,QACD,CAAC,YAA2B;AAC1B,OAAK,OAAO,EAAE,IAAI,SAAS,GAAG;AAChC;AAOF,IAAM,UAAU,CAAC,UAAoB,UAAyB,MAAa,eACzE,MAAM,IAAI,EACP,GAAG,QAAQ,EACX,IAAI,CAAAA,WAAS,EAAE,MAAAA,OAAM,UAAU,UAAU,YAAY,cAAc,CAAC,EAAE,EAAW,EACjF,OAAO;AAEZ,IAAM,SAAN,MAA+B;AAAA,EAC7B,YAAqB,UAAoB;AAApB;AAAA,EAAqB;AAAA,EAE1C,IAAI,QAAa;AACf,WAAO,KAAK,KAAK,QAAQ,EAAE,IAAI,OAAO;AAAA,EACxC;AAAA,EAEA,IAAI,aAA+B;AACjC,WAAO,KAAK,KAAK,QAAQ,EAAE,IAAsB,YAAY,KAAK,CAAC;AAAA,EACrE;AAAA,EAEA,IAAI,YAAyB;AAC3B,WAAO,KAAK,KAAK,QAAQ,EACtB,WAAW,MAAM,EACjB;AAAA,MAAW,OACV;AAAA,QACE,KAAK,SAAS,EAAE,QAAQ;AAAA,QACxB;AAAA,UACE,SAAS,EAAE,IAAa,SAAS,KAAK;AAAA,UACtC,OAAO,EAAE,IAAa,OAAO,KAAK;AAAA,UAClC,OAAO,EAAE,IAAW,OAAO;AAAA,UAC3B,IAAI,EAAE,IAAa,IAAI;AAAA,QACzB;AAAA,QACA,EAAE,IAAU,MAAM;AAAA,QAClB,EAAE,IAAsB,YAAY;AAAA,MACtC;AAAA,IACF;AAAA,EACJ;AACF;AAEO,IAAM,SAAS,CAAC,aAA+B,IAAI,OAAO,QAAQ;","names":["verb"]}