@antelopejs/interface-dms 0.7.4 → 0.9.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 (239) hide show
  1. package/CHANGELOG.md +176 -0
  2. package/dist/auth/index.d.ts +3 -3
  3. package/dist/auth/index.js +11 -9
  4. package/dist/auth/index.js.map +1 -1
  5. package/dist/auth/internal/jwt-auth-decorator.d.ts +20 -0
  6. package/dist/auth/internal/jwt-auth-decorator.js +51 -0
  7. package/dist/auth/internal/jwt-auth-decorator.js.map +1 -0
  8. package/dist/auth/internal/request-authenticators.d.ts +12 -0
  9. package/dist/auth/internal/request-authenticators.js +22 -0
  10. package/dist/auth/internal/request-authenticators.js.map +1 -1
  11. package/dist/base/activity-feed.d.ts +6 -6
  12. package/dist/base/block-registry/types.d.ts +16 -0
  13. package/dist/base/block-types.d.ts +1 -0
  14. package/dist/base/block-types.js +1 -0
  15. package/dist/base/block-types.js.map +1 -1
  16. package/dist/base/chart-card.d.ts +15 -0
  17. package/dist/base/chart-card.js +4 -0
  18. package/dist/base/chart-card.js.map +1 -1
  19. package/dist/base/chart-schemas.d.ts +26 -26
  20. package/dist/base/code-block.d.ts +3 -3
  21. package/dist/base/data-types/compare-types.js +19 -13
  22. package/dist/base/data-types/compare-types.js.map +1 -1
  23. package/dist/base/data-types/core.d.ts +11 -0
  24. package/dist/base/data-types/core.js +14 -1
  25. package/dist/base/data-types/core.js.map +1 -1
  26. package/dist/base/data-types/default-types.d.ts +112 -2
  27. package/dist/base/data-types/default-types.js +90 -19
  28. package/dist/base/data-types/default-types.js.map +1 -1
  29. package/dist/base/data-types/field-types.d.ts +10 -4
  30. package/dist/base/data-types/field-types.js +12 -2
  31. package/dist/base/data-types/field-types.js.map +1 -1
  32. package/dist/base/data-types/internal/compare-types.d.ts +3 -0
  33. package/dist/base/data-types/internal/compare-types.js +7 -0
  34. package/dist/base/data-types/internal/compare-types.js.map +1 -1
  35. package/dist/base/empty-state.d.ts +4 -4
  36. package/dist/base/form-block-schema.d.ts +59 -3
  37. package/dist/base/form-block-schema.js +12 -2
  38. package/dist/base/form-block-schema.js.map +1 -1
  39. package/dist/base/form-schema.d.ts +57 -5
  40. package/dist/base/form-schema.js +22 -0
  41. package/dist/base/form-schema.js.map +1 -1
  42. package/dist/base/form-types.d.ts +82 -13
  43. package/dist/base/form-types.js +12 -4
  44. package/dist/base/form-types.js.map +1 -1
  45. package/dist/base/guard.d.ts +6 -6
  46. package/dist/base/helpers/archive-mode-helpers.js +6 -2
  47. package/dist/base/helpers/archive-mode-helpers.js.map +1 -1
  48. package/dist/base/index.d.ts +1 -0
  49. package/dist/base/index.js +1 -0
  50. package/dist/base/index.js.map +1 -1
  51. package/dist/base/internal/form-schema.js +5 -0
  52. package/dist/base/internal/form-schema.js.map +1 -1
  53. package/dist/base/internal/layouts.d.ts +15 -3
  54. package/dist/base/key-value-list.d.ts +12 -9
  55. package/dist/base/key-value-list.js +1 -1
  56. package/dist/base/key-value-list.js.map +1 -1
  57. package/dist/base/kpi-card.d.ts +39 -5
  58. package/dist/base/kpi-card.js +18 -6
  59. package/dist/base/kpi-card.js.map +1 -1
  60. package/dist/base/layouts.d.ts +24 -1
  61. package/dist/base/layouts.js.map +1 -1
  62. package/dist/base/live-toggle.d.ts +11 -0
  63. package/dist/base/live-toggle.js +8 -1
  64. package/dist/base/live-toggle.js.map +1 -1
  65. package/dist/base/page-toolbar.d.ts +158 -0
  66. package/dist/base/page-toolbar.js +198 -0
  67. package/dist/base/page-toolbar.js.map +1 -0
  68. package/dist/base/period-selector.d.ts +9 -2
  69. package/dist/base/period-selector.js.map +1 -1
  70. package/dist/base/placeholder.d.ts +2 -2
  71. package/dist/base/section.d.ts +2 -2
  72. package/dist/base/stack.d.ts +2 -2
  73. package/dist/base/stat-group.d.ts +18 -6
  74. package/dist/base/stat-group.js +9 -0
  75. package/dist/base/stat-group.js.map +1 -1
  76. package/dist/base/table-view/column-display.d.ts +9 -5
  77. package/dist/base/table-view/column-display.js +1 -1
  78. package/dist/base/table-view/column-display.js.map +1 -1
  79. package/dist/base/table-view/data-functions.d.ts +26 -7
  80. package/dist/base/table-view/data-functions.js +10 -6
  81. package/dist/base/table-view/data-functions.js.map +1 -1
  82. package/dist/base/table-view/factory.js +24 -13
  83. package/dist/base/table-view/factory.js.map +1 -1
  84. package/dist/base/table-view/internal/auth.d.ts +2 -0
  85. package/dist/base/table-view/internal/auth.js +3 -1
  86. package/dist/base/table-view/internal/auth.js.map +1 -1
  87. package/dist/base/table-view/internal/column-conditions.d.ts +15 -0
  88. package/dist/base/table-view/internal/column-conditions.js +94 -0
  89. package/dist/base/table-view/internal/column-conditions.js.map +1 -0
  90. package/dist/base/table-view/internal/factory-helpers.d.ts +5 -0
  91. package/dist/base/table-view/internal/factory-helpers.js +55 -11
  92. package/dist/base/table-view/internal/factory-helpers.js.map +1 -1
  93. package/dist/base/table-view/internal/guards.js +19 -2
  94. package/dist/base/table-view/internal/guards.js.map +1 -1
  95. package/dist/base/table-view/internal/realtime.js +17 -0
  96. package/dist/base/table-view/internal/realtime.js.map +1 -1
  97. package/dist/base/table-view/internal/resource-form.js +1 -0
  98. package/dist/base/table-view/internal/resource-form.js.map +1 -1
  99. package/dist/base/table-view/internal/row-actions-schema.d.ts +296 -0
  100. package/dist/base/table-view/internal/row-actions-schema.js +62 -0
  101. package/dist/base/table-view/internal/row-actions-schema.js.map +1 -0
  102. package/dist/base/table-view/internal/validation.d.ts +22 -3
  103. package/dist/base/table-view/internal/validation.js +92 -2
  104. package/dist/base/table-view/internal/validation.js.map +1 -1
  105. package/dist/base/table-view/meta.d.ts +25 -1
  106. package/dist/base/table-view/meta.js +36 -4
  107. package/dist/base/table-view/meta.js.map +1 -1
  108. package/dist/base/table-view/options.d.ts +92 -16
  109. package/dist/base/table-view/options.js.map +1 -1
  110. package/dist/base/table-view/realtime.d.ts +8 -0
  111. package/dist/base/table-view/realtime.js.map +1 -1
  112. package/dist/base/table-view/routes.js +8 -4
  113. package/dist/base/table-view/routes.js.map +1 -1
  114. package/dist/base/table-view/schema.d.ts +36 -30
  115. package/dist/base/table-view/schema.js +11 -57
  116. package/dist/base/table-view/schema.js.map +1 -1
  117. package/dist/base/table-view/source.d.ts +1 -1
  118. package/dist/base/table-view/source.js +4 -1
  119. package/dist/base/table-view/source.js.map +1 -1
  120. package/dist/base/table-view.d.ts +2 -2
  121. package/dist/base/table-view.js.map +1 -1
  122. package/dist/base/top-list-card.d.ts +5 -5
  123. package/dist/base/types/action-target.d.ts +77 -20
  124. package/dist/base/types/confirm-dialog.d.ts +5 -1
  125. package/dist/base/types/custom-button.d.ts +5 -3
  126. package/dist/base/types/field-config.d.ts +4 -4
  127. package/dist/base/types/guards.d.ts +10 -0
  128. package/dist/base/types/row-action.d.ts +6 -1
  129. package/dist/base/types/size.d.ts +3 -1
  130. package/dist/client-ip.d.ts +6 -2
  131. package/dist/client-ip.js +4 -2
  132. package/dist/client-ip.js.map +1 -1
  133. package/dist/component.d.ts +14 -0
  134. package/dist/component.js.map +1 -1
  135. package/dist/data-controllers/members.d.ts +0 -3
  136. package/dist/data-controllers/members.js +30 -8
  137. package/dist/data-controllers/members.js.map +1 -1
  138. package/dist/db/internal/tenantLifecycle.model.js +5 -2
  139. package/dist/db/internal/tenantLifecycle.model.js.map +1 -1
  140. package/dist/guards.js +2 -3
  141. package/dist/guards.js.map +1 -1
  142. package/dist/hooks.d.ts +54 -10
  143. package/dist/hooks.js +12 -4
  144. package/dist/hooks.js.map +1 -1
  145. package/dist/index.d.ts +3 -3
  146. package/dist/index.js +3 -2
  147. package/dist/index.js.map +1 -1
  148. package/dist/internal/invite-membership.d.ts +9 -0
  149. package/dist/internal/invite-membership.js +25 -7
  150. package/dist/internal/invite-membership.js.map +1 -1
  151. package/dist/internal/member-changes.d.ts +24 -0
  152. package/dist/internal/member-changes.js +66 -0
  153. package/dist/internal/member-changes.js.map +1 -0
  154. package/dist/internal/tenant-ownership.d.ts +4 -1
  155. package/dist/internal/tenant-ownership.js +4 -10
  156. package/dist/internal/tenant-ownership.js.map +1 -1
  157. package/dist/invite-extensions/internal/form-slot.js +1 -1
  158. package/dist/invite-extensions/internal/form-slot.js.map +1 -1
  159. package/dist/invite-extensions.d.ts +0 -9
  160. package/dist/invite-extensions.js +1 -36
  161. package/dist/invite-extensions.js.map +1 -1
  162. package/dist/invite-resolution.js +6 -2
  163. package/dist/invite-resolution.js.map +1 -1
  164. package/dist/invites.js +36 -22
  165. package/dist/invites.js.map +1 -1
  166. package/dist/layout-banners.d.ts +40 -4
  167. package/dist/layout-banners.js +25 -3
  168. package/dist/layout-banners.js.map +1 -1
  169. package/dist/notifications/internal.d.ts +2 -2
  170. package/dist/notifications/internal.js.map +1 -1
  171. package/dist/notifications/sendable.d.ts +3 -2
  172. package/dist/notifications/sendable.js +2 -1
  173. package/dist/notifications/sendable.js.map +1 -1
  174. package/dist/notifications/types.d.ts +9 -0
  175. package/dist/page/controllers.d.ts +44 -0
  176. package/dist/page/controllers.js +14 -1
  177. package/dist/page/controllers.js.map +1 -1
  178. package/dist/page/internal/layout-filter.d.ts +10 -4
  179. package/dist/page/internal/layout-filter.js +27 -14
  180. package/dist/page/internal/layout-filter.js.map +1 -1
  181. package/dist/page/internal/metadata-helpers.d.ts +7 -0
  182. package/dist/page/internal/metadata-helpers.js +13 -2
  183. package/dist/page/internal/metadata-helpers.js.map +1 -1
  184. package/dist/page/internal/page-record.d.ts +34 -0
  185. package/dist/page/internal/page-record.js +87 -0
  186. package/dist/page/internal/page-record.js.map +1 -0
  187. package/dist/page/internal/page-registration.d.ts +2 -0
  188. package/dist/page/internal/page-registration.js.map +1 -1
  189. package/dist/page/layout-filter.js +31 -10
  190. package/dist/page/layout-filter.js.map +1 -1
  191. package/dist/page/metadata.js +36 -26
  192. package/dist/page/metadata.js.map +1 -1
  193. package/dist/page/types.d.ts +39 -4
  194. package/dist/page/types.js.map +1 -1
  195. package/dist/page.d.ts +1 -1
  196. package/dist/page.js +2 -1
  197. package/dist/page.js.map +1 -1
  198. package/dist/permissions-resolver.d.ts +26 -3
  199. package/dist/permissions-resolver.js +2 -1
  200. package/dist/permissions-resolver.js.map +1 -1
  201. package/dist/permissions.d.ts +7 -3
  202. package/dist/permissions.js +8 -6
  203. package/dist/permissions.js.map +1 -1
  204. package/dist/realtime.d.ts +24 -1
  205. package/dist/realtime.js +7 -1
  206. package/dist/realtime.js.map +1 -1
  207. package/dist/request-tenant.d.ts +17 -13
  208. package/dist/request-tenant.js +54 -42
  209. package/dist/request-tenant.js.map +1 -1
  210. package/dist/tenant-members.d.ts +26 -0
  211. package/dist/tenant-members.js +29 -0
  212. package/dist/tenant-members.js.map +1 -0
  213. package/dist/tenant-ownership.d.ts +4 -1
  214. package/dist/tenant-ownership.js +12 -17
  215. package/dist/tenant-ownership.js.map +1 -1
  216. package/dist/tenant-provisioning.d.ts +15 -0
  217. package/dist/tenant-provisioning.js +27 -0
  218. package/dist/tenant-provisioning.js.map +1 -0
  219. package/dist/tenant-scoped-model.d.ts +2 -1
  220. package/dist/tenant-scoped-model.js +4 -3
  221. package/dist/tenant-scoped-model.js.map +1 -1
  222. package/docs/1.core/10.layout-banners.md +57 -2
  223. package/docs/1.core/2.pages-and-modules.md +20 -11
  224. package/docs/1.core/4.permissions.md +34 -1
  225. package/docs/1.core/5.tenancy.md +37 -6
  226. package/docs/1.core/7.hooks.md +24 -4
  227. package/docs/1.core/8.realtime.md +24 -3
  228. package/docs/2.auth/2.authentication.md +3 -3
  229. package/docs/3.base/1.introduction.md +1 -0
  230. package/docs/3.base/10.display-blocks.md +20 -2
  231. package/docs/3.base/2.types.md +7 -5
  232. package/docs/3.base/3.forms.md +28 -8
  233. package/docs/3.base/4.tables.md +27 -9
  234. package/docs/3.base/5.charts-and-widgets.md +8 -4
  235. package/docs/3.base/6.layout.md +47 -1
  236. package/docs/3.base/8.data-types.md +16 -9
  237. package/docs/4.notifications/3.sending.md +4 -3
  238. package/docs/5.html-render/1.introduction.md +5 -7
  239. package/package.json +7 -11
@@ -1,5 +1,27 @@
1
1
  import { RegisteringProxy } from "@antelopejs/interface-core";
2
- export type PermissionsResolverFn = (userId: string, tenantId: string, currentPermissions: Set<string>) => Promise<Set<string>> | Set<string>;
2
+ /**
3
+ * A role preview a resolver call computes the set for (Settings › Roles ›
4
+ * Preview as role), instead of a real member's.
5
+ */
6
+ export interface PermissionsResolverPreview {
7
+ /** The previewed role's permissions, before any resolver reshaped them. */
8
+ rolePermissions: ReadonlySet<string>;
9
+ }
10
+ /** What a resolver call is for, besides the user and the tenant. */
11
+ export interface PermissionsResolverContext {
12
+ /**
13
+ * Set when the call previews a role. `userId` is then the viewer's, but the
14
+ * set is the previewed role's: a resolver keyed on the user (an owner
15
+ * handed more, a screen kept for owners) must shape it as for an ordinary
16
+ * member holding only that role, never from the viewer's own standing.
17
+ */
18
+ preview?: PermissionsResolverPreview;
19
+ }
20
+ /**
21
+ * Reshape a user's permission set for a tenant. `context` says what the set is
22
+ * computed for: always passed, `{}` for a real member.
23
+ */
24
+ export type PermissionsResolverFn = (userId: string, tenantId: string, currentPermissions: Set<string>, context: PermissionsResolverContext) => Promise<Set<string>> | Set<string>;
3
25
  export interface PermissionsResolverInfo {
4
26
  id: string;
5
27
  resolver: PermissionsResolverFn;
@@ -31,6 +53,7 @@ export declare function RegisterPermissionsResolver(info: PermissionsResolverInf
31
53
  /**
32
54
  * Run the registered resolvers over a base permission set and return the
33
55
  * effective set. Prefer `GetEffectiveUserPermissions` from `dms/permissions`,
34
- * which composes the base set computation with this pipeline.
56
+ * which composes the base set computation with this pipeline. `context` is
57
+ * handed to every resolver as is.
35
58
  */
36
- export declare const ApplyPermissionsResolvers: (userId: string, tenantId: string, basePermissions: Set<string>) => Promise<Set<string>>;
59
+ export declare const ApplyPermissionsResolvers: (userId: string, tenantId: string, basePermissions: Set<string>, context: PermissionsResolverContext) => Promise<Set<string>>;
@@ -32,7 +32,8 @@ function RegisterPermissionsResolver(info) {
32
32
  /**
33
33
  * Run the registered resolvers over a base permission set and return the
34
34
  * effective set. Prefer `GetEffectiveUserPermissions` from `dms/permissions`,
35
- * which composes the base set computation with this pipeline.
35
+ * which composes the base set computation with this pipeline. `context` is
36
+ * handed to every resolver as is.
36
37
  */
37
38
  exports.ApplyPermissionsResolvers = (0, interface_core_1.InterfaceFunction)();
38
39
  //# sourceMappingURL=permissions-resolver.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"permissions-resolver.js","sourceRoot":"","sources":["../src/permissions-resolver.ts"],"names":[],"mappings":";;;AA0CA,kEAIC;AA9CD,+DAGoC;AAcpC,gBAAgB;AAChB,IAAiB,QAAQ,CAIxB;AAJD,WAAiB,QAAQ;IACV,oCAA2B,GAAG,IAAI,iCAAgB,EAE5D,CAAC;AACN,CAAC,EAJgB,QAAQ,wBAAR,QAAQ,QAIxB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAgB,2BAA2B,CACzC,IAA6B;IAE7B,QAAQ,CAAC,2BAA2B,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACtD,CAAC;AAED;;;;GAIG;AACU,QAAA,yBAAyB,GACpC,IAAA,kCAAiB,GAMd,CAAC"}
1
+ {"version":3,"file":"permissions-resolver.js","sourceRoot":"","sources":["../src/permissions-resolver.ts"],"names":[],"mappings":";;;AAmEA,kEAIC;AAvED,+DAGoC;AAuCpC,gBAAgB;AAChB,IAAiB,QAAQ,CAIxB;AAJD,WAAiB,QAAQ;IACV,oCAA2B,GAAG,IAAI,iCAAgB,EAE5D,CAAC;AACN,CAAC,EAJgB,QAAQ,wBAAR,QAAQ,QAIxB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAgB,2BAA2B,CACzC,IAA6B;IAE7B,QAAQ,CAAC,2BAA2B,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACtD,CAAC;AAED;;;;;GAKG;AACU,QAAA,yBAAyB,GACpC,IAAA,kCAAiB,GAOd,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { RegisteringProxy } from "@antelopejs/interface-core";
2
2
  import type { RoleModel } from "./db";
3
+ import { type PermissionsResolverContext } from "./permissions-resolver";
3
4
  export interface Permission {
4
5
  id: string;
5
6
  title: string;
@@ -54,17 +55,20 @@ export declare function GetUserPermissions(user: {
54
55
  * (`ApplyPermissionsResolvers`): the dms module wires it in `construct()`.
55
56
  * In standalone contexts (unit tests, thin consumers) connect it manually
56
57
  * with `ImplementInterface`, otherwise the call queues until wired.
58
+ *
59
+ * `context` is handed to the resolvers: `{}` for the user's own set, `preview`
60
+ * when the set is a role previewed by that user.
57
61
  */
58
62
  export declare function GetEffectiveUserPermissions(user: {
59
63
  _id: string;
60
64
  owner?: boolean;
61
- }, tenantId: string, roleIds: string[], roleModel: RoleModel): Promise<Set<string>>;
65
+ }, tenantId: string, roleIds: string[], roleModel: RoleModel, context?: PermissionsResolverContext): Promise<Set<string>>;
62
66
  /**
63
67
  * Whether `permissions` grants `permissionId`: on the `*` wildcard, on a
64
68
  * `defaultGranted` permission, or on a direct grant whose ancestors (the ids
65
69
  * it sits under) and `dependencies` are held too — a table's delete action
66
- * grants nothing without its table and its page, its edit nothing without
67
- * the view that loads the row.
70
+ * grants nothing without its table, its page and its list, its edit nothing
71
+ * without the view that loads the row.
68
72
  */
69
73
  export declare function HasPermission(permissions: Set<string>, permissionId: string): Promise<boolean>;
70
74
  /** Whether `permissions` grants at least one of `permissionIds`. */
@@ -76,17 +76,20 @@ async function GetUserPermissions(user, roleIds, roleModel) {
76
76
  * (`ApplyPermissionsResolvers`): the dms module wires it in `construct()`.
77
77
  * In standalone contexts (unit tests, thin consumers) connect it manually
78
78
  * with `ImplementInterface`, otherwise the call queues until wired.
79
+ *
80
+ * `context` is handed to the resolvers: `{}` for the user's own set, `preview`
81
+ * when the set is a role previewed by that user.
79
82
  */
80
- async function GetEffectiveUserPermissions(user, tenantId, roleIds, roleModel) {
83
+ async function GetEffectiveUserPermissions(user, tenantId, roleIds, roleModel, context = {}) {
81
84
  const basePermissions = await GetUserPermissions(user, roleIds, roleModel);
82
- return (0, permissions_resolver_1.ApplyPermissionsResolvers)(user._id, tenantId, basePermissions);
85
+ return (0, permissions_resolver_1.ApplyPermissionsResolvers)(user._id, tenantId, basePermissions, context);
83
86
  }
84
87
  /**
85
88
  * Whether `permissions` grants `permissionId`: on the `*` wildcard, on a
86
89
  * `defaultGranted` permission, or on a direct grant whose ancestors (the ids
87
90
  * it sits under) and `dependencies` are held too — a table's delete action
88
- * grants nothing without its table and its page, its edit nothing without
89
- * the view that loads the row.
91
+ * grants nothing without its table, its page and its list, its edit nothing
92
+ * without the view that loads the row.
90
93
  */
91
94
  async function HasPermission(permissions, permissionId) {
92
95
  return grantsPermission(permissions, permissionId, new Set());
@@ -111,8 +114,7 @@ async function grantsPermission(permissions, permissionId, checked) {
111
114
  return ((await holdsAncestors(permissions, permissionId)) &&
112
115
  holdsDependencies(permissions, permission, checked));
113
116
  }
114
- // The role routes store a grant with every id it sits under, but a role saved
115
- // before they did, or a set a resolver reshaped, may lack some. An ancestor
117
+ // The role routes store a grant with every id it sits under. An ancestor
116
118
  // counts as held when granted, `defaultGranted`, or not a registered
117
119
  // permission at all (a page declaring `permission: { id: "mailing.access" }`
118
120
  // has no `mailing` above it).
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":";;;AAuDA,gEAEC;AAED,oEAEC;AAED,4DAIC;AAaD,gDAaC;AAcD,kEAQC;AASD,sCAKC;AA4DD,4CAQC;AArMD,+DAGoC;AAEpC,8DAAkE;AAClE,iEAAmE;AAoBnE;;GAEG;AACH,IAAiB,QAAQ,CAIxB;AAJD,WAAiB,QAAQ;IACV,2BAAkB,GAAG,IAAI,iCAAgB,EAEnD,CAAC;AACN,CAAC,EAJgB,QAAQ,wBAAR,QAAQ,QAIxB;AAEM,MAAM,kBAAkB,GAAG,CAAC,EAAU,EAAE,UAAsB,EAAE,EAAE;IACvE,QAAQ,CAAC,kBAAkB,CAAC,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;AACvD,CAAC,CAAC;AAFW,QAAA,kBAAkB,sBAE7B;AAEF;;;GAGG;AACI,MAAM,oBAAoB,GAAG,CAAC,EAAU,EAAE,EAAE;IACjD,QAAQ,CAAC,kBAAkB,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;AAC7C,CAAC,CAAC;AAFW,QAAA,oBAAoB,wBAE/B;AAEF,0EAA0E;AAC1E,8EAA8E;AAC9E,8EAA8E;AAC9E,0EAA0E;AAC1E,2EAA2E;AAC3E,sCAAsC;AACtC,MAAM,yBAAyB,GAAG,IAAI,GAAG,EAAU,CAAC;AAEpD,SAAgB,0BAA0B,CAAC,EAAU;IACnD,yBAAyB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AACpC,CAAC;AAED,SAAgB,4BAA4B,CAAC,EAAU;IACrD,yBAAyB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AACvC,CAAC;AAED,SAAgB,wBAAwB,CAAC,EAAU;IACjD,OAAO,CAAC,EAAE,EAAE,GAAG,IAAA,sCAAqB,EAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAC3D,yBAAyB,CAAC,GAAG,CAAC,SAAS,CAAC,CACzC,CAAC;AACJ,CAAC;AACY,QAAA,aAAa,GACxB,IAAA,kCAAiB,GAA0C,CAAC;AACjD,QAAA,cAAc,GACzB,IAAA,kCAAiB,GAAwC,CAAC;AAE5D;;;;;;GAMG;AACI,KAAK,UAAU,kBAAkB,CACtC,IAAyB,EACzB,OAAiB,EACjB,SAAoB;IAEpB,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,OAAO,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,GAAG,EAAE,CAAC;IACnB,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,OAAO,CAAC,CAAC;IACvD,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAU,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;;;;;;GAWG;AACI,KAAK,UAAU,2BAA2B,CAC/C,IAAsC,EACtC,QAAgB,EAChB,OAAiB,EACjB,SAAoB;IAEpB,MAAM,eAAe,GAAG,MAAM,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IAC3E,OAAO,IAAA,gDAAyB,EAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;AACxE,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,aAAa,CACjC,WAAwB,EACxB,YAAoB;IAEpB,OAAO,gBAAgB,CAAC,WAAW,EAAE,YAAY,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;AAChE,CAAC;AAED,0EAA0E;AAC1E,gEAAgE;AAChE,KAAK,UAAU,gBAAgB,CAC7B,WAAwB,EACxB,YAAoB,EACpB,OAAoB;IAEpB,IAAI,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,2EAA2E;IAC3E,uEAAuE;IACvE,2EAA2E;IAC3E,yEAAyE;IACzE,IAAI,wBAAwB,CAAC,YAAY,CAAC;QAAE,OAAO,KAAK,CAAC;IACzD,MAAM,UAAU,GAAG,MAAM,IAAA,qBAAa,EAAC,YAAY,CAAC,CAAC;IACrD,IAAI,UAAU,EAAE,cAAc;QAAE,OAAO,IAAI,CAAC;IAC5C,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC;QAAE,OAAO,KAAK,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAC1B,OAAO,CACL,CAAC,MAAM,cAAc,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;QACjD,iBAAiB,CAAC,WAAW,EAAE,UAAU,EAAE,OAAO,CAAC,CACpD,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,4EAA4E;AAC5E,qEAAqE;AACrE,6EAA6E;AAC7E,8BAA8B;AAC9B,KAAK,UAAU,cAAc,CAC3B,WAAwB,EACxB,YAAoB;IAEpB,KAAK,MAAM,UAAU,IAAI,IAAA,sCAAqB,EAAC,YAAY,CAAC,EAAE,CAAC;QAC7D,IAAI,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC;YAAE,SAAS;QAC1C,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAa,EAAC,UAAU,CAAC,CAAC;QACjD,IAAI,QAAQ,IAAI,CAAC,QAAQ,CAAC,cAAc;YAAE,OAAO,KAAK,CAAC;IACzD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,2EAA2E;AAC3E,yEAAyE;AACzE,KAAK,UAAU,iBAAiB,CAC9B,WAAwB,EACxB,UAAkC,EAClC,OAAoB;IAEpB,KAAK,MAAM,YAAY,IAAI,UAAU,EAAE,YAAY,IAAI,EAAE,EAAE,CAAC;QAC1D,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;YAAE,SAAS;QACxC,IAAI,CAAC,CAAC,MAAM,IAAA,qBAAa,EAAC,YAAY,CAAC,CAAC;YAAE,SAAS;QACnD,IAAI,CAAC,CAAC,MAAM,gBAAgB,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;YAClE,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,oEAAoE;AAC7D,KAAK,UAAU,gBAAgB,CACpC,WAAwB,EACxB,aAAuB;IAEvB,KAAK,MAAM,YAAY,IAAI,aAAa,EAAE,CAAC;QACzC,IAAI,MAAM,aAAa,CAAC,WAAW,EAAE,YAAY,CAAC;YAAE,OAAO,IAAI,CAAC;IAClE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,17 @@ import { RegisteringProxy } from "@antelopejs/interface-core";
2
2
  export interface PublishMessageOptions {
3
3
  payload?: Record<string, unknown>;
4
4
  actorId?: string;
5
+ /**
6
+ * The tenant (workspace) the message is about. A message published with it
7
+ * reaches only the page sessions of that tenant; without it, the message is
8
+ * global and reaches every session subscribed to the topic, whatever their
9
+ * tenant.
10
+ *
11
+ * Pass it whenever the topic carries one workspace's data — a row changed, a
12
+ * send finished, a run completed — so the other workspaces' pages neither
13
+ * refetch nor count the message as missed.
14
+ */
15
+ tenantId?: string;
5
16
  }
6
17
  /** One message delivered to a {@link SubscribeMessage} handler. */
7
18
  export interface RealtimeMessage {
@@ -9,6 +20,12 @@ export interface RealtimeMessage {
9
20
  type: string;
10
21
  payload?: Record<string, unknown>;
11
22
  actorId?: string;
23
+ /**
24
+ * The tenant the message was published for, absent on a global message. A
25
+ * {@link SubscribeMessage} handler receives the messages of every tenant
26
+ * and filters on this field itself when it serves one.
27
+ */
28
+ tenantId?: string;
12
29
  ts: number;
13
30
  }
14
31
  export type RealtimeMessageHandler = (message: RealtimeMessage) => void;
@@ -29,9 +46,15 @@ export declare namespace internal {
29
46
  * module is unloaded, and it outlives a reload of the DMS module.
30
47
  */
31
48
  export declare const RegisterPageTopic: (pageId: string, topic: string) => void;
49
+ /**
50
+ * Publish a message on `topic`. The page sessions bound to the topic refetch
51
+ * on it; with `options.tenantId` only those of that tenant do, without it the
52
+ * message is global.
53
+ */
32
54
  export declare const PublishMessage: (topic: string, type: string, options?: PublishMessageOptions | undefined) => Promise<void>;
33
55
  /**
34
- * Receive every message published on `topic`, whichever instance published it:
56
+ * Receive every message published on `topic`, whichever instance published it
57
+ * and whichever tenant it names (see {@link RealtimeMessage.tenantId}):
35
58
  * the subscription rides the same broker as {@link PublishMessage}, so what one
36
59
  * instance publishes reaches the subscribers of every other.
37
60
  *
package/dist/realtime.js CHANGED
@@ -29,9 +29,15 @@ const RegisterPageTopic = (pageId, topic) => {
29
29
  internal.RegisterPageTopic.register(pageTopicId(pageId, topic), pageId, topic);
30
30
  };
31
31
  exports.RegisterPageTopic = RegisterPageTopic;
32
+ /**
33
+ * Publish a message on `topic`. The page sessions bound to the topic refetch
34
+ * on it; with `options.tenantId` only those of that tenant do, without it the
35
+ * message is global.
36
+ */
32
37
  exports.PublishMessage = (0, interface_core_1.InterfaceFunction)();
33
38
  /**
34
- * Receive every message published on `topic`, whichever instance published it:
39
+ * Receive every message published on `topic`, whichever instance published it
40
+ * and whichever tenant it names (see {@link RealtimeMessage.tenantId}):
35
41
  * the subscription rides the same broker as {@link PublishMessage}, so what one
36
42
  * instance publishes reaches the subscribers of every other.
37
43
  *
@@ -1 +1 @@
1
- {"version":3,"file":"realtime.js","sourceRoot":"","sources":["../src/realtime.ts"],"names":[],"mappings":";;;AAsFA,4CAOC;AA7FD,6CAAyC;AACzC,+DAGoC;AAqBpC;;GAEG;AACH,IAAiB,QAAQ,CAQxB;AARD,WAAiB,QAAQ;IACV,0BAAiB,GAAG,IAAI,iCAAgB,EAElD,CAAC;IAES,yBAAgB,GAAG,IAAI,iCAAgB,EAEjD,CAAC;AACN,CAAC,EARgB,QAAQ,wBAAR,QAAQ,QAQxB;AAED,+EAA+E;AAC/E,2EAA2E;AAC3E,0CAA0C;AAC1C,SAAS,WAAW,CAAC,MAAc,EAAE,KAAa;IAChD,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;GAMG;AACI,MAAM,iBAAiB,GAAG,CAAC,MAAc,EAAE,KAAa,EAAQ,EAAE;IACvE,QAAQ,CAAC,iBAAiB,CAAC,QAAQ,CACjC,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,EAC1B,MAAM,EACN,KAAK,CACN,CAAC;AACJ,CAAC,CAAC;AANW,QAAA,iBAAiB,qBAM5B;AAEW,QAAA,cAAc,GACzB,IAAA,kCAAiB,GAMd,CAAC;AAEN;;;;;;;;;;;;;;;;GAgBG;AACH,SAAgB,gBAAgB,CAC9B,KAAa,EACb,OAA+B;IAE/B,MAAM,EAAE,GAAG,IAAA,wBAAU,GAAE,CAAC;IACxB,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IACvD,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;AACxD,CAAC"}
1
+ {"version":3,"file":"realtime.js","sourceRoot":"","sources":["../src/realtime.ts"],"names":[],"mappings":";;;AA6GA,4CAOC;AApHD,6CAAyC;AACzC,+DAGoC;AAsCpC;;GAEG;AACH,IAAiB,QAAQ,CAQxB;AARD,WAAiB,QAAQ;IACV,0BAAiB,GAAG,IAAI,iCAAgB,EAElD,CAAC;IAES,yBAAgB,GAAG,IAAI,iCAAgB,EAEjD,CAAC;AACN,CAAC,EARgB,QAAQ,wBAAR,QAAQ,QAQxB;AAED,+EAA+E;AAC/E,2EAA2E;AAC3E,0CAA0C;AAC1C,SAAS,WAAW,CAAC,MAAc,EAAE,KAAa;IAChD,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;GAMG;AACI,MAAM,iBAAiB,GAAG,CAAC,MAAc,EAAE,KAAa,EAAQ,EAAE;IACvE,QAAQ,CAAC,iBAAiB,CAAC,QAAQ,CACjC,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,EAC1B,MAAM,EACN,KAAK,CACN,CAAC;AACJ,CAAC,CAAC;AANW,QAAA,iBAAiB,qBAM5B;AAEF;;;;GAIG;AACU,QAAA,cAAc,GACzB,IAAA,kCAAiB,GAMd,CAAC;AAEN;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAgB,gBAAgB,CAC9B,KAAa,EACb,OAA+B;IAE/B,MAAM,EAAE,GAAG,IAAA,wBAAU,GAAE,CAAC;IACxB,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IACvD,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;AACxD,CAAC"}
@@ -1,19 +1,23 @@
1
1
  import type { RequestContext } from "@antelopejs/interface-api";
2
2
  /**
3
- * Prefer the tenant bound by authenticateRequestPrincipal or the tenant guards.
4
- * An authentication failure or changed credential makes this accessor throw.
5
- * Without a bound principal, preserve legacy JWT decoding / DEFAULT_TENANT_ID.
3
+ * The tenant of the request's verified credential: the one bound by the DMS
4
+ * auth decorators (`AuthUser`, `AuthUserWithPermission`, `IfAuthUser` with a
5
+ * valid token…), the tenant guards or `authenticateRequestPrincipal`.
6
+ * Without a verified credential, `DEFAULT_TENANT_ID`: a token is never read
7
+ * for its tenant before its signature, user and session are checked.
6
8
  *
7
- * The legacy value is only *decoded*: this function does NOT verify the
8
- * JWT signature. It is safe when the request has already been authenticated
9
- * upstream (auth decorators such as `@AuthUser`, `@AuthTenantMember`, or the
10
- * gating performed by `PageController`) — those validators verify the signature
11
- * before this function runs, so the decoded `tenantId` is authentic.
9
+ * Call it once the route's auth decorator has run (in the handler). A
10
+ * parameter or property provider resolved alongside the auth decorator uses
11
+ * {@link resolveRequestTenantId} instead.
12
12
  *
13
- * For routes that legitimately accept anonymous traffic (e.g. `@IfAuthUser`),
14
- * the fallback resolves to `DEFAULT_TENANT_ID` so public layouts can be served.
15
- *
16
- * Do NOT introduce new routes that rely on `tenantId` for authorization without
17
- * upstream auth verification — without signature checks, the claim is forgeable.
13
+ * @throws HTTPResult 401 when the request's authentication failed or its
14
+ * credential changed since
18
15
  */
19
16
  export declare function getRequestTenantId(ctx: RequestContext): string;
17
+ /**
18
+ * {@link getRequestTenantId} for a provider that may run before the route's
19
+ * auth decorator (`TenantScopedModel`, a tenant-scoped `Model`): a bearer
20
+ * token not yet verified is verified here, and its tenant bound to the
21
+ * request. An invalid token reads as anonymous: `DEFAULT_TENANT_ID`.
22
+ */
23
+ export declare function resolveRequestTenantId(ctx: RequestContext): Promise<string>;
@@ -1,58 +1,70 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getRequestTenantId = getRequestTenantId;
4
- const jsonwebtoken_1 = require("jsonwebtoken");
4
+ exports.resolveRequestTenantId = resolveRequestTenantId;
5
+ const auth_1 = require("./auth");
5
6
  const request_authenticators_1 = require("./auth/internal/request-authenticators");
6
7
  const constants_1 = require("./constants");
7
- const BEARER_PREFIX = "Bearer ";
8
- function extractBearerToken(authHeader) {
9
- if (typeof authHeader !== "string")
10
- return undefined;
11
- if (!authHeader.startsWith(BEARER_PREFIX))
12
- return undefined;
13
- return authHeader.slice(BEARER_PREFIX.length);
8
+ const BEARER_SCHEME = /^Bearer\s+(\S+)$/i;
9
+ const pendingResolutions = new WeakMap();
10
+ /**
11
+ * The tenant of the request's verified credential: the one bound by the DMS
12
+ * auth decorators (`AuthUser`, `AuthUserWithPermission`, `IfAuthUser` with a
13
+ * valid token…), the tenant guards or `authenticateRequestPrincipal`.
14
+ * Without a verified credential, `DEFAULT_TENANT_ID`: a token is never read
15
+ * for its tenant before its signature, user and session are checked.
16
+ *
17
+ * Call it once the route's auth decorator has run (in the handler). A
18
+ * parameter or property provider resolved alongside the auth decorator uses
19
+ * {@link resolveRequestTenantId} instead.
20
+ *
21
+ * @throws HTTPResult 401 when the request's authentication failed or its
22
+ * credential changed since
23
+ */
24
+ function getRequestTenantId(ctx) {
25
+ return (0, request_authenticators_1.getAuthenticatedRequestTenantId)(ctx) ?? constants_1.DEFAULT_TENANT_ID;
14
26
  }
15
- function readTenantIdFromToken(token) {
27
+ async function verifyRequestTenantId(ctx, token) {
16
28
  try {
17
- const payload = (0, jsonwebtoken_1.decode)(token);
18
- if (payload &&
19
- typeof payload.tenantId === "string" &&
20
- payload.tenantId.length > 0) {
21
- return payload.tenantId;
22
- }
29
+ const data = await auth_1.internal.IfAuthUserAuthenticator(token);
30
+ if (!data)
31
+ return constants_1.DEFAULT_TENANT_ID;
32
+ const user = await auth_1.internal.AuthRawUserValidator(data);
33
+ if (!user || typeof user === "boolean")
34
+ return constants_1.DEFAULT_TENANT_ID;
35
+ const tenantId = data.tenantId || constants_1.DEFAULT_TENANT_ID;
36
+ (0, request_authenticators_1.bindVerifiedRequestPrincipal)(ctx, { userId: user._id, tenantId });
37
+ return tenantId;
23
38
  }
24
39
  catch {
25
- return undefined;
40
+ return constants_1.DEFAULT_TENANT_ID;
26
41
  }
27
- return undefined;
28
42
  }
29
43
  /**
30
- * Prefer the tenant bound by authenticateRequestPrincipal or the tenant guards.
31
- * An authentication failure or changed credential makes this accessor throw.
32
- * Without a bound principal, preserve legacy JWT decoding / DEFAULT_TENANT_ID.
33
- *
34
- * The legacy value is only *decoded*: this function does NOT verify the
35
- * JWT signature. It is safe when the request has already been authenticated
36
- * upstream (auth decorators such as `@AuthUser`, `@AuthTenantMember`, or the
37
- * gating performed by `PageController`) — those validators verify the signature
38
- * before this function runs, so the decoded `tenantId` is authentic.
39
- *
40
- * For routes that legitimately accept anonymous traffic (e.g. `@IfAuthUser`),
41
- * the fallback resolves to `DEFAULT_TENANT_ID` so public layouts can be served.
42
- *
43
- * Do NOT introduce new routes that rely on `tenantId` for authorization without
44
- * upstream auth verification — without signature checks, the claim is forgeable.
44
+ * {@link getRequestTenantId} for a provider that may run before the route's
45
+ * auth decorator (`TenantScopedModel`, a tenant-scoped `Model`): a bearer
46
+ * token not yet verified is verified here, and its tenant bound to the
47
+ * request. An invalid token reads as anonymous: `DEFAULT_TENANT_ID`.
45
48
  */
46
- function getRequestTenantId(ctx) {
47
- const authenticatedTenantId = (0, request_authenticators_1.getAuthenticatedRequestTenantId)(ctx);
48
- if (authenticatedTenantId)
49
- return authenticatedTenantId;
50
- const token = extractBearerToken(ctx.rawRequest?.headers?.authorization);
51
- if (token) {
52
- const tenantIdFromJwt = readTenantIdFromToken(token);
53
- if (tenantIdFromJwt)
54
- return tenantIdFromJwt;
49
+ async function resolveRequestTenantId(ctx) {
50
+ const bound = (0, request_authenticators_1.getAuthenticatedRequestTenantId)(ctx);
51
+ if (bound)
52
+ return bound;
53
+ const header = ctx.rawRequest?.headers?.authorization;
54
+ const token = typeof header === "string" ? header.match(BEARER_SCHEME)?.[1] : undefined;
55
+ if (!token)
56
+ return constants_1.DEFAULT_TENANT_ID;
57
+ const request = ctx.rawRequest;
58
+ const pending = pendingResolutions.get(request);
59
+ if (pending)
60
+ return pending;
61
+ const resolution = verifyRequestTenantId(ctx, token);
62
+ pendingResolutions.set(request, resolution);
63
+ try {
64
+ return await resolution;
65
+ }
66
+ finally {
67
+ pendingResolutions.delete(request);
55
68
  }
56
- return constants_1.DEFAULT_TENANT_ID;
57
69
  }
58
70
  //# sourceMappingURL=request-tenant.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"request-tenant.js","sourceRoot":"","sources":["../src/request-tenant.ts"],"names":[],"mappings":";;AAkDA,gDASC;AA1DD,+CAAsC;AACtC,mFAAyF;AACzF,2CAAgD;AAEhD,MAAM,aAAa,GAAG,SAAS,CAAC;AAMhC,SAAS,kBAAkB,CAAC,UAAmB;IAC7C,IAAI,OAAO,UAAU,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IACrD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,aAAa,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5D,OAAO,UAAU,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAa;IAC1C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAA,qBAAM,EAAC,KAAK,CAAgC,CAAC;QAC7D,IACE,OAAO;YACP,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ;YACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAC3B,CAAC;YACD,OAAO,OAAO,CAAC,QAAQ,CAAC;QAC1B,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,SAAgB,kBAAkB,CAAC,GAAmB;IACpD,MAAM,qBAAqB,GAAG,IAAA,wDAA+B,EAAC,GAAG,CAAC,CAAC;IACnE,IAAI,qBAAqB;QAAE,OAAO,qBAAqB,CAAC;IACxD,MAAM,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;IACzE,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,eAAe,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACrD,IAAI,eAAe;YAAE,OAAO,eAAe,CAAC;IAC9C,CAAC;IACD,OAAO,6BAAiB,CAAC;AAC3B,CAAC"}
1
+ {"version":3,"file":"request-tenant.js","sourceRoot":"","sources":["../src/request-tenant.ts"],"names":[],"mappings":";;AA2BA,gDAEC;AAyBD,wDAmBC;AAvED,iCAAkC;AAClC,mFAGgD;AAChD,2CAAgD;AAEhD,MAAM,aAAa,GAAG,mBAAmB,CAAC;AAE1C,MAAM,kBAAkB,GAAG,IAAI,OAAO,EAAoC,CAAC;AAE3E;;;;;;;;;;;;;GAaG;AACH,SAAgB,kBAAkB,CAAC,GAAmB;IACpD,OAAO,IAAA,wDAA+B,EAAC,GAAG,CAAC,IAAI,6BAAiB,CAAC;AACnE,CAAC;AAED,KAAK,UAAU,qBAAqB,CAClC,GAAmB,EACnB,KAAa;IAEb,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,eAAQ,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC;QAC3D,IAAI,CAAC,IAAI;YAAE,OAAO,6BAAiB,CAAC;QACpC,MAAM,IAAI,GAAG,MAAM,eAAQ,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,SAAS;YAAE,OAAO,6BAAiB,CAAC;QACjE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,6BAAiB,CAAC;QACpD,IAAA,qDAA4B,EAAC,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QAClE,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,6BAAiB,CAAC;IAC3B,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,sBAAsB,CAC1C,GAAmB;IAEnB,MAAM,KAAK,GAAG,IAAA,wDAA+B,EAAC,GAAG,CAAC,CAAC;IACnD,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IACxB,MAAM,MAAM,GAAG,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,aAAa,CAAC;IACtD,MAAM,KAAK,GACT,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5E,IAAI,CAAC,KAAK;QAAE,OAAO,6BAAiB,CAAC;IACrC,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU,CAAC;IAC/B,MAAM,OAAO,GAAG,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAChD,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAC5B,MAAM,UAAU,GAAG,qBAAqB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACrD,kBAAkB,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC5C,IAAI,CAAC;QACH,OAAO,MAAM,UAAU,CAAC;IAC1B,CAAC;YAAS,CAAC;QACT,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;AACH,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { type MemberChange } from "./hooks";
2
+ /** What one membership or invitation write changes, and the write itself. */
3
+ export interface TenantMembersWrite<T> {
4
+ /**
5
+ * Announced through `Hook.MEMBER_BEING_CHANGED`, in order, before `write`
6
+ * runs. Empty for a write that changes no membership, such as an invitation
7
+ * created, edited or retired.
8
+ */
9
+ changes: MemberChange[];
10
+ write: () => Promise<T>;
11
+ }
12
+ /**
13
+ * The one entry point for writing tenant members and invitations: every
14
+ * insert, update or delete of a `TenantMemberModel` or `UserInviteModel` row
15
+ * goes through it. It admits the write under the tenant's lifecycle (refused
16
+ * while a barrier is held or once the tenant is closed), calls `plan` to read
17
+ * the current state and describe the change, fires `Hook.MEMBER_BEING_CHANGED`
18
+ * for each change (a throwing handler refuses the write, replays included),
19
+ * then runs the write and releases the admission.
20
+ *
21
+ * `plan` runs inside the admission so the change it describes is read from
22
+ * state no paused initiator is validating. Never call this from inside
23
+ * another `changeTenantMembers` or `runTenantLifecycleOperation` callback:
24
+ * each call takes its own admission.
25
+ */
26
+ export declare function changeTenantMembers<T>(tenantId: string, plan: () => Promise<TenantMembersWrite<T>>): Promise<T>;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.changeTenantMembers = changeTenantMembers;
4
+ const hooks_1 = require("./hooks");
5
+ const tenant_lifecycle_1 = require("./tenant-lifecycle");
6
+ /**
7
+ * The one entry point for writing tenant members and invitations: every
8
+ * insert, update or delete of a `TenantMemberModel` or `UserInviteModel` row
9
+ * goes through it. It admits the write under the tenant's lifecycle (refused
10
+ * while a barrier is held or once the tenant is closed), calls `plan` to read
11
+ * the current state and describe the change, fires `Hook.MEMBER_BEING_CHANGED`
12
+ * for each change (a throwing handler refuses the write, replays included),
13
+ * then runs the write and releases the admission.
14
+ *
15
+ * `plan` runs inside the admission so the change it describes is read from
16
+ * state no paused initiator is validating. Never call this from inside
17
+ * another `changeTenantMembers` or `runTenantLifecycleOperation` callback:
18
+ * each call takes its own admission.
19
+ */
20
+ async function changeTenantMembers(tenantId, plan) {
21
+ return (0, tenant_lifecycle_1.runTenantLifecycleOperation)(tenantId, async () => {
22
+ const { changes, write } = await plan();
23
+ for (const change of changes) {
24
+ await (0, hooks_1.ExecuteHooks)(hooks_1.Hook.MEMBER_BEING_CHANGED, { tenantId, ...change });
25
+ }
26
+ return write();
27
+ });
28
+ }
29
+ //# sourceMappingURL=tenant-members.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-members.js","sourceRoot":"","sources":["../src/tenant-members.ts"],"names":[],"mappings":";;AA4BA,kDAWC;AAvCD,mCAAgE;AAChE,yDAAiE;AAajE;;;;;;;;;;;;;GAaG;AACI,KAAK,UAAU,mBAAmB,CACvC,QAAgB,EAChB,IAA0C;IAE1C,OAAO,IAAA,8CAA2B,EAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QACxC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,IAAA,oBAAY,EAAC,YAAI,CAAC,oBAAoB,EAAE,EAAE,QAAQ,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;QACzE,CAAC;QACD,OAAO,KAAK,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -6,7 +6,10 @@ export interface TenantMembershipPatch {
6
6
  /** Durable invite delivery; grants membership without replacing later edits. */
7
7
  deliveryId?: string;
8
8
  }
9
- /** Admits membership writes before a tenant can begin destructive deletion. */
9
+ /**
10
+ * Adds the user to the tenant, or sets the roles and ownership of an existing
11
+ * member, through `changeTenantMembers`.
12
+ */
10
13
  export declare function applyTenantOwnership(userModel: UserModel, userId: string, tenantId: string, patch: TenantMembershipPatch): Promise<void>;
11
14
  export declare function syncPlatformOwnerOnTenantOwnerChange(userModel: UserModel, userId: string, tenantId: string, nextIsTenantOwner: boolean): Promise<void>;
12
15
  export declare function clearPlatformOwnerOnMemberRemoval(userModel: UserModel, userId: string, tenantId: string, removedMemberWasTenantOwner: boolean): Promise<void>;
@@ -5,25 +5,20 @@ exports.syncPlatformOwnerOnTenantOwnerChange = syncPlatformOwnerOnTenantOwnerCha
5
5
  exports.clearPlatformOwnerOnMemberRemoval = clearPlatformOwnerOnMemberRemoval;
6
6
  const interface_database_decorators_1 = require("@antelopejs/interface-database-decorators");
7
7
  const tenantMembers_model_1 = require("./db/models/tenantMembers.model");
8
- const hooks_1 = require("./hooks");
9
- const tenant_lifecycle_1 = require("./tenant-lifecycle");
8
+ const tenant_members_1 = require("./tenant-members");
9
+ const member_changes_1 = require("./internal/member-changes");
10
10
  const tenant_ownership_1 = require("./internal/tenant-ownership");
11
- /** Admits membership writes before a tenant can begin destructive deletion. */
11
+ /**
12
+ * Adds the user to the tenant, or sets the roles and ownership of an existing
13
+ * member, through `changeTenantMembers`.
14
+ */
12
15
  async function applyTenantOwnership(userModel, userId, tenantId, patch) {
13
- await (0, tenant_lifecycle_1.runTenantLifecycleOperation)(tenantId, async () => {
14
- // Public callers supplying a delivery identity still need the policy veto.
15
- // Internal resolution checks it before persisting its applying phase.
16
- if (patch.deliveryId &&
17
- !(await (0, interface_database_decorators_1.GetModel)(tenantMembers_model_1.TenantMemberModel, tenantId).getByUser(userId))) {
18
- await (0, hooks_1.ExecuteHooks)(hooks_1.Hook.MEMBER_BEING_CHANGED, {
19
- tenantId,
20
- userId,
21
- isTenantOwner: patch.isTenantOwner,
22
- previousIsTenantOwner: null,
23
- deliveryId: patch.deliveryId,
24
- });
25
- }
26
- await (0, tenant_ownership_1.applyAdmittedTenantOwnership)(userModel, userId, tenantId, patch);
16
+ await (0, tenant_members_1.changeTenantMembers)(tenantId, async () => {
17
+ const existing = await (0, interface_database_decorators_1.GetModel)(tenantMembers_model_1.TenantMemberModel, tenantId).getByUser(userId);
18
+ return {
19
+ changes: (0, member_changes_1.describeMembershipPatch)(existing, userId, patch),
20
+ write: () => (0, tenant_ownership_1.applyAdmittedTenantOwnership)(userModel, userId, tenantId, patch),
21
+ };
27
22
  });
28
23
  }
29
24
  async function syncPlatformOwnerOnTenantOwnerChange(userModel, userId, tenantId, nextIsTenantOwner) {
@@ -1 +1 @@
1
- {"version":3,"file":"tenant-ownership.js","sourceRoot":"","sources":["../src/tenant-ownership.ts"],"names":[],"mappings":";;AAmBA,oDAuBC;AAED,oFAOC;AAED,8EAQC;AA5DD,6FAAqE;AACrE,yEAAoE;AACpE,mCAA6C;AAC7C,yDAAiE;AACjE,kEAGqC;AAUrC,+EAA+E;AACxE,KAAK,UAAU,oBAAoB,CACxC,SAAoB,EACpB,MAAc,EACd,QAAgB,EAChB,KAA4B;IAE5B,MAAM,IAAA,8CAA2B,EAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QACrD,2EAA2E;QAC3E,sEAAsE;QACtE,IACE,KAAK,CAAC,UAAU;YAChB,CAAC,CAAC,MAAM,IAAA,wCAAQ,EAAC,uCAAiB,EAAE,QAAQ,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAChE,CAAC;YACD,MAAM,IAAA,oBAAY,EAAC,YAAI,CAAC,oBAAoB,EAAE;gBAC5C,QAAQ;gBACR,MAAM;gBACN,aAAa,EAAE,KAAK,CAAC,aAAa;gBAClC,qBAAqB,EAAE,IAAI;gBAC3B,UAAU,EAAE,KAAK,CAAC,UAAU;aAC7B,CAAC,CAAC;QACL,CAAC;QACD,MAAM,IAAA,+CAA4B,EAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;AACL,CAAC;AAEM,KAAK,UAAU,oCAAoC,CACxD,SAAoB,EACpB,MAAc,EACd,QAAgB,EAChB,iBAA0B;IAE1B,MAAM,IAAA,sCAAmB,EAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC;AAC5E,CAAC;AAEM,KAAK,UAAU,iCAAiC,CACrD,SAAoB,EACpB,MAAc,EACd,QAAgB,EAChB,2BAAoC;IAEpC,IAAI,CAAC,2BAA2B;QAAE,OAAO;IACzC,MAAM,IAAA,sCAAmB,EAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;AAChE,CAAC"}
1
+ {"version":3,"file":"tenant-ownership.js","sourceRoot":"","sources":["../src/tenant-ownership.ts"],"names":[],"mappings":";;AAsBA,oDAgBC;AAED,oFAOC;AAED,8EAQC;AAxDD,6FAAqE;AACrE,yEAAoE;AACpE,qDAAuD;AACvD,8DAAoE;AACpE,kEAGqC;AAUrC;;;GAGG;AACI,KAAK,UAAU,oBAAoB,CACxC,SAAoB,EACpB,MAAc,EACd,QAAgB,EAChB,KAA4B;IAE5B,MAAM,IAAA,oCAAmB,EAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QAC7C,MAAM,QAAQ,GAAG,MAAM,IAAA,wCAAQ,EAAC,uCAAiB,EAAE,QAAQ,CAAC,CAAC,SAAS,CACpE,MAAM,CACP,CAAC;QACF,OAAO;YACL,OAAO,EAAE,IAAA,wCAAuB,EAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC;YACzD,KAAK,EAAE,GAAG,EAAE,CACV,IAAA,+CAA4B,EAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC;SACnE,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAEM,KAAK,UAAU,oCAAoC,CACxD,SAAoB,EACpB,MAAc,EACd,QAAgB,EAChB,iBAA0B;IAE1B,MAAM,IAAA,sCAAmB,EAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC;AAC5E,CAAC;AAEM,KAAK,UAAU,iCAAiC,CACrD,SAAoB,EACpB,MAAc,EACd,QAAgB,EAChB,2BAAoC;IAEpC,IAAI,CAAC,2BAA2B;QAAE,OAAO;IACzC,MAAM,IAAA,sCAAmB,EAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;AAChE,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { type TenantProvisioningHookPayload } from "./hooks";
2
+ /**
3
+ * Provision a tenant whose row was just created: register it as an instance
4
+ * of the tenant schema, then run the `Hook.TENANT_BEING_PROVISIONED`
5
+ * handlers in series. The instance is registered first, here rather than by a
6
+ * handler, so no handler ever runs before it, whatever order the modules
7
+ * registered in.
8
+ *
9
+ * Call it once per tenant, at its creation, and fire the hook through it
10
+ * only. A handler that throws rejects the call, and the caller unwinds the
11
+ * tenant it was creating.
12
+ *
13
+ * @param payload Tenant being provisioned and what the caller carries along
14
+ */
15
+ export declare function ProvisionTenant(payload: TenantProvisioningHookPayload): Promise<void>;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProvisionTenant = ProvisionTenant;
4
+ const node_assert_1 = require("node:assert");
5
+ const interface_database_1 = require("@antelopejs/interface-database");
6
+ const constants_1 = require("./constants");
7
+ const hooks_1 = require("./hooks");
8
+ /**
9
+ * Provision a tenant whose row was just created: register it as an instance
10
+ * of the tenant schema, then run the `Hook.TENANT_BEING_PROVISIONED`
11
+ * handlers in series. The instance is registered first, here rather than by a
12
+ * handler, so no handler ever runs before it, whatever order the modules
13
+ * registered in.
14
+ *
15
+ * Call it once per tenant, at its creation, and fire the hook through it
16
+ * only. A handler that throws rejects the call, and the caller unwinds the
17
+ * tenant it was creating.
18
+ *
19
+ * @param payload Tenant being provisioned and what the caller carries along
20
+ */
21
+ async function ProvisionTenant(payload) {
22
+ const schema = interface_database_1.Schema.get(constants_1.TENANT_SCHEMA_NAME);
23
+ (0, node_assert_1.strict)(schema, `Schema '${constants_1.TENANT_SCHEMA_NAME}' is not registered`);
24
+ await schema.createInstance(payload.tenantId);
25
+ await (0, hooks_1.ExecuteHooks)(hooks_1.Hook.TENANT_BEING_PROVISIONED, payload);
26
+ }
27
+ //# sourceMappingURL=tenant-provisioning.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-provisioning.js","sourceRoot":"","sources":["../src/tenant-provisioning.ts"],"names":[],"mappings":";;AAsBA,0CAOC;AA7BD,6CAA+C;AAC/C,uEAAwD;AACxD,2CAAiD;AACjD,mCAIiB;AAEjB;;;;;;;;;;;;GAYG;AACI,KAAK,UAAU,eAAe,CACnC,OAAsC;IAEtC,MAAM,MAAM,GAAG,2BAAM,CAAC,GAAG,CAAC,8BAAkB,CAAC,CAAC;IAC9C,IAAA,oBAAM,EAAC,MAAM,EAAE,WAAW,8BAAkB,qBAAqB,CAAC,CAAC;IACnE,MAAM,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,IAAA,oBAAY,EAAC,YAAI,CAAC,wBAAwB,EAAE,OAAO,CAAC,CAAC;AAC7D,CAAC"}
@@ -2,7 +2,8 @@ import { type Class } from "@antelopejs/interface-core/decorators";
2
2
  import { type DataModel } from "@antelopejs/interface-database-decorators";
3
3
  /**
4
4
  * Parameter/property decorator that injects `GetModel(cl, currentTenantId)`,
5
- * where `currentTenantId` is resolved per-request via {@link getRequestTenantId}.
5
+ * where `currentTenantId` is the tenant of the request's verified credential
6
+ * ({@link resolveRequestTenantId}), `DEFAULT_TENANT_ID` without one.
6
7
  *
7
8
  * Use on a `Model`-typed parameter of a route handler or DataAPI field. Only
8
9
  * applicable when the target table is registered in the `dms-tenant` schema
@@ -7,15 +7,16 @@ const interface_database_decorators_1 = require("@antelopejs/interface-database-
7
7
  const request_tenant_1 = require("./request-tenant");
8
8
  /**
9
9
  * Parameter/property decorator that injects `GetModel(cl, currentTenantId)`,
10
- * where `currentTenantId` is resolved per-request via {@link getRequestTenantId}.
10
+ * where `currentTenantId` is the tenant of the request's verified credential
11
+ * ({@link resolveRequestTenantId}), `DEFAULT_TENANT_ID` without one.
11
12
  *
12
13
  * Use on a `Model`-typed parameter of a route handler or DataAPI field. Only
13
14
  * applicable when the target table is registered in the `dms-tenant` schema
14
15
  * (or any schema with one instance per tenant).
15
16
  */
16
17
  exports.TenantScopedModel = (0, decorators_1.MakeParameterAndPropertyDecorator)((target, key, index, cl) => {
17
- (0, interface_api_1.SetParameterProvider)(target, key, index, (ctx) => {
18
- return (0, interface_database_decorators_1.GetModel)(cl, (0, request_tenant_1.getRequestTenantId)(ctx));
18
+ (0, interface_api_1.SetParameterProvider)(target, key, index, async (ctx) => {
19
+ return (0, interface_database_decorators_1.GetModel)(cl, await (0, request_tenant_1.resolveRequestTenantId)(ctx));
19
20
  });
20
21
  });
21
22
  //# sourceMappingURL=tenant-scoped-model.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tenant-scoped-model.js","sourceRoot":"","sources":["../src/tenant-scoped-model.ts"],"names":[],"mappings":";;;AAAA,6DAGmC;AACnC,sEAG+C;AAC/C,6FAGmD;AACnD,qDAAsD;AAEtD;;;;;;;GAOG;AACU,QAAA,iBAAiB,GAAG,IAAA,8CAAiC,EAChE,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,EAA8C,EAAE,EAAE;IACrE,IAAA,oCAAoB,EAAC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,GAAmB,EAAE,EAAE;QAC/D,OAAO,IAAA,wCAAQ,EAAC,EAAE,EAAE,IAAA,mCAAkB,EAAC,GAAG,CAAC,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;AACL,CAAC,CACF,CAAC"}
1
+ {"version":3,"file":"tenant-scoped-model.js","sourceRoot":"","sources":["../src/tenant-scoped-model.ts"],"names":[],"mappings":";;;AAAA,6DAGmC;AACnC,sEAG+C;AAC/C,6FAGmD;AACnD,qDAA0D;AAE1D;;;;;;;;GAQG;AACU,QAAA,iBAAiB,GAAG,IAAA,8CAAiC,EAChE,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,EAA8C,EAAE,EAAE;IACrE,IAAA,oCAAoB,EAAC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,GAAmB,EAAE,EAAE;QACrE,OAAO,IAAA,wCAAQ,EAAC,EAAE,EAAE,MAAM,IAAA,uCAAsB,EAAC,GAAG,CAAC,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;AACL,CAAC,CACF,CAAC"}