@lenne.tech/nest-server 11.34.1 → 11.35.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 (143) hide show
  1. package/.claude/rules/architecture.md +3 -1
  2. package/.claude/rules/configurable-features.md +3 -3
  3. package/.claude/rules/role-system.md +281 -0
  4. package/CLAUDE.md +11 -1
  5. package/FRAMEWORK-API.md +7 -3
  6. package/dist/core/common/decorators/nested-type.registry.d.ts +2 -0
  7. package/dist/core/common/decorators/nested-type.registry.js +17 -0
  8. package/dist/core/common/decorators/nested-type.registry.js.map +1 -0
  9. package/dist/core/common/decorators/restricted.decorator.d.ts +2 -1
  10. package/dist/core/common/decorators/restricted.decorator.js +52 -16
  11. package/dist/core/common/decorators/restricted.decorator.js.map +1 -1
  12. package/dist/core/common/decorators/restrictions-checked.marker.d.ts +4 -0
  13. package/dist/core/common/decorators/restrictions-checked.marker.js +30 -0
  14. package/dist/core/common/decorators/restrictions-checked.marker.js.map +1 -0
  15. package/dist/core/common/decorators/unified-field.decorator.d.ts +1 -1
  16. package/dist/core/common/decorators/unified-field.decorator.js +6 -3
  17. package/dist/core/common/decorators/unified-field.decorator.js.map +1 -1
  18. package/dist/core/common/enums/role.enum.d.ts +8 -0
  19. package/dist/core/common/enums/role.enum.js +28 -1
  20. package/dist/core/common/enums/role.enum.js.map +1 -1
  21. package/dist/core/common/helpers/execution-context-request.helper.d.ts +7 -0
  22. package/dist/core/common/helpers/execution-context-request.helper.js +31 -0
  23. package/dist/core/common/helpers/execution-context-request.helper.js.map +1 -0
  24. package/dist/core/common/helpers/graphql-ws-context.helper.d.ts +15 -0
  25. package/dist/core/common/helpers/graphql-ws-context.helper.js +96 -0
  26. package/dist/core/common/helpers/graphql-ws-context.helper.js.map +1 -0
  27. package/dist/core/common/helpers/gridfs.helper.js +1 -1
  28. package/dist/core/common/helpers/gridfs.helper.js.map +1 -1
  29. package/dist/core/common/interceptors/check-security.interceptor.js +2 -1
  30. package/dist/core/common/interceptors/check-security.interceptor.js.map +1 -1
  31. package/dist/core/common/interceptors/response-model.interceptor.js +3 -2
  32. package/dist/core/common/interceptors/response-model.interceptor.js.map +1 -1
  33. package/dist/core/common/interfaces/server-options.interface.d.ts +5 -0
  34. package/dist/core/common/plugins/mongoose-system-role.plugin.d.ts +1 -0
  35. package/dist/core/common/plugins/mongoose-system-role.plugin.js +106 -0
  36. package/dist/core/common/plugins/mongoose-system-role.plugin.js.map +1 -0
  37. package/dist/core/common/plugins/mongoose-tenant.plugin.js +134 -9
  38. package/dist/core/common/plugins/mongoose-tenant.plugin.js.map +1 -1
  39. package/dist/core/common/services/core-s3.service.js +4 -1
  40. package/dist/core/common/services/core-s3.service.js.map +1 -1
  41. package/dist/core/common/services/core-tenant-context.registry.d.ts +10 -0
  42. package/dist/core/common/services/core-tenant-context.registry.js +12 -0
  43. package/dist/core/common/services/core-tenant-context.registry.js.map +1 -0
  44. package/dist/core/modules/auth/guards/roles.guard.d.ts +1 -1
  45. package/dist/core/modules/auth/guards/roles.guard.js +2 -2
  46. package/dist/core/modules/auth/guards/roles.guard.js.map +1 -1
  47. package/dist/core/modules/better-auth/better-auth-roles.guard.js +2 -10
  48. package/dist/core/modules/better-auth/better-auth-roles.guard.js.map +1 -1
  49. package/dist/core/modules/file/core-file.service.d.ts +3 -1
  50. package/dist/core/modules/file/core-file.service.js +62 -7
  51. package/dist/core/modules/file/core-file.service.js.map +1 -1
  52. package/dist/core/modules/file/file-access.helper.d.ts +18 -0
  53. package/dist/core/modules/file/file-access.helper.js +46 -0
  54. package/dist/core/modules/file/file-access.helper.js.map +1 -0
  55. package/dist/core/modules/file/file-metadata.helper.js +1 -1
  56. package/dist/core/modules/file/file-metadata.helper.js.map +1 -1
  57. package/dist/core/modules/file/file-roles.config.d.ts +10 -0
  58. package/dist/core/modules/file/file-roles.config.js +78 -0
  59. package/dist/core/modules/file/file-roles.config.js.map +1 -0
  60. package/dist/core/modules/file/file-roles.helper.d.ts +2 -2
  61. package/dist/core/modules/file/file-roles.helper.js +8 -20
  62. package/dist/core/modules/file/file-roles.helper.js.map +1 -1
  63. package/dist/core/modules/tenant/core-role-scope.registry.d.ts +28 -0
  64. package/dist/core/modules/tenant/core-role-scope.registry.js +93 -0
  65. package/dist/core/modules/tenant/core-role-scope.registry.js.map +1 -0
  66. package/dist/core/modules/tenant/core-tenant.guard.d.ts +5 -0
  67. package/dist/core/modules/tenant/core-tenant.guard.js +37 -11
  68. package/dist/core/modules/tenant/core-tenant.guard.js.map +1 -1
  69. package/dist/core/modules/tenant/core-tenant.helpers.d.ts +9 -1
  70. package/dist/core/modules/tenant/core-tenant.helpers.js +65 -4
  71. package/dist/core/modules/tenant/core-tenant.helpers.js.map +1 -1
  72. package/dist/core/modules/tenant/core-tenant.module.js +5 -0
  73. package/dist/core/modules/tenant/core-tenant.module.js.map +1 -1
  74. package/dist/core/modules/tenant/core-tenant.service.d.ts +1 -0
  75. package/dist/core/modules/tenant/core-tenant.service.js +25 -0
  76. package/dist/core/modules/tenant/core-tenant.service.js.map +1 -1
  77. package/dist/core/modules/tus/core-tus.service.d.ts +2 -0
  78. package/dist/core/modules/tus/core-tus.service.js +34 -4
  79. package/dist/core/modules/tus/core-tus.service.js.map +1 -1
  80. package/dist/core/modules/tus/index.d.ts +1 -0
  81. package/dist/core/modules/tus/index.js +1 -0
  82. package/dist/core/modules/tus/index.js.map +1 -1
  83. package/dist/core/modules/tus/tus.constants.d.ts +1 -0
  84. package/dist/core/modules/tus/tus.constants.js +2 -1
  85. package/dist/core/modules/tus/tus.constants.js.map +1 -1
  86. package/dist/core/modules/user/core-user.service.js +5 -0
  87. package/dist/core/modules/user/core-user.service.js.map +1 -1
  88. package/dist/core/modules/user/inputs/core-user.input.js +8 -0
  89. package/dist/core/modules/user/inputs/core-user.input.js.map +1 -1
  90. package/dist/core.module.js +10 -0
  91. package/dist/core.module.js.map +1 -1
  92. package/dist/index.d.ts +3 -0
  93. package/dist/index.js +3 -0
  94. package/dist/index.js.map +1 -1
  95. package/dist/server/modules/file/file.service.js +4 -1
  96. package/dist/server/modules/file/file.service.js.map +1 -1
  97. package/dist/test/test.helper.d.ts +1 -0
  98. package/dist/test/test.helper.js +26 -6
  99. package/dist/test/test.helper.js.map +1 -1
  100. package/dist/tsconfig.build.tsbuildinfo +1 -1
  101. package/docs/REQUEST-LIFECYCLE.md +60 -1
  102. package/migration-guides/11.34.x-to-11.35.x.md +832 -0
  103. package/package.json +1 -1
  104. package/src/core/common/decorators/nested-type.registry.ts +42 -0
  105. package/src/core/common/decorators/restricted.decorator.ts +149 -21
  106. package/src/core/common/decorators/restrictions-checked.marker.ts +87 -0
  107. package/src/core/common/decorators/unified-field.decorator.ts +4 -3
  108. package/src/core/common/enums/role.enum.ts +116 -0
  109. package/src/core/common/helpers/execution-context-request.helper.ts +102 -0
  110. package/src/core/common/helpers/graphql-ws-context.helper.ts +192 -0
  111. package/src/core/common/helpers/gridfs.helper.ts +18 -2
  112. package/src/core/common/interceptors/check-security.interceptor.ts +4 -1
  113. package/src/core/common/interceptors/response-model.interceptor.ts +3 -2
  114. package/src/core/common/interfaces/server-options.interface.ts +139 -7
  115. package/src/core/common/plugins/mongoose-system-role.plugin.ts +193 -0
  116. package/src/core/common/plugins/mongoose-tenant.plugin.ts +244 -12
  117. package/src/core/common/services/core-s3.service.ts +9 -1
  118. package/src/core/common/services/core-tenant-context.registry.ts +50 -0
  119. package/src/core/modules/auth/guards/roles.guard.ts +7 -5
  120. package/src/core/modules/better-auth/better-auth-roles.guard.ts +7 -13
  121. package/src/core/modules/file/INTEGRATION-CHECKLIST.md +95 -1
  122. package/src/core/modules/file/README.md +61 -0
  123. package/src/core/modules/file/core-file.service.ts +166 -9
  124. package/src/core/modules/file/file-access.helper.ts +149 -0
  125. package/src/core/modules/file/file-metadata.helper.ts +13 -5
  126. package/src/core/modules/file/file-roles.config.ts +202 -0
  127. package/src/core/modules/file/file-roles.helper.ts +11 -40
  128. package/src/core/modules/tenant/README.md +20 -1
  129. package/src/core/modules/tenant/core-role-scope.registry.ts +195 -0
  130. package/src/core/modules/tenant/core-tenant.guard.ts +92 -12
  131. package/src/core/modules/tenant/core-tenant.helpers.ts +139 -7
  132. package/src/core/modules/tenant/core-tenant.module.ts +12 -0
  133. package/src/core/modules/tenant/core-tenant.service.ts +56 -0
  134. package/src/core/modules/tus/README.md +46 -7
  135. package/src/core/modules/tus/core-tus.service.ts +94 -5
  136. package/src/core/modules/tus/index.ts +1 -0
  137. package/src/core/modules/tus/tus.constants.ts +17 -1
  138. package/src/core/modules/user/core-user.service.ts +12 -0
  139. package/src/core/modules/user/inputs/core-user.input.ts +28 -2
  140. package/src/core.module.ts +62 -1
  141. package/src/index.ts +3 -0
  142. package/src/server/modules/file/file.service.ts +45 -2
  143. package/src/test/test.helper.ts +54 -11
@@ -92,6 +92,16 @@ export interface TestGraphQLOptions {
92
92
  */
93
93
  cookies?: Record<string, string> | string;
94
94
 
95
+ /**
96
+ * Additional `connectionParams` for a SUBSCRIPTION handshake.
97
+ *
98
+ * Merged on top of the `Authorization` entry derived from `token`. A WebSocket carries no HTTP
99
+ * headers per operation, so anything the server reads from a header on the HTTP path — the tenant
100
+ * header above all — has to travel here instead. Without this a tenant-scoped subscription could
101
+ * not be tested at all.
102
+ */
103
+ connectionParams?: Record<string, string>;
104
+
95
105
  /**
96
106
  * Count of subscription messages, specifies how many messages are to be received on subscription
97
107
  */
@@ -788,10 +798,13 @@ export class TestHelper {
788
798
  }
789
799
 
790
800
  // Prepare subscription
791
- let connectionParams;
801
+ let connectionParams: Record<string, string> | undefined;
792
802
  if (options?.token) {
793
803
  connectionParams = { Authorization: `Bearer ${options?.token}` };
794
804
  }
805
+ if (options?.connectionParams) {
806
+ connectionParams = { ...connectionParams, ...options.connectionParams };
807
+ }
795
808
 
796
809
  // Init client
797
810
  if (options.log) {
@@ -800,10 +813,27 @@ export class TestHelper {
800
813
  const client = createClient({ connectionParams, url: this.subscriptionUrl, webSocketImpl: ws });
801
814
  const messages: any[] = [];
802
815
  let unsubscribe: () => void;
816
+ let rejectSubscription: (reason: unknown) => void;
817
+
803
818
  const onNext = (message) => {
804
819
  if (options.log) {
805
820
  console.info('Subscription message', JSON.stringify(message, null, 2));
806
821
  }
822
+
823
+ // A REFUSED subscription arrives as a `next` message carrying `errors`, not through the
824
+ // transport's `error` callback: when a guard throws, graphql's `subscribe()` returns an
825
+ // ExecutionResult instead of an async iterable, and graphql-ws emits that as one payload
826
+ // followed by `complete`. Projecting only `data[name]` therefore turned "you may not subscribe
827
+ // to this" into an indistinguishable `undefined`/`null` message — so a test asserting that an
828
+ // unauthorized subscriber gets nothing passed just as well when the gate was wide open.
829
+ // Rejecting makes the refusal observable, which is what the caller actually experiences.
830
+ if (message?.errors?.length) {
831
+ const detail = message.errors.map((error: any) => error?.message ?? String(error)).join('; ');
832
+ rejectSubscription?.(new Error(`Subscription "${graphql.name}" failed: ${detail}`));
833
+ unsubscribe?.();
834
+ return;
835
+ }
836
+
807
837
  messages.push(message?.data?.[graphql.name]);
808
838
  if (messages.length <= options.countOfSubscriptionMessages) {
809
839
  unsubscribe();
@@ -811,16 +841,29 @@ export class TestHelper {
811
841
  };
812
842
 
813
843
  // Subscribe
814
- await new Promise((resolve, reject) => {
815
- unsubscribe = client.subscribe(
816
- { query },
817
- {
818
- complete: resolve as any,
819
- error: reject,
820
- next: onNext,
821
- },
822
- );
823
- });
844
+ //
845
+ // Disposed in `finally`, including on the refusal path: without it the client keeps its socket
846
+ // (and graphql-ws its reconnect timer) open past the end of the test, which surfaces later as a
847
+ // hanging process or as an error attributed to whichever test happened to run next.
848
+ try {
849
+ await new Promise((resolve, reject) => {
850
+ rejectSubscription = reject;
851
+ unsubscribe = client.subscribe(
852
+ { query },
853
+ {
854
+ complete: resolve as any,
855
+ error: reject,
856
+ next: onNext,
857
+ },
858
+ );
859
+ });
860
+ } finally {
861
+ try {
862
+ await client.dispose?.();
863
+ } catch {
864
+ // Already closing — nothing to clean up, and a teardown error must not mask the result.
865
+ }
866
+ }
824
867
 
825
868
  // Return subscribed messages
826
869
  return messages;