nesties 1.1.6 → 1.1.8

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, {
288
399
  description: "Server token",
289
400
  required: false
290
- }),
291
- ApiError(401, "Incorrect server token provided")
292
- ]);
401
+ }) : (0, import_swagger5.ApiHeader)({
402
+ name: defaultHeaderName,
403
+ description: "Server token",
404
+ required: false
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,92 +850,26 @@ 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");
862
+ var import_core5 = require("@nestjs/core");
807
863
  var LocalePipe = class {
808
- constructor(i18nService) {
864
+ constructor(i18nService, moduleRef) {
809
865
  this.i18nService = i18nService;
866
+ this.moduleRef = moduleRef;
810
867
  }
811
868
  async transform(ctx, metadata) {
812
869
  const resolver = ctx.resolver;
813
870
  if (resolver) {
814
- const _resolver = createDynamicResolverFromStatic(resolver);
815
- const locale = await _resolver(ctx.ctx, void 0);
871
+ const _resolver = createResolver(resolver);
872
+ const locale = await _resolver(ctx.ctx, this.moduleRef);
816
873
  return this.i18nService.getExactLocale(locale);
817
874
  } else {
818
875
  return this.i18nService.getExactLocaleFromRequest(ctx.ctx);
@@ -821,7 +878,8 @@ var LocalePipe = class {
821
878
  };
822
879
  LocalePipe = __decorateClass([
823
880
  (0, import_common10.Injectable)(),
824
- __decorateParam(0, (0, import_common10.Inject)(I18nService))
881
+ __decorateParam(0, (0, import_common10.Inject)(I18nService)),
882
+ __decorateParam(1, (0, import_common10.Inject)(import_core5.ModuleRef))
825
883
  ], LocalePipe);
826
884
  var _dec = (0, import_common10.createParamDecorator)((resolver, ctx) => {
827
885
  return { ctx, resolver };
@@ -834,17 +892,7 @@ var I18nModule = class extends ConfigurableModuleClass {
834
892
  I18nModule = __decorateClass([
835
893
  (0, import_common11.Global)(),
836
894
  (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
- ],
895
+ providers: [I18nService, LocalePipe],
848
896
  exports: [I18nService, LocalePipe]
849
897
  })
850
898
  ], I18nModule);
@@ -888,21 +936,15 @@ I18nInterceptor = __decorateClass([
888
936
  ], I18nInterceptor);
889
937
 
890
938
  // src/i18n-module/i18n-decorator.ts
891
- var import_swagger5 = require("@nestjs/swagger");
892
939
  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
940
  return () => MergeClassOrMethodDecorators([
904
941
  (0, import_common13.UseInterceptors)(I18nInterceptor),
905
- ...paramType ? [dec()] : []
942
+ ApiFromResolver(options.resolver, {
943
+ description: "Locale for internationalization",
944
+ required: false,
945
+ default: options.defaultLocale ?? options.locales[0],
946
+ enum: options.locales
947
+ })
906
948
  ]);
907
949
  };
908
950
 
@@ -920,7 +962,7 @@ var createI18n = (options) => {
920
962
  };
921
963
  };
922
964
 
923
- // src/i18n-module/middelewares/lookup.ts
965
+ // src/i18n-module/middlewares/lookup.ts
924
966
  var I18nLookupMiddleware = (dict, options) => {
925
967
  const matchType = options?.matchType ?? "exact";
926
968
  const dictFactory = typeof dict === "function" ? dict : () => dict;
@@ -958,7 +1000,9 @@ var I18nLookupMiddleware = (dict, options) => {
958
1000
  }
959
1001
  if (dictionary && Object.prototype.hasOwnProperty.call(dictionary, key)) {
960
1002
  const val = dictionary[key];
961
- if (val != null) return val;
1003
+ if (val != null) {
1004
+ return val;
1005
+ }
962
1006
  }
963
1007
  return next();
964
1008
  };
@@ -971,6 +1015,7 @@ var I18nLookupMiddleware = (dict, options) => {
971
1015
  ApiBlankResponse,
972
1016
  ApiError,
973
1017
  ApiErrorTyped,
1018
+ ApiFromResolver,
974
1019
  ApiTypeResponse,
975
1020
  As,
976
1021
  BlankPaginatedReturnMessageDto,
@@ -1004,6 +1049,7 @@ var I18nLookupMiddleware = (dict, options) => {
1004
1049
  createI18n,
1005
1050
  createI18nDecorator,
1006
1051
  createProvider,
1052
+ createResolver,
1007
1053
  fromAbortable,
1008
1054
  getClassFromClassOrArray,
1009
1055
  takeUntilAbort