velocious 1.0.643 → 1.0.645

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 (279) hide show
  1. package/README.md +21 -10
  2. package/build/authorization/ability.js +36 -13
  3. package/build/background-jobs/adapter.js +9 -0
  4. package/build/background-jobs/main.js +35 -10
  5. package/build/background-jobs/store.js +217 -38
  6. package/build/background-jobs/types.js +15 -0
  7. package/build/configuration-types.js +1 -1
  8. package/build/configuration.js +45 -9
  9. package/build/database/drivers/base-column.js +8 -0
  10. package/build/database/drivers/mssql/sql/update.js +1 -3
  11. package/build/database/drivers/mysql/sql/update.js +1 -3
  12. package/build/database/drivers/pgsql/column.js +22 -0
  13. package/build/database/drivers/pgsql/sql/update.js +1 -3
  14. package/build/database/drivers/sqlite/sql/alter-table.js +11 -1
  15. package/build/database/drivers/sqlite/sql/update.js +1 -3
  16. package/build/database/query/index.js +2 -2
  17. package/build/database/query/model-class-query.js +26 -10
  18. package/build/database/query/preloader/has-many.js +4 -1
  19. package/build/database/query/query-data.js +2 -1
  20. package/build/database/query/update-base.js +14 -0
  21. package/build/database/query/with-count.js +3 -1
  22. package/build/database/record/acts-as-list.js +37 -13
  23. package/build/database/record/attachments/store.js +336 -26
  24. package/build/database/record/auditing.js +6 -3
  25. package/build/database/record/index.js +197 -42
  26. package/build/database/record/instance-relationships/belongs-to.js +2 -1
  27. package/build/database/record/validators/uniqueness.js +8 -5
  28. package/build/environment-handlers/node/cli/commands/generate/frontend-models.js +24 -8
  29. package/build/frontend-model-controller.js +136 -53
  30. package/build/frontend-model-resource/base-resource.js +87 -37
  31. package/build/frontend-model-resource/velocious-attachment-resource.js +98 -31
  32. package/build/frontend-models/base.js +307 -59
  33. package/build/frontend-models/preloader.js +6 -3
  34. package/build/frontend-models/query.js +15 -6
  35. package/build/frontend-models/resource-definition.js +21 -2
  36. package/build/frontend-models/use-destroyed-event.js +1 -1
  37. package/build/frontend-models/use-model-class-event.js +2 -2
  38. package/build/frontend-models/use-updated-event.js +1 -1
  39. package/build/frontend-models/websocket-channel.js +256 -93
  40. package/build/frontend-models/websocket-publishers.js +218 -18
  41. package/build/http-server/client/websocket-session.js +13 -1
  42. package/build/http-server/websocket-channel.js +15 -2
  43. package/build/src/authorization/ability.d.ts +9 -3
  44. package/build/src/authorization/ability.d.ts.map +1 -1
  45. package/build/src/authorization/ability.js +33 -14
  46. package/build/src/background-jobs/adapter.d.ts +6 -0
  47. package/build/src/background-jobs/adapter.d.ts.map +1 -1
  48. package/build/src/background-jobs/adapter.js +9 -1
  49. package/build/src/background-jobs/main.d.ts +6 -0
  50. package/build/src/background-jobs/main.d.ts.map +1 -1
  51. package/build/src/background-jobs/main.js +34 -11
  52. package/build/src/background-jobs/store.d.ts +66 -12
  53. package/build/src/background-jobs/store.d.ts.map +1 -1
  54. package/build/src/background-jobs/store.js +191 -35
  55. package/build/src/background-jobs/types.d.ts +55 -0
  56. package/build/src/background-jobs/types.d.ts.map +1 -1
  57. package/build/src/background-jobs/types.js +16 -1
  58. package/build/src/configuration-types.d.ts +3 -3
  59. package/build/src/configuration-types.d.ts.map +1 -1
  60. package/build/src/configuration-types.js +2 -2
  61. package/build/src/configuration.d.ts +18 -8
  62. package/build/src/configuration.d.ts.map +1 -1
  63. package/build/src/configuration.js +38 -7
  64. package/build/src/database/drivers/base-column.d.ts +5 -0
  65. package/build/src/database/drivers/base-column.d.ts.map +1 -1
  66. package/build/src/database/drivers/base-column.js +8 -1
  67. package/build/src/database/drivers/mssql/sql/update.d.ts.map +1 -1
  68. package/build/src/database/drivers/mssql/sql/update.js +2 -4
  69. package/build/src/database/drivers/mysql/sql/update.d.ts.map +1 -1
  70. package/build/src/database/drivers/mysql/sql/update.js +2 -4
  71. package/build/src/database/drivers/pgsql/column.d.ts +5 -0
  72. package/build/src/database/drivers/pgsql/column.d.ts.map +1 -1
  73. package/build/src/database/drivers/pgsql/column.js +19 -1
  74. package/build/src/database/drivers/pgsql/sql/update.d.ts.map +1 -1
  75. package/build/src/database/drivers/pgsql/sql/update.js +2 -4
  76. package/build/src/database/drivers/sqlite/sql/alter-table.d.ts.map +1 -1
  77. package/build/src/database/drivers/sqlite/sql/alter-table.js +6 -2
  78. package/build/src/database/drivers/sqlite/sql/update.d.ts.map +1 -1
  79. package/build/src/database/drivers/sqlite/sql/update.js +2 -4
  80. package/build/src/database/query/index.d.ts +4 -4
  81. package/build/src/database/query/index.d.ts.map +1 -1
  82. package/build/src/database/query/index.js +3 -3
  83. package/build/src/database/query/model-class-query.d.ts +8 -2
  84. package/build/src/database/query/model-class-query.d.ts.map +1 -1
  85. package/build/src/database/query/model-class-query.js +25 -11
  86. package/build/src/database/query/preloader/has-many.d.ts.map +1 -1
  87. package/build/src/database/query/preloader/has-many.js +4 -2
  88. package/build/src/database/query/query-data.d.ts.map +1 -1
  89. package/build/src/database/query/query-data.js +3 -2
  90. package/build/src/database/query/update-base.d.ts +7 -0
  91. package/build/src/database/query/update-base.d.ts.map +1 -1
  92. package/build/src/database/query/update-base.js +13 -1
  93. package/build/src/database/query/with-count.d.ts.map +1 -1
  94. package/build/src/database/query/with-count.js +3 -2
  95. package/build/src/database/record/acts-as-list.d.ts.map +1 -1
  96. package/build/src/database/record/acts-as-list.js +35 -14
  97. package/build/src/database/record/attachments/store.d.ts +67 -0
  98. package/build/src/database/record/attachments/store.d.ts.map +1 -1
  99. package/build/src/database/record/attachments/store.js +301 -25
  100. package/build/src/database/record/auditing.d.ts.map +1 -1
  101. package/build/src/database/record/auditing.js +7 -4
  102. package/build/src/database/record/index.d.ts +78 -26
  103. package/build/src/database/record/index.d.ts.map +1 -1
  104. package/build/src/database/record/index.js +171 -42
  105. package/build/src/database/record/instance-relationships/belongs-to.d.ts.map +1 -1
  106. package/build/src/database/record/instance-relationships/belongs-to.js +3 -2
  107. package/build/src/database/record/validators/uniqueness.d.ts.map +1 -1
  108. package/build/src/database/record/validators/uniqueness.js +8 -6
  109. package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts +4 -4
  110. package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts.map +1 -1
  111. package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.js +24 -12
  112. package/build/src/frontend-model-controller.d.ts +29 -8
  113. package/build/src/frontend-model-controller.d.ts.map +1 -1
  114. package/build/src/frontend-model-controller.js +122 -51
  115. package/build/src/frontend-model-resource/base-resource.d.ts +51 -24
  116. package/build/src/frontend-model-resource/base-resource.d.ts.map +1 -1
  117. package/build/src/frontend-model-resource/base-resource.js +83 -37
  118. package/build/src/frontend-model-resource/velocious-attachment-resource.d.ts +45 -26
  119. package/build/src/frontend-model-resource/velocious-attachment-resource.d.ts.map +1 -1
  120. package/build/src/frontend-model-resource/velocious-attachment-resource.js +89 -31
  121. package/build/src/frontend-models/base.d.ts +53 -20
  122. package/build/src/frontend-models/base.d.ts.map +1 -1
  123. package/build/src/frontend-models/base.js +275 -59
  124. package/build/src/frontend-models/preloader.d.ts.map +1 -1
  125. package/build/src/frontend-models/preloader.js +6 -4
  126. package/build/src/frontend-models/query.d.ts +2 -2
  127. package/build/src/frontend-models/query.d.ts.map +1 -1
  128. package/build/src/frontend-models/query.js +14 -7
  129. package/build/src/frontend-models/resource-definition.d.ts.map +1 -1
  130. package/build/src/frontend-models/resource-definition.js +20 -3
  131. package/build/src/frontend-models/use-destroyed-event.d.ts +1 -1
  132. package/build/src/frontend-models/use-destroyed-event.d.ts.map +1 -1
  133. package/build/src/frontend-models/use-destroyed-event.js +2 -2
  134. package/build/src/frontend-models/use-model-class-event.d.ts +2 -2
  135. package/build/src/frontend-models/use-model-class-event.d.ts.map +1 -1
  136. package/build/src/frontend-models/use-model-class-event.js +3 -3
  137. package/build/src/frontend-models/use-updated-event.d.ts +1 -1
  138. package/build/src/frontend-models/use-updated-event.d.ts.map +1 -1
  139. package/build/src/frontend-models/use-updated-event.js +2 -2
  140. package/build/src/frontend-models/websocket-channel.d.ts +60 -41
  141. package/build/src/frontend-models/websocket-channel.d.ts.map +1 -1
  142. package/build/src/frontend-models/websocket-channel.js +225 -85
  143. package/build/src/frontend-models/websocket-publishers.d.ts +9 -0
  144. package/build/src/frontend-models/websocket-publishers.d.ts.map +1 -1
  145. package/build/src/frontend-models/websocket-publishers.js +190 -19
  146. package/build/src/http-server/client/websocket-session.d.ts.map +1 -1
  147. package/build/src/http-server/client/websocket-session.js +11 -2
  148. package/build/src/http-server/websocket-channel.d.ts +20 -8
  149. package/build/src/http-server/websocket-channel.d.ts.map +1 -1
  150. package/build/src/http-server/websocket-channel.js +15 -3
  151. package/build/src/sync/assets/cache.d.ts +288 -0
  152. package/build/src/sync/assets/cache.d.ts.map +1 -0
  153. package/build/src/sync/assets/cache.js +883 -0
  154. package/build/src/sync/assets/types.d.ts +199 -0
  155. package/build/src/sync/assets/types.d.ts.map +1 -0
  156. package/build/src/sync/assets/types.js +56 -0
  157. package/build/src/sync/sync-api-client.d.ts.map +1 -1
  158. package/build/src/sync/sync-api-client.js +4 -3
  159. package/build/src/sync/sync-client.d.ts.map +1 -1
  160. package/build/src/sync/sync-client.js +3 -2
  161. package/build/src/sync/sync-envelope-replay-service.d.ts.map +1 -1
  162. package/build/src/sync/sync-envelope-replay-service.js +6 -5
  163. package/build/src/sync/sync-publisher.d.ts.map +1 -1
  164. package/build/src/sync/sync-publisher.js +4 -3
  165. package/build/src/testing/browser-frontend-model-event-hook-scenarios.d.ts +2 -2
  166. package/build/src/testing/browser-frontend-model-event-hook-scenarios.d.ts.map +1 -1
  167. package/build/src/testing/browser-frontend-model-event-hook-scenarios.js +3 -3
  168. package/build/src/testing/test-profiler.d.ts +4 -4
  169. package/build/src/testing/test-profiler.d.ts.map +1 -1
  170. package/build/src/testing/test-profiler.js +3 -3
  171. package/build/src/testing/test-runner.d.ts +279 -117
  172. package/build/src/testing/test-runner.d.ts.map +1 -1
  173. package/build/src/testing/test-runner.js +503 -933
  174. package/build/src/testing/test.d.ts +11 -72
  175. package/build/src/testing/test.d.ts.map +1 -1
  176. package/build/src/testing/test.js +131 -284
  177. package/build/src/testing/velocious-attempt-executor.d.ts +54 -0
  178. package/build/src/testing/velocious-attempt-executor.d.ts.map +1 -0
  179. package/build/src/testing/velocious-attempt-executor.js +408 -0
  180. package/build/src/testing/velocious-runner-reporter.d.ts +67 -0
  181. package/build/src/testing/velocious-runner-reporter.d.ts.map +1 -0
  182. package/build/src/testing/velocious-runner-reporter.js +240 -0
  183. package/build/src/testing/velocious-suite-hook-executor.d.ts +19 -0
  184. package/build/src/testing/velocious-suite-hook-executor.d.ts.map +1 -0
  185. package/build/src/testing/velocious-suite-hook-executor.js +41 -0
  186. package/build/src/testing/velocious-test-arguments.d.ts +39 -0
  187. package/build/src/testing/velocious-test-arguments.d.ts.map +1 -0
  188. package/build/src/testing/velocious-test-arguments.js +55 -0
  189. package/build/src/utils/model-primary-key.d.ts +73 -0
  190. package/build/src/utils/model-primary-key.d.ts.map +1 -0
  191. package/build/src/utils/model-primary-key.js +144 -0
  192. package/build/src/utils/sha256-bytes-hex.d.ts +7 -0
  193. package/build/src/utils/sha256-bytes-hex.d.ts.map +1 -0
  194. package/build/src/utils/sha256-bytes-hex.js +117 -0
  195. package/build/src/utils/sha256-hex.d.ts +2 -4
  196. package/build/src/utils/sha256-hex.d.ts.map +1 -1
  197. package/build/src/utils/sha256-hex.js +6 -120
  198. package/build/sync/assets/cache.js +998 -0
  199. package/build/sync/assets/types.js +62 -0
  200. package/build/sync/sync-api-client.js +3 -2
  201. package/build/sync/sync-client.js +2 -1
  202. package/build/sync/sync-envelope-replay-service.js +5 -4
  203. package/build/sync/sync-publisher.js +3 -2
  204. package/build/testing/browser-frontend-model-event-hook-scenarios.js +2 -2
  205. package/build/testing/test-profiler.js +2 -2
  206. package/build/testing/test-runner.js +496 -990
  207. package/build/testing/test.js +164 -306
  208. package/build/testing/velocious-attempt-executor.js +441 -0
  209. package/build/testing/velocious-runner-reporter.js +264 -0
  210. package/build/testing/velocious-suite-hook-executor.js +43 -0
  211. package/build/testing/velocious-test-arguments.js +64 -0
  212. package/build/tsconfig.tsbuildinfo +1 -1
  213. package/build/utils/model-primary-key.js +171 -0
  214. package/build/utils/sha256-bytes-hex.js +132 -0
  215. package/build/utils/sha256-hex.js +7 -135
  216. package/package.json +5 -4
  217. package/src/authorization/ability.js +36 -13
  218. package/src/background-jobs/adapter.js +9 -0
  219. package/src/background-jobs/main.js +35 -10
  220. package/src/background-jobs/store.js +217 -38
  221. package/src/background-jobs/types.js +15 -0
  222. package/src/configuration-types.js +1 -1
  223. package/src/configuration.js +45 -9
  224. package/src/database/drivers/base-column.js +8 -0
  225. package/src/database/drivers/mssql/sql/update.js +1 -3
  226. package/src/database/drivers/mysql/sql/update.js +1 -3
  227. package/src/database/drivers/pgsql/column.js +22 -0
  228. package/src/database/drivers/pgsql/sql/update.js +1 -3
  229. package/src/database/drivers/sqlite/sql/alter-table.js +11 -1
  230. package/src/database/drivers/sqlite/sql/update.js +1 -3
  231. package/src/database/query/index.js +2 -2
  232. package/src/database/query/model-class-query.js +26 -10
  233. package/src/database/query/preloader/has-many.js +4 -1
  234. package/src/database/query/query-data.js +2 -1
  235. package/src/database/query/update-base.js +14 -0
  236. package/src/database/query/with-count.js +3 -1
  237. package/src/database/record/acts-as-list.js +37 -13
  238. package/src/database/record/attachments/store.js +336 -26
  239. package/src/database/record/auditing.js +6 -3
  240. package/src/database/record/index.js +197 -42
  241. package/src/database/record/instance-relationships/belongs-to.js +2 -1
  242. package/src/database/record/validators/uniqueness.js +8 -5
  243. package/src/environment-handlers/node/cli/commands/generate/frontend-models.js +24 -8
  244. package/src/frontend-model-controller.js +136 -53
  245. package/src/frontend-model-resource/base-resource.js +87 -37
  246. package/src/frontend-model-resource/velocious-attachment-resource.js +98 -31
  247. package/src/frontend-models/base.js +307 -59
  248. package/src/frontend-models/preloader.js +6 -3
  249. package/src/frontend-models/query.js +15 -6
  250. package/src/frontend-models/resource-definition.js +21 -2
  251. package/src/frontend-models/use-destroyed-event.js +1 -1
  252. package/src/frontend-models/use-model-class-event.js +2 -2
  253. package/src/frontend-models/use-updated-event.js +1 -1
  254. package/src/frontend-models/websocket-channel.js +256 -93
  255. package/src/frontend-models/websocket-publishers.js +218 -18
  256. package/src/http-server/client/websocket-session.js +13 -1
  257. package/src/http-server/websocket-channel.js +15 -2
  258. package/src/sync/assets/cache.js +998 -0
  259. package/src/sync/assets/types.js +62 -0
  260. package/src/sync/sync-api-client.js +3 -2
  261. package/src/sync/sync-client.js +2 -1
  262. package/src/sync/sync-envelope-replay-service.js +5 -4
  263. package/src/sync/sync-publisher.js +3 -2
  264. package/src/testing/browser-frontend-model-event-hook-scenarios.js +2 -2
  265. package/src/testing/test-profiler.js +2 -2
  266. package/src/testing/test-runner.js +496 -990
  267. package/src/testing/test.js +164 -306
  268. package/src/testing/velocious-attempt-executor.js +441 -0
  269. package/src/testing/velocious-runner-reporter.js +264 -0
  270. package/src/testing/velocious-suite-hook-executor.js +43 -0
  271. package/src/testing/velocious-test-arguments.js +64 -0
  272. package/src/utils/model-primary-key.js +171 -0
  273. package/src/utils/sha256-bytes-hex.js +132 -0
  274. package/src/utils/sha256-hex.js +7 -135
  275. package/build/src/testing/testing-package-adapter.d.ts +0 -9
  276. package/build/src/testing/testing-package-adapter.d.ts.map +0 -1
  277. package/build/src/testing/testing-package-adapter.js +0 -69
  278. package/build/testing/testing-package-adapter.js +0 -76
  279. package/src/testing/testing-package-adapter.js +0 -76
@@ -1,5 +1,19 @@
1
1
  import FrontendModelBaseResource from "./base-resource.js";
2
2
  import VelociousAttachment from "../database/record/attachments/attachment-record.js";
3
+ export type AttachmentOwnerScope = {
4
+ name: string;
5
+ recordId: string;
6
+ recordType: string;
7
+ resourceName: string | null;
8
+ };
9
+ export type AttachmentOwnerResource = {
10
+ backendProject: import("../configuration-types.js").BackendProjectConfiguration;
11
+ modelName: string;
12
+ resourceClass: import("../configuration-types.js").FrontendModelResourceClassType;
13
+ resourceConfiguration: import("../configuration-types.js").NormalizedFrontendModelResourceConfiguration;
14
+ };
15
+ /** @typedef {{name: string, recordId: string, recordType: string, resourceName: string | null}} AttachmentOwnerScope */
16
+ /** @typedef {{backendProject: import("../configuration-types.js").BackendProjectConfiguration, modelName: string, resourceClass: import("../configuration-types.js").FrontendModelResourceClassType, resourceConfiguration: import("../configuration-types.js").NormalizedFrontendModelResourceConfiguration}} AttachmentOwnerResource */
3
17
  /**
4
18
  * Framework-owned frontend resource exposing safe attachment metadata while
5
19
  * delegating read authorization to the attached owner record.
@@ -26,6 +40,11 @@ export default class VelociousAttachmentResource extends FrontendModelBaseResour
26
40
  * @returns {Promise<void>}
27
41
  */
28
42
  beforeAction(action: "index" | "find" | "create" | "update" | "destroy" | "attach" | "download" | "url"): Promise<void>;
43
+ /**
44
+ * Loads attachment metadata after removing the authorization-only resource name from database filters.
45
+ * @returns {Promise<VelociousAttachment[]>} - Attachment metadata rows.
46
+ */
47
+ records(): Promise<VelociousAttachment[]>;
29
48
  /**
30
49
  * Runs find.
31
50
  * @param {"find" | "update" | "destroy" | "attach" | "download" | "url"} action - Action.
@@ -47,13 +66,14 @@ export default class VelociousAttachmentResource extends FrontendModelBaseResour
47
66
  updatedAtAttribute(model: VelociousAttachment): Date;
48
67
  /**
49
68
  * Returns a validated owner scope from frontend-model where params.
50
- * @returns {{name: string, recordId: string, recordType: string}} - Attachment owner scope.
69
+ * @returns {AttachmentOwnerScope} - Attachment owner scope.
51
70
  */
52
- requiredOwnerScopeFromParams(): {
53
- name: string;
54
- recordId: string;
55
- recordType: string;
56
- };
71
+ requiredOwnerScopeFromParams(): AttachmentOwnerScope;
72
+ /**
73
+ * Returns the required attachment metadata where object.
74
+ * @returns {Record<string, ReturnType<typeof JSON.parse>>} - Attachment where filters.
75
+ */
76
+ requiredWhereFromParams(): Record<string, ReturnType<typeof JSON.parse>>;
57
77
  /**
58
78
  * Reads one required string-like where value.
59
79
  * @param {object} args - Args.
@@ -68,29 +88,32 @@ export default class VelociousAttachmentResource extends FrontendModelBaseResour
68
88
  /**
69
89
  * Builds owner scope from a stored attachment row.
70
90
  * @param {VelociousAttachment} attachment - Attachment row.
71
- * @returns {{name: string, recordId: string, recordType: string}} - Owner scope.
91
+ * @returns {AttachmentOwnerScope} - Owner scope.
72
92
  */
73
- ownerScopeFromAttachment(attachment: VelociousAttachment): {
74
- name: string;
75
- recordId: string;
76
- recordType: string;
77
- };
93
+ ownerScopeFromAttachment(attachment: VelociousAttachment): AttachmentOwnerScope;
78
94
  /**
79
95
  * Checks whether the current ability can read the attachment owner.
80
- * @param {{name: string, recordId: string, recordType: string}} ownerScope - Owner scope.
96
+ * @param {AttachmentOwnerScope} ownerScope - Owner scope.
81
97
  * @returns {Promise<boolean>} - Whether owner is readable.
82
98
  */
83
- attachmentOwnerAuthorized(ownerScope: {
84
- name: string;
85
- recordId: string;
86
- recordType: string;
87
- }): Promise<boolean>;
99
+ attachmentOwnerAuthorized(ownerScope: AttachmentOwnerScope): Promise<boolean>;
100
+ /**
101
+ * Resolves the explicit owner resource for scoped queries or every matching alias for member lookups.
102
+ * @param {object} args - Options object.
103
+ * @param {import("../frontend-model-controller.js").default} args.controller - Frontend-model controller.
104
+ * @param {AttachmentOwnerScope} args.ownerScope - Owner scope.
105
+ * @returns {AttachmentOwnerResource[]} - Matching owner resources.
106
+ */
107
+ attachmentOwnerResources({ controller, ownerScope }: {
108
+ controller: import("../frontend-model-controller.js").default;
109
+ ownerScope: AttachmentOwnerScope;
110
+ }): AttachmentOwnerResource[];
88
111
  /**
89
112
  * Finds the frontend-model resource that owns an attachment scope.
90
113
  * @param {object} args - Options object.
91
114
  * @param {import("../frontend-model-controller.js").default} args.controller - Frontend-model controller.
92
- * @param {{name: string, recordId: string, recordType: string}} args.ownerScope - Owner scope.
93
- * @returns {{backendProject: import("../configuration-types.js").BackendProjectConfiguration, modelName: string, resourceClass: import("../configuration-types.js").FrontendModelResourceClassType, resourceConfiguration: import("../configuration-types.js").NormalizedFrontendModelResourceConfiguration} | null} - Owner resource configuration.
115
+ * @param {{name: string, recordId: string, recordType: string, resourceName: string}} args.ownerScope - Owner scope.
116
+ * @returns {AttachmentOwnerResource | null} - Owner resource configuration.
94
117
  */
95
118
  attachmentOwnerResource({ controller, ownerScope }: {
96
119
  controller: import("../frontend-model-controller.js").default;
@@ -98,12 +121,8 @@ export default class VelociousAttachmentResource extends FrontendModelBaseResour
98
121
  name: string;
99
122
  recordId: string;
100
123
  recordType: string;
124
+ resourceName: string;
101
125
  };
102
- }): {
103
- backendProject: import("../configuration-types.js").BackendProjectConfiguration;
104
- modelName: string;
105
- resourceClass: import("../configuration-types.js").FrontendModelResourceClassType;
106
- resourceConfiguration: import("../configuration-types.js").NormalizedFrontendModelResourceConfiguration;
107
- } | null;
126
+ }): AttachmentOwnerResource | null;
108
127
  }
109
128
  //# sourceMappingURL=velocious-attachment-resource.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"velocious-attachment-resource.d.ts","sourceRoot":"","sources":["../../../src/frontend-model-resource/velocious-attachment-resource.js"],"names":[],"mappings":"AAEA,OAAO,yBAAyB,MAAM,oBAAoB,CAAA;AAC1D,OAAO,mBAAmB,MAAM,qDAAqD,CAAA;AAGrF;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,2BAA4B,SAAQ,yBAAyB,CAF1C,OAAO,mBAAmB,CAEgB;IAChF,MAAM,CAAC,UAAU,6BAAsB;IAEvC,sGAAsG;IACtG,MAAM,CAAC,UAAU,EADN,MAAM,CAAC,MAAM,EAAE,OAAO,2BAA2B,EAAE,mCAAmC,CAAC,CAYjG;IAED,uBAAuB;IACvB,MAAM,CAAC,yBAAyB,EADrB,MAAM,EAAE,CACyB;IAE5C,uBAAuB;IACvB,MAAM,CAAC,qBAAqB,EADjB,MAAM,EAAE,CACoB;IAEvC;;;;;OAKG;IACH,eAAe,CAAC,MAAM,EAHX,OAAO,oBAAoB,EAAE,2BAGlB,GAFT,OAAO,wCAAwC,EAAE,OAAO,CAAC,OAAO,mBAAmB,CAAC,CAMhG;IAED;;;;OAIG;IACG,YAAY,CAAC,MAAM,EAHd,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,KAG/D,GAFZ,OAAO,CAAC,IAAI,CAAC,CAUzB;IAED;;;;;OAKG;IACG,IAAI,CAAC,MAAM,EAJN,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,KAIlD,EAAE,EAAE,EAHV,MAAM,GAAG,MAGC,GAFR,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAW/C;IAED;;;;OAIG;IACH,kBAAkB,CAAC,KAAK,EAHb,mBAGa,GAFX,IAAI,CAIhB;IAED;;;;OAIG;IACH,kBAAkB,CAAC,KAAK,EAHb,mBAGa,GAFX,IAAI,CAIhB;IAED;;;OAGG;IACH,4BAA4B,IAFf;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAC,CAchE;IAED;;;;;;OAMG;IACH,wBAAwB,CAAC,EAAC,aAAa,EAAE,KAAK,EAAC,EAJ5C;QAAqB,aAAa,EAA1B,MAAM,CACd;QAA4D,KAAK,EAAzD,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CACrD;KAE4C,GAFlC,MAAM,CAQlB;IAED;;;;OAIG;IACH,wBAAwB,CAAC,UAAU,EAHxB,mBAGwB,GAFtB;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAC,CAQhE;IAED;;;;OAIG;IACG,yBAAyB,CAAC,UAAU,EAH/B;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAGpB,GAF7B,OAAO,CAAC,OAAO,CAAC,CA8B5B;IAED;;;;;;OAMG;IACH,uBAAuB,CAAC,EAAC,UAAU,EAAE,UAAU,EAAC,EAJ7C;QAAgE,UAAU,EAAlE,OAAO,iCAAiC,EAAE,OAAO,CACzD;QAAmE,UAAU,EAArE;YAAC,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAA;SAAC,CAC5D;KAE6C,GAFnC;QAAC,cAAc,EAAE,OAAO,2BAA2B,EAAE,2BAA2B,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,OAAO,2BAA2B,EAAE,8BAA8B,CAAC;QAAC,qBAAqB,EAAE,OAAO,2BAA2B,EAAE,4CAA4C,CAAA;KAAC,GAAG,IAAI,CAkCnT;CACF"}
1
+ {"version":3,"file":"velocious-attachment-resource.d.ts","sourceRoot":"","sources":["../../../src/frontend-model-resource/velocious-attachment-resource.js"],"names":[],"mappings":"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"}
@@ -1,7 +1,11 @@
1
1
  // @ts-check
2
2
  import FrontendModelBaseResource from "./base-resource.js";
3
3
  import VelociousAttachment from "../database/record/attachments/attachment-record.js";
4
+ import { frontendModelResourcesForBackendProject } from "../frontend-models/resource-definition.js";
4
5
  import isPlainObject from "../utils/plain-object.js";
6
+ import { modelPrimaryKeyConditions, modelPrimaryKeyValueFromCacheKey } from "../utils/model-primary-key.js";
7
+ /** @typedef {{name: string, recordId: string, recordType: string, resourceName: string | null}} AttachmentOwnerScope */
8
+ /** @typedef {{backendProject: import("../configuration-types.js").BackendProjectConfiguration, modelName: string, resourceClass: import("../configuration-types.js").FrontendModelResourceClassType, resourceConfiguration: import("../configuration-types.js").NormalizedFrontendModelResourceConfiguration}} AttachmentOwnerResource */
5
9
  /**
6
10
  * Framework-owned frontend resource exposing safe attachment metadata while
7
11
  * delegating read authorization to the attached owner record.
@@ -49,6 +53,17 @@ export default class VelociousAttachmentResource extends FrontendModelBaseResour
49
53
  throw new Error("Attachment owner not found or not authorized");
50
54
  }
51
55
  }
56
+ /**
57
+ * Loads attachment metadata after removing the authorization-only resource name from database filters.
58
+ * @returns {Promise<VelociousAttachment[]>} - Attachment metadata rows.
59
+ */
60
+ async records() {
61
+ const controller = /** @type {import("../frontend-model-controller.js").default} */ (this.controllerInstance());
62
+ const params = controller.frontendModelParams();
63
+ const where = { ...this.requiredWhereFromParams() };
64
+ delete where.resourceName;
65
+ return await controller.withFrontendModelParams({ ...params, where }, async () => await this.indexQuery().toArray());
66
+ }
52
67
  /**
53
68
  * Runs find.
54
69
  * @param {"find" | "update" | "destroy" | "attach" | "download" | "url"} action - Action.
@@ -82,19 +97,29 @@ export default class VelociousAttachmentResource extends FrontendModelBaseResour
82
97
  }
83
98
  /**
84
99
  * Returns a validated owner scope from frontend-model where params.
85
- * @returns {{name: string, recordId: string, recordType: string}} - Attachment owner scope.
100
+ * @returns {AttachmentOwnerScope} - Attachment owner scope.
86
101
  */
87
102
  requiredOwnerScopeFromParams() {
88
- const where = this.params().where;
89
- if (!isPlainObject(where)) {
90
- throw new Error("VelociousAttachment index requires recordType, recordId, and name where filters");
91
- }
103
+ const where = this.requiredWhereFromParams();
104
+ const recordType = this.requiredSingleWhereValue({ attributeName: "recordType", where });
92
105
  return {
93
106
  name: this.requiredSingleWhereValue({ attributeName: "name", where }),
94
107
  recordId: this.requiredSingleWhereValue({ attributeName: "recordId", where }),
95
- recordType: this.requiredSingleWhereValue({ attributeName: "recordType", where })
108
+ recordType,
109
+ resourceName: this.requiredSingleWhereValue({ attributeName: "resourceName", where })
96
110
  };
97
111
  }
112
+ /**
113
+ * Returns the required attachment metadata where object.
114
+ * @returns {Record<string, ReturnType<typeof JSON.parse>>} - Attachment where filters.
115
+ */
116
+ requiredWhereFromParams() {
117
+ const where = this.params().where;
118
+ if (!isPlainObject(where)) {
119
+ throw new Error("VelociousAttachment index requires resourceName, recordType, recordId, and name where filters");
120
+ }
121
+ return where;
122
+ }
98
123
  /**
99
124
  * Reads one required string-like where value.
100
125
  * @param {object} args - Args.
@@ -111,47 +136,78 @@ export default class VelociousAttachmentResource extends FrontendModelBaseResour
111
136
  /**
112
137
  * Builds owner scope from a stored attachment row.
113
138
  * @param {VelociousAttachment} attachment - Attachment row.
114
- * @returns {{name: string, recordId: string, recordType: string}} - Owner scope.
139
+ * @returns {AttachmentOwnerScope} - Owner scope.
115
140
  */
116
141
  ownerScopeFromAttachment(attachment) {
117
142
  return {
118
143
  name: attachment.name(),
119
144
  recordId: attachment.recordId(),
120
- recordType: attachment.recordType()
145
+ recordType: attachment.recordType(),
146
+ resourceName: null
121
147
  };
122
148
  }
123
149
  /**
124
150
  * Checks whether the current ability can read the attachment owner.
125
- * @param {{name: string, recordId: string, recordType: string}} ownerScope - Owner scope.
151
+ * @param {AttachmentOwnerScope} ownerScope - Owner scope.
126
152
  * @returns {Promise<boolean>} - Whether owner is readable.
127
153
  */
128
154
  async attachmentOwnerAuthorized(ownerScope) {
129
155
  const controller = /** @type {import("../frontend-model-controller.js").default} */ (this.controllerInstance());
130
- const ownerResource = this.attachmentOwnerResource({ controller, ownerScope });
131
- if (!ownerResource) {
132
- throw new Error(`No frontend model resource configured for attachment owner ${ownerScope.recordType}`);
156
+ const ownerResources = this.attachmentOwnerResources({ controller, ownerScope });
157
+ if (ownerResources.length < 1) {
158
+ throw new Error(`No frontend model resource configured for attachment owner ${ownerScope.resourceName ?? ownerScope.recordType}`);
133
159
  }
134
- const ownerModelClass = controller.frontendModelResourceModelClass(ownerResource);
135
- if (!ownerModelClass) {
136
- throw new Error(`No model class configured for attachment owner ${ownerScope.recordType}`);
160
+ for (const ownerResource of ownerResources) {
161
+ const ownerModelClass = controller.frontendModelResourceModelClass(ownerResource);
162
+ await controller.ensureFrontendModelRecordClassInitialized(ownerModelClass);
163
+ const abilityAction = ownerResource.resourceConfiguration.abilities.find || ownerResource.resourceConfiguration.abilities.index || "read";
164
+ const primaryKey = ownerModelClass.primaryKey();
165
+ const ownerIdentity = modelPrimaryKeyValueFromCacheKey(primaryKey, ownerScope.recordId);
166
+ const owner = await ownerModelClass
167
+ .accessibleFor(abilityAction, this.ability)
168
+ .findBy(modelPrimaryKeyConditions(primaryKey, ownerIdentity));
169
+ if (owner)
170
+ return true;
137
171
  }
138
- const attachmentDefinitions = ownerModelClass.getAttachmentsMap();
139
- if (!attachmentDefinitions[ownerScope.name]) {
140
- throw new Error(`No attachment '${ownerScope.name}' configured for ${ownerScope.recordType}`);
172
+ return false;
173
+ }
174
+ /**
175
+ * Resolves the explicit owner resource for scoped queries or every matching alias for member lookups.
176
+ * @param {object} args - Options object.
177
+ * @param {import("../frontend-model-controller.js").default} args.controller - Frontend-model controller.
178
+ * @param {AttachmentOwnerScope} args.ownerScope - Owner scope.
179
+ * @returns {AttachmentOwnerResource[]} - Matching owner resources.
180
+ */
181
+ attachmentOwnerResources({ controller, ownerScope }) {
182
+ if (ownerScope.resourceName) {
183
+ const ownerResource = this.attachmentOwnerResource({
184
+ controller,
185
+ ownerScope: { ...ownerScope, resourceName: ownerScope.resourceName }
186
+ });
187
+ return ownerResource ? [ownerResource] : [];
141
188
  }
142
- await controller.ensureFrontendModelRecordClassInitialized(ownerModelClass);
143
- const abilityAction = ownerResource.resourceConfiguration.abilities.find || ownerResource.resourceConfiguration.abilities.index || "read";
144
- const owner = await ownerModelClass
145
- .accessibleFor(abilityAction, this.ability)
146
- .findBy({ [ownerModelClass.primaryKey()]: ownerScope.recordId });
147
- return Boolean(owner);
189
+ const ownerResources = [];
190
+ for (const backendProject of controller.getConfiguration().getBackendProjects()) {
191
+ for (const resourceName of Object.keys(frontendModelResourcesForBackendProject(backendProject))) {
192
+ const ownerResource = controller.frontendModelResourceConfigurationForBackendProjectModelName({ backendProject, modelName: resourceName });
193
+ if (!ownerResource)
194
+ continue;
195
+ const ownerModelClass = controller.frontendModelResourceModelClass(ownerResource);
196
+ if (ownerModelClass.getModelName() !== ownerScope.recordType)
197
+ continue;
198
+ if (!ownerResource.resourceConfiguration.attachments?.[ownerScope.name])
199
+ continue;
200
+ ownerResources.push(ownerResource);
201
+ }
202
+ }
203
+ return ownerResources;
148
204
  }
149
205
  /**
150
206
  * Finds the frontend-model resource that owns an attachment scope.
151
207
  * @param {object} args - Options object.
152
208
  * @param {import("../frontend-model-controller.js").default} args.controller - Frontend-model controller.
153
- * @param {{name: string, recordId: string, recordType: string}} args.ownerScope - Owner scope.
154
- * @returns {{backendProject: import("../configuration-types.js").BackendProjectConfiguration, modelName: string, resourceClass: import("../configuration-types.js").FrontendModelResourceClassType, resourceConfiguration: import("../configuration-types.js").NormalizedFrontendModelResourceConfiguration} | null} - Owner resource configuration.
209
+ * @param {{name: string, recordId: string, recordType: string, resourceName: string}} args.ownerScope - Owner scope.
210
+ * @returns {AttachmentOwnerResource | null} - Owner resource configuration.
155
211
  */
156
212
  attachmentOwnerResource({ controller, ownerScope }) {
157
213
  const backendProjects = controller.getConfiguration().getBackendProjects();
@@ -161,23 +217,25 @@ export default class VelociousAttachmentResource extends FrontendModelBaseResour
161
217
  for (const backendProject of backendProjects) {
162
218
  const ownerResource = controller.frontendModelResourceConfigurationForBackendProjectModelName({
163
219
  backendProject,
164
- modelName: ownerScope.recordType
220
+ modelName: ownerScope.resourceName
165
221
  });
166
222
  if (!ownerResource)
167
223
  continue;
168
224
  const ownerModelClass = controller.frontendModelResourceModelClass(ownerResource);
169
225
  if (!ownerModelClass) {
170
- throw new Error(`No model class configured for attachment owner ${ownerScope.recordType}`);
226
+ throw new Error(`No model class configured for attachment owner ${ownerScope.resourceName}`);
171
227
  }
172
- const attachmentDefinitions = ownerModelClass.getAttachmentsMap();
228
+ if (ownerModelClass.getModelName() !== ownerScope.recordType)
229
+ continue;
230
+ const attachmentDefinitions = ownerResource.resourceConfiguration.attachments || {};
173
231
  if (attachmentDefinitions[ownerScope.name])
174
232
  return ownerResource;
175
233
  resourceWithoutAttachment ||= ownerResource;
176
234
  }
177
235
  if (resourceWithoutAttachment) {
178
- throw new Error(`No attachment '${ownerScope.name}' configured for ${ownerScope.recordType}`);
236
+ throw new Error(`No attachment '${ownerScope.name}' configured for ${ownerScope.resourceName}`);
179
237
  }
180
238
  return null;
181
239
  }
182
240
  }
183
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVsb2Npb3VzLWF0dGFjaG1lbnQtcmVzb3VyY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZnJvbnRlbmQtbW9kZWwtcmVzb3VyY2UvdmVsb2Npb3VzLWF0dGFjaG1lbnQtcmVzb3VyY2UuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8seUJBQXlCLE1BQU0sb0JBQW9CLENBQUE7QUFDMUQsT0FBTyxtQkFBbUIsTUFBTSxxREFBcUQsQ0FBQTtBQUNyRixPQUFPLGFBQWEsTUFBTSwwQkFBMEIsQ0FBQTtBQUVwRDs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLE9BQU8sT0FBTywyQkFBNEIsU0FBUSx5QkFBeUI7SUFDaEYsTUFBTSxDQUFDLFVBQVUsR0FBRyxtQkFBbUIsQ0FBQTtJQUV2QyxzR0FBc0c7SUFDdEcsTUFBTSxDQUFDLFVBQVUsR0FBRztRQUNsQixRQUFRLEVBQUUsRUFBQyxJQUFJLEVBQUUsU0FBUyxFQUFDO1FBQzNCLFdBQVcsRUFBRSxFQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBQztRQUMxQyxTQUFTLEVBQUUsRUFBQyxJQUFJLEVBQUUsVUFBVSxFQUFDO1FBQzdCLFFBQVEsRUFBRSxFQUFDLElBQUksRUFBRSxTQUFTLEVBQUM7UUFDM0IsRUFBRSxFQUFFLEVBQUMsSUFBSSxFQUFFLE1BQU0sRUFBQztRQUNsQixJQUFJLEVBQUUsRUFBQyxJQUFJLEVBQUUsU0FBUyxFQUFDO1FBQ3ZCLFFBQVEsRUFBRSxFQUFDLElBQUksRUFBRSxTQUFTLEVBQUM7UUFDM0IsUUFBUSxFQUFFLEVBQUMsSUFBSSxFQUFFLFNBQVMsRUFBQztRQUMzQixVQUFVLEVBQUUsRUFBQyxJQUFJLEVBQUUsU0FBUyxFQUFDO1FBQzdCLFNBQVMsRUFBRSxFQUFDLElBQUksRUFBRSxVQUFVLEVBQUM7S0FDOUIsQ0FBQTtJQUVELHVCQUF1QjtJQUN2QixNQUFNLENBQUMseUJBQXlC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QUM7UUFFRCxJQUFJLHlCQUF5QixFQUFFLENBQUM7WUFDOUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxrQkFBa0IsVUFBVSxDQUFDLElBQUksb0JBQW9CLFVBQVUsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFBO1FBQy9GLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQTtJQUNiLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgRnJvbnRlbmRNb2RlbEJhc2VSZXNvdXJjZSBmcm9tIFwiLi9iYXNlLXJlc291cmNlLmpzXCJcbmltcG9ydCBWZWxvY2lvdXNBdHRhY2htZW50IGZyb20gXCIuLi9kYXRhYmFzZS9yZWNvcmQvYXR0YWNobWVudHMvYXR0YWNobWVudC1yZWNvcmQuanNcIlxuaW1wb3J0IGlzUGxhaW5PYmplY3QgZnJvbSBcIi4uL3V0aWxzL3BsYWluLW9iamVjdC5qc1wiXG5cbi8qKlxuICogRnJhbWV3b3JrLW93bmVkIGZyb250ZW5kIHJlc291cmNlIGV4cG9zaW5nIHNhZmUgYXR0YWNobWVudCBtZXRhZGF0YSB3aGlsZVxuICogZGVsZWdhdGluZyByZWFkIGF1dGhvcml6YXRpb24gdG8gdGhlIGF0dGFjaGVkIG93bmVyIHJlY29yZC5cbiAqIEBhdWdtZW50cyB7RnJvbnRlbmRNb2RlbEJhc2VSZXNvdXJjZTx0eXBlb2YgVmVsb2Npb3VzQXR0YWNobWVudD59XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFZlbG9jaW91c0F0dGFjaG1lbnRSZXNvdXJjZSBleHRlbmRzIEZyb250ZW5kTW9kZWxCYXNlUmVzb3VyY2Uge1xuICBzdGF0aWMgTW9kZWxDbGFzcyA9IFZlbG9jaW91c0F0dGFjaG1lbnRcblxuICAvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsIGltcG9ydChcIi4uL2NvbmZpZ3VyYXRpb24tdHlwZXMuanNcIikuRnJvbnRlbmRNb2RlbEF0dHJpYnV0ZUNvbmZpZ3VyYXRpb24+fSAqL1xuICBzdGF0aWMgYXR0cmlidXRlcyA9IHtcbiAgICBieXRlU2l6ZToge3R5cGU6IFwiaW50ZWdlclwifSxcbiAgICBjb250ZW50VHlwZToge251bGw6IHRydWUsIHR5cGU6IFwidmFyY2hhclwifSxcbiAgICBjcmVhdGVkQXQ6IHt0eXBlOiBcImRhdGV0aW1lXCJ9LFxuICAgIGZpbGVuYW1lOiB7dHlwZTogXCJ2YXJjaGFyXCJ9LFxuICAgIGlkOiB7dHlwZTogXCJ1dWlkXCJ9LFxuICAgIG5hbWU6IHt0eXBlOiBcInZhcmNoYXJcIn0sXG4gICAgcG9zaXRpb246IHt0eXBlOiBcImludGVnZXJcIn0sXG4gICAgcmVjb3JkSWQ6IHt0eXBlOiBcInZhcmNoYXJcIn0sXG4gICAgcmVjb3JkVHlwZToge3R5cGU6IFwidmFyY2hhclwifSxcbiAgICB1cGRhdGVkQXQ6IHt0eXBlOiBcImRhdGV0aW1lXCJ9XG4gIH1cblxuICAvKiogQHR5cGUge3N0cmluZ1tdfSAqL1xuICBzdGF0aWMgYnVpbHRJbkNvbGxlY3Rpb25Db21tYW5kcyA9IFtcImluZGV4XCJdXG5cbiAgLyoqIEB0eXBlIHtzdHJpbmdbXX0gKi9cbiAgc3RhdGljIGJ1aWx0SW5NZW1iZXJDb21tYW5kcyA9IFtcImZpbmRcIl1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgYXR0YWNobWVudCBtZXRhZGF0YSBxdWVyeSBhZnRlciBvd25lci1zY29wZSBhdXRob3JpemF0aW9uIGhhc1xuICAgKiB2YWxpZGF0ZWQgdGhlIHJlcXVlc3QgdGhyb3VnaCBiZWZvcmVBY3Rpb24vZmluZC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL2Jhc2UtcmVzb3VyY2UuanNcIikuRnJvbnRlbmRNb2RlbFJlc291cmNlQWN0aW9ufSBhY3Rpb24gLSBGcm9udGVuZC1tb2RlbCBhY3Rpb24uXG4gICAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9kYXRhYmFzZS9xdWVyeS9tb2RlbC1jbGFzcy1xdWVyeS5qc1wiKS5kZWZhdWx0PHR5cGVvZiBWZWxvY2lvdXNBdHRhY2htZW50Pn0gLSBBdHRhY2htZW50IHF1ZXJ5LlxuICAgKi9cbiAgYXV0aG9yaXplZFF1ZXJ5KGFjdGlvbikge1xuICAgIHZvaWQgYWN0aW9uXG5cbiAgICByZXR1cm4gVmVsb2Npb3VzQXR0YWNobWVudC5hbGwoKVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgYmVmb3JlIGFjdGlvbi5cbiAgICogQHBhcmFtIHtcImluZGV4XCIgfCBcImZpbmRcIiB8IFwiY3JlYXRlXCIgfCBcInVwZGF0ZVwiIHwgXCJkZXN0cm95XCIgfCBcImF0dGFjaFwiIHwgXCJkb3dubG9hZFwiIHwgXCJ1cmxcIn0gYWN0aW9uIC0gQWN0aW9uLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIGJlZm9yZUFjdGlvbihhY3Rpb24pIHtcbiAgICBpZiAoYWN0aW9uICE9PSBcImluZGV4XCIpIHJldHVyblxuXG4gICAgY29uc3QgYXV0aG9yaXplZCA9IGF3YWl0IHRoaXMuYXR0YWNobWVudE93bmVyQXV0aG9yaXplZCh0aGlzLnJlcXVpcmVkT3duZXJTY29wZUZyb21QYXJhbXMoKSlcblxuICAgIGlmICghYXV0aG9yaXplZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQXR0YWNobWVudCBvd25lciBub3QgZm91bmQgb3Igbm90IGF1dGhvcml6ZWRcIilcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUnVucyBmaW5kLlxuICAgKiBAcGFyYW0ge1wiZmluZFwiIHwgXCJ1cGRhdGVcIiB8IFwiZGVzdHJveVwiIHwgXCJhdHRhY2hcIiB8IFwiZG93bmxvYWRcIiB8IFwidXJsXCJ9IGFjdGlvbiAtIEFjdGlvbi5cbiAgICogQHBhcmFtIHtzdHJpbmcgfCBudW1iZXJ9IGlkIC0gQXR0YWNobWVudCBpZC5cbiAgICogQHJldHVybnMge1Byb21pc2U8VmVsb2Npb3VzQXR0YWNobWVudCB8IG51bGw+fSAtIExvY2F0ZWQgYXR0YWNobWVudCB3aGVuIG93bmVyIGlzIGF1dGhvcml6ZWQuXG4gICAqL1xuICBhc3luYyBmaW5kKGFjdGlvbiwgaWQpIHtcbiAgICB2b2lkIGFjdGlvblxuXG4gICAgY29uc3QgYXR0YWNobWVudCA9IGF3YWl0IFZlbG9jaW91c0F0dGFjaG1lbnQuZmluZEJ5KHtpZH0pXG5cbiAgICBpZiAoIWF0dGFjaG1lbnQpIHJldHVybiBudWxsXG4gICAgaWYgKCFhd2FpdCB0aGlzLmF0dGFjaG1lbnRPd25lckF1dGhvcml6ZWQodGhpcy5vd25lclNjb3BlRnJvbUF0dGFjaG1lbnQoYXR0YWNobWVudCkpKSByZXR1cm4gbnVsbFxuXG4gICAgcmV0dXJuIGF0dGFjaG1lbnRcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGNyZWF0ZWQgYXQgYXR0cmlidXRlLlxuICAgKiBAcGFyYW0ge1ZlbG9jaW91c0F0dGFjaG1lbnR9IG1vZGVsIC0gQXR0YWNobWVudCBtb2RlbC5cbiAgICogQHJldHVybnMge0RhdGV9IC0gQ3JlYXRlZC1hdCB0aW1lc3RhbXAuXG4gICAqL1xuICBjcmVhdGVkQXRBdHRyaWJ1dGUobW9kZWwpIHtcbiAgICByZXR1cm4gbmV3IERhdGUobW9kZWwuY3JlYXRlZEF0TXMoKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHVwZGF0ZWQgYXQgYXR0cmlidXRlLlxuICAgKiBAcGFyYW0ge1ZlbG9jaW91c0F0dGFjaG1lbnR9IG1vZGVsIC0gQXR0YWNobWVudCBtb2RlbC5cbiAgICogQHJldHVybnMge0RhdGV9IC0gVXBkYXRlZC1hdCB0aW1lc3RhbXAuXG4gICAqL1xuICB1cGRhdGVkQXRBdHRyaWJ1dGUobW9kZWwpIHtcbiAgICByZXR1cm4gbmV3IERhdGUobW9kZWwudXBkYXRlZEF0TXMoKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgdmFsaWRhdGVkIG93bmVyIHNjb3BlIGZyb20gZnJvbnRlbmQtbW9kZWwgd2hlcmUgcGFyYW1zLlxuICAgKiBAcmV0dXJucyB7e25hbWU6IHN0cmluZywgcmVjb3JkSWQ6IHN0cmluZywgcmVjb3JkVHlwZTogc3RyaW5nfX0gLSBBdHRhY2htZW50IG93bmVyIHNjb3BlLlxuICAgKi9cbiAgcmVxdWlyZWRPd25lclNjb3BlRnJvbVBhcmFtcygpIHtcbiAgICBjb25zdCB3aGVyZSA9IHRoaXMucGFyYW1zKCkud2hlcmVcblxuICAgIGlmICghaXNQbGFpbk9iamVjdCh3aGVyZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlZlbG9jaW91c0F0dGFjaG1lbnQgaW5kZXggcmVxdWlyZXMgcmVjb3JkVHlwZSwgcmVjb3JkSWQsIGFuZCBuYW1lIHdoZXJlIGZpbHRlcnNcIilcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogdGhpcy5yZXF1aXJlZFNpbmdsZVdoZXJlVmFsdWUoe2F0dHJpYnV0ZU5hbWU6IFwibmFtZVwiLCB3aGVyZX0pLFxuICAgICAgcmVjb3JkSWQ6IHRoaXMucmVxdWlyZWRTaW5nbGVXaGVyZVZhbHVlKHthdHRyaWJ1dGVOYW1lOiBcInJlY29yZElkXCIsIHdoZXJlfSksXG4gICAgICByZWNvcmRUeXBlOiB0aGlzLnJlcXVpcmVkU2luZ2xlV2hlcmVWYWx1ZSh7YXR0cmlidXRlTmFtZTogXCJyZWNvcmRUeXBlXCIsIHdoZXJlfSlcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVhZHMgb25lIHJlcXVpcmVkIHN0cmluZy1saWtlIHdoZXJlIHZhbHVlLlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIEFyZ3MuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLmF0dHJpYnV0ZU5hbWUgLSBBdHRyaWJ1dGUgbmFtZS5cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj59IGFyZ3Mud2hlcmUgLSBXaGVyZSBoYXNoLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSAtIFN0cmluZyB2YWx1ZS5cbiAgICovXG4gIHJlcXVpcmVkU2luZ2xlV2hlcmVWYWx1ZSh7YXR0cmlidXRlTmFtZSwgd2hlcmV9KSB7XG4gICAgY29uc3QgdmFsdWUgPSB3aGVyZVthdHRyaWJ1dGVOYW1lXVxuXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiB8fCB0eXBlb2YgdmFsdWUgPT09IFwibnVtYmVyXCIpIHJldHVybiBTdHJpbmcodmFsdWUpXG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYFZlbG9jaW91c0F0dGFjaG1lbnQgaW5kZXggcmVxdWlyZXMgYSBzaW5nbGUgJHthdHRyaWJ1dGVOYW1lfSB3aGVyZSBmaWx0ZXJgKVxuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyBvd25lciBzY29wZSBmcm9tIGEgc3RvcmVkIGF0dGFjaG1lbnQgcm93LlxuICAgKiBAcGFyYW0ge1ZlbG9jaW91c0F0dGFjaG1lbnR9IGF0dGFjaG1lbnQgLSBBdHRhY2htZW50IHJvdy5cbiAgICogQHJldHVybnMge3tuYW1lOiBzdHJpbmcsIHJlY29yZElkOiBzdHJpbmcsIHJlY29yZFR5cGU6IHN0cmluZ319IC0gT3duZXIgc2NvcGUuXG4gICAqL1xuICBvd25lclNjb3BlRnJvbUF0dGFjaG1lbnQoYXR0YWNobWVudCkge1xuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiBhdHRhY2htZW50Lm5hbWUoKSxcbiAgICAgIHJlY29yZElkOiBhdHRhY2htZW50LnJlY29yZElkKCksXG4gICAgICByZWNvcmRUeXBlOiBhdHRhY2htZW50LnJlY29yZFR5cGUoKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3Mgd2hldGhlciB0aGUgY3VycmVudCBhYmlsaXR5IGNhbiByZWFkIHRoZSBhdHRhY2htZW50IG93bmVyLlxuICAgKiBAcGFyYW0ge3tuYW1lOiBzdHJpbmcsIHJlY29yZElkOiBzdHJpbmcsIHJlY29yZFR5cGU6IHN0cmluZ319IG93bmVyU2NvcGUgLSBPd25lciBzY29wZS5cbiAgICogQHJldHVybnMge1Byb21pc2U8Ym9vbGVhbj59IC0gV2hldGhlciBvd25lciBpcyByZWFkYWJsZS5cbiAgICovXG4gIGFzeW5jIGF0dGFjaG1lbnRPd25lckF1dGhvcml6ZWQob3duZXJTY29wZSkge1xuICAgIGNvbnN0IGNvbnRyb2xsZXIgPSAvKiogQHR5cGUge2ltcG9ydChcIi4uL2Zyb250ZW5kLW1vZGVsLWNvbnRyb2xsZXIuanNcIikuZGVmYXVsdH0gKi8gKHRoaXMuY29udHJvbGxlckluc3RhbmNlKCkpXG4gICAgY29uc3Qgb3duZXJSZXNvdXJjZSA9IHRoaXMuYXR0YWNobWVudE93bmVyUmVzb3VyY2Uoe2NvbnRyb2xsZXIsIG93bmVyU2NvcGV9KVxuXG4gICAgaWYgKCFvd25lclJlc291cmNlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIGZyb250ZW5kIG1vZGVsIHJlc291cmNlIGNvbmZpZ3VyZWQgZm9yIGF0dGFjaG1lbnQgb3duZXIgJHtvd25lclNjb3BlLnJlY29yZFR5cGV9YClcbiAgICB9XG5cbiAgICBjb25zdCBvd25lck1vZGVsQ2xhc3MgPSBjb250cm9sbGVyLmZyb250ZW5kTW9kZWxSZXNvdXJjZU1vZGVsQ2xhc3Mob3duZXJSZXNvdXJjZSlcblxuICAgIGlmICghb3duZXJNb2RlbENsYXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIG1vZGVsIGNsYXNzIGNvbmZpZ3VyZWQgZm9yIGF0dGFjaG1lbnQgb3duZXIgJHtvd25lclNjb3BlLnJlY29yZFR5cGV9YClcbiAgICB9XG5cbiAgICBjb25zdCBhdHRhY2htZW50RGVmaW5pdGlvbnMgPSBvd25lck1vZGVsQ2xhc3MuZ2V0QXR0YWNobWVudHNNYXAoKVxuXG4gICAgaWYgKCFhdHRhY2htZW50RGVmaW5pdGlvbnNbb3duZXJTY29wZS5uYW1lXSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyBhdHRhY2htZW50ICcke293bmVyU2NvcGUubmFtZX0nIGNvbmZpZ3VyZWQgZm9yICR7b3duZXJTY29wZS5yZWNvcmRUeXBlfWApXG4gICAgfVxuXG4gICAgYXdhaXQgY29udHJvbGxlci5lbnN1cmVGcm9udGVuZE1vZGVsUmVjb3JkQ2xhc3NJbml0aWFsaXplZChvd25lck1vZGVsQ2xhc3MpXG5cbiAgICBjb25zdCBhYmlsaXR5QWN0aW9uID0gb3duZXJSZXNvdXJjZS5yZXNvdXJjZUNvbmZpZ3VyYXRpb24uYWJpbGl0aWVzLmZpbmQgfHwgb3duZXJSZXNvdXJjZS5yZXNvdXJjZUNvbmZpZ3VyYXRpb24uYWJpbGl0aWVzLmluZGV4IHx8IFwicmVhZFwiXG4gICAgY29uc3Qgb3duZXIgPSBhd2FpdCBvd25lck1vZGVsQ2xhc3NcbiAgICAgIC5hY2Nlc3NpYmxlRm9yKGFiaWxpdHlBY3Rpb24sIHRoaXMuYWJpbGl0eSlcbiAgICAgIC5maW5kQnkoe1tvd25lck1vZGVsQ2xhc3MucHJpbWFyeUtleSgpXTogb3duZXJTY29wZS5yZWNvcmRJZH0pXG5cbiAgICByZXR1cm4gQm9vbGVhbihvd25lcilcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyB0aGUgZnJvbnRlbmQtbW9kZWwgcmVzb3VyY2UgdGhhdCBvd25zIGFuIGF0dGFjaG1lbnQgc2NvcGUuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucyBvYmplY3QuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZnJvbnRlbmQtbW9kZWwtY29udHJvbGxlci5qc1wiKS5kZWZhdWx0fSBhcmdzLmNvbnRyb2xsZXIgLSBGcm9udGVuZC1tb2RlbCBjb250cm9sbGVyLlxuICAgKiBAcGFyYW0ge3tuYW1lOiBzdHJpbmcsIHJlY29yZElkOiBzdHJpbmcsIHJlY29yZFR5cGU6IHN0cmluZ319IGFyZ3Mub3duZXJTY29wZSAtIE93bmVyIHNjb3BlLlxuICAgKiBAcmV0dXJucyB7e2JhY2tlbmRQcm9qZWN0OiBpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLXR5cGVzLmpzXCIpLkJhY2tlbmRQcm9qZWN0Q29uZmlndXJhdGlvbiwgbW9kZWxOYW1lOiBzdHJpbmcsIHJlc291cmNlQ2xhc3M6IGltcG9ydChcIi4uL2NvbmZpZ3VyYXRpb24tdHlwZXMuanNcIikuRnJvbnRlbmRNb2RlbFJlc291cmNlQ2xhc3NUeXBlLCByZXNvdXJjZUNvbmZpZ3VyYXRpb246IGltcG9ydChcIi4uL2NvbmZpZ3VyYXRpb24tdHlwZXMuanNcIikuTm9ybWFsaXplZEZyb250ZW5kTW9kZWxSZXNvdXJjZUNvbmZpZ3VyYXRpb259IHwgbnVsbH0gLSBPd25lciByZXNvdXJjZSBjb25maWd1cmF0aW9uLlxuICAgKi9cbiAgYXR0YWNobWVudE93bmVyUmVzb3VyY2Uoe2NvbnRyb2xsZXIsIG93bmVyU2NvcGV9KSB7XG4gICAgY29uc3QgYmFja2VuZFByb2plY3RzID0gY29udHJvbGxlci5nZXRDb25maWd1cmF0aW9uKCkuZ2V0QmFja2VuZFByb2plY3RzKClcbiAgICBsZXQgcmVzb3VyY2VXaXRob3V0QXR0YWNobWVudCA9IG51bGxcblxuICAgIGlmIChiYWNrZW5kUHJvamVjdHMubGVuZ3RoIDwgMSkgdGhyb3cgbmV3IEVycm9yKFwiVmVsb2Npb3VzQXR0YWNobWVudCByZXF1aXJlcyBhIGJhY2tlbmQgcHJvamVjdFwiKVxuXG4gICAgZm9yIChjb25zdCBiYWNrZW5kUHJvamVjdCBvZiBiYWNrZW5kUHJvamVjdHMpIHtcbiAgICAgIGNvbnN0IG93bmVyUmVzb3VyY2UgPSBjb250cm9sbGVyLmZyb250ZW5kTW9kZWxSZXNvdXJjZUNvbmZpZ3VyYXRpb25Gb3JCYWNrZW5kUHJvamVjdE1vZGVsTmFtZSh7XG4gICAgICAgIGJhY2tlbmRQcm9qZWN0LFxuICAgICAgICBtb2RlbE5hbWU6IG93bmVyU2NvcGUucmVjb3JkVHlwZVxuICAgICAgfSlcblxuICAgICAgaWYgKCFvd25lclJlc291cmNlKSBjb250aW51ZVxuXG4gICAgICBjb25zdCBvd25lck1vZGVsQ2xhc3MgPSBjb250cm9sbGVyLmZyb250ZW5kTW9kZWxSZXNvdXJjZU1vZGVsQ2xhc3Mob3duZXJSZXNvdXJjZSlcblxuICAgICAgaWYgKCFvd25lck1vZGVsQ2xhc3MpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyBtb2RlbCBjbGFzcyBjb25maWd1cmVkIGZvciBhdHRhY2htZW50IG93bmVyICR7b3duZXJTY29wZS5yZWNvcmRUeXBlfWApXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGF0dGFjaG1lbnREZWZpbml0aW9ucyA9IG93bmVyTW9kZWxDbGFzcy5nZXRBdHRhY2htZW50c01hcCgpXG5cbiAgICAgIGlmIChhdHRhY2htZW50RGVmaW5pdGlvbnNbb3duZXJTY29wZS5uYW1lXSkgcmV0dXJuIG93bmVyUmVzb3VyY2VcblxuICAgICAgcmVzb3VyY2VXaXRob3V0QXR0YWNobWVudCB8fD0gb3duZXJSZXNvdXJjZVxuICAgIH1cblxuICAgIGlmIChyZXNvdXJjZVdpdGhvdXRBdHRhY2htZW50KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIGF0dGFjaG1lbnQgJyR7b3duZXJTY29wZS5uYW1lfScgY29uZmlndXJlZCBmb3IgJHtvd25lclNjb3BlLnJlY29yZFR5cGV9YClcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbFxuICB9XG59XG4iXX0=
241
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVsb2Npb3VzLWF0dGFjaG1lbnQtcmVzb3VyY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZnJvbnRlbmQtbW9kZWwtcmVzb3VyY2UvdmVsb2Npb3VzLWF0dGFjaG1lbnQtcmVzb3VyY2UuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8seUJBQXlCLE1BQU0sb0JBQW9CLENBQUE7QUFDMUQsT0FBTyxtQkFBbUIsTUFBTSxxREFBcUQsQ0FBQTtBQUNyRixPQUFPLEVBQUMsdUNBQXVDLEVBQUMsTUFBTSwyQ0FBMkMsQ0FBQTtBQUNqRyxPQUFPLGFBQWEsTUFBTSwwQkFBMEIsQ0FBQTtBQUNwRCxPQUFPLEVBQUMseUJBQXlCLEVBQUUsZ0NBQWdDLEVBQUMsTUFBTSwrQkFBK0IsQ0FBQTtBQUV6Ryx3SEFBd0g7QUFDeEgsMFVBQTBVO0FBRTFVOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsT0FBTyxPQUFPLDJCQUE0QixTQUFRLHlCQUF5QjtJQUNoRixNQUFNLENBQUMsVUFBVSxHQUFHLG1CQUFtQixDQUFBO0lBRXZDLHNHQUFzRztJQUN0RyxNQUFNLENBQUMsVUFBVSxHQUFHO1FBQ2xCLFFBQVEsRUFBRSxFQUFDLElBQUksRUFBRSxTQUFTLEVBQUM7UUFDM0IsV0FBVyxFQUFFLEVBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFDO1FBQzFDLFNBQVMsRUFBRSxFQUFDLElBQUksRUFBRSxVQUFVLEVBQUM7UUFDN0IsUUFBUSxFQUFFLEVBQUMsSUFBSSxFQUFFLFNBQVMsRUFBQztRQUMzQixFQUFFLEVBQUUsRUFBQyxJQUFJLEVBQUUsTUFBTSxFQUFDO1FBQ2xCLElBQUksRUFBRSxFQUFDLElBQUksRUFBRSxTQUFTLEVBQUM7UUFDdkIsUUFBUSxFQUFFLEVBQUMsSUFBSSxFQUFFLFNBQVMsRUFBQztRQUMzQixRQUFRLEVBQUUsRUFBQyxJQUFJLEVBQUUsU0FBUyxFQUFD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cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCBGcm9udGVuZE1vZGVsQmFzZVJlc291cmNlIGZyb20gXCIuL2Jhc2UtcmVzb3VyY2UuanNcIlxuaW1wb3J0IFZlbG9jaW91c0F0dGFjaG1lbnQgZnJvbSBcIi4uL2RhdGFiYXNlL3JlY29yZC9hdHRhY2htZW50cy9hdHRhY2htZW50LXJlY29yZC5qc1wiXG5pbXBvcnQge2Zyb250ZW5kTW9kZWxSZXNvdXJjZXNGb3JCYWNrZW5kUHJvamVjdH0gZnJvbSBcIi4uL2Zyb250ZW5kLW1vZGVscy9yZXNvdXJjZS1kZWZpbml0aW9uLmpzXCJcbmltcG9ydCBpc1BsYWluT2JqZWN0IGZyb20gXCIuLi91dGlscy9wbGFpbi1vYmplY3QuanNcIlxuaW1wb3J0IHttb2RlbFByaW1hcnlLZXlDb25kaXRpb25zLCBtb2RlbFByaW1hcnlLZXlWYWx1ZUZyb21DYWNoZUtleX0gZnJvbSBcIi4uL3V0aWxzL21vZGVsLXByaW1hcnkta2V5LmpzXCJcblxuLyoqIEB0eXBlZGVmIHt7bmFtZTogc3RyaW5nLCByZWNvcmRJZDogc3RyaW5nLCByZWNvcmRUeXBlOiBzdHJpbmcsIHJlc291cmNlTmFtZTogc3RyaW5nIHwgbnVsbH19IEF0dGFjaG1lbnRPd25lclNjb3BlICovXG4vKiogQHR5cGVkZWYge3tiYWNrZW5kUHJvamVjdDogaW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi10eXBlcy5qc1wiKS5CYWNrZW5kUHJvamVjdENvbmZpZ3VyYXRpb24sIG1vZGVsTmFtZTogc3RyaW5nLCByZXNvdXJjZUNsYXNzOiBpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLXR5cGVzLmpzXCIpLkZyb250ZW5kTW9kZWxSZXNvdXJjZUNsYXNzVHlwZSwgcmVzb3VyY2VDb25maWd1cmF0aW9uOiBpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLXR5cGVzLmpzXCIpLk5vcm1hbGl6ZWRGcm9udGVuZE1vZGVsUmVzb3VyY2VDb25maWd1cmF0aW9ufX0gQXR0YWNobWVudE93bmVyUmVzb3VyY2UgKi9cblxuLyoqXG4gKiBGcmFtZXdvcmstb3duZWQgZnJvbnRlbmQgcmVzb3VyY2UgZXhwb3Npbmcgc2FmZSBhdHRhY2htZW50IG1ldGFkYXRhIHdoaWxlXG4gKiBkZWxlZ2F0aW5nIHJlYWQgYXV0aG9yaXphdGlvbiB0byB0aGUgYXR0YWNoZWQgb3duZXIgcmVjb3JkLlxuICogQGF1Z21lbnRzIHtGcm9udGVuZE1vZGVsQmFzZVJlc291cmNlPHR5cGVvZiBWZWxvY2lvdXNBdHRhY2htZW50Pn1cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVmVsb2Npb3VzQXR0YWNobWVudFJlc291cmNlIGV4dGVuZHMgRnJvbnRlbmRNb2RlbEJhc2VSZXNvdXJjZSB7XG4gIHN0YXRpYyBNb2RlbENsYXNzID0gVmVsb2Npb3VzQXR0YWNobWVudFxuXG4gIC8qKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgaW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi10eXBlcy5qc1wiKS5Gcm9udGVuZE1vZGVsQXR0cmlidXRlQ29uZmlndXJhdGlvbj59ICovXG4gIHN0YXRpYyBhdHRyaWJ1dGVzID0ge1xuICAgIGJ5dGVTaXplOiB7dHlwZTogXCJpbnRlZ2VyXCJ9LFxuICAgIGNvbnRlbnRUeXBlOiB7bnVsbDogdHJ1ZSwgdHlwZTogXCJ2YXJjaGFyXCJ9LFxuICAgIGNyZWF0ZWRBdDoge3R5cGU6IFwiZGF0ZXRpbWVcIn0sXG4gICAgZmlsZW5hbWU6IHt0eXBlOiBcInZhcmNoYXJcIn0sXG4gICAgaWQ6IHt0eXBlOiBcInV1aWRcIn0sXG4gICAgbmFtZToge3R5cGU6IFwidmFyY2hhclwifSxcbiAgICBwb3NpdGlvbjoge3R5cGU6IFwiaW50ZWdlclwifSxcbiAgICByZWNvcmRJZDoge3R5cGU6IFwidmFyY2hhclwifSxcbiAgICByZWNvcmRUeXBlOiB7dHlwZTogXCJ2YXJjaGFyXCJ9LFxuICAgIHVwZGF0ZWRBdDoge3R5cGU6IFwiZGF0ZXRpbWVcIn1cbiAgfVxuXG4gIC8qKiBAdHlwZSB7c3RyaW5nW119ICovXG4gIHN0YXRpYyBidWlsdEluQ29sbGVjdGlvbkNvbW1hbmRzID0gW1wiaW5kZXhcIl1cblxuICAvKiogQHR5cGUge3N0cmluZ1tdfSAqL1xuICBzdGF0aWMgYnVpbHRJbk1lbWJlckNvbW1hbmRzID0gW1wiZmluZFwiXVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBhdHRhY2htZW50IG1ldGFkYXRhIHF1ZXJ5IGFmdGVyIG93bmVyLXNjb3BlIGF1dGhvcml6YXRpb24gaGFzXG4gICAqIHZhbGlkYXRlZCB0aGUgcmVxdWVzdCB0aHJvdWdoIGJlZm9yZUFjdGlvbi9maW5kLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vYmFzZS1yZXNvdXJjZS5qc1wiKS5Gcm9udGVuZE1vZGVsUmVzb3VyY2VBY3Rpb259IGFjdGlvbiAtIEZyb250ZW5kLW1vZGVsIGFjdGlvbi5cbiAgICogQHJldHVybnMge2ltcG9ydChcIi4uL2RhdGFiYXNlL3F1ZXJ5L21vZGVsLWNsYXNzLXF1ZXJ5LmpzXCIpLmRlZmF1bHQ8dHlwZW9mIFZlbG9jaW91c0F0dGFjaG1lbnQ+fSAtIEF0dGFjaG1lbnQgcXVlcnkuXG4gICAqL1xuICBhdXRob3JpemVkUXVlcnkoYWN0aW9uKSB7XG4gICAgdm9pZCBhY3Rpb25cblxuICAgIHJldHVybiBWZWxvY2lvdXNBdHRhY2htZW50LmFsbCgpXG4gIH1cblxuICAvKipcbiAgICogUnVucyBiZWZvcmUgYWN0aW9uLlxuICAgKiBAcGFyYW0ge1wiaW5kZXhcIiB8IFwiZmluZFwiIHwgXCJjcmVhdGVcIiB8IFwidXBkYXRlXCIgfCBcImRlc3Ryb3lcIiB8IFwiYXR0YWNoXCIgfCBcImRvd25sb2FkXCIgfCBcInVybFwifSBhY3Rpb24gLSBBY3Rpb24uXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgYmVmb3JlQWN0aW9uKGFjdGlvbikge1xuICAgIGlmIChhY3Rpb24gIT09IFwiaW5kZXhcIikgcmV0dXJuXG5cbiAgICBjb25zdCBhdXRob3JpemVkID0gYXdhaXQgdGhpcy5hdHRhY2htZW50T3duZXJBdXRob3JpemVkKHRoaXMucmVxdWlyZWRPd25lclNjb3BlRnJvbVBhcmFtcygpKVxuXG4gICAgaWYgKCFhdXRob3JpemVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJBdHRhY2htZW50IG93bmVyIG5vdCBmb3VuZCBvciBub3QgYXV0aG9yaXplZFwiKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBMb2FkcyBhdHRhY2htZW50IG1ldGFkYXRhIGFmdGVyIHJlbW92aW5nIHRoZSBhdXRob3JpemF0aW9uLW9ubHkgcmVzb3VyY2UgbmFtZSBmcm9tIGRhdGFiYXNlIGZpbHRlcnMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFZlbG9jaW91c0F0dGFjaG1lbnRbXT59IC0gQXR0YWNobWVudCBtZXRhZGF0YSByb3dzLlxuICAgKi9cbiAgYXN5bmMgcmVjb3JkcygpIHtcbiAgICBjb25zdCBjb250cm9sbGVyID0gLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9mcm9udGVuZC1tb2RlbC1jb250cm9sbGVyLmpzXCIpLmRlZmF1bHR9ICovICh0aGlzLmNvbnRyb2xsZXJJbnN0YW5jZSgpKVxuICAgIGNvbnN0IHBhcmFtcyA9IGNvbnRyb2xsZXIuZnJvbnRlbmRNb2RlbFBhcmFtcygpXG4gICAgY29uc3Qgd2hlcmUgPSB7Li4udGhpcy5yZXF1aXJlZFdoZXJlRnJvbVBhcmFtcygpfVxuXG4gICAgZGVsZXRlIHdoZXJlLnJlc291cmNlTmFtZVxuXG4gICAgcmV0dXJuIGF3YWl0IGNvbnRyb2xsZXIud2l0aEZyb250ZW5kTW9kZWxQYXJhbXMoey4uLnBhcmFtcywgd2hlcmV9LCBhc3luYyAoKSA9PiBhd2FpdCB0aGlzLmluZGV4UXVlcnkoKS50b0FycmF5KCkpXG4gIH1cblxuICAvKipcbiAgICogUnVucyBmaW5kLlxuICAgKiBAcGFyYW0ge1wiZmluZFwiIHwgXCJ1cGRhdGVcIiB8IFwiZGVzdHJveVwiIHwgXCJhdHRhY2hcIiB8IFwiZG93bmxvYWRcIiB8IFwidXJsXCJ9IGFjdGlvbiAtIEFjdGlvbi5cbiAgICogQHBhcmFtIHtzdHJpbmcgfCBudW1iZXJ9IGlkIC0gQXR0YWNobWVudCBpZC5cbiAgICogQHJldHVybnMge1Byb21pc2U8VmVsb2Npb3VzQXR0YWNobWVudCB8IG51bGw+fSAtIExvY2F0ZWQgYXR0YWNobWVudCB3aGVuIG93bmVyIGlzIGF1dGhvcml6ZWQuXG4gICAqL1xuICBhc3luYyBmaW5kKGFjdGlvbiwgaWQpIHtcbiAgICB2b2lkIGFjdGlvblxuXG4gICAgY29uc3QgYXR0YWNobWVudCA9IGF3YWl0IFZlbG9jaW91c0F0dGFjaG1lbnQuZmluZEJ5KHtpZH0pXG5cbiAgICBpZiAoIWF0dGFjaG1lbnQpIHJldHVybiBudWxsXG4gICAgaWYgKCFhd2FpdCB0aGlzLmF0dGFjaG1lbnRPd25lckF1dGhvcml6ZWQodGhpcy5vd25lclNjb3BlRnJvbUF0dGFjaG1lbnQoYXR0YWNobWVudCkpKSByZXR1cm4gbnVsbFxuXG4gICAgcmV0dXJuIGF0dGFjaG1lbnRcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGNyZWF0ZWQgYXQgYXR0cmlidXRlLlxuICAgKiBAcGFyYW0ge1ZlbG9jaW91c0F0dGFjaG1lbnR9IG1vZGVsIC0gQXR0YWNobWVudCBtb2RlbC5cbiAgICogQHJldHVybnMge0RhdGV9IC0gQ3JlYXRlZC1hdCB0aW1lc3RhbXAuXG4gICAqL1xuICBjcmVhdGVkQXRBdHRyaWJ1dGUobW9kZWwpIHtcbiAgICByZXR1cm4gbmV3IERhdGUobW9kZWwuY3JlYXRlZEF0TXMoKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHVwZGF0ZWQgYXQgYXR0cmlidXRlLlxuICAgKiBAcGFyYW0ge1ZlbG9jaW91c0F0dGFjaG1lbnR9IG1vZGVsIC0gQXR0YWNobWVudCBtb2RlbC5cbiAgICogQHJldHVybnMge0RhdGV9IC0gVXBkYXRlZC1hdCB0aW1lc3RhbXAuXG4gICAqL1xuICB1cGRhdGVkQXRBdHRyaWJ1dGUobW9kZWwpIHtcbiAgICByZXR1cm4gbmV3IERhdGUobW9kZWwudXBkYXRlZEF0TXMoKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgdmFsaWRhdGVkIG93bmVyIHNjb3BlIGZyb20gZnJvbnRlbmQtbW9kZWwgd2hlcmUgcGFyYW1zLlxuICAgKiBAcmV0dXJucyB7QXR0YWNobWVudE93bmVyU2NvcGV9IC0gQXR0YWNobWVudCBvd25lciBzY29wZS5cbiAgICovXG4gIHJlcXVpcmVkT3duZXJTY29wZUZyb21QYXJhbXMoKSB7XG4gICAgY29uc3Qgd2hlcmUgPSB0aGlzLnJlcXVpcmVkV2hlcmVGcm9tUGFyYW1zKClcbiAgICBjb25zdCByZWNvcmRUeXBlID0gdGhpcy5yZXF1aXJlZFNpbmdsZVdoZXJlVmFsdWUoe2F0dHJpYnV0ZU5hbWU6IFwicmVjb3JkVHlwZVwiLCB3aGVyZX0pXG5cbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogdGhpcy5yZXF1aXJlZFNpbmdsZVdoZXJlVmFsdWUoe2F0dHJpYnV0ZU5hbWU6IFwibmFtZVwiLCB3aGVyZX0pLFxuICAgICAgcmVjb3JkSWQ6IHRoaXMucmVxdWlyZWRTaW5nbGVXaGVyZVZhbHVlKHthdHRyaWJ1dGVOYW1lOiBcInJlY29yZElkXCIsIHdoZXJlfSksXG4gICAgICByZWNvcmRUeXBlLFxuICAgICAgcmVzb3VyY2VOYW1lOiB0aGlzLnJlcXVpcmVkU2luZ2xlV2hlcmVWYWx1ZSh7YXR0cmlidXRlTmFtZTogXCJyZXNvdXJjZU5hbWVcIiwgd2hlcmV9KVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSByZXF1aXJlZCBhdHRhY2htZW50IG1ldGFkYXRhIHdoZXJlIG9iamVjdC5cbiAgICogQHJldHVybnMge1JlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn0gLSBBdHRhY2htZW50IHdoZXJlIGZpbHRlcnMuXG4gICAqL1xuICByZXF1aXJlZFdoZXJlRnJvbVBhcmFtcygpIHtcbiAgICBjb25zdCB3aGVyZSA9IHRoaXMucGFyYW1zKCkud2hlcmVcblxuICAgIGlmICghaXNQbGFpbk9iamVjdCh3aGVyZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlZlbG9jaW91c0F0dGFjaG1lbnQgaW5kZXggcmVxdWlyZXMgcmVzb3VyY2VOYW1lLCByZWNvcmRUeXBlLCByZWNvcmRJZCwgYW5kIG5hbWUgd2hlcmUgZmlsdGVyc1wiKVxuICAgIH1cblxuICAgIHJldHVybiB3aGVyZVxuICB9XG5cbiAgLyoqXG4gICAqIFJlYWRzIG9uZSByZXF1aXJlZCBzdHJpbmctbGlrZSB3aGVyZSB2YWx1ZS5cbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBBcmdzLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYXJncy5hdHRyaWJ1dGVOYW1lIC0gQXR0cmlidXRlIG5hbWUuXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+fSBhcmdzLndoZXJlIC0gV2hlcmUgaGFzaC5cbiAgICogQHJldHVybnMge3N0cmluZ30gLSBTdHJpbmcgdmFsdWUuXG4gICAqL1xuICByZXF1aXJlZFNpbmdsZVdoZXJlVmFsdWUoe2F0dHJpYnV0ZU5hbWUsIHdoZXJlfSkge1xuICAgIGNvbnN0IHZhbHVlID0gd2hlcmVbYXR0cmlidXRlTmFtZV1cblxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgfHwgdHlwZW9mIHZhbHVlID09PSBcIm51bWJlclwiKSByZXR1cm4gU3RyaW5nKHZhbHVlKVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGBWZWxvY2lvdXNBdHRhY2htZW50IGluZGV4IHJlcXVpcmVzIGEgc2luZ2xlICR7YXR0cmlidXRlTmFtZX0gd2hlcmUgZmlsdGVyYClcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgb3duZXIgc2NvcGUgZnJvbSBhIHN0b3JlZCBhdHRhY2htZW50IHJvdy5cbiAgICogQHBhcmFtIHtWZWxvY2lvdXNBdHRhY2htZW50fSBhdHRhY2htZW50IC0gQXR0YWNobWVudCByb3cuXG4gICAqIEByZXR1cm5zIHtBdHRhY2htZW50T3duZXJTY29wZX0gLSBPd25lciBzY29wZS5cbiAgICovXG4gIG93bmVyU2NvcGVGcm9tQXR0YWNobWVudChhdHRhY2htZW50KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWU6IGF0dGFjaG1lbnQubmFtZSgpLFxuICAgICAgcmVjb3JkSWQ6IGF0dGFjaG1lbnQucmVjb3JkSWQoKSxcbiAgICAgIHJlY29yZFR5cGU6IGF0dGFjaG1lbnQucmVjb3JkVHlwZSgpLFxuICAgICAgcmVzb3VyY2VOYW1lOiBudWxsXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyB3aGV0aGVyIHRoZSBjdXJyZW50IGFiaWxpdHkgY2FuIHJlYWQgdGhlIGF0dGFjaG1lbnQgb3duZXIuXG4gICAqIEBwYXJhbSB7QXR0YWNobWVudE93bmVyU2NvcGV9IG93bmVyU2NvcGUgLSBPd25lciBzY29wZS5cbiAgICogQHJldHVybnMge1Byb21pc2U8Ym9vbGVhbj59IC0gV2hldGhlciBvd25lciBpcyByZWFkYWJsZS5cbiAgICovXG4gIGFzeW5jIGF0dGFjaG1lbnRPd25lckF1dGhvcml6ZWQob3duZXJTY29wZSkge1xuICAgIGNvbnN0IGNvbnRyb2xsZXIgPSAvKiogQHR5cGUge2ltcG9ydChcIi4uL2Zyb250ZW5kLW1vZGVsLWNvbnRyb2xsZXIuanNcIikuZGVmYXVsdH0gKi8gKHRoaXMuY29udHJvbGxlckluc3RhbmNlKCkpXG4gICAgY29uc3Qgb3duZXJSZXNvdXJjZXMgPSB0aGlzLmF0dGFjaG1lbnRPd25lclJlc291cmNlcyh7Y29udHJvbGxlciwgb3duZXJTY29wZX0pXG5cbiAgICBpZiAob3duZXJSZXNvdXJjZXMubGVuZ3RoIDwgMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyBmcm9udGVuZCBtb2RlbCByZXNvdXJjZSBjb25maWd1cmVkIGZvciBhdHRhY2htZW50IG93bmVyICR7b3duZXJTY29wZS5yZXNvdXJjZU5hbWUgPz8gb3duZXJTY29wZS5yZWNvcmRUeXBlfWApXG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBvd25lclJlc291cmNlIG9mIG93bmVyUmVzb3VyY2VzKSB7XG4gICAgICBjb25zdCBvd25lck1vZGVsQ2xhc3MgPSBjb250cm9sbGVyLmZyb250ZW5kTW9kZWxSZXNvdXJjZU1vZGVsQ2xhc3Mob3duZXJSZXNvdXJjZSlcblxuICAgICAgYXdhaXQgY29udHJvbGxlci5lbnN1cmVGcm9udGVuZE1vZGVsUmVjb3JkQ2xhc3NJbml0aWFsaXplZChvd25lck1vZGVsQ2xhc3MpXG5cbiAgICAgIGNvbnN0IGFiaWxpdHlBY3Rpb24gPSBvd25lclJlc291cmNlLnJlc291cmNlQ29uZmlndXJhdGlvbi5hYmlsaXRpZXMuZmluZCB8fCBvd25lclJlc291cmNlLnJlc291cmNlQ29uZmlndXJhdGlvbi5hYmlsaXRpZXMuaW5kZXggfHwgXCJyZWFkXCJcbiAgICAgIGNvbnN0IHByaW1hcnlLZXkgPSBvd25lck1vZGVsQ2xhc3MucHJpbWFyeUtleSgpXG4gICAgICBjb25zdCBvd25lcklkZW50aXR5ID0gbW9kZWxQcmltYXJ5S2V5VmFsdWVGcm9tQ2FjaGVLZXkocHJpbWFyeUtleSwgb3duZXJTY29wZS5yZWNvcmRJZClcbiAgICAgIGNvbnN0IG93bmVyID0gYXdhaXQgb3duZXJNb2RlbENsYXNzXG4gICAgICAgIC5hY2Nlc3NpYmxlRm9yKGFiaWxpdHlBY3Rpb24sIHRoaXMuYWJpbGl0eSlcbiAgICAgICAgLmZpbmRCeShtb2RlbFByaW1hcnlLZXlDb25kaXRpb25zKHByaW1hcnlLZXksIG93bmVySWRlbnRpdHkpKVxuXG4gICAgICBpZiAob3duZXIpIHJldHVybiB0cnVlXG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZXMgdGhlIGV4cGxpY2l0IG93bmVyIHJlc291cmNlIGZvciBzY29wZWQgcXVlcmllcyBvciBldmVyeSBtYXRjaGluZyBhbGlhcyBmb3IgbWVtYmVyIGxvb2t1cHMuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucyBvYmplY3QuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZnJvbnRlbmQtbW9kZWwtY29udHJvbGxlci5qc1wiKS5kZWZhdWx0fSBhcmdzLmNvbnRyb2xsZXIgLSBGcm9udGVuZC1tb2RlbCBjb250cm9sbGVyLlxuICAgKiBAcGFyYW0ge0F0dGFjaG1lbnRPd25lclNjb3BlfSBhcmdzLm93bmVyU2NvcGUgLSBPd25lciBzY29wZS5cbiAgICogQHJldHVybnMge0F0dGFjaG1lbnRPd25lclJlc291cmNlW119IC0gTWF0Y2hpbmcgb3duZXIgcmVzb3VyY2VzLlxuICAgKi9cbiAgYXR0YWNobWVudE93bmVyUmVzb3VyY2VzKHtjb250cm9sbGVyLCBvd25lclNjb3BlfSkge1xuICAgIGlmIChvd25lclNjb3BlLnJlc291cmNlTmFtZSkge1xuICAgICAgY29uc3Qgb3duZXJSZXNvdXJjZSA9IHRoaXMuYXR0YWNobWVudE93bmVyUmVzb3VyY2Uoe1xuICAgICAgICBjb250cm9sbGVyLFxuICAgICAgICBvd25lclNjb3BlOiB7Li4ub3duZXJTY29wZSwgcmVzb3VyY2VOYW1lOiBvd25lclNjb3BlLnJlc291cmNlTmFtZX1cbiAgICAgIH0pXG5cbiAgICAgIHJldHVybiBvd25lclJlc291cmNlID8gW293bmVyUmVzb3VyY2VdIDogW11cbiAgICB9XG5cbiAgICBjb25zdCBvd25lclJlc291cmNlcyA9IFtdXG5cbiAgICBmb3IgKGNvbnN0IGJhY2tlbmRQcm9qZWN0IG9mIGNvbnRyb2xsZXIuZ2V0Q29uZmlndXJhdGlvbigpLmdldEJhY2tlbmRQcm9qZWN0cygpKSB7XG4gICAgICBmb3IgKGNvbnN0IHJlc291cmNlTmFtZSBvZiBPYmplY3Qua2V5cyhmcm9udGVuZE1vZGVsUmVzb3VyY2VzRm9yQmFja2VuZFByb2plY3QoYmFja2VuZFByb2plY3QpKSkge1xuICAgICAgICBjb25zdCBvd25lclJlc291cmNlID0gY29udHJvbGxlci5mcm9udGVuZE1vZGVsUmVzb3VyY2VDb25maWd1cmF0aW9uRm9yQmFja2VuZFByb2plY3RNb2RlbE5hbWUoe2JhY2tlbmRQcm9qZWN0LCBtb2RlbE5hbWU6IHJlc291cmNlTmFtZX0pXG5cbiAgICAgICAgaWYgKCFvd25lclJlc291cmNlKSBjb250aW51ZVxuXG4gICAgICAgIGNvbnN0IG93bmVyTW9kZWxDbGFzcyA9IGNvbnRyb2xsZXIuZnJvbnRlbmRNb2RlbFJlc291cmNlTW9kZWxDbGFzcyhvd25lclJlc291cmNlKVxuXG4gICAgICAgIGlmIChvd25lck1vZGVsQ2xhc3MuZ2V0TW9kZWxOYW1lKCkgIT09IG93bmVyU2NvcGUucmVjb3JkVHlwZSkgY29udGludWVcbiAgICAgICAgaWYgKCFvd25lclJlc291cmNlLnJlc291cmNlQ29uZmlndXJhdGlvbi5hdHRhY2htZW50cz8uW293bmVyU2NvcGUubmFtZV0pIGNvbnRpbnVlXG5cbiAgICAgICAgb3duZXJSZXNvdXJjZXMucHVzaChvd25lclJlc291cmNlKVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBvd25lclJlc291cmNlc1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmRzIHRoZSBmcm9udGVuZC1tb2RlbCByZXNvdXJjZSB0aGF0IG93bnMgYW4gYXR0YWNobWVudCBzY29wZS5cbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zIG9iamVjdC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9mcm9udGVuZC1tb2RlbC1jb250cm9sbGVyLmpzXCIpLmRlZmF1bHR9IGFyZ3MuY29udHJvbGxlciAtIEZyb250ZW5kLW1vZGVsIGNvbnRyb2xsZXIuXG4gICAqIEBwYXJhbSB7e25hbWU6IHN0cmluZywgcmVjb3JkSWQ6IHN0cmluZywgcmVjb3JkVHlwZTogc3RyaW5nLCByZXNvdXJjZU5hbWU6IHN0cmluZ319IGFyZ3Mub3duZXJTY29wZSAtIE93bmVyIHNjb3BlLlxuICAgKiBAcmV0dXJucyB7QXR0YWNobWVudE93bmVyUmVzb3VyY2UgfCBudWxsfSAtIE93bmVyIHJlc291cmNlIGNvbmZpZ3VyYXRpb24uXG4gICAqL1xuICBhdHRhY2htZW50T3duZXJSZXNvdXJjZSh7Y29udHJvbGxlciwgb3duZXJTY29wZX0pIHtcbiAgICBjb25zdCBiYWNrZW5kUHJvamVjdHMgPSBjb250cm9sbGVyLmdldENvbmZpZ3VyYXRpb24oKS5nZXRCYWNrZW5kUHJvamVjdHMoKVxuICAgIGxldCByZXNvdXJjZVdpdGhvdXRBdHRhY2htZW50ID0gbnVsbFxuXG4gICAgaWYgKGJhY2tlbmRQcm9qZWN0cy5sZW5ndGggPCAxKSB0aHJvdyBuZXcgRXJyb3IoXCJWZWxvY2lvdXNBdHRhY2htZW50IHJlcXVpcmVzIGEgYmFja2VuZCBwcm9qZWN0XCIpXG5cbiAgICBmb3IgKGNvbnN0IGJhY2tlbmRQcm9qZWN0IG9mIGJhY2tlbmRQcm9qZWN0cykge1xuICAgICAgY29uc3Qgb3duZXJSZXNvdXJjZSA9IGNvbnRyb2xsZXIuZnJvbnRlbmRNb2RlbFJlc291cmNlQ29uZmlndXJhdGlvbkZvckJhY2tlbmRQcm9qZWN0TW9kZWxOYW1lKHtcbiAgICAgICAgYmFja2VuZFByb2plY3QsXG4gICAgICAgIG1vZGVsTmFtZTogb3duZXJTY29wZS5yZXNvdXJjZU5hbWVcbiAgICAgIH0pXG5cbiAgICAgIGlmICghb3duZXJSZXNvdXJjZSkgY29udGludWVcblxuICAgICAgY29uc3Qgb3duZXJNb2RlbENsYXNzID0gY29udHJvbGxlci5mcm9udGVuZE1vZGVsUmVzb3VyY2VNb2RlbENsYXNzKG93bmVyUmVzb3VyY2UpXG5cbiAgICAgIGlmICghb3duZXJNb2RlbENsYXNzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gbW9kZWwgY2xhc3MgY29uZmlndXJlZCBmb3IgYXR0YWNobWVudCBvd25lciAke293bmVyU2NvcGUucmVzb3VyY2VOYW1lfWApXG4gICAgICB9XG5cbiAgICAgIGlmIChvd25lck1vZGVsQ2xhc3MuZ2V0TW9kZWxOYW1lKCkgIT09IG93bmVyU2NvcGUucmVjb3JkVHlwZSkgY29udGludWVcblxuICAgICAgY29uc3QgYXR0YWNobWVudERlZmluaXRpb25zID0gb3duZXJSZXNvdXJjZS5yZXNvdXJjZUNvbmZpZ3VyYXRpb24uYXR0YWNobWVudHMgfHwge31cblxuICAgICAgaWYgKGF0dGFjaG1lbnREZWZpbml0aW9uc1tvd25lclNjb3BlLm5hbWVdKSByZXR1cm4gb3duZXJSZXNvdXJjZVxuXG4gICAgICByZXNvdXJjZVdpdGhvdXRBdHRhY2htZW50IHx8PSBvd25lclJlc291cmNlXG4gICAgfVxuXG4gICAgaWYgKHJlc291cmNlV2l0aG91dEF0dGFjaG1lbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gYXR0YWNobWVudCAnJHtvd25lclNjb3BlLm5hbWV9JyBjb25maWd1cmVkIGZvciAke293bmVyU2NvcGUucmVzb3VyY2VOYW1lfWApXG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGxcbiAgfVxufVxuIl19
@@ -2,7 +2,7 @@ import FrontendModelQuery from "./query.js";
2
2
  export type FrontendModelRelationship = FrontendModelHasManyRelationship<any, any, any> | FrontendModelSingularRelationship<any, any, any>;
3
3
  export type FrontendModelModelEventCallbackEntry = {
4
4
  callback: (payload: {
5
- id: string;
5
+ id: string | import("../utils/model-primary-key.js").CompositeModelPrimaryKeyValue;
6
6
  model: FrontendModelBase;
7
7
  }) => void;
8
8
  eventFilterKey: string | null;
@@ -11,7 +11,7 @@ export type FrontendModelModelEventCallbackEntry = {
11
11
  };
12
12
  export type FrontendModelDestroyEventCallbackEntry = {
13
13
  callback: (payload: {
14
- id: string;
14
+ id: string | import("../utils/model-primary-key.js").CompositeModelPrimaryKeyValue;
15
15
  }) => void;
16
16
  };
17
17
  export type FrontendModelCommandType = "create" | "find" | "index" | "update" | "destroy" | "attach" | "attachmentList" | "download" | "url";
@@ -65,7 +65,7 @@ export type FrontendModelResourceConfig = {
65
65
  allowDestroy?: boolean;
66
66
  limit?: number;
67
67
  }>;
68
- primaryKey?: string;
68
+ primaryKey?: string | string[];
69
69
  relationships?: string[];
70
70
  sync?: FrontendModelSyncConfig;
71
71
  };
@@ -523,6 +523,15 @@ export default class FrontendModelBase<Attributes extends object = any, CreateAt
523
523
  * @type {Array<FrontendModelBase> | undefined} - Shared reference to sibling records loaded in the same batch. Used by auto-batch-preload.
524
524
  */
525
525
  _loadCohort: Array<FrontendModelBase> | undefined;
526
+ /**
527
+ * Canonical backing-record attachment owner returned by the server.
528
+ * @type {{recordId: string, recordType: string, resourceName: string} | null}
529
+ */
530
+ _attachmentOwner: {
531
+ recordId: string;
532
+ recordType: string;
533
+ resourceName: string;
534
+ } | null;
526
535
  /**
527
536
  * Runs constructor.
528
537
  * @param {Attributes | CreateAttributes} [attributes] - Initial attributes.
@@ -725,14 +734,25 @@ export default class FrontendModelBase<Attributes extends object = any, CreateAt
725
734
  /**
726
735
  * Runs primary key.
727
736
  * @this {FrontendModelClass}
728
- * @returns {string} - Primary key name.
737
+ * @returns {import("../utils/model-primary-key.js").ModelPrimaryKeyDefinition} - Primary key name.
729
738
  */
730
- static primaryKey(this: FrontendModelClass): string;
739
+ static primaryKey(this: FrontendModelClass): import("../utils/model-primary-key.js").ModelPrimaryKeyDefinition;
731
740
  /**
732
741
  * Runs primary key value.
733
- * @returns {number | string} - Primary key value.
742
+ * @returns {import("../utils/model-primary-key.js").ModelPrimaryKeyValue} - Primary key value.
743
+ */
744
+ primaryKeyValue(): import("../utils/model-primary-key.js").ModelPrimaryKeyValue;
745
+ /**
746
+ * Returns the scalar identity required by scalar-only frontend features.
747
+ * @param {string} operation - Operation requiring a scalar identity.
748
+ * @returns {import("../utils/model-primary-key.js").ModelPrimaryKeyScalar} - Scalar primary-key value.
749
+ */
750
+ scalarPrimaryKeyValue(operation: string): import("../utils/model-primary-key.js").ModelPrimaryKeyScalar;
751
+ /**
752
+ * Returns the identity represented by the last persisted frontend attributes.
753
+ * @returns {import("../utils/model-primary-key.js").ModelPrimaryKeyValue} - Persisted primary-key value.
734
754
  */
735
- primaryKeyValue(): number | string;
755
+ persistedPrimaryKeyValue(): import("../utils/model-primary-key.js").ModelPrimaryKeyValue;
736
756
  /**
737
757
  * Runs read attribute.
738
758
  * @param {string} attributeName - Attribute name.
@@ -980,10 +1000,15 @@ export default class FrontendModelBase<Attributes extends object = any, CreateAt
980
1000
  * Runs model data from response.
981
1001
  * @this {FrontendModelClass}
982
1002
  * @param {object} response - Response payload.
983
- * @returns {{abilities: Record<string, boolean>, attributes: Record<string, FrontendModelAttributeValue>, associationCounts: Record<string, number>, queryData: Record<string, FrontendModelAttributeValue>, preloadedRelationships: Record<string, FrontendModelAttributeValue>, selectedAttributes: Set<string>}} - Attributes, preloaded relationships, association counts, queryData, abilities, and the selected-attributes set.
1003
+ * @returns {{abilities: Record<string, boolean>, attachmentOwner: {recordId: string, recordType: string, resourceName: string} | null, attributes: Record<string, FrontendModelAttributeValue>, associationCounts: Record<string, number>, queryData: Record<string, FrontendModelAttributeValue>, preloadedRelationships: Record<string, FrontendModelAttributeValue>, selectedAttributes: Set<string>}} - Attributes, attachment owner, preloaded relationships, association counts, queryData, abilities, and selected attributes.
984
1004
  */
985
1005
  static modelDataFromResponse(this: FrontendModelClass, response: object): {
986
1006
  abilities: Record<string, boolean>;
1007
+ attachmentOwner: {
1008
+ recordId: string;
1009
+ recordType: string;
1010
+ resourceName: string;
1011
+ } | null;
987
1012
  attributes: Record<string, FrontendModelAttributeValue>;
988
1013
  associationCounts: Record<string, number>;
989
1014
  queryData: Record<string, FrontendModelAttributeValue>;
@@ -1018,10 +1043,10 @@ export default class FrontendModelBase<Attributes extends object = any, CreateAt
1018
1043
  * Runs find.
1019
1044
  * @template {FrontendModelClass} T
1020
1045
  * @this {T}
1021
- * @param {number | string} id - Record identifier.
1046
+ * @param {import("../utils/model-primary-key.js").ModelPrimaryKeyValue} id - Record identifier.
1022
1047
  * @returns {Promise<InstanceType<T>>} - Resolved model.
1023
1048
  */
1024
- static find<T extends FrontendModelClass>(this: T, id: number | string): Promise<InstanceType<T>>;
1049
+ static find<T extends FrontendModelClass>(this: T, id: import("../utils/model-primary-key.js").ModelPrimaryKeyValue): Promise<InstanceType<T>>;
1025
1050
  /**
1026
1051
  * Runs find by.
1027
1052
  * @template {FrontendModelClass} T
@@ -1121,56 +1146,56 @@ export default class FrontendModelBase<Attributes extends object = any, CreateAt
1121
1146
  * without re-checking per-record visibility. Query options can still
1122
1147
  * narrow which events reach this callback.
1123
1148
  * @this {FrontendModelClass}
1124
- * @param {(payload: {id: string, model: FrontendModelBase}) => void} callback - Event callback.
1149
+ * @param {(payload: {id: string | import("../utils/model-primary-key.js").CompositeModelPrimaryKeyValue, model: FrontendModelBase}) => void} callback - Event callback.
1125
1150
  * @param {import("./query.js").FrontendModelEventOptions} [options] - Event query or record projection options.
1126
1151
  * @returns {Promise<() => void>} - Unsubscribe callback.
1127
1152
  */
1128
1153
  static onCreate(this: FrontendModelClass, callback: (payload: {
1129
- id: string;
1154
+ id: string | import("../utils/model-primary-key.js").CompositeModelPrimaryKeyValue;
1130
1155
  model: FrontendModelBase;
1131
1156
  }) => void, options?: import("./query.js").FrontendModelEventOptions): Promise<() => void>;
1132
1157
  /**
1133
1158
  * Class-level hook fired when any record of this model is updated.
1134
1159
  * @this {FrontendModelClass}
1135
- * @param {(payload: {id: string, model: FrontendModelBase}) => void} callback - Event callback.
1160
+ * @param {(payload: {id: string | import("../utils/model-primary-key.js").CompositeModelPrimaryKeyValue, model: FrontendModelBase}) => void} callback - Event callback.
1136
1161
  * @param {import("./query.js").FrontendModelEventOptions} [options] - Event query or record projection options.
1137
1162
  * @returns {Promise<() => void>} - Unsubscribe callback.
1138
1163
  */
1139
1164
  static onUpdate(this: FrontendModelClass, callback: (payload: {
1140
- id: string;
1165
+ id: string | import("../utils/model-primary-key.js").CompositeModelPrimaryKeyValue;
1141
1166
  model: FrontendModelBase;
1142
1167
  }) => void, options?: import("./query.js").FrontendModelEventOptions): Promise<() => void>;
1143
1168
  /**
1144
1169
  * Class-level hook fired when any record of this model is destroyed.
1145
1170
  * @this {FrontendModelClass}
1146
- * @param {(payload: {id: string}) => void} callback - Event callback.
1171
+ * @param {(payload: {id: string | import("../utils/model-primary-key.js").CompositeModelPrimaryKeyValue}) => void} callback - Event callback.
1147
1172
  * @param {import("./query.js").FrontendModelEventOptions} [options] - Accepted for API symmetry; destroy events carry ids only.
1148
1173
  * @returns {Promise<() => void>} - Unsubscribe callback.
1149
1174
  */
1150
1175
  static onDestroy(this: FrontendModelClass, callback: (payload: {
1151
- id: string;
1176
+ id: string | import("../utils/model-primary-key.js").CompositeModelPrimaryKeyValue;
1152
1177
  }) => void, options?: import("./query.js").FrontendModelEventOptions): Promise<() => void>;
1153
1178
  /**
1154
1179
  * Instance-level hook fired when THIS record is updated. The
1155
1180
  * instance's attributes are auto-merged with the broadcast payload
1156
1181
  * before the callback runs, so callers can read fresh values via
1157
1182
  * `this.someAttr()` without re-fetching.
1158
- * @param {(payload: {id: string, model: FrontendModelBase}) => void} callback - Event callback.
1183
+ * @param {(payload: {id: string | import("../utils/model-primary-key.js").CompositeModelPrimaryKeyValue, model: FrontendModelBase}) => void} callback - Event callback.
1159
1184
  * @param {import("./query.js").FrontendModelEventOptions} [options] - Event query or record projection options.
1160
1185
  * @returns {Promise<() => void>} - Unsubscribe callback.
1161
1186
  */
1162
1187
  onUpdate(callback: (payload: {
1163
- id: string;
1188
+ id: string | import("../utils/model-primary-key.js").CompositeModelPrimaryKeyValue;
1164
1189
  model: FrontendModelBase;
1165
1190
  }) => void, options?: import("./query.js").FrontendModelEventOptions): Promise<() => void>;
1166
1191
  /**
1167
1192
  * Instance-level hook fired when THIS record is destroyed.
1168
- * @param {(payload: {id: string}) => void} callback - Event callback.
1193
+ * @param {(payload: {id: string | import("../utils/model-primary-key.js").CompositeModelPrimaryKeyValue}) => void} callback - Event callback.
1169
1194
  * @param {import("./query.js").FrontendModelEventOptions} [options] - Accepted for API symmetry; destroy events carry ids only.
1170
1195
  * @returns {Promise<() => void>} - Unsubscribe callback.
1171
1196
  */
1172
1197
  onDestroy(callback: (payload: {
1173
- id: string;
1198
+ id: string | import("../utils/model-primary-key.js").CompositeModelPrimaryKeyValue;
1174
1199
  }) => void, options?: import("./query.js").FrontendModelEventOptions): Promise<() => void>;
1175
1200
  /**
1176
1201
  * Runs pluck.
@@ -1485,6 +1510,14 @@ export declare class VelociousAttachment extends FrontendModelBase {
1485
1510
  * @returns {FrontendModelResourceConfig} - Resource config.
1486
1511
  */
1487
1512
  static resourceConfig(): FrontendModelResourceConfig;
1513
+ /**
1514
+ * Finds attachment metadata by its public id through the member authorization path.
1515
+ * @template {FrontendModelClass} T
1516
+ * @this {T}
1517
+ * @param {import("../utils/model-primary-key.js").ModelPrimaryKeyValue} id - Attachment id.
1518
+ * @returns {Promise<InstanceType<T>>} - Resolved attachment metadata.
1519
+ */
1520
+ static find<T extends FrontendModelClass>(this: T, id: import("../utils/model-primary-key.js").ModelPrimaryKeyValue): Promise<InstanceType<T>>;
1488
1521
  /**
1489
1522
  * Returns the attachment id.
1490
1523
  * @returns {string} - Attachment id.