nesties 1.1.6 → 1.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -34,6 +34,7 @@ __export(index_exports, {
34
34
  ApiBlankResponse: () => ApiBlankResponse,
35
35
  ApiError: () => ApiError,
36
36
  ApiErrorTyped: () => ApiErrorTyped,
37
+ ApiFromResolver: () => ApiFromResolver,
37
38
  ApiTypeResponse: () => ApiTypeResponse,
38
39
  As: () => As,
39
40
  BlankPaginatedReturnMessageDto: () => BlankPaginatedReturnMessageDto,
@@ -67,6 +68,7 @@ __export(index_exports, {
67
68
  createI18n: () => createI18n,
68
69
  createI18nDecorator: () => createI18nDecorator,
69
70
  createProvider: () => createProvider,
71
+ createResolver: () => createResolver,
70
72
  fromAbortable: () => fromAbortable,
71
73
  getClassFromClassOrArray: () => getClassFromClassOrArray,
72
74
  takeUntilAbort: () => takeUntilAbort
@@ -262,34 +264,155 @@ var DataBody = createDataPipeDec(import_common2.Body);
262
264
  // src/token.guard.ts
263
265
  var import_common3 = require("@nestjs/common");
264
266
  var import_config = require("@nestjs/config");
267
+ var import_swagger5 = require("@nestjs/swagger");
268
+
269
+ // src/resolver.ts
265
270
  var import_swagger4 = require("@nestjs/swagger");
271
+ var coerceToString = (v) => {
272
+ if (v == null) return void 0;
273
+ if (v === false) return void 0;
274
+ if (Array.isArray(v)) return v.length ? coerceToString(v[0]) : void 0;
275
+ if (typeof v === "string") return v;
276
+ if (typeof v === "number") return String(v);
277
+ return void 0;
278
+ };
279
+ var getHeader = (req, name) => {
280
+ const viaMethod = typeof req.getHeader === "function" && req.getHeader(name) || typeof req.header === "function" && req.header(name) || typeof req.get === "function" && req.get(name);
281
+ if (viaMethod) {
282
+ return coerceToString(viaMethod);
283
+ }
284
+ const n = name.toLowerCase();
285
+ const headers = req.headers ?? {};
286
+ if (n in headers) return coerceToString(headers[n]);
287
+ const hit = Object.entries(headers).find(([k]) => k.toLowerCase() === n)?.[1];
288
+ return coerceToString(hit);
289
+ };
290
+ var pickPrimaryFromAcceptLanguage = (v) => {
291
+ if (!v) return void 0;
292
+ const first = v.split(",")[0]?.trim();
293
+ return first?.split(";")[0]?.trim() || first;
294
+ };
295
+ function getQueryValue(req, key) {
296
+ const q = req.query;
297
+ if (q && typeof q === "object" && !("raw" in q)) {
298
+ const v = q[key];
299
+ if (v != null) return coerceToString(v);
300
+ }
301
+ const rawUrl = req.originalUrl ?? req.url;
302
+ if (typeof rawUrl === "string" && rawUrl.includes("?")) {
303
+ try {
304
+ const search = rawUrl.startsWith("http") ? new URL(rawUrl).search : new URL(rawUrl, "http://localhost").search;
305
+ if (search) {
306
+ const params = new URLSearchParams(search);
307
+ const val = params.get(key);
308
+ if (val != null) return val;
309
+ }
310
+ } catch {
311
+ }
312
+ }
313
+ return void 0;
314
+ }
315
+ var createResolver = (_options) => {
316
+ if (typeof _options === "function") {
317
+ return _options;
318
+ }
319
+ const options = _options;
320
+ const field = options.paramType;
321
+ let name = options.paramName;
322
+ if (field === "header") name = name.toLowerCase();
323
+ return (ctx) => {
324
+ const req = ctx.switchToHttp().getRequest();
325
+ if (field === "header") {
326
+ let raw = getHeader(req, name);
327
+ if (name === "accept-language") raw = pickPrimaryFromAcceptLanguage(raw);
328
+ return raw;
329
+ }
330
+ if (field === "query") {
331
+ return getQueryValue(req, name);
332
+ }
333
+ throw new Error(`Unsupported paramType: ${field}`);
334
+ };
335
+ };
336
+ var ApiFromResolver = (_options, extras = {}) => {
337
+ if (typeof _options === "function") {
338
+ return () => {
339
+ };
340
+ }
341
+ const options = _options;
342
+ const paramType = options?.paramType;
343
+ const apiOptions = {
344
+ name: options.paramName,
345
+ ...extras
346
+ };
347
+ return paramType === "header" ? (0, import_swagger4.ApiHeader)(apiOptions) : paramType === "query" ? (0, import_swagger4.ApiQuery)({ type: "string", ...apiOptions }) : () => {
348
+ };
349
+ };
350
+
351
+ // src/token.guard.ts
352
+ var import_typed_reflector = require("typed-reflector");
353
+ var import_core = require("@nestjs/core");
354
+ var reflector = new import_typed_reflector.Reflector();
355
+ var Metadata = new import_typed_reflector.MetadataSetter();
356
+ var defaultHeaderName = "x-server-token";
357
+ var defaultConfigName = "SERVER_TOKEN";
358
+ var defaultErrorCode = 401;
266
359
  var TokenGuard = class {
267
- constructor(config) {
360
+ constructor(config, moduleRef) {
268
361
  this.config = config;
269
- this.token = this.config.get("SERVER_TOKEN");
362
+ this.moduleRef = moduleRef;
270
363
  }
271
364
  async canActivate(context) {
272
- const request = context.switchToHttp().getRequest();
273
- const token = request.headers["x-server-token"];
274
- if (this.token && token !== this.token) {
275
- throw new BlankReturnMessageDto(401, "Unauthorized").toException();
365
+ const controller = context.getClass();
366
+ const handlerName = context.getHandler()?.name;
367
+ let config = {};
368
+ if (controller) {
369
+ if (handlerName) {
370
+ config = reflector.get("requireTokenOptions", controller, handlerName) || {};
371
+ } else {
372
+ config = reflector.get("requireTokenOptions", controller) || {};
373
+ }
374
+ }
375
+ const resolver = createResolver(
376
+ config.resolver || { paramType: "header", paramName: defaultHeaderName }
377
+ );
378
+ const tokenSource = config.tokenSource || defaultConfigName;
379
+ const [tokenFromClient, tokenFromConfig] = await Promise.all([
380
+ resolver(context, this.moduleRef),
381
+ typeof tokenSource === "function" ? tokenSource(context, this.moduleRef) : this.config.get(tokenSource)
382
+ ]);
383
+ if (tokenFromConfig && tokenFromConfig !== tokenFromClient) {
384
+ throw new BlankReturnMessageDto(
385
+ config.errorCode || defaultErrorCode,
386
+ "Unauthorized"
387
+ ).toException();
276
388
  }
277
389
  return true;
278
390
  }
279
391
  };
280
392
  TokenGuard = __decorateClass([
281
393
  (0, import_common3.Injectable)(),
282
- __decorateParam(0, (0, import_common3.Inject)(import_config.ConfigService))
394
+ __decorateParam(0, (0, import_common3.Inject)(import_config.ConfigService)),
395
+ __decorateParam(1, (0, import_common3.Inject)(import_core.ModuleRef))
283
396
  ], TokenGuard);
284
- var RequireToken = () => MergeClassOrMethodDecorators([
285
- (0, import_common3.UseGuards)(TokenGuard),
286
- (0, import_swagger4.ApiHeader)({
287
- name: "x-server-token",
397
+ var RequireToken = (options = {}) => {
398
+ const swaggerDec = options.resolver ? ApiFromResolver(options.resolver, {
399
+ description: "Server token",
400
+ required: false
401
+ }) : (0, import_swagger5.ApiHeader)({
402
+ name: defaultHeaderName,
288
403
  description: "Server token",
289
404
  required: false
290
- }),
291
- ApiError(401, "Incorrect server token provided")
292
- ]);
405
+ });
406
+ return MergeClassOrMethodDecorators([
407
+ (0, import_common3.UseGuards)(TokenGuard),
408
+ swaggerDec,
409
+ ApiError(
410
+ options.errorCode || defaultErrorCode,
411
+ "Incorrect server token provided"
412
+ ),
413
+ ...options ? [Metadata.set("requireTokenOptions", options)] : []
414
+ ]);
415
+ };
293
416
 
294
417
  // src/abort-utils.ts
295
418
  var import_rxjs = require("rxjs");
@@ -372,7 +495,7 @@ var import_nfkit = require("nfkit");
372
495
 
373
496
  // src/abortable-module/abort-signal.provider.ts
374
497
  var import_common5 = require("@nestjs/common");
375
- var import_core = require("@nestjs/core");
498
+ var import_core2 = require("@nestjs/core");
376
499
 
377
500
  // src/create-provider.ts
378
501
  var createProvider = (options, factory) => {
@@ -390,14 +513,14 @@ var AbortSignalProvider = createProvider(
390
513
  {
391
514
  provide: ABORT_SIGNAL,
392
515
  scope: import_common5.Scope.REQUEST,
393
- inject: [import_core.REQUEST]
516
+ inject: [import_core2.REQUEST]
394
517
  },
395
518
  createAbortSignalFromHttp
396
519
  );
397
520
  var InjectAbortSignal = () => (0, import_common5.Inject)(ABORT_SIGNAL);
398
521
 
399
522
  // src/abortable-module/abortable.token.ts
400
- var import_core2 = require("@nestjs/core");
523
+ var import_core3 = require("@nestjs/core");
401
524
  var tokenMemo = /* @__PURE__ */ new Map();
402
525
  var abortableToken = (token) => {
403
526
  if (tokenMemo.has(token)) return tokenMemo.get(token);
@@ -427,10 +550,10 @@ function createAbortableProvider(token, opts) {
427
550
  {
428
551
  provide,
429
552
  scope: import_common6.Scope.REQUEST,
430
- inject: [import_core2.ModuleRef, import_core2.REQUEST, ABORT_SIGNAL]
553
+ inject: [import_core3.ModuleRef, import_core3.REQUEST, ABORT_SIGNAL]
431
554
  },
432
555
  async (moduleRef, req, signal) => {
433
- const ctxId = import_core2.ContextIdFactory.getByRequest(req);
556
+ const ctxId = import_core3.ContextIdFactory.getByRequest(req);
434
557
  const svc = await moduleRef.resolve(token, ctxId, { strict: false });
435
558
  if (svc == null) {
436
559
  throw new Error(
@@ -515,12 +638,12 @@ var parseI18n = (text) => {
515
638
  };
516
639
 
517
640
  // src/i18n-module/i18n.service.ts
518
- var import_core3 = require("@nestjs/core");
641
+ var import_core4 = require("@nestjs/core");
519
642
  var I18nService = class {
520
- constructor(resolver, options, moduleRef) {
521
- this.resolver = resolver;
643
+ constructor(options, moduleRef) {
522
644
  this.options = options;
523
645
  this.moduleRef = moduleRef;
646
+ this.resolver = createResolver(this.options.resolver);
524
647
  this.locales = new Set(this.options.locales);
525
648
  this.defaultLocale = this.options.defaultLocale ?? this.options.locales[0];
526
649
  this.middlewares = [];
@@ -727,81 +850,13 @@ var I18nService = class {
727
850
  };
728
851
  I18nService = __decorateClass([
729
852
  (0, import_common9.Injectable)(),
730
- __decorateParam(0, (0, import_common9.Inject)(I18nResolverToken)),
731
- __decorateParam(1, (0, import_common9.Inject)(I18nModuleOptionsToken)),
732
- __decorateParam(2, (0, import_common9.Inject)(import_core3.ModuleRef))
853
+ __decorateParam(0, (0, import_common9.Inject)(I18nModuleOptionsToken)),
854
+ __decorateParam(1, (0, import_common9.Inject)(import_core4.ModuleRef))
733
855
  ], I18nService);
734
856
 
735
857
  // src/i18n-module/i18n.module.ts
736
858
  var import_common11 = require("@nestjs/common");
737
859
 
738
- // src/i18n-module/i18n-resolver.ts
739
- var coerceToString = (v) => {
740
- if (v == null) return void 0;
741
- if (v === false) return void 0;
742
- if (Array.isArray(v)) return v.length ? coerceToString(v[0]) : void 0;
743
- if (typeof v === "string") return v;
744
- if (typeof v === "number") return String(v);
745
- return void 0;
746
- };
747
- var getHeader = (req, name) => {
748
- const viaMethod = typeof req.getHeader === "function" && req.getHeader(name) || typeof req.header === "function" && req.header(name) || typeof req.get === "function" && req.get(name);
749
- if (viaMethod) {
750
- return coerceToString(viaMethod);
751
- }
752
- const n = name.toLowerCase();
753
- const headers = req.headers ?? {};
754
- if (n in headers) return coerceToString(headers[n]);
755
- const hit = Object.entries(headers).find(([k]) => k.toLowerCase() === n)?.[1];
756
- return coerceToString(hit);
757
- };
758
- var pickPrimaryFromAcceptLanguage = (v) => {
759
- if (!v) return void 0;
760
- const first = v.split(",")[0]?.trim();
761
- return first?.split(";")[0]?.trim() || first;
762
- };
763
- function getQueryValue(req, key) {
764
- const q = req.query;
765
- if (q && typeof q === "object" && !("raw" in q)) {
766
- const v = q[key];
767
- if (v != null) return coerceToString(v);
768
- }
769
- const rawUrl = req.originalUrl ?? req.url;
770
- if (typeof rawUrl === "string" && rawUrl.includes("?")) {
771
- try {
772
- const search = rawUrl.startsWith("http") ? new URL(rawUrl).search : new URL(rawUrl, "http://localhost").search;
773
- if (search) {
774
- const params = new URLSearchParams(search);
775
- const val = params.get(key);
776
- if (val != null) return val;
777
- }
778
- } catch {
779
- }
780
- }
781
- return void 0;
782
- }
783
- var createDynamicResolverFromStatic = (_options) => {
784
- if (typeof _options === "function") {
785
- return _options;
786
- }
787
- const options = _options;
788
- const field = options.paramType;
789
- let name = options.paramName;
790
- if (field === "header") name = name.toLowerCase();
791
- return (ctx) => {
792
- const req = ctx.switchToHttp().getRequest();
793
- if (field === "header") {
794
- let raw = getHeader(req, name);
795
- if (name === "accept-language") raw = pickPrimaryFromAcceptLanguage(raw);
796
- return raw;
797
- }
798
- if (field === "query") {
799
- return getQueryValue(req, name);
800
- }
801
- throw new Error(`Unsupported paramType: ${field}`);
802
- };
803
- };
804
-
805
860
  // src/i18n-module/locale.pipe.ts
806
861
  var import_common10 = require("@nestjs/common");
807
862
  var LocalePipe = class {
@@ -811,7 +866,7 @@ var LocalePipe = class {
811
866
  async transform(ctx, metadata) {
812
867
  const resolver = ctx.resolver;
813
868
  if (resolver) {
814
- const _resolver = createDynamicResolverFromStatic(resolver);
869
+ const _resolver = createResolver(resolver);
815
870
  const locale = await _resolver(ctx.ctx, void 0);
816
871
  return this.i18nService.getExactLocale(locale);
817
872
  } else {
@@ -834,17 +889,7 @@ var I18nModule = class extends ConfigurableModuleClass {
834
889
  I18nModule = __decorateClass([
835
890
  (0, import_common11.Global)(),
836
891
  (0, import_common11.Module)({
837
- providers: [
838
- createProvider(
839
- {
840
- provide: I18nResolverToken,
841
- inject: [I18nModuleOptionsToken]
842
- },
843
- (o) => createDynamicResolverFromStatic(o.resolver)
844
- ),
845
- I18nService,
846
- LocalePipe
847
- ],
892
+ providers: [I18nService, LocalePipe],
848
893
  exports: [I18nService, LocalePipe]
849
894
  })
850
895
  ], I18nModule);
@@ -888,21 +933,15 @@ I18nInterceptor = __decorateClass([
888
933
  ], I18nInterceptor);
889
934
 
890
935
  // src/i18n-module/i18n-decorator.ts
891
- var import_swagger5 = require("@nestjs/swagger");
892
936
  var createI18nDecorator = (options) => {
893
- const paramType = options.resolver?.paramType;
894
- const apiOptions = {
895
- name: options.resolver.paramName,
896
- description: "Locale for internationalization",
897
- required: false,
898
- default: options.defaultLocale ?? options.locales[0],
899
- enum: options.locales
900
- };
901
- const dec = paramType === "header" ? () => (0, import_swagger5.ApiHeader)(apiOptions) : paramType === "query" ? () => (0, import_swagger5.ApiQuery)({ ...apiOptions, type: "string" }) : () => () => {
902
- };
903
937
  return () => MergeClassOrMethodDecorators([
904
938
  (0, import_common13.UseInterceptors)(I18nInterceptor),
905
- ...paramType ? [dec()] : []
939
+ ApiFromResolver(options.resolver, {
940
+ description: "Locale for internationalization",
941
+ required: false,
942
+ default: options.defaultLocale ?? options.locales[0],
943
+ enum: options.locales
944
+ })
906
945
  ]);
907
946
  };
908
947
 
@@ -920,7 +959,7 @@ var createI18n = (options) => {
920
959
  };
921
960
  };
922
961
 
923
- // src/i18n-module/middelewares/lookup.ts
962
+ // src/i18n-module/middlewares/lookup.ts
924
963
  var I18nLookupMiddleware = (dict, options) => {
925
964
  const matchType = options?.matchType ?? "exact";
926
965
  const dictFactory = typeof dict === "function" ? dict : () => dict;
@@ -958,7 +997,9 @@ var I18nLookupMiddleware = (dict, options) => {
958
997
  }
959
998
  if (dictionary && Object.prototype.hasOwnProperty.call(dictionary, key)) {
960
999
  const val = dictionary[key];
961
- if (val != null) return val;
1000
+ if (val != null) {
1001
+ return val;
1002
+ }
962
1003
  }
963
1004
  return next();
964
1005
  };
@@ -971,6 +1012,7 @@ var I18nLookupMiddleware = (dict, options) => {
971
1012
  ApiBlankResponse,
972
1013
  ApiError,
973
1014
  ApiErrorTyped,
1015
+ ApiFromResolver,
974
1016
  ApiTypeResponse,
975
1017
  As,
976
1018
  BlankPaginatedReturnMessageDto,
@@ -1004,6 +1046,7 @@ var I18nLookupMiddleware = (dict, options) => {
1004
1046
  createI18n,
1005
1047
  createI18nDecorator,
1006
1048
  createProvider,
1049
+ createResolver,
1007
1050
  fromAbortable,
1008
1051
  getClassFromClassOrArray,
1009
1052
  takeUntilAbort