nestjs-tenant-shield 0.1.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.
Files changed (167) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +612 -0
  3. package/dist/cache/cache.registry.d.ts +19 -0
  4. package/dist/cache/cache.registry.d.ts.map +1 -0
  5. package/dist/cache/cache.registry.js +51 -0
  6. package/dist/cache/cache.registry.js.map +1 -0
  7. package/dist/cache/cache.service.d.ts +44 -0
  8. package/dist/cache/cache.service.d.ts.map +1 -0
  9. package/dist/cache/cache.service.js +64 -0
  10. package/dist/cache/cache.service.js.map +1 -0
  11. package/dist/cache/index.d.ts +3 -0
  12. package/dist/cache/index.d.ts.map +1 -0
  13. package/dist/cache/index.js +19 -0
  14. package/dist/cache/index.js.map +1 -0
  15. package/dist/constants/index.d.ts +64 -0
  16. package/dist/constants/index.d.ts.map +1 -0
  17. package/dist/constants/index.js +67 -0
  18. package/dist/constants/index.js.map +1 -0
  19. package/dist/context/get-current-tenant-id.d.ts +30 -0
  20. package/dist/context/get-current-tenant-id.d.ts.map +1 -0
  21. package/dist/context/get-current-tenant-id.js +40 -0
  22. package/dist/context/get-current-tenant-id.js.map +1 -0
  23. package/dist/context/index.d.ts +7 -0
  24. package/dist/context/index.d.ts.map +1 -0
  25. package/dist/context/index.js +23 -0
  26. package/dist/context/index.js.map +1 -0
  27. package/dist/context/run-with-tenant.d.ts +84 -0
  28. package/dist/context/run-with-tenant.d.ts.map +1 -0
  29. package/dist/context/run-with-tenant.js +95 -0
  30. package/dist/context/run-with-tenant.js.map +1 -0
  31. package/dist/context/tenant-context.storage.d.ts +43 -0
  32. package/dist/context/tenant-context.storage.d.ts.map +1 -0
  33. package/dist/context/tenant-context.storage.js +45 -0
  34. package/dist/context/tenant-context.storage.js.map +1 -0
  35. package/dist/decorators/cacheable.decorator.d.ts +27 -0
  36. package/dist/decorators/cacheable.decorator.d.ts.map +1 -0
  37. package/dist/decorators/cacheable.decorator.js +108 -0
  38. package/dist/decorators/cacheable.decorator.js.map +1 -0
  39. package/dist/decorators/index.d.ts +13 -0
  40. package/dist/decorators/index.d.ts.map +1 -0
  41. package/dist/decorators/index.js +29 -0
  42. package/dist/decorators/index.js.map +1 -0
  43. package/dist/decorators/require-tenant.decorator.d.ts +41 -0
  44. package/dist/decorators/require-tenant.decorator.d.ts.map +1 -0
  45. package/dist/decorators/require-tenant.decorator.js +125 -0
  46. package/dist/decorators/require-tenant.decorator.js.map +1 -0
  47. package/dist/decorators/system-action.decorator.d.ts +39 -0
  48. package/dist/decorators/system-action.decorator.d.ts.map +1 -0
  49. package/dist/decorators/system-action.decorator.js +50 -0
  50. package/dist/decorators/system-action.decorator.js.map +1 -0
  51. package/dist/decorators/tenant-context.decorator.d.ts +33 -0
  52. package/dist/decorators/tenant-context.decorator.d.ts.map +1 -0
  53. package/dist/decorators/tenant-context.decorator.js +54 -0
  54. package/dist/decorators/tenant-context.decorator.js.map +1 -0
  55. package/dist/errors/cross-tenant-access.error.d.ts +29 -0
  56. package/dist/errors/cross-tenant-access.error.d.ts.map +1 -0
  57. package/dist/errors/cross-tenant-access.error.js +37 -0
  58. package/dist/errors/cross-tenant-access.error.js.map +1 -0
  59. package/dist/errors/index.d.ts +10 -0
  60. package/dist/errors/index.d.ts.map +1 -0
  61. package/dist/errors/index.js +26 -0
  62. package/dist/errors/index.js.map +1 -0
  63. package/dist/errors/invalid-tenant-source.error.d.ts +20 -0
  64. package/dist/errors/invalid-tenant-source.error.d.ts.map +1 -0
  65. package/dist/errors/invalid-tenant-source.error.js +28 -0
  66. package/dist/errors/invalid-tenant-source.error.js.map +1 -0
  67. package/dist/errors/missing-tenant-context.error.d.ts +22 -0
  68. package/dist/errors/missing-tenant-context.error.d.ts.map +1 -0
  69. package/dist/errors/missing-tenant-context.error.js +32 -0
  70. package/dist/errors/missing-tenant-context.error.js.map +1 -0
  71. package/dist/index.d.ts +36 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +56 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/interfaces/cacheable-options.interface.d.ts +37 -0
  76. package/dist/interfaces/cacheable-options.interface.d.ts.map +1 -0
  77. package/dist/interfaces/cacheable-options.interface.js +3 -0
  78. package/dist/interfaces/cacheable-options.interface.js.map +1 -0
  79. package/dist/interfaces/index.d.ts +13 -0
  80. package/dist/interfaces/index.d.ts.map +1 -0
  81. package/dist/interfaces/index.js +30 -0
  82. package/dist/interfaces/index.js.map +1 -0
  83. package/dist/interfaces/require-tenant-options.interface.d.ts +23 -0
  84. package/dist/interfaces/require-tenant-options.interface.d.ts.map +1 -0
  85. package/dist/interfaces/require-tenant-options.interface.js +3 -0
  86. package/dist/interfaces/require-tenant-options.interface.js.map +1 -0
  87. package/dist/interfaces/tenant-context-options.interface.d.ts +19 -0
  88. package/dist/interfaces/tenant-context-options.interface.d.ts.map +1 -0
  89. package/dist/interfaces/tenant-context-options.interface.js +3 -0
  90. package/dist/interfaces/tenant-context-options.interface.js.map +1 -0
  91. package/dist/interfaces/tenant-context.interface.d.ts +26 -0
  92. package/dist/interfaces/tenant-context.interface.d.ts.map +1 -0
  93. package/dist/interfaces/tenant-context.interface.js +3 -0
  94. package/dist/interfaces/tenant-context.interface.js.map +1 -0
  95. package/dist/interfaces/tenant-shield-options.interface.d.ts +141 -0
  96. package/dist/interfaces/tenant-shield-options.interface.d.ts.map +1 -0
  97. package/dist/interfaces/tenant-shield-options.interface.js +11 -0
  98. package/dist/interfaces/tenant-shield-options.interface.js.map +1 -0
  99. package/dist/middleware/index.d.ts +2 -0
  100. package/dist/middleware/index.d.ts.map +1 -0
  101. package/dist/middleware/index.js +18 -0
  102. package/dist/middleware/index.js.map +1 -0
  103. package/dist/middleware/tenant-context.middleware.d.ts +30 -0
  104. package/dist/middleware/tenant-context.middleware.d.ts.map +1 -0
  105. package/dist/middleware/tenant-context.middleware.js +68 -0
  106. package/dist/middleware/tenant-context.middleware.js.map +1 -0
  107. package/dist/options/index.d.ts +2 -0
  108. package/dist/options/index.d.ts.map +1 -0
  109. package/dist/options/index.js +18 -0
  110. package/dist/options/index.js.map +1 -0
  111. package/dist/options/options.registry.d.ts +8 -0
  112. package/dist/options/options.registry.d.ts.map +1 -0
  113. package/dist/options/options.registry.js +36 -0
  114. package/dist/options/options.registry.js.map +1 -0
  115. package/dist/resolvers/custom.resolver.d.ts +29 -0
  116. package/dist/resolvers/custom.resolver.d.ts.map +1 -0
  117. package/dist/resolvers/custom.resolver.js +47 -0
  118. package/dist/resolvers/custom.resolver.js.map +1 -0
  119. package/dist/resolvers/header.resolver.d.ts +22 -0
  120. package/dist/resolvers/header.resolver.d.ts.map +1 -0
  121. package/dist/resolvers/header.resolver.js +39 -0
  122. package/dist/resolvers/header.resolver.js.map +1 -0
  123. package/dist/resolvers/index.d.ts +13 -0
  124. package/dist/resolvers/index.d.ts.map +1 -0
  125. package/dist/resolvers/index.js +29 -0
  126. package/dist/resolvers/index.js.map +1 -0
  127. package/dist/resolvers/jwt.resolver.d.ts +35 -0
  128. package/dist/resolvers/jwt.resolver.d.ts.map +1 -0
  129. package/dist/resolvers/jwt.resolver.js +51 -0
  130. package/dist/resolvers/jwt.resolver.js.map +1 -0
  131. package/dist/resolvers/resolver.factory.d.ts +12 -0
  132. package/dist/resolvers/resolver.factory.d.ts.map +1 -0
  133. package/dist/resolvers/resolver.factory.js +43 -0
  134. package/dist/resolvers/resolver.factory.js.map +1 -0
  135. package/dist/resolvers/subdomain.resolver.d.ts +37 -0
  136. package/dist/resolvers/subdomain.resolver.d.ts.map +1 -0
  137. package/dist/resolvers/subdomain.resolver.js +57 -0
  138. package/dist/resolvers/subdomain.resolver.js.map +1 -0
  139. package/dist/resolvers/tenant-resolver.interface.d.ts +22 -0
  140. package/dist/resolvers/tenant-resolver.interface.d.ts.map +1 -0
  141. package/dist/resolvers/tenant-resolver.interface.js +3 -0
  142. package/dist/resolvers/tenant-resolver.interface.js.map +1 -0
  143. package/dist/tenant-shield.module.d.ts +88 -0
  144. package/dist/tenant-shield.module.d.ts.map +1 -0
  145. package/dist/tenant-shield.module.js +263 -0
  146. package/dist/tenant-shield.module.js.map +1 -0
  147. package/dist/testing/index.d.ts +12 -0
  148. package/dist/testing/index.d.ts.map +1 -0
  149. package/dist/testing/index.js +28 -0
  150. package/dist/testing/index.js.map +1 -0
  151. package/dist/testing/test-helpers.d.ts +52 -0
  152. package/dist/testing/test-helpers.d.ts.map +1 -0
  153. package/dist/testing/test-helpers.js +72 -0
  154. package/dist/testing/test-helpers.js.map +1 -0
  155. package/dist/typeorm/index.d.ts +10 -0
  156. package/dist/typeorm/index.d.ts.map +1 -0
  157. package/dist/typeorm/index.js +26 -0
  158. package/dist/typeorm/index.js.map +1 -0
  159. package/dist/typeorm/raw-sql.helper.d.ts +35 -0
  160. package/dist/typeorm/raw-sql.helper.d.ts.map +1 -0
  161. package/dist/typeorm/raw-sql.helper.js +24 -0
  162. package/dist/typeorm/raw-sql.helper.js.map +1 -0
  163. package/dist/typeorm/tenant.subscriber.d.ts +61 -0
  164. package/dist/typeorm/tenant.subscriber.d.ts.map +1 -0
  165. package/dist/typeorm/tenant.subscriber.js +487 -0
  166. package/dist/typeorm/tenant.subscriber.js.map +1 -0
  167. package/package.json +109 -0
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TenantContext = TenantContext;
4
+ const tenant_context_storage_1 = require("../context/tenant-context.storage");
5
+ /**
6
+ * ─────────────────────────────────────────────────────────────
7
+ * @TenantContext() — 백그라운드 큐 작업용 tenant 컨텍스트 복원 데코레이터.
8
+ *
9
+ * ⚠️ v0.2 정식 출시 예정. v0.1 스켈레톤만 존재.
10
+ *
11
+ * 동작:
12
+ * BullMQ/Bull의 @Process 핸들러에 붙이면, job payload에서 tenant ID를
13
+ * 꺼내 AsyncLocalStorage.run()으로 컨텍스트를 만든 채 핸들러를 실행.
14
+ *
15
+ * 결과적으로 HTTP 요청과 동일한 보호망(@RequireTenant, Subscriber 등)이
16
+ * 백그라운드 작업에서도 그대로 동작합니다.
17
+ *
18
+ * ─────────────────────────────────────────────────────────────
19
+ *
20
+ * [예시]
21
+ *
22
+ * @Processor('reports')
23
+ * export class ReportProcessor {
24
+ * @Process('monthly')
25
+ * @TenantContext() // job.data.tenantId 자동 추출
26
+ * async generateMonthlyReport(job: Job) { ... }
27
+ *
28
+ * @Process('quarterly')
29
+ * @TenantContext({ extractFrom: j => j.data.orgId }) // 커스텀 추출
30
+ * async generateQuarterly(job: Job) { ... }
31
+ * }
32
+ *
33
+ * ─────────────────────────────────────────────────────────────
34
+ */
35
+ function TenantContext(options = {}) {
36
+ return function (_target, _propertyKey, descriptor) {
37
+ const originalMethod = descriptor.value;
38
+ // 추출 함수 — 미지정 시 job.data.tenantId 기본 사용.
39
+ const extract = options.extractFrom ?? ((job) => job?.data?.tenantId);
40
+ descriptor.value = async function (...args) {
41
+ // BullMQ는 핸들러 첫 번째 인자로 Job 객체를 넘깁니다.
42
+ const job = args[0];
43
+ const tenantId = extract(job);
44
+ if (!tenantId) {
45
+ // 추출 실패 — payload 구조를 점검하라는 명확한 에러로.
46
+ throw new Error('@TenantContext: job payload에서 tenant ID를 추출하지 못했습니다. extractFrom 옵션을 확인하세요.');
47
+ }
48
+ // 컨텍스트를 새로 만들어서 원본 핸들러 실행.
49
+ return tenant_context_storage_1.tenantContextStorage.run({ tenantId, isSystemAction: false }, () => originalMethod.apply(this, args));
50
+ };
51
+ return descriptor;
52
+ };
53
+ }
54
+ //# sourceMappingURL=tenant-context.decorator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-context.decorator.js","sourceRoot":"","sources":["../../src/decorators/tenant-context.decorator.ts"],"names":[],"mappings":";;AAiCA,sCAgCC;AAhED,8EAAyE;AAEzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,SAAgB,aAAa,CAAC,UAAgC,EAAE;IAC9D,OAAO,UACL,OAAY,EACZ,YAA6B,EAC7B,UAA8B;QAE9B,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC;QAExC,yCAAyC;QACzC,MAAM,OAAO,GACX,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,QAAkB,CAAC,CAAC;QAEvE,UAAU,CAAC,KAAK,GAAG,KAAK,WAAsB,GAAG,IAAe;YAC9D,qCAAqC;YACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACpB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;YAE9B,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,qCAAqC;gBACrC,MAAM,IAAI,KAAK,CACb,6EAA6E,CAC9E,CAAC;YACJ,CAAC;YAED,2BAA2B;YAC3B,OAAO,6CAAoB,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,CACxE,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CACjC,CAAC;QACJ,CAAC,CAAC;QAEF,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * 한 tenant가 다른 tenant의 데이터에 접근을 시도했을 때 throw 되는 에러.
3
+ *
4
+ * 이 에러가 나면 그 자체로 보안 사고 신호입니다.
5
+ * 정상 흐름에서는 절대 발생하지 않아야 합니다 (Subscriber가 자동 WHERE를 주입하므로).
6
+ *
7
+ * 발생 가능 시나리오:
8
+ * - 어딘가에서 escape hatch(raw SQL, getManager 직접 사용)로 우회한 경우
9
+ * - Subscriber가 등록되지 않은 entity를 사용한 경우
10
+ * - 캐시 키 분리가 안 된 상태에서 다른 tenant 데이터가 응답된 경우
11
+ *
12
+ * 처리 권장:
13
+ * - 즉시 알림 (Slack, Sentry, PagerDuty 등)
14
+ * - 해당 요청 ID, 사용자, IP 함께 기록
15
+ * - 코드 리뷰로 우회 경로 점검
16
+ */
17
+ export declare class CrossTenantAccessError extends Error {
18
+ readonly currentTenant: string;
19
+ readonly attemptedTenant: string;
20
+ readonly entityName?: string | undefined;
21
+ /**
22
+ * @param message - 에러 메시지
23
+ * @param currentTenant - 현재 요청의 tenant ID
24
+ * @param attemptedTenant - 접근 시도한 데이터의 tenant ID
25
+ * @param entityName - 해당 entity 클래스 이름 (선택)
26
+ */
27
+ constructor(message: string, currentTenant: string, attemptedTenant: string, entityName?: string | undefined);
28
+ }
29
+ //# sourceMappingURL=cross-tenant-access.error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-tenant-access.error.d.ts","sourceRoot":"","sources":["../../src/errors/cross-tenant-access.error.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;aAS7B,aAAa,EAAE,MAAM;aACrB,eAAe,EAAE,MAAM;aACvB,UAAU,CAAC,EAAE,MAAM;IAVrC;;;;;OAKG;gBAED,OAAO,EAAE,MAAM,EACC,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,EACvB,UAAU,CAAC,EAAE,MAAM,YAAA;CAMtC"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CrossTenantAccessError = void 0;
4
+ /**
5
+ * 한 tenant가 다른 tenant의 데이터에 접근을 시도했을 때 throw 되는 에러.
6
+ *
7
+ * 이 에러가 나면 그 자체로 보안 사고 신호입니다.
8
+ * 정상 흐름에서는 절대 발생하지 않아야 합니다 (Subscriber가 자동 WHERE를 주입하므로).
9
+ *
10
+ * 발생 가능 시나리오:
11
+ * - 어딘가에서 escape hatch(raw SQL, getManager 직접 사용)로 우회한 경우
12
+ * - Subscriber가 등록되지 않은 entity를 사용한 경우
13
+ * - 캐시 키 분리가 안 된 상태에서 다른 tenant 데이터가 응답된 경우
14
+ *
15
+ * 처리 권장:
16
+ * - 즉시 알림 (Slack, Sentry, PagerDuty 등)
17
+ * - 해당 요청 ID, 사용자, IP 함께 기록
18
+ * - 코드 리뷰로 우회 경로 점검
19
+ */
20
+ class CrossTenantAccessError extends Error {
21
+ /**
22
+ * @param message - 에러 메시지
23
+ * @param currentTenant - 현재 요청의 tenant ID
24
+ * @param attemptedTenant - 접근 시도한 데이터의 tenant ID
25
+ * @param entityName - 해당 entity 클래스 이름 (선택)
26
+ */
27
+ constructor(message, currentTenant, attemptedTenant, entityName) {
28
+ super(message);
29
+ this.currentTenant = currentTenant;
30
+ this.attemptedTenant = attemptedTenant;
31
+ this.entityName = entityName;
32
+ this.name = 'CrossTenantAccessError';
33
+ Object.setPrototypeOf(this, CrossTenantAccessError.prototype);
34
+ }
35
+ }
36
+ exports.CrossTenantAccessError = CrossTenantAccessError;
37
+ //# sourceMappingURL=cross-tenant-access.error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-tenant-access.error.js","sourceRoot":"","sources":["../../src/errors/cross-tenant-access.error.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;GAeG;AACH,MAAa,sBAAuB,SAAQ,KAAK;IAC/C;;;;;OAKG;IACH,YACE,OAAe,EACC,aAAqB,EACrB,eAAuB,EACvB,UAAmB;QAEnC,KAAK,CAAC,OAAO,CAAC,CAAC;QAJC,kBAAa,GAAb,aAAa,CAAQ;QACrB,oBAAe,GAAf,eAAe,CAAQ;QACvB,eAAU,GAAV,UAAU,CAAS;QAGnC,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,sBAAsB,CAAC,SAAS,CAAC,CAAC;IAChE,CAAC;CACF;AAjBD,wDAiBC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * 라이브러리가 throw할 수 있는 모든 에러 타입을 한 곳에서 export.
3
+ *
4
+ * 사용자는 catch 블록에서 instanceof로 분기할 수 있습니다:
5
+ * if (e instanceof CrossTenantAccessError) { ... }
6
+ */
7
+ export * from './missing-tenant-context.error';
8
+ export * from './cross-tenant-access.error';
9
+ export * from './invalid-tenant-source.error';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ /**
18
+ * 라이브러리가 throw할 수 있는 모든 에러 타입을 한 곳에서 export.
19
+ *
20
+ * 사용자는 catch 블록에서 instanceof로 분기할 수 있습니다:
21
+ * if (e instanceof CrossTenantAccessError) { ... }
22
+ */
23
+ __exportStar(require("./missing-tenant-context.error"), exports);
24
+ __exportStar(require("./cross-tenant-access.error"), exports);
25
+ __exportStar(require("./invalid-tenant-source.error"), exports);
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA;;;;;GAKG;AACH,iEAA+C;AAC/C,8DAA4C;AAC5C,gEAA8C"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * TenantShieldModule.forRoot() 설정이 잘못됐을 때 throw 되는 에러.
3
+ *
4
+ * 예시 케이스:
5
+ * - tenantSource: 'custom' 인데 customResolver가 없음
6
+ * - tenantSource: 'subdomain' 인데 subdomainPattern이 없음
7
+ * - strategy: 'schema' (v0.1에서는 미지원)
8
+ *
9
+ * 이 에러는 앱 부팅 단계(@Module 초기화)에서 발생해
10
+ * 잘못된 설정의 앱이 트래픽을 받기 전에 즉시 실패하도록 합니다.
11
+ */
12
+ export declare class InvalidTenantSourceError extends Error {
13
+ readonly source: string;
14
+ /**
15
+ * @param message - 사용자에게 어떤 설정이 잘못됐는지 알려주는 메시지
16
+ * @param source - 문제가 발생한 source 타입 (header/jwt/...)
17
+ */
18
+ constructor(message: string, source: string);
19
+ }
20
+ //# sourceMappingURL=invalid-tenant-source.error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invalid-tenant-source.error.d.ts","sourceRoot":"","sources":["../../src/errors/invalid-tenant-source.error.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;aAO/B,MAAM,EAAE,MAAM;IANhC;;;OAGG;gBAED,OAAO,EAAE,MAAM,EACC,MAAM,EAAE,MAAM;CAMjC"}
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InvalidTenantSourceError = void 0;
4
+ /**
5
+ * TenantShieldModule.forRoot() 설정이 잘못됐을 때 throw 되는 에러.
6
+ *
7
+ * 예시 케이스:
8
+ * - tenantSource: 'custom' 인데 customResolver가 없음
9
+ * - tenantSource: 'subdomain' 인데 subdomainPattern이 없음
10
+ * - strategy: 'schema' (v0.1에서는 미지원)
11
+ *
12
+ * 이 에러는 앱 부팅 단계(@Module 초기화)에서 발생해
13
+ * 잘못된 설정의 앱이 트래픽을 받기 전에 즉시 실패하도록 합니다.
14
+ */
15
+ class InvalidTenantSourceError extends Error {
16
+ /**
17
+ * @param message - 사용자에게 어떤 설정이 잘못됐는지 알려주는 메시지
18
+ * @param source - 문제가 발생한 source 타입 (header/jwt/...)
19
+ */
20
+ constructor(message, source) {
21
+ super(message);
22
+ this.source = source;
23
+ this.name = 'InvalidTenantSourceError';
24
+ Object.setPrototypeOf(this, InvalidTenantSourceError.prototype);
25
+ }
26
+ }
27
+ exports.InvalidTenantSourceError = InvalidTenantSourceError;
28
+ //# sourceMappingURL=invalid-tenant-source.error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invalid-tenant-source.error.js","sourceRoot":"","sources":["../../src/errors/invalid-tenant-source.error.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;GAUG;AACH,MAAa,wBAAyB,SAAQ,KAAK;IACjD;;;OAGG;IACH,YACE,OAAe,EACC,MAAc;QAE9B,KAAK,CAAC,OAAO,CAAC,CAAC;QAFC,WAAM,GAAN,MAAM,CAAQ;QAG9B,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;QACvC,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,wBAAwB,CAAC,SAAS,CAAC,CAAC;IAClE,CAAC;CACF;AAbD,4DAaC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Tenant 컨텍스트가 설정되지 않은 상태에서
3
+ * @RequireTenant()가 적용된 메서드를 호출했을 때 throw 되는 에러.
4
+ *
5
+ * 발생 원인:
6
+ * 1) 미들웨어가 동작하지 않은 경로 (정적 파일, public 라우트 등)
7
+ * 2) 백그라운드 작업에서 컨텍스트 전파 누락
8
+ * 3) 테스트 코드에서 runWithTenant() 누락
9
+ *
10
+ * 처리 권장:
11
+ * - NestJS Exception Filter에서 잡아 401 또는 500으로 응답
12
+ * - 로그에 source(어디서 추출 시도했는지) 기록해 디버깅 시간 단축
13
+ */
14
+ export declare class MissingTenantContextError extends Error {
15
+ readonly source: string;
16
+ /**
17
+ * @param message - 에러 메시지 (한국어/영어 자유)
18
+ * @param source - tenant 추출을 시도한 위치 (header/jwt/subdomain/custom)
19
+ */
20
+ constructor(message: string, source: string);
21
+ }
22
+ //# sourceMappingURL=missing-tenant-context.error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"missing-tenant-context.error.d.ts","sourceRoot":"","sources":["../../src/errors/missing-tenant-context.error.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;aAOhC,MAAM,EAAE,MAAM;IANhC;;;OAGG;gBAED,OAAO,EAAE,MAAM,EACC,MAAM,EAAE,MAAM;CASjC"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MissingTenantContextError = void 0;
4
+ /**
5
+ * Tenant 컨텍스트가 설정되지 않은 상태에서
6
+ * @RequireTenant()가 적용된 메서드를 호출했을 때 throw 되는 에러.
7
+ *
8
+ * 발생 원인:
9
+ * 1) 미들웨어가 동작하지 않은 경로 (정적 파일, public 라우트 등)
10
+ * 2) 백그라운드 작업에서 컨텍스트 전파 누락
11
+ * 3) 테스트 코드에서 runWithTenant() 누락
12
+ *
13
+ * 처리 권장:
14
+ * - NestJS Exception Filter에서 잡아 401 또는 500으로 응답
15
+ * - 로그에 source(어디서 추출 시도했는지) 기록해 디버깅 시간 단축
16
+ */
17
+ class MissingTenantContextError extends Error {
18
+ /**
19
+ * @param message - 에러 메시지 (한국어/영어 자유)
20
+ * @param source - tenant 추출을 시도한 위치 (header/jwt/subdomain/custom)
21
+ */
22
+ constructor(message, source) {
23
+ super(message);
24
+ this.source = source;
25
+ // V8 엔진(Node.js) 스택 트레이스에서 이 클래스 이름이 정확히 보이도록 설정.
26
+ // 이게 없으면 인스턴스 검사가 깨질 수 있고, 디버깅 시 스택이 어색하게 찍힘.
27
+ this.name = 'MissingTenantContextError';
28
+ Object.setPrototypeOf(this, MissingTenantContextError.prototype);
29
+ }
30
+ }
31
+ exports.MissingTenantContextError = MissingTenantContextError;
32
+ //# sourceMappingURL=missing-tenant-context.error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"missing-tenant-context.error.js","sourceRoot":"","sources":["../../src/errors/missing-tenant-context.error.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;GAYG;AACH,MAAa,yBAA0B,SAAQ,KAAK;IAClD;;;OAGG;IACH,YACE,OAAe,EACC,MAAc;QAE9B,KAAK,CAAC,OAAO,CAAC,CAAC;QAFC,WAAM,GAAN,MAAM,CAAQ;QAI9B,kDAAkD;QAClD,8CAA8C;QAC9C,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;QACxC,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC;IACnE,CAAC;CACF;AAhBD,8DAgBC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * ─────────────────────────────────────────────────────────────
3
+ * nestjs-tenant-shield의 public 진입점.
4
+ *
5
+ * 라이브러리 사용자는 항상 이 경로에서 import 합니다:
6
+ *
7
+ * import {
8
+ * TenantShieldModule,
9
+ * RequireTenant,
10
+ * SystemAction,
11
+ * Cacheable,
12
+ * getCurrentTenantId,
13
+ * runWithTenant,
14
+ * MissingTenantContextError,
15
+ * CrossTenantAccessError,
16
+ * } from 'nestjs-tenant-shield';
17
+ *
18
+ * 내부 구현 디테일(폴더 구조 등)은 사용자에게 노출하지 않습니다.
19
+ * 모든 외부 API는 여기서만 export 됨.
20
+ * ─────────────────────────────────────────────────────────────
21
+ */
22
+ export * from './tenant-shield.module';
23
+ export * from './decorators';
24
+ export * from './context';
25
+ export * from './middleware';
26
+ export { TenantShieldOptions, TenantShieldAsyncOptions, TenantSource, TenantStrategy, } from './interfaces/tenant-shield-options.interface';
27
+ export { RequireTenantOptions } from './interfaces/require-tenant-options.interface';
28
+ export { CacheableOptions } from './interfaces/cacheable-options.interface';
29
+ export { TenantContextOptions } from './interfaces/tenant-context-options.interface';
30
+ export { TenantContext as TenantContextState } from './interfaces/tenant-context.interface';
31
+ export * from './errors';
32
+ export * from './cache';
33
+ export * from './typeorm';
34
+ export * from './constants';
35
+ export * from './testing';
36
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,cAAc,wBAAwB,CAAC;AAGvC,cAAc,cAAc,CAAC;AAG7B,cAAc,WAAW,CAAC;AAG1B,cAAc,cAAc,CAAC;AAG7B,OAAO,EACN,mBAAmB,EACnB,wBAAwB,EACxB,YAAY,EACZ,cAAc,GACd,MAAM,8CAA8C,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,+CAA+C,CAAC;AACrF,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,+CAA+C,CAAC;AACrF,OAAO,EAAE,aAAa,IAAI,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAG5F,cAAc,UAAU,CAAC;AAGzB,cAAc,SAAS,CAAC;AAGxB,cAAc,WAAW,CAAC;AAG1B,cAAc,aAAa,CAAC;AAG5B,cAAc,WAAW,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ /**
3
+ * ─────────────────────────────────────────────────────────────
4
+ * nestjs-tenant-shield의 public 진입점.
5
+ *
6
+ * 라이브러리 사용자는 항상 이 경로에서 import 합니다:
7
+ *
8
+ * import {
9
+ * TenantShieldModule,
10
+ * RequireTenant,
11
+ * SystemAction,
12
+ * Cacheable,
13
+ * getCurrentTenantId,
14
+ * runWithTenant,
15
+ * MissingTenantContextError,
16
+ * CrossTenantAccessError,
17
+ * } from 'nestjs-tenant-shield';
18
+ *
19
+ * 내부 구현 디테일(폴더 구조 등)은 사용자에게 노출하지 않습니다.
20
+ * 모든 외부 API는 여기서만 export 됨.
21
+ * ─────────────────────────────────────────────────────────────
22
+ */
23
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
24
+ if (k2 === undefined) k2 = k;
25
+ var desc = Object.getOwnPropertyDescriptor(m, k);
26
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
27
+ desc = { enumerable: true, get: function() { return m[k]; } };
28
+ }
29
+ Object.defineProperty(o, k2, desc);
30
+ }) : (function(o, m, k, k2) {
31
+ if (k2 === undefined) k2 = k;
32
+ o[k2] = m[k];
33
+ }));
34
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
35
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
36
+ };
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ // 메인 모듈
39
+ __exportStar(require("./tenant-shield.module"), exports);
40
+ // 데코레이터
41
+ __exportStar(require("./decorators"), exports);
42
+ // 컨텍스트 헬퍼 (getCurrentTenantId, runWithTenant 등)
43
+ __exportStar(require("./context"), exports);
44
+ // 미들웨어 (사용자가 수동 설정하고 싶을 때 직접 가져갈 수 있게 노출)
45
+ __exportStar(require("./middleware"), exports);
46
+ // 에러
47
+ __exportStar(require("./errors"), exports);
48
+ // 캐시 (사용자가 커스텀 백엔드 구현 시 인터페이스 필요)
49
+ __exportStar(require("./cache"), exports);
50
+ // TypeORM 통합 (raw SQL 헬퍼 등)
51
+ __exportStar(require("./typeorm"), exports);
52
+ // 상수 (DI 토큰)
53
+ __exportStar(require("./constants"), exports);
54
+ // 테스트 헬퍼 (runWithTenant 등은 context에서도 export 되지만, expectCurrentTenant 등 테스트 전용 유틸 포함)
55
+ __exportStar(require("./testing"), exports);
56
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;;;;;;;;;;;;;;AAEH,QAAQ;AACR,yDAAuC;AAEvC,QAAQ;AACR,+CAA6B;AAE7B,gDAAgD;AAChD,4CAA0B;AAE1B,0CAA0C;AAC1C,+CAA6B;AAc7B,KAAK;AACL,2CAAyB;AAEzB,kCAAkC;AAClC,0CAAwB;AAExB,4BAA4B;AAC5B,4CAA0B;AAE1B,aAAa;AACb,8CAA4B;AAE5B,sFAAsF;AACtF,4CAA0B"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @Cacheable() 데코레이터에 넘기는 옵션.
3
+ *
4
+ * 메서드 결과를 캐시에 저장하고, 동일한 인자로 호출하면 캐시된 값을 즉시 반환.
5
+ * tenant 단위 캐시 분리는 이 라이브러리의 핵심 차별점.
6
+ */
7
+ export interface CacheableOptions {
8
+ /**
9
+ * 캐시 유효 시간 (초 단위). 필수.
10
+ *
11
+ * 예: 300 → 5분 동안 동일한 결과를 캐시에서 반환.
12
+ * TTL이 지나면 자동으로 메서드를 다시 실행하고 결과를 갱신.
13
+ */
14
+ ttl: number;
15
+ /**
16
+ * 캐시 키에 tenant ID prefix를 자동으로 붙일지 여부 (기본 false).
17
+ *
18
+ * true로 설정 시:
19
+ * 캐시 키 = `${tenantId}:${className}.${methodName}:${args}`
20
+ *
21
+ * → 동일한 메서드를 A학원과 B학원이 호출해도 캐시가 섞이지 않음.
22
+ *
23
+ * 멀티테넌시 환경에서는 거의 항상 true가 정답.
24
+ * false로 두는 경우는 전 tenant 공통 데이터(공지사항 등)일 때만.
25
+ */
26
+ tenantScoped?: boolean;
27
+ /**
28
+ * 커스텀 캐시 키 생성 함수.
29
+ *
30
+ * 미지정 시: 메서드 이름 + 인자 JSON 직렬화로 자동 생성.
31
+ *
32
+ * 인자가 복잡한 객체이거나 일부 필드만 키에 반영하고 싶을 때 사용.
33
+ * 예: keyGenerator: (args) => `student:${args[0].id}`
34
+ */
35
+ keyGenerator?: (args: unknown[]) => string;
36
+ }
37
+ //# sourceMappingURL=cacheable-options.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cacheable-options.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/cacheable-options.interface.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;;;;;;;;OAUG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,MAAM,CAAC;CAC5C"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=cacheable-options.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cacheable-options.interface.js","sourceRoot":"","sources":["../../src/interfaces/cacheable-options.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * interfaces 폴더의 모든 public 타입을 한 곳에서 re-export 하는 배럴 파일.
3
+ *
4
+ * 이렇게 해두면 라이브러리 외부에서:
5
+ * import { TenantShieldOptions } from 'nestjs-tenant-shield';
6
+ * 처럼 깔끔하게 import 할 수 있습니다.
7
+ */
8
+ export * from './tenant-shield-options.interface';
9
+ export * from './require-tenant-options.interface';
10
+ export * from './cacheable-options.interface';
11
+ export * from './tenant-context-options.interface';
12
+ export * from './tenant-context.interface';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/interfaces/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,cAAc,mCAAmC,CAAC;AAClD,cAAc,oCAAoC,CAAC;AACnD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,oCAAoC,CAAC;AAEnD,cAAc,4BAA4B,CAAC"}
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ /**
18
+ * interfaces 폴더의 모든 public 타입을 한 곳에서 re-export 하는 배럴 파일.
19
+ *
20
+ * 이렇게 해두면 라이브러리 외부에서:
21
+ * import { TenantShieldOptions } from 'nestjs-tenant-shield';
22
+ * 처럼 깔끔하게 import 할 수 있습니다.
23
+ */
24
+ __exportStar(require("./tenant-shield-options.interface"), exports);
25
+ __exportStar(require("./require-tenant-options.interface"), exports);
26
+ __exportStar(require("./cacheable-options.interface"), exports);
27
+ __exportStar(require("./tenant-context-options.interface"), exports);
28
+ // TenantContext는 데코레이터와 이름이 충돌하므로 public 진입점에서는 별칭으로 export.
29
+ __exportStar(require("./tenant-context.interface"), exports);
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/interfaces/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA;;;;;;GAMG;AACH,oEAAkD;AAClD,qEAAmD;AACnD,gEAA8C;AAC9C,qEAAmD;AACnD,6DAA6D;AAC7D,6DAA2C"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @RequireTenant() 데코레이터에 넘기는 옵션.
3
+ *
4
+ * 대부분의 경우 옵션 없이 그냥 @RequireTenant() 형태로 사용하면 됩니다.
5
+ * 옵션은 forRoot의 전역 설정을 메서드 단위로 오버라이드하고 싶을 때만 사용.
6
+ */
7
+ export interface RequireTenantOptions {
8
+ /**
9
+ * 이 메서드에 한해 tenant 없이 실행을 허용할지.
10
+ *
11
+ * forRoot.allowSystemActions와 무관하게 메서드별 허용 가능.
12
+ * 다만 권장하지 않음 — 가능하면 @SystemAction()을 사용하세요.
13
+ */
14
+ allowSystem?: boolean;
15
+ /**
16
+ * Strict mode 메서드별 오버라이드.
17
+ * 미지정 시 forRoot의 strictMode 따름.
18
+ *
19
+ * 예: 마이그레이션 중인 특정 메서드만 임시로 strict를 끄고 싶을 때.
20
+ */
21
+ strictMode?: boolean;
22
+ }
23
+ //# sourceMappingURL=require-tenant-options.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-tenant-options.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/require-tenant-options.interface.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=require-tenant-options.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-tenant-options.interface.js","sourceRoot":"","sources":["../../src/interfaces/require-tenant-options.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @TenantContext() 데코레이터 옵션 (v0.2 — 큐 통합).
3
+ *
4
+ * BullMQ/Bull 같은 백그라운드 큐 워커에서 job을 처리할 때,
5
+ * job payload에 들어있는 tenant ID로 AsyncLocalStorage 컨텍스트를
6
+ * 자동 설정해주는 데코레이터입니다.
7
+ */
8
+ export interface TenantContextOptions {
9
+ /**
10
+ * 큐 페이로드에서 tenant ID를 추출하는 함수.
11
+ *
12
+ * 미지정 시 기본값: job.data.tenantId
13
+ *
14
+ * payload 구조가 다르면 명시:
15
+ * extractFrom: (job) => job.data.organizationId
16
+ */
17
+ extractFrom?: (job: unknown) => string;
18
+ }
19
+ //# sourceMappingURL=tenant-context-options.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-context-options.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/tenant-context-options.interface.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC;CACxC"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=tenant-context-options.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-context-options.interface.js","sourceRoot":"","sources":["../../src/interfaces/tenant-context-options.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * AsyncLocalStorage에 저장되는 컨텍스트의 형태.
3
+ *
4
+ * 요청 하나당 하나의 TenantContext가 생성되고,
5
+ * 비동기 호출 체인 끝까지 동일한 인스턴스가 공유됩니다.
6
+ *
7
+ * 비유: 손님 한 명에게 발급되는 일회용 출입 카드.
8
+ * 어느 부서를 거치든 카드의 정보(어느 회사 손님인지)는 유지됨.
9
+ */
10
+ export interface TenantContext {
11
+ /**
12
+ * 현재 요청의 tenant ID.
13
+ * null이면 시스템 작업 또는 컨텍스트 미설정 상태.
14
+ */
15
+ tenantId: string | null;
16
+ /**
17
+ * 이 요청이 명시적으로 "시스템 작업"으로 표시됐는지.
18
+ *
19
+ * true: @SystemAction()이 적용된 경로 또는 runWithoutTenant()로 진입.
20
+ * tenantId가 null이어도 strict mode가 throw하지 않음.
21
+ *
22
+ * 일반 요청에서는 false 또는 undefined.
23
+ */
24
+ isSystemAction?: boolean;
25
+ }
26
+ //# sourceMappingURL=tenant-context.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-context.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/tenant-context.interface.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=tenant-context.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-context.interface.js","sourceRoot":"","sources":["../../src/interfaces/tenant-context.interface.ts"],"names":[],"mappings":""}