@stratum-hq/nestjs 1.0.0 → 1.2.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.
package/README.md CHANGED
@@ -16,12 +16,19 @@ Peer dependencies: `@nestjs/common >= 10`, `@nestjs/core >= 10`, `reflect-metada
16
16
  import { Module } from "@nestjs/common";
17
17
  import { StratumModule } from "@stratum-hq/nestjs";
18
18
 
19
+ // Without jwtSecret, the guard does not verify tokens and reads the tenant
20
+ // from the X-Tenant-ID header, which any client can send.
21
+ const jwtSecret = process.env.JWT_SECRET;
22
+ if (!jwtSecret) {
23
+ throw new Error("JWT_SECRET is required to verify bearer tokens.");
24
+ }
25
+
19
26
  @Module({
20
27
  imports: [
21
28
  StratumModule.forRoot({
22
29
  controlPlaneUrl: "http://localhost:3001",
23
30
  apiKey: "sk_live_your_key",
24
- jwtSecret: process.env.JWT_SECRET, // optional: enables JWT verification
31
+ jwtSecret, // optional: enables JWT verification
25
32
  jwtClaimPath: "tenant_id",
26
33
  }),
27
34
  ],
@@ -48,7 +55,7 @@ export class DataController {
48
55
  ## API
49
56
 
50
57
  - **`StratumModule.forRoot(options)` / `forRootAsync(options)`** — register the SDK client for DI. `forRootAsync` supports `useFactory` + `inject` for config that depends on other providers (e.g. `ConfigService`).
51
- - **`StratumGuard`** — resolves the tenant from the `X-Tenant-ID` header, a verified JWT claim, or custom `resolvers` (in that order). Sets `req.tenant` (full `TenantContext`), plus `req.impersonating` / `req.originalTenantId` when impersonation is enabled. Throws `UnauthorizedException` (401) if no tenant is found.
58
+ - **`StratumGuard`** — resolves the tenant from a verified JWT claim, then the `X-Tenant-ID` header, then custom `resolvers`. When `jwtSecret` or `jwtVerify` is set, the guard reads the header only with `trustTenantHeader: true`, and it rejects a Bearer token that fails verification with 401. Sets `req.tenant` (full `TenantContext`), plus `req.impersonating` / `req.originalTenantId` when impersonation is enabled. Throws `UnauthorizedException` (401) if the request has no tenant ID, `NotFoundException` (404) if the tenant does not exist, `ForbiddenException` (403) if the tenant is suspended or access is denied, and `GoneException` (410) if the tenant is archived. A control plane timeout throws `GatewayTimeoutException` (504). A rejected SDK API key throws `InternalServerErrorException` (500) and writes the cause to `console.error`.
52
59
  - **`@Tenant()`** — parameter decorator that extracts `req.tenant`.
53
60
  - **`StratumContextInterceptor`** — binds the resolved context to AsyncLocalStorage so services can call `getTenantContext()` from `@stratum-hq/sdk` without the request object.
54
61
 
@@ -1 +1 @@
1
- {"version":3,"file":"stratum.guard.d.ts","sourceRoot":"","sources":["../src/stratum.guard.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAEhE,qBACa,YAAa,YAAW,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADR,MAAM,EAAE,aAAa,EACpB,OAAO,EAAE,oBAAoB;IAGnE,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;CAsF/D"}
1
+ {"version":3,"file":"stratum.guard.d.ts","sourceRoot":"","sources":["../src/stratum.guard.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAuBhE,qBACa,YAAa,YAAW,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADR,MAAM,EAAE,aAAa,EACpB,OAAO,EAAE,oBAAoB;IAKnE,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;CAmE/D"}
@@ -10,57 +10,62 @@ var __metadata = (this && this.__metadata) || function (k, v) {
10
10
  var __param = (this && this.__param) || function (paramIndex, decorator) {
11
11
  return function (target, key) { decorator(target, key, paramIndex); }
12
12
  };
13
- import { Inject, Injectable, UnauthorizedException, ForbiddenException } from "@nestjs/common";
14
- import { resolveFromHeader, resolveFromJwt } from "@stratum-hq/sdk";
15
- import { TenantNotFoundError } from "@stratum-hq/core";
13
+ import { Inject, Injectable, UnauthorizedException, ForbiddenException, GatewayTimeoutException, GoneException, HttpException, InternalServerErrorException, NotFoundException, } from "@nestjs/common";
14
+ import { assertJwtSupport, controlPlaneErrorResponse, resolveTenantId, tenantErrorResponse } from "@stratum-hq/sdk";
16
15
  import { STRATUM_CLIENT, STRATUM_OPTIONS } from "./constants.js";
16
+ const EXCEPTIONS = {
17
+ 403: ForbiddenException,
18
+ 404: NotFoundException,
19
+ 410: GoneException,
20
+ 500: InternalServerErrorException,
21
+ 504: GatewayTimeoutException,
22
+ };
23
+ /**
24
+ * Convert a tenant resolution error into the HTTP exception for the status
25
+ * that the SDK's Express and Fastify middleware send for the same error.
26
+ * Other errors come back unchanged, so Nest answers them with a 500.
27
+ */
28
+ function resolutionException(err, tenantId) {
29
+ const response = tenantErrorResponse(err, tenantId) ?? controlPlaneErrorResponse(err);
30
+ if (!response)
31
+ return err;
32
+ const Exception = EXCEPTIONS[response.status];
33
+ const message = response.body.error.message;
34
+ return Exception ? new Exception(message) : new HttpException(message, response.status);
35
+ }
17
36
  let StratumGuard = class StratumGuard {
18
37
  client;
19
38
  options;
20
39
  constructor(client, options) {
21
40
  this.client = client;
22
41
  this.options = options;
42
+ assertJwtSupport(options);
23
43
  }
24
44
  async canActivate(context) {
25
45
  const req = context.switchToHttp().getRequest();
26
46
  // 1. Resolve tenant ID: JWT (verified) → header → custom resolvers.
27
- // The verified JWT is authoritative; the header is only a fallback when
28
- // no JWT tenant is present, so it can never override a verified identity.
47
+ // When JWT verification is configured, a token that fails verification
48
+ // is rejected, and the header is only read if trustTenantHeader is set.
29
49
  // Order mirrors express.ts.
30
- let tenantId = null;
31
- tenantId = resolveFromJwt(req, this.options.jwtClaimPath, {
32
- secret: this.options.jwtSecret,
33
- verify: this.options.jwtVerify,
34
- });
35
- if (!tenantId) {
36
- tenantId = resolveFromHeader(req);
50
+ const resolution = await resolveTenantId(req, this.options);
51
+ if (resolution.status === "invalid_token") {
52
+ throw new UnauthorizedException("Bearer token could not be verified");
37
53
  }
38
- if (!tenantId && this.options.resolvers) {
39
- for (const resolver of this.options.resolvers) {
40
- const result = await resolver.resolve(req);
41
- if (result) {
42
- tenantId = result;
43
- break;
44
- }
45
- }
46
- }
47
- if (!tenantId) {
54
+ if (resolution.status === "missing") {
48
55
  throw new UnauthorizedException("Tenant ID could not be resolved from request");
49
56
  }
57
+ const tenantId = resolution.tenantId;
50
58
  // 2. Resolve caller tenant context
51
59
  let callerContext;
52
60
  try {
53
61
  callerContext = await this.client.resolveTenant(tenantId);
54
62
  }
55
63
  catch (err) {
56
- if (err instanceof TenantNotFoundError) {
57
- throw new UnauthorizedException(`Tenant not found: ${tenantId}`);
58
- }
59
- throw err;
64
+ throw resolutionException(err, tenantId);
60
65
  }
61
66
  req["tenant"] = callerContext;
62
67
  req["impersonating"] = false;
63
- // 3. Impersonation support — mirrors express.ts lines 52-81
68
+ // 3. Impersonation support — mirrors express.ts
64
69
  if (this.options.impersonation?.enabled) {
65
70
  const impersonateHeader = this.options.impersonation.headerName ?? "X-Impersonate-Tenant";
66
71
  const headers = req.headers;
@@ -76,10 +81,7 @@ let StratumGuard = class StratumGuard {
76
81
  impersonatedContext = await this.client.resolveTenant(impersonateTenantId);
77
82
  }
78
83
  catch (err) {
79
- if (err instanceof TenantNotFoundError) {
80
- throw new UnauthorizedException(`Impersonated tenant not found: ${impersonateTenantId}`);
81
- }
82
- throw err;
84
+ throw resolutionException(err, impersonateTenantId);
83
85
  }
84
86
  req["tenant"] = impersonatedContext;
85
87
  req["impersonating"] = true;
@@ -1 +1 @@
1
- {"version":3,"file":"stratum.guard.js","sourceRoot":"","sources":["../src/stratum.guard.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stratum.guard.js","sourceRoot":"","sources":["../src/stratum.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EACL,MAAM,EACN,UAAU,EACV,qBAAqB,EACrB,kBAAkB,EAClB,uBAAuB,EACvB,aAAa,EACb,aAAa,EACb,4BAA4B,EAC5B,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACpH,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGjE,MAAM,UAAU,GAA2D;IACzE,GAAG,EAAE,kBAAkB;IACvB,GAAG,EAAE,iBAAiB;IACtB,GAAG,EAAE,aAAa;IAClB,GAAG,EAAE,4BAA4B;IACjC,GAAG,EAAE,uBAAuB;CAC7B,CAAC;AAEF;;;;GAIG;AACH,SAAS,mBAAmB,CAAC,GAAY,EAAE,QAAgB;IACzD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,yBAAyB,CAAC,GAAG,CAAC,CAAC;IACtF,IAAI,CAAC,QAAQ;QAAE,OAAO,GAAG,CAAC;IAC1B,MAAM,SAAS,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;IAC5C,OAAO,SAAS,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC1F,CAAC;AAGM,IAAM,YAAY,GAAlB,MAAM,YAAY;IAEoB;IACC;IAF5C,YAC2C,MAAqB,EACpB,OAA6B;QAD9B,WAAM,GAAN,MAAM,CAAe;QACpB,YAAO,GAAP,OAAO,CAAsB;QAEvE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAyB;QACzC,MAAM,GAAG,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAKzC,CAAC;QAEL,oEAAoE;QACpE,0EAA0E;QAC1E,2EAA2E;QAC3E,+BAA+B;QAC/B,MAAM,UAAU,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAE5D,IAAI,UAAU,CAAC,MAAM,KAAK,eAAe,EAAE,CAAC;YAC1C,MAAM,IAAI,qBAAqB,CAAC,oCAAoC,CAAC,CAAC;QACxE,CAAC;QAED,IAAI,UAAU,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACpC,MAAM,IAAI,qBAAqB,CAAC,8CAA8C,CAAC,CAAC;QAClF,CAAC;QAED,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC;QAErC,mCAAmC;QACnC,IAAI,aAAa,CAAC;QAClB,IAAI,CAAC;YACH,aAAa,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC5D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,mBAAmB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC3C,CAAC;QAED,GAAG,CAAC,QAAQ,CAAC,GAAG,aAAa,CAAC;QAC9B,GAAG,CAAC,eAAe,CAAC,GAAG,KAAK,CAAC;QAE7B,gDAAgD;QAChD,IAAI,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,OAAO,EAAE,CAAC;YACxC,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,UAAU,IAAI,sBAAsB,CAAC;YAC1F,MAAM,OAAO,GAAG,GAAG,CAAC,OAAoE,CAAC;YACzF,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC,iBAAiB,CAAC,WAAW,EAAE,CAAC,CAAC;YAC1D,MAAM,mBAAmB,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YAEvE,IAAI,mBAAmB,IAAI,mBAAmB,KAAK,QAAQ,EAAE,CAAC;gBAC5D,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,GAAG,EAAE,QAAQ,EAAE,mBAAmB,CAAC,CAAC;gBAClG,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,MAAM,IAAI,kBAAkB,CAAC,2CAA2C,CAAC,CAAC;gBAC5E,CAAC;gBAED,IAAI,mBAAmB,CAAC;gBACxB,IAAI,CAAC;oBACH,mBAAmB,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAAC;gBAC7E,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,mBAAmB,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;gBACtD,CAAC;gBAED,GAAG,CAAC,QAAQ,CAAC,GAAG,mBAAmB,CAAC;gBACpC,GAAG,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC;gBAC5B,GAAG,CAAC,kBAAkB,CAAC,GAAG,QAAQ,CAAC;gBAEnC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,mBAAmB,CAAC,CAAC;gBAE/E,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AA3EY,YAAY;IADxB,UAAU,EAAE;IAGR,WAAA,MAAM,CAAC,cAAc,CAAC,CAAA;IACtB,WAAA,MAAM,CAAC,eAAe,CAAC,CAAA;;GAHf,YAAY,CA2ExB"}
@@ -1,6 +1,6 @@
1
1
  import type { NestInterceptor, ExecutionContext, CallHandler } from "@nestjs/common";
2
2
  import { Observable } from "rxjs";
3
3
  export declare class StratumContextInterceptor implements NestInterceptor {
4
- intercept(context: ExecutionContext, next: CallHandler): Observable<any>;
4
+ intercept(context: ExecutionContext, next: CallHandler): Observable<unknown>;
5
5
  }
6
6
  //# sourceMappingURL=stratum.interceptor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stratum.interceptor.d.ts","sourceRoot":"","sources":["../src/stratum.interceptor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACrF,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAGlC,qBACa,yBAA0B,YAAW,eAAe;IAC/D,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC,GAAG,CAAC;CAUzE"}
1
+ {"version":3,"file":"stratum.interceptor.d.ts","sourceRoot":"","sources":["../src/stratum.interceptor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACrF,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAGlC,qBACa,yBAA0B,YAAW,eAAe;IAC/D,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC;CAU7E"}
@@ -9,6 +9,14 @@ export interface StratumModuleOptions {
9
9
  jwtSecret?: string;
10
10
  /** Custom JWT verify function — takes priority over jwtSecret. */
11
11
  jwtVerify?: (token: string) => Record<string, unknown> | null;
12
+ /** Header to read the tenant ID from. When set, only this header is read (default: X-Tenant-ID). */
13
+ headerName?: string;
14
+ /**
15
+ * When jwtSecret or jwtVerify is configured, the tenant header is ignored
16
+ * unless this is true. A bearer token that fails verification is always
17
+ * rejected. Default: false.
18
+ */
19
+ trustTenantHeader?: boolean;
12
20
  /** Custom tenant resolvers evaluated after header and JWT resolution. */
13
21
  resolvers?: import("@stratum-hq/sdk").TenantResolver[];
14
22
  /** Enable tenant impersonation via X-Impersonate-Tenant header. */
@@ -1 +1 @@
1
- {"version":3,"file":"stratum.module.d.ts","sourceRoot":"","sources":["../src/stratum.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,aAAa,EAAU,MAAM,gBAAgB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAOtE,MAAM,WAAW,oBAAoB;IACnC,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,uHAAuH;IACvH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9D,yEAAyE;IACzE,SAAS,CAAC,EAAE,OAAO,iBAAiB,EAAE,cAAc,EAAE,CAAC;IACvD,mEAAmE;IACnE,aAAa,CAAC,EAAE;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACxG,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;KACxF,CAAC;CACH;AAED,MAAM,WAAW,yBAA0B,SAAQ,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC;IAChF,UAAU,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACzF,MAAM,CAAC,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC;CACpC;AAED,qBAEa,aAAa;IACxB;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa;IAqB5D;;;OAGG;IACH,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,yBAAyB,GAAG,aAAa;CA0B5E"}
1
+ {"version":3,"file":"stratum.module.d.ts","sourceRoot":"","sources":["../src/stratum.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,aAAa,EAAU,MAAM,gBAAgB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAOtE,MAAM,WAAW,oBAAoB;IACnC,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,uHAAuH;IACvH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9D,oGAAoG;IACpG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,yEAAyE;IACzE,SAAS,CAAC,EAAE,OAAO,iBAAiB,EAAE,cAAc,EAAE,CAAC;IACvD,mEAAmE;IACnE,aAAa,CAAC,EAAE;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACxG,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;KACxF,CAAC;CACH;AAED,MAAM,WAAW,yBAA0B,SAAQ,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC;IAChF,UAAU,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACzF,MAAM,CAAC,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC;CACpC;AAED,qBAEa,aAAa;IACxB;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa;IAqB5D;;;OAGG;IACH,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,yBAAyB,GAAG,aAAa;CA0B5E"}
@@ -1 +1 @@
1
- {"version":3,"file":"stratum.module.js","sourceRoot":"","sources":["../src/stratum.module.ts"],"names":[],"mappings":";;;;;;;AAAA,OAAO,EAAE,MAAM,EAAiB,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE/D,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AA6B9D,IAAM,aAAa,qBAAnB,MAAM,aAAa;IACxB;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,OAA6B;QAC1C,MAAM,cAAc,GAAG;YACrB,OAAO,EAAE,cAAc;YACvB,QAAQ,EAAE,IAAI,aAAa,CAAC;gBAC1B,eAAe,EAAE,OAAO,CAAC,eAAe;gBACxC,MAAM,EAAE,OAAO,CAAC,MAAM;aACvB,CAAC;SACH,CAAC;QAEF,MAAM,eAAe,GAAG;YACtB,OAAO,EAAE,eAAe;YACxB,QAAQ,EAAE,OAAO;SAClB,CAAC;QAEF,OAAO;YACL,MAAM,EAAE,eAAa;YACrB,SAAS,EAAE,CAAC,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,yBAAyB,EAAE,CAAC;YAC7H,OAAO,EAAE,CAAC,cAAc,EAAE,YAAY,CAAC;SACxC,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,YAAY,CAAC,YAAuC;QACzD,MAAM,eAAe,GAAoB;YACvC,OAAO,EAAE,eAAe;YACxB,UAAU,EAAE,YAAY,CAAC,UAAU;YACnC,MAAM,EAAE,YAAY,CAAC,MAAM,IAAI,EAAE;SAClC,CAAC;QAEF,MAAM,cAAc,GAAoB;YACtC,OAAO,EAAE,cAAc;YACvB,UAAU,EAAE,KAAK,EAAE,GAAG,IAAe,EAAE,EAAE;gBACvC,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,CAAC;gBACvD,OAAO,IAAI,aAAa,CAAC;oBACvB,eAAe,EAAE,OAAO,CAAC,eAAe;oBACxC,MAAM,EAAE,OAAO,CAAC,MAAM;iBACvB,CAAC,CAAC;YACL,CAAC;YACD,MAAM,EAAE,YAAY,CAAC,MAAM,IAAI,EAAE;SAClC,CAAC;QAEF,OAAO;YACL,MAAM,EAAE,eAAa;YACrB,OAAO,EAAE,YAAY,CAAC,OAAO,IAAI,EAAE;YACnC,SAAS,EAAE,CAAC,eAAe,EAAE,cAAc,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,yBAAyB,EAAE,CAAC;YAC7H,OAAO,EAAE,CAAC,cAAc,EAAE,YAAY,CAAC;SACxC,CAAC;IACJ,CAAC;CACF,CAAA;AAvDY,aAAa;IAFzB,MAAM,EAAE;IACR,MAAM,CAAC,EAAE,CAAC;GACE,aAAa,CAuDzB"}
1
+ {"version":3,"file":"stratum.module.js","sourceRoot":"","sources":["../src/stratum.module.ts"],"names":[],"mappings":";;;;;;;AAAA,OAAO,EAAE,MAAM,EAAiB,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE/D,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAqC9D,IAAM,aAAa,qBAAnB,MAAM,aAAa;IACxB;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,OAA6B;QAC1C,MAAM,cAAc,GAAG;YACrB,OAAO,EAAE,cAAc;YACvB,QAAQ,EAAE,IAAI,aAAa,CAAC;gBAC1B,eAAe,EAAE,OAAO,CAAC,eAAe;gBACxC,MAAM,EAAE,OAAO,CAAC,MAAM;aACvB,CAAC;SACH,CAAC;QAEF,MAAM,eAAe,GAAG;YACtB,OAAO,EAAE,eAAe;YACxB,QAAQ,EAAE,OAAO;SAClB,CAAC;QAEF,OAAO;YACL,MAAM,EAAE,eAAa;YACrB,SAAS,EAAE,CAAC,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,yBAAyB,EAAE,CAAC;YAC7H,OAAO,EAAE,CAAC,cAAc,EAAE,YAAY,CAAC;SACxC,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,YAAY,CAAC,YAAuC;QACzD,MAAM,eAAe,GAAoB;YACvC,OAAO,EAAE,eAAe;YACxB,UAAU,EAAE,YAAY,CAAC,UAAU;YACnC,MAAM,EAAE,YAAY,CAAC,MAAM,IAAI,EAAE;SAClC,CAAC;QAEF,MAAM,cAAc,GAAoB;YACtC,OAAO,EAAE,cAAc;YACvB,UAAU,EAAE,KAAK,EAAE,GAAG,IAAe,EAAE,EAAE;gBACvC,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,CAAC;gBACvD,OAAO,IAAI,aAAa,CAAC;oBACvB,eAAe,EAAE,OAAO,CAAC,eAAe;oBACxC,MAAM,EAAE,OAAO,CAAC,MAAM;iBACvB,CAAC,CAAC;YACL,CAAC;YACD,MAAM,EAAE,YAAY,CAAC,MAAM,IAAI,EAAE;SAClC,CAAC;QAEF,OAAO;YACL,MAAM,EAAE,eAAa;YACrB,OAAO,EAAE,YAAY,CAAC,OAAO,IAAI,EAAE;YACnC,SAAS,EAAE,CAAC,eAAe,EAAE,cAAc,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,yBAAyB,EAAE,CAAC;YAC7H,OAAO,EAAE,CAAC,cAAc,EAAE,YAAY,CAAC;SACxC,CAAC;IACJ,CAAC;CACF,CAAA;AAvDY,aAAa;IAFzB,MAAM,EAAE;IACR,MAAM,CAAC,EAAE,CAAC;GACE,aAAa,CAuDzB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stratum-hq/nestjs",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "Stratum NestJS integration — StratumGuard, @Tenant() decorator, and StratumModule",
5
5
  "keywords": [
6
6
  "multi-tenancy",
@@ -43,19 +43,19 @@
43
43
  "peerDependencies": {
44
44
  "@nestjs/common": ">=10.0.0",
45
45
  "@nestjs/core": ">=10.0.0",
46
- "@stratum-hq/core": ">=1.0.0",
47
- "@stratum-hq/sdk": ">=1.0.0",
46
+ "@stratum-hq/core": "^1.0.0",
47
+ "@stratum-hq/sdk": "^1.2.0",
48
48
  "reflect-metadata": ">=0.1.13"
49
49
  },
50
50
  "devDependencies": {
51
- "@nestjs/common": "^10.0.0",
52
- "@nestjs/core": "^10.0.0",
53
- "@nestjs/testing": "^10.0.0",
51
+ "@nestjs/common": "^12.1.2",
52
+ "@nestjs/core": "^12.1.2",
53
+ "@nestjs/testing": "^12.1.2",
54
54
  "@stratum-hq/core": "*",
55
55
  "@stratum-hq/sdk": "*",
56
- "reflect-metadata": "^0.1.13",
56
+ "reflect-metadata": "^0.2.2",
57
57
  "typescript": "^5.4.0",
58
- "vitest": "^1.6.0"
58
+ "vitest": "^4.1.11"
59
59
  },
60
60
  "license": "MIT",
61
61
  "author": "Christian Crank",