@jini-ai/cms 0.3.11 → 0.4.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 (258) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/README.md +47 -19
  3. package/dist/content-types/agent-tools.d.ts +3 -56
  4. package/dist/content-types/agent-tools.js +22 -6
  5. package/dist/content-types/cleanup.d.ts +18 -13
  6. package/dist/content-types/cleanup.js +16 -11
  7. package/dist/content-types/errors.d.ts +57 -24
  8. package/dist/content-types/errors.js +56 -39
  9. package/dist/content-types/field-defs.d.ts +8 -4
  10. package/dist/content-types/field-defs.js +19 -14
  11. package/dist/content-types/index-provisioning.d.ts +61 -47
  12. package/dist/content-types/index-provisioning.js +90 -66
  13. package/dist/content-types/index.d.ts +4 -3
  14. package/dist/content-types/lifecycle-dispatch.d.ts +11 -5
  15. package/dist/content-types/lifecycle-dispatch.js +5 -4
  16. package/dist/content-types/lifecycle.d.ts +23 -18
  17. package/dist/content-types/lifecycle.js +71 -64
  18. package/dist/content-types/repo.memory.d.ts +5 -4
  19. package/dist/content-types/repo.memory.js +3 -2
  20. package/dist/content-types/tool-registrations.d.ts +6 -8
  21. package/dist/content-types/tool-registrations.js +24 -28
  22. package/dist/content-types/types.d.ts +17 -13
  23. package/dist/content-types/types.js +11 -5
  24. package/dist/content-types/write-service.d.ts +20 -22
  25. package/dist/content-types/write-service.js +78 -75
  26. package/dist/core/authorization.d.ts +15 -0
  27. package/dist/core/authorization.js +2 -0
  28. package/dist/core/commands/change-set.d.ts +15 -7
  29. package/dist/core/commands/command.d.ts +45 -26
  30. package/dist/core/commands/command.js +73 -63
  31. package/dist/core/entity-liveness.d.ts +11 -7
  32. package/dist/core/entity-liveness.js +5 -4
  33. package/dist/core/index.d.ts +12 -5
  34. package/dist/core/index.js +10 -4
  35. package/dist/core/ports.d.ts +25 -24
  36. package/dist/core/ports.js +1 -0
  37. package/dist/core/tools/args.d.ts +49 -0
  38. package/dist/core/tools/args.js +46 -0
  39. package/dist/core/tools/index.d.ts +3 -0
  40. package/dist/core/tools/index.js +3 -0
  41. package/dist/entries/agent-tools.d.ts +1 -73
  42. package/dist/entries/agent-tools.js +19 -13
  43. package/dist/entries/errors.d.ts +28 -14
  44. package/dist/entries/errors.js +17 -11
  45. package/dist/entries/field-validation.d.ts +5 -3
  46. package/dist/entries/field-validation.js +7 -5
  47. package/dist/entries/index.d.ts +2 -2
  48. package/dist/entries/lifecycle-dispatch.d.ts +5 -2
  49. package/dist/entries/lifecycle-dispatch.js +2 -1
  50. package/dist/entries/list.d.ts +4 -2
  51. package/dist/entries/list.js +4 -3
  52. package/dist/entries/repo.memory.d.ts +12 -10
  53. package/dist/entries/repo.memory.js +11 -10
  54. package/dist/entries/tool-registrations.d.ts +6 -8
  55. package/dist/entries/tool-registrations.js +42 -41
  56. package/dist/entries/types.d.ts +0 -7
  57. package/dist/entries/write-service.d.ts +28 -29
  58. package/dist/entries/write-service.js +114 -105
  59. package/dist/http/settings/cms-adapter.d.ts +20 -0
  60. package/dist/http/settings/cms-adapter.js +124 -0
  61. package/dist/http/settings/contracts.d.ts +135 -0
  62. package/dist/http/settings/contracts.js +2 -0
  63. package/dist/http/settings/http.d.ts +10 -0
  64. package/dist/http/settings/http.js +211 -0
  65. package/dist/http/settings/index.d.ts +5 -0
  66. package/dist/http/settings/index.js +4 -0
  67. package/dist/http/settings/shared.d.ts +68 -0
  68. package/dist/http/settings/shared.js +54 -0
  69. package/dist/http/settings/stream.d.ts +24 -0
  70. package/dist/http/settings/stream.js +147 -0
  71. package/dist/media/agent-tools.d.ts +1 -66
  72. package/dist/media/agent-tools.js +5 -1
  73. package/dist/media/blob-gc-lock.d.ts +6 -2
  74. package/dist/media/blob-gc-lock.js +4 -2
  75. package/dist/media/blob-gc.d.ts +64 -51
  76. package/dist/media/blob-gc.js +62 -52
  77. package/dist/media/blob-key.d.ts +1 -1
  78. package/dist/media/content-type-sniffer.d.ts +3 -1
  79. package/dist/media/content-type-sniffer.js +1 -1
  80. package/dist/media/html-attributes.d.ts +9 -5
  81. package/dist/media/html-attributes.js +8 -6
  82. package/dist/media/image-transformer.js +1 -1
  83. package/dist/media/image-transformer.sharp.d.ts +6 -0
  84. package/dist/media/image-transformer.sharp.js +12 -6
  85. package/dist/media/import/fetch-image.d.ts +24 -0
  86. package/dist/media/import/fetch-image.js +137 -0
  87. package/dist/media/import/index.d.ts +3 -0
  88. package/dist/media/import/index.js +3 -0
  89. package/dist/media/import/ports.d.ts +38 -0
  90. package/dist/media/index.d.ts +7 -1
  91. package/dist/media/index.js +1 -0
  92. package/dist/media/media-service.d.ts +14 -10
  93. package/dist/media/media-service.js +57 -52
  94. package/dist/media/ports.d.ts +3 -2
  95. package/dist/media/rendition-service.d.ts +3 -3
  96. package/dist/media/rendition-service.js +38 -37
  97. package/dist/media/repo.memory.d.ts +18 -7
  98. package/dist/media/repo.memory.js +12 -6
  99. package/dist/media/tool-registrations.d.ts +16 -15
  100. package/dist/media/tool-registrations.js +84 -72
  101. package/dist/media/transform-lock.d.ts +22 -12
  102. package/dist/media/transform-lock.js +14 -13
  103. package/dist/media/transform-registry.d.ts +3 -3
  104. package/dist/media/transform-registry.js +19 -18
  105. package/dist/media/transform-types.d.ts +8 -3
  106. package/dist/media/transform-types.js +10 -5
  107. package/dist/media/types.d.ts +21 -4
  108. package/dist/media/types.js +15 -2
  109. package/dist/navigation/agent-tools.d.ts +1 -80
  110. package/dist/navigation/agent-tools.js +15 -3
  111. package/dist/navigation/contracts.d.ts +1 -1
  112. package/dist/navigation/index.d.ts +2 -2
  113. package/dist/navigation/menu-service.d.ts +57 -40
  114. package/dist/navigation/menu-service.js +80 -69
  115. package/dist/navigation/ports.d.ts +1 -1
  116. package/dist/navigation/read-model.d.ts +3 -1
  117. package/dist/navigation/read-model.js +2 -2
  118. package/dist/navigation/reconcile.d.ts +2 -2
  119. package/dist/navigation/reconcile.js +2 -1
  120. package/dist/navigation/repo.memory.d.ts +7 -3
  121. package/dist/navigation/repo.memory.js +4 -2
  122. package/dist/navigation/resolver.d.ts +4 -1
  123. package/dist/navigation/resolver.js +1 -1
  124. package/dist/navigation/tool-registrations.d.ts +6 -8
  125. package/dist/navigation/tool-registrations.js +44 -42
  126. package/dist/navigation/types.d.ts +1 -1
  127. package/dist/presentation/presentation.d.ts +11 -3
  128. package/dist/presentation/presentation.js +13 -6
  129. package/dist/presentation/repo.memory.d.ts +6 -2
  130. package/dist/presentation/repo.memory.js +3 -2
  131. package/dist/settings/agent-tools.d.ts +2 -75
  132. package/dist/settings/agent-tools.js +49 -45
  133. package/dist/settings/agent-value-write-tools.d.ts +22 -0
  134. package/dist/settings/agent-value-write-tools.js +154 -0
  135. package/dist/settings/agent-writable-preferences.js +8 -20
  136. package/dist/settings/agent-write-denylist.d.ts +19 -0
  137. package/dist/settings/agent-write-denylist.js +15 -0
  138. package/dist/settings/change-feed.d.ts +11 -2
  139. package/dist/settings/change-feed.js +4 -4
  140. package/dist/settings/definitions-dispatch.d.ts +8 -3
  141. package/dist/settings/definitions-dispatch.js +5 -5
  142. package/dist/settings/dictionaries/index.d.ts +5 -2
  143. package/dist/settings/dictionaries/index.js +2 -2
  144. package/dist/settings/dictionaries/settings-dialog.ar.js +0 -1
  145. package/dist/settings/dictionaries/settings-dialog.bn.js +0 -1
  146. package/dist/settings/dictionaries/settings-dialog.de.js +0 -1
  147. package/dist/settings/dictionaries/settings-dialog.es.js +0 -1
  148. package/dist/settings/dictionaries/settings-dialog.fa.js +0 -1
  149. package/dist/settings/dictionaries/settings-dialog.fr.js +0 -1
  150. package/dist/settings/dictionaries/settings-dialog.hi.js +0 -1
  151. package/dist/settings/dictionaries/settings-dialog.hu.js +0 -1
  152. package/dist/settings/dictionaries/settings-dialog.id.js +0 -1
  153. package/dist/settings/dictionaries/settings-dialog.it.js +0 -1
  154. package/dist/settings/dictionaries/settings-dialog.ja.js +0 -1
  155. package/dist/settings/dictionaries/settings-dialog.ko.js +0 -1
  156. package/dist/settings/dictionaries/settings-dialog.pl.js +0 -1
  157. package/dist/settings/dictionaries/settings-dialog.pt-BR.js +0 -1
  158. package/dist/settings/dictionaries/settings-dialog.ru.js +0 -1
  159. package/dist/settings/dictionaries/settings-dialog.th.js +0 -1
  160. package/dist/settings/dictionaries/settings-dialog.tr.js +0 -1
  161. package/dist/settings/dictionaries/settings-dialog.uk.js +0 -1
  162. package/dist/settings/dictionaries/settings-dialog.ur.js +0 -1
  163. package/dist/settings/dictionaries/settings-dialog.zh-CN.js +0 -1
  164. package/dist/settings/dictionaries/settings-dialog.zh-TW.js +0 -1
  165. package/dist/settings/ensure-definitions.d.ts +5 -5
  166. package/dist/settings/errors.d.ts +7 -1
  167. package/dist/settings/errors.js +7 -1
  168. package/dist/settings/index.d.ts +4 -1
  169. package/dist/settings/index.js +1 -0
  170. package/dist/settings/ports.d.ts +6 -5
  171. package/dist/settings/principal-lookup.d.ts +9 -0
  172. package/dist/settings/principal-lookup.js +2 -0
  173. package/dist/settings/purge-service.d.ts +5 -4
  174. package/dist/settings/purge-service.js +3 -2
  175. package/dist/settings/settings.d.ts +22 -7
  176. package/dist/settings/settings.js +47 -26
  177. package/dist/settings/tool-registrations.d.ts +25 -32
  178. package/dist/settings/tool-registrations.js +66 -56
  179. package/dist/settings/types.d.ts +1 -1
  180. package/dist/settings/ui-tab-definitions.d.ts +1 -1
  181. package/dist/settings/write-service.d.ts +32 -26
  182. package/dist/settings/write-service.js +26 -20
  183. package/dist/taxonomy/agent-tools.d.ts +1 -66
  184. package/dist/taxonomy/agent-tools.js +25 -15
  185. package/dist/taxonomy/content-lookup.js +1 -1
  186. package/dist/taxonomy/index.d.ts +2 -2
  187. package/dist/taxonomy/merge-term.d.ts +7 -4
  188. package/dist/taxonomy/merge-term.js +7 -5
  189. package/dist/taxonomy/repo.memory.d.ts +42 -19
  190. package/dist/taxonomy/repo.memory.js +14 -12
  191. package/dist/taxonomy/validation-chain.d.ts +39 -18
  192. package/dist/taxonomy/validation-chain.js +35 -25
  193. package/dist/taxonomy/write-service.d.ts +103 -44
  194. package/dist/taxonomy/write-service.js +221 -179
  195. package/dist/trash/adapters/record-store.d.ts +52 -0
  196. package/dist/trash/adapters/record-store.js +36 -0
  197. package/dist/trash/cursor.d.ts +20 -0
  198. package/dist/trash/cursor.js +36 -0
  199. package/dist/trash/follow-ups.d.ts +76 -0
  200. package/dist/trash/follow-ups.js +46 -0
  201. package/dist/trash/index.d.ts +8 -0
  202. package/dist/trash/index.js +8 -0
  203. package/dist/trash/ports.d.ts +308 -0
  204. package/dist/trash/ports.js +2 -0
  205. package/dist/trash/repo.memory.d.ts +50 -0
  206. package/dist/trash/repo.memory.js +114 -0
  207. package/dist/trash/sweeper.d.ts +77 -0
  208. package/dist/trash/sweeper.js +127 -0
  209. package/dist/trash/write-service.d.ts +100 -0
  210. package/dist/trash/write-service.js +242 -0
  211. package/dist/workspace/agent-tools.d.ts +1 -59
  212. package/dist/workspace/agent-tools.js +27 -12
  213. package/dist/workspace/create.d.ts +31 -6
  214. package/dist/workspace/create.js +18 -5
  215. package/dist/workspace/delete.d.ts +18 -13
  216. package/dist/workspace/delete.js +20 -12
  217. package/dist/workspace/index.d.ts +1 -1
  218. package/dist/workspace/repo.memory.d.ts +19 -4
  219. package/dist/workspace/repo.memory.js +26 -4
  220. package/dist/workspace/tool-registrations.d.ts +2 -2
  221. package/dist/workspace/tool-registrations.js +13 -13
  222. package/dist/workspace/update.d.ts +6 -5
  223. package/dist/workspace/update.js +9 -8
  224. package/package.json +44 -38
  225. package/dist/identity/admin-crud-service.d.ts +0 -280
  226. package/dist/identity/admin-crud-service.js +0 -468
  227. package/dist/identity/agent-tool-input.d.ts +0 -58
  228. package/dist/identity/agent-tool-input.js +0 -126
  229. package/dist/identity/agent-tools.d.ts +0 -101
  230. package/dist/identity/agent-tools.js +0 -290
  231. package/dist/identity/auth-service.d.ts +0 -118
  232. package/dist/identity/auth-service.js +0 -170
  233. package/dist/identity/authorize.d.ts +0 -90
  234. package/dist/identity/authorize.js +0 -94
  235. package/dist/identity/grant-service.d.ts +0 -198
  236. package/dist/identity/grant-service.js +0 -361
  237. package/dist/identity/hasher.d.ts +0 -39
  238. package/dist/identity/hasher.js +0 -39
  239. package/dist/identity/index.d.ts +0 -62
  240. package/dist/identity/index.js +0 -54
  241. package/dist/identity/password-policy.d.ts +0 -57
  242. package/dist/identity/password-policy.js +0 -66
  243. package/dist/identity/permission-migrations.d.ts +0 -86
  244. package/dist/identity/permission-migrations.js +0 -67
  245. package/dist/identity/permissions.d.ts +0 -35
  246. package/dist/identity/permissions.js +0 -603
  247. package/dist/identity/ports.d.ts +0 -201
  248. package/dist/identity/repo.memory.d.ts +0 -164
  249. package/dist/identity/repo.memory.js +0 -224
  250. package/dist/identity/seed.d.ts +0 -54
  251. package/dist/identity/seed.js +0 -429
  252. package/dist/identity/tool-registrations.d.ts +0 -50
  253. package/dist/identity/tool-registrations.js +0 -419
  254. package/dist/identity/types.d.ts +0 -185
  255. package/dist/identity/types.js +0 -64
  256. package/dist/identity/username.d.ts +0 -12
  257. package/dist/identity/username.js +0 -14
  258. /package/dist/{identity → media/import}/ports.js +0 -0
@@ -1,5 +1,6 @@
1
- import type { ClockPort } from "../core/ports.js";
2
- import type { ActorIdentityInput, EntryRecord, EntryStatus, OwningContentType, Result } from "./types.js";
1
+ import type { Clock } from "@jini-ai/core/primitives";
2
+ import type { Result } from "@jini-ai/core/primitives";
3
+ import type { ActorIdentityInput, EntryRecord, EntryStatus, OwningContentType } from "./types.js";
3
4
  /**
4
5
  * @file The `entries` write chokepoint: `createEntry`,
5
6
  * `updateEntry`, `publishEntry`, `unpublishEntry`.
@@ -38,16 +39,8 @@ import type { ActorIdentityInput, EntryRecord, EntryStatus, OwningContentType, R
38
39
  * tools call these functions directly, never through an HTTP route), so it must be at least as
39
40
  * expressive as the route, not merely consistent with it.
40
41
  */
41
- export type AuthorizeFn = (params: {
42
- principalId: string;
43
- permission: string;
44
- workspaceId: string;
45
- entityType?: string | undefined;
46
- entityId?: string | undefined;
47
- }) => Promise<{
48
- allowed: boolean;
49
- reason: string;
50
- }>;
42
+ export type { AuthorizationPort as AuthorizeFn } from '../core/authorization.js';
43
+ import type { AuthorizationPort as AuthorizeFn } from '../core/authorization.js';
51
44
  export interface EntryRevisionInput {
52
45
  entryId: string;
53
46
  workspaceId: string;
@@ -70,7 +63,9 @@ export interface EntryRepoPort {
70
63
  }): Promise<EntryRecord | null>;
71
64
  save(row: EntryRecord): Promise<void>;
72
65
  appendRevision(revision: EntryRevisionInput): Promise<void>;
73
- transaction<T>(fn: () => Promise<T>): Promise<T>;
66
+ transaction<T>(required: {
67
+ fn: () => Promise<T>;
68
+ }): Promise<T>;
74
69
  }
75
70
  export interface ContentTypeLookupPort {
76
71
  findByKey(params: {
@@ -94,7 +89,7 @@ export interface CreateEntryRequired {
94
89
  deps: {
95
90
  entryRepo: EntryRepoPort;
96
91
  contentTypeRepo: ContentTypeLookupPort;
97
- clock: ClockPort;
92
+ clock: Clock;
98
93
  ids: {
99
94
  newId: () => string;
100
95
  };
@@ -121,15 +116,16 @@ export interface CreateEntryRequired {
121
116
  };
122
117
  }
123
118
  /**
124
- * REQ-13/14/19 — creates a new entry. Order: authorize -> owning-type exists AND is owned by this
125
- * workspace (INV-01) -> owning-type is `active` (REQ-10) -> `fieldsJson` validates against the
126
- * type's current schema -> `(workspaceId, type, slug)` uniqueness (AC-21) -> same-tx write +
119
+ * — creates a new entry. Order: authorize -> owning-type exists AND is owned by this
120
+ * workspace -> owning-type is `active` -> `fieldsJson` validates against the
121
+ * type's current schema -> `(workspaceId, type, slug)` uniqueness -> same-tx write +
127
122
  * revision + watermark + optional `deps.onWritten` side effect -> `entry.created` outbox event
128
- * (AC-27).
123
+ *
129
124
  *
130
125
  * @complexity O(1) plus one content-type read, one field-validation pass, one slug lookup, and one
131
126
  * same-tx write pair.
132
127
  * @overallScore 100
128
+ * See docs/decisions/DR-002-content-lifecycle-and-cleanup.md.
133
129
  */
134
130
  export declare function createEntry(required: CreateEntryRequired): Promise<Result<{
135
131
  entry: EntryRecord;
@@ -137,7 +133,7 @@ export declare function createEntry(required: CreateEntryRequired): Promise<Resu
137
133
  interface ExistingEntryTransitionDeps {
138
134
  entryRepo: EntryRepoPort;
139
135
  contentTypeRepo: ContentTypeLookupPort;
140
- clock: ClockPort;
136
+ clock: Clock;
141
137
  authorize: AuthorizeFn;
142
138
  outbox: OutboxPort;
143
139
  watermark?: WatermarkPort;
@@ -173,13 +169,14 @@ export interface UpdateEntryRequired {
173
169
  };
174
170
  }
175
171
  /**
176
- * REQ-28 — updates an existing entry's `title`/`fieldsJson`/`bodyJson` (only the fields supplied
172
+ * — updates an existing entry's `title`/`fieldsJson`/`bodyJson` (only the fields supplied
177
173
  * are changed). Rejected `ContentTypeNotActiveError` only if the owning type is `tombstone`
178
- * (AC-44/EC-13); a `deprecated` owning type is fine (AC-46).
174
+ * a `deprecated` owning type is fine.
179
175
  *
180
176
  * @complexity O(1) plus the shared resolve step and, when `fieldsJson` is supplied, one
181
177
  * field-validation pass.
182
178
  * @overallScore 100
179
+ * See docs/decisions/DR-002-content-lifecycle-and-cleanup.md.
183
180
  */
184
181
  export declare function updateEntry(required: UpdateEntryRequired): Promise<Result<{
185
182
  entry: EntryRecord;
@@ -188,7 +185,7 @@ export interface ImportEntryRequired {
188
185
  deps: {
189
186
  entryRepo: EntryRepoPort;
190
187
  contentTypeRepo: ContentTypeLookupPort;
191
- clock: ClockPort;
188
+ clock: Clock;
192
189
  authorize: AuthorizeFn;
193
190
  outbox: OutboxPort;
194
191
  watermark?: WatermarkPort;
@@ -229,14 +226,15 @@ export interface ImportEntryRequired {
229
226
  * cannot produce, and the reason this is a new function rather than a wider `createEntry`.
230
227
  *
231
228
  * A tombstoned owning type refuses the import (mirrors `resolveExistingEntryForTransition`'s
232
- * REQ-28 rule); unlike `createEntry`'s REQ-10, a `deprecated` owning type does NOT block an
233
- * import — REQ-10 exists to stop new manual authoring against a type an operator is winding down,
229
+ * rule); unlike `createEntry`'s, a `deprecated` owning type does NOT block an
230
+ * import — exists to stop new manual authoring against a type an operator is winding down,
234
231
  * not to stop a publish run from keeping an already-existing entry's already-existing type in
235
232
  * sync. Slug uniqueness is deliberately not checked here: the publish factory's own `address`
236
233
  * precheck (config.address, F1) owns that refusal before `importEntry` is ever called.
237
234
  *
238
235
  * @complexity O(1) plus one content-type read, one field-validation pass, one id lookup, and one
239
236
  * same-tx write pair.
237
+ * See docs/decisions/DR-002-content-lifecycle-and-cleanup.md.
240
238
  */
241
239
  export declare function importEntry(required: ImportEntryRequired): Promise<Result<{
242
240
  entry: EntryRecord;
@@ -250,24 +248,25 @@ export interface PublishUnpublishEntryRequired {
250
248
  };
251
249
  }
252
250
  /**
253
- * REQ-28 — flips an entry to `published`. Rejected `ContentTypeNotActiveError` only if the owning
254
- * type is `tombstone` (AC-45), with NO outbox event enqueued on rejection.
251
+ * — flips an entry to `published`. Rejected `ContentTypeNotActiveError` only if the owning
252
+ * type is `tombstone`, with NO outbox event enqueued on rejection.
255
253
  *
256
254
  * @complexity O(1) plus the shared resolve step and one same-tx write pair.
257
255
  * @overallScore 100
256
+ * See docs/decisions/DR-002-content-lifecycle-and-cleanup.md.
258
257
  */
259
258
  export declare function publishEntry(required: PublishUnpublishEntryRequired): Promise<Result<{
260
259
  entry: EntryRecord;
261
260
  }, Error>>;
262
261
  /**
263
- * REQ-28 — flips an entry to `unpublished`. Rejected `ContentTypeNotActiveError` only if the
264
- * owning type is `tombstone` (AC-45), with NO outbox event enqueued on rejection.
262
+ * — flips an entry to `unpublished`. Rejected `ContentTypeNotActiveError` only if the
263
+ * owning type is `tombstone`, with NO outbox event enqueued on rejection.
265
264
  *
266
265
  * @complexity O(1) plus the shared resolve step and one same-tx write pair.
267
266
  * @overallScore 100
267
+ * See docs/decisions/DR-002-content-lifecycle-and-cleanup.md.
268
268
  */
269
269
  export declare function unpublishEntry(required: PublishUnpublishEntryRequired): Promise<Result<{
270
270
  entry: EntryRecord;
271
271
  }, Error>>;
272
- export {};
273
272
  //# sourceMappingURL=write-service.d.ts.map
@@ -1,3 +1,4 @@
1
+ import { nowIso as kernelNowIso } from "@jini-ai/core/primitives";
1
2
  import { ContentTypeNotActiveError, ContentTypeNotFoundError, EntryFieldValidationError, EntryNotFoundError, EntrySlugConflictError, ForbiddenError, VersionConflictError, } from "./errors.js";
2
3
  import { validateFieldsAgainstSchema } from "./field-validation.js";
3
4
  function delegationFields(input) {
@@ -7,38 +8,40 @@ function delegationFields(input) {
7
8
  };
8
9
  }
9
10
  /**
10
- * REQ-13/14/19 — creates a new entry. Order: authorize -> owning-type exists AND is owned by this
11
- * workspace (INV-01) -> owning-type is `active` (REQ-10) -> `fieldsJson` validates against the
12
- * type's current schema -> `(workspaceId, type, slug)` uniqueness (AC-21) -> same-tx write +
11
+ * — creates a new entry. Order: authorize -> owning-type exists AND is owned by this
12
+ * workspace -> owning-type is `active` -> `fieldsJson` validates against the
13
+ * type's current schema -> `(workspaceId, type, slug)` uniqueness -> same-tx write +
13
14
  * revision + watermark + optional `deps.onWritten` side effect -> `entry.created` outbox event
14
- * (AC-27).
15
+ *
15
16
  *
16
17
  * @complexity O(1) plus one content-type read, one field-validation pass, one slug lookup, and one
17
18
  * same-tx write pair.
18
19
  * @overallScore 100
20
+ * See docs/decisions/DR-002-content-lifecycle-and-cleanup.md.
19
21
  */
20
22
  export async function createEntry(required) {
21
23
  const { deps, input } = required;
22
- const authResult = await deps.authorize({ principalId: input.actorId, permission: "admin.collections.manage", workspaceId: input.workspaceId, entityType: "entry" });
24
+ const authResult = await deps.authorize({ principalId: input.actorId, permission: "admin.collections.manage", workspaceId: input.workspaceId }, { entityType: "entry" });
23
25
  if (!authResult.allowed) {
24
- return { ok: false, error: new ForbiddenError(`principal '${input.actorId}' cannot create an entry (${authResult.reason})`) };
26
+ return { ok: false, error: new ForbiddenError({ message: `principal '${input.actorId}' cannot create an entry (${authResult.reason})` }) };
25
27
  }
26
28
  const contentType = await deps.contentTypeRepo.findByKey({ workspaceId: input.workspaceId, key: input.type });
27
29
  if (!contentType || contentType.workspaceId !== input.workspaceId) {
28
- return { ok: false, error: new ContentTypeNotFoundError(`content type '${input.type}' was not found in workspace '${input.workspaceId}'`) };
30
+ return { ok: false, error: new ContentTypeNotFoundError({ message: `content type '${input.type}' was not found in workspace '${input.workspaceId}'` }) };
29
31
  }
30
32
  if (contentType.status !== "active") {
31
- return { ok: false, error: new ContentTypeNotActiveError(`content type '${input.type}' is not active; new entries cannot be created (REQ-10)`) };
33
+ // See docs/decisions/DR-002-content-lifecycle-and-cleanup.md for the invariant behind this refusal; keep external identifiers out of caller-facing messages.
34
+ return { ok: false, error: new ContentTypeNotActiveError({ message: `content type '${input.type}' is not active; new entries cannot be created` }) };
32
35
  }
33
- const validation = validateFieldsAgainstSchema({ schema: contentType.fields, fieldsJson: input.fieldsJson, owner: input.owner });
36
+ const validation = validateFieldsAgainstSchema({ schema: contentType.fields, fieldsJson: input.fieldsJson }, { owner: input.owner });
34
37
  if (!validation.valid) {
35
- return { ok: false, error: new EntryFieldValidationError(validation.fieldErrors) };
38
+ return { ok: false, error: new EntryFieldValidationError({ fieldErrors: validation.fieldErrors }) };
36
39
  }
37
40
  const existing = await deps.entryRepo.findBySlug({ workspaceId: input.workspaceId, type: input.type, slug: input.slug });
38
41
  if (existing) {
39
- return { ok: false, error: new EntrySlugConflictError(`an entry with slug '${input.slug}' already exists for type '${input.type}' in workspace '${input.workspaceId}'`) };
42
+ return { ok: false, error: new EntrySlugConflictError({ message: `an entry with slug '${input.slug}' already exists for type '${input.type}' in workspace '${input.workspaceId}'` }) };
40
43
  }
41
- const now = deps.clock.nowIso();
44
+ const now = kernelNowIso({ clock: deps.clock });
42
45
  const entry = {
43
46
  id: deps.ids.newId(),
44
47
  workspaceId: input.workspaceId,
@@ -53,60 +56,63 @@ export async function createEntry(required) {
53
56
  updatedAt: now,
54
57
  version: 1,
55
58
  };
56
- await deps.entryRepo.transaction(async () => {
57
- await deps.entryRepo.save(entry);
58
- await deps.entryRepo.appendRevision({
59
- entryId: entry.id,
60
- workspaceId: input.workspaceId,
61
- op: "create",
62
- stateJson: entry,
63
- actorId: input.actorId,
64
- ...delegationFields(input),
65
- recordedAt: now,
66
- });
67
- if (deps.watermark)
68
- await deps.watermark.stampWatermark({ workspaceId: input.workspaceId });
69
- if (deps.onWritten)
70
- await deps.onWritten(entry);
71
- });
59
+ await deps.entryRepo.transaction({ fn: async () => {
60
+ await deps.entryRepo.save(entry);
61
+ await deps.entryRepo.appendRevision({
62
+ entryId: entry.id,
63
+ workspaceId: input.workspaceId,
64
+ op: "create",
65
+ stateJson: entry,
66
+ actorId: input.actorId,
67
+ ...delegationFields(input),
68
+ recordedAt: now,
69
+ });
70
+ if (deps.watermark)
71
+ await deps.watermark.stampWatermark({ workspaceId: input.workspaceId });
72
+ if (deps.onWritten)
73
+ await deps.onWritten(entry);
74
+ } });
72
75
  await deps.outbox.enqueue({ name: "entry.created", payload: { workspaceId: input.workspaceId, entryId: entry.id, type: input.type, slug: input.slug } });
73
76
  return { ok: true, value: { entry } };
74
77
  }
75
78
  /**
76
- * REQ-28's shared resolve step for `updateEntry`/`publishEntry`/`unpublishEntry`: authorize ->
79
+ * shared resolve step for `updateEntry`/`publishEntry`/`unpublishEntry`: authorize ->
77
80
  * find the entry -> find its owning type -> reject ONLY if that type is `tombstone`
78
- * (`deprecated` blocks nothing here, unlike `createEntry`'s REQ-10 rule) -> `expectedVersion`
81
+ * (`deprecated` blocks nothing here, unlike `createEntry`'s rule) -> `expectedVersion`
79
82
  * check.
80
83
  *
81
84
  * @complexity O(1) plus one entry read and one content-type read.
82
85
  * @overallScore 100
86
+ * See docs/decisions/DR-002-content-lifecycle-and-cleanup.md.
83
87
  */
84
88
  async function resolveExistingEntryForTransition(deps, input) {
85
- const authResult = await deps.authorize({ principalId: input.actorId, permission: "admin.collections.manage", workspaceId: input.workspaceId, entityType: "entry" });
89
+ const authResult = await deps.authorize({ principalId: input.actorId, permission: "admin.collections.manage", workspaceId: input.workspaceId }, { entityType: "entry" });
86
90
  if (!authResult.allowed) {
87
- return { ok: false, error: new ForbiddenError(`principal '${input.actorId}' cannot modify entry '${input.id}' (${authResult.reason})`) };
91
+ return { ok: false, error: new ForbiddenError({ message: `principal '${input.actorId}' cannot modify entry '${input.id}' (${authResult.reason})` }) };
88
92
  }
89
93
  const entry = await deps.entryRepo.findById({ workspaceId: input.workspaceId, id: input.id });
90
94
  if (!entry) {
91
- return { ok: false, error: new EntryNotFoundError(`entry '${input.id}' was not found in workspace '${input.workspaceId}'`) };
95
+ return { ok: false, error: new EntryNotFoundError({ message: `entry '${input.id}' was not found in workspace '${input.workspaceId}'` }) };
92
96
  }
93
97
  const contentType = await deps.contentTypeRepo.findByKey({ workspaceId: input.workspaceId, key: entry.type });
94
98
  if (contentType && contentType.status === "tombstone") {
95
- return { ok: false, error: new ContentTypeNotActiveError(`content type '${entry.type}' is tombstoned; existing entries cannot be updated/published/unpublished (REQ-28)`) };
99
+ // See docs/decisions/DR-002-content-lifecycle-and-cleanup.md for the invariant behind this refusal; keep external identifiers out of caller-facing messages.
100
+ return { ok: false, error: new ContentTypeNotActiveError({ message: `content type '${entry.type}' is tombstoned; existing entries cannot be updated/published/unpublished` }) };
96
101
  }
97
102
  if (input.expectedVersion !== entry.version) {
98
- return { ok: false, error: new VersionConflictError(`expected version ${input.expectedVersion} for entry '${input.id}', found ${entry.version}`) };
103
+ return { ok: false, error: new VersionConflictError({ message: `expected version ${input.expectedVersion} for entry '${input.id}', found ${entry.version}` }) };
99
104
  }
100
105
  return { ok: true, value: { entry, contentType } };
101
106
  }
102
107
  /**
103
- * REQ-28 — updates an existing entry's `title`/`fieldsJson`/`bodyJson` (only the fields supplied
108
+ * — updates an existing entry's `title`/`fieldsJson`/`bodyJson` (only the fields supplied
104
109
  * are changed). Rejected `ContentTypeNotActiveError` only if the owning type is `tombstone`
105
- * (AC-44/EC-13); a `deprecated` owning type is fine (AC-46).
110
+ * a `deprecated` owning type is fine.
106
111
  *
107
112
  * @complexity O(1) plus the shared resolve step and, when `fieldsJson` is supplied, one
108
113
  * field-validation pass.
109
114
  * @overallScore 100
115
+ * See docs/decisions/DR-002-content-lifecycle-and-cleanup.md.
110
116
  */
111
117
  export async function updateEntry(required) {
112
118
  const { deps, input } = required;
@@ -116,13 +122,13 @@ export async function updateEntry(required) {
116
122
  const { entry: current, contentType } = resolved.value;
117
123
  let fieldsJson = current.fieldsJson;
118
124
  if (input.fieldsJson !== undefined) {
119
- const validation = validateFieldsAgainstSchema({ schema: contentType?.fields ?? [], fieldsJson: input.fieldsJson, owner: input.owner });
125
+ const validation = validateFieldsAgainstSchema({ schema: contentType?.fields ?? [], fieldsJson: input.fieldsJson }, { owner: input.owner });
120
126
  if (!validation.valid) {
121
- return { ok: false, error: new EntryFieldValidationError(validation.fieldErrors) };
127
+ return { ok: false, error: new EntryFieldValidationError({ fieldErrors: validation.fieldErrors }) };
122
128
  }
123
129
  fieldsJson = input.fieldsJson;
124
130
  }
125
- const now = deps.clock.nowIso();
131
+ const now = kernelNowIso({ clock: deps.clock });
126
132
  const updated = {
127
133
  ...current,
128
134
  title: input.title ?? current.title,
@@ -131,22 +137,22 @@ export async function updateEntry(required) {
131
137
  updatedAt: now,
132
138
  version: current.version + 1,
133
139
  };
134
- await deps.entryRepo.transaction(async () => {
135
- await deps.entryRepo.save(updated);
136
- await deps.entryRepo.appendRevision({
137
- entryId: current.id,
138
- workspaceId: input.workspaceId,
139
- op: "update",
140
- stateJson: updated,
141
- actorId: input.actorId,
142
- ...delegationFields(input),
143
- recordedAt: now,
144
- });
145
- if (deps.watermark)
146
- await deps.watermark.stampWatermark({ workspaceId: input.workspaceId });
147
- if (deps.onWritten)
148
- await deps.onWritten(updated);
149
- });
140
+ await deps.entryRepo.transaction({ fn: async () => {
141
+ await deps.entryRepo.save(updated);
142
+ await deps.entryRepo.appendRevision({
143
+ entryId: current.id,
144
+ workspaceId: input.workspaceId,
145
+ op: "update",
146
+ stateJson: updated,
147
+ actorId: input.actorId,
148
+ ...delegationFields(input),
149
+ recordedAt: now,
150
+ });
151
+ if (deps.watermark)
152
+ await deps.watermark.stampWatermark({ workspaceId: input.workspaceId });
153
+ if (deps.onWritten)
154
+ await deps.onWritten(updated);
155
+ } });
150
156
  await deps.outbox.enqueue({ name: "entry.updated", payload: { workspaceId: input.workspaceId, entryId: current.id } });
151
157
  return { ok: true, value: { entry: updated } };
152
158
  }
@@ -158,52 +164,53 @@ export async function updateEntry(required) {
158
164
  * cannot produce, and the reason this is a new function rather than a wider `createEntry`.
159
165
  *
160
166
  * A tombstoned owning type refuses the import (mirrors `resolveExistingEntryForTransition`'s
161
- * REQ-28 rule); unlike `createEntry`'s REQ-10, a `deprecated` owning type does NOT block an
162
- * import — REQ-10 exists to stop new manual authoring against a type an operator is winding down,
167
+ * rule); unlike `createEntry`'s, a `deprecated` owning type does NOT block an
168
+ * import — exists to stop new manual authoring against a type an operator is winding down,
163
169
  * not to stop a publish run from keeping an already-existing entry's already-existing type in
164
170
  * sync. Slug uniqueness is deliberately not checked here: the publish factory's own `address`
165
171
  * precheck (config.address, F1) owns that refusal before `importEntry` is ever called.
166
172
  *
167
173
  * @complexity O(1) plus one content-type read, one field-validation pass, one id lookup, and one
168
174
  * same-tx write pair.
175
+ * See docs/decisions/DR-002-content-lifecycle-and-cleanup.md.
169
176
  */
170
177
  export async function importEntry(required) {
171
178
  const { deps, input } = required;
172
- const authResult = await deps.authorize({ principalId: input.actorId, permission: "admin.collections.manage", workspaceId: input.workspaceId, entityType: "entry" });
179
+ const authResult = await deps.authorize({ principalId: input.actorId, permission: "admin.collections.manage", workspaceId: input.workspaceId }, { entityType: "entry" });
173
180
  if (!authResult.allowed) {
174
- return { ok: false, error: new ForbiddenError(`principal '${input.actorId}' cannot import entry '${input.id}' (${authResult.reason})`) };
181
+ return { ok: false, error: new ForbiddenError({ message: `principal '${input.actorId}' cannot import entry '${input.id}' (${authResult.reason})` }) };
175
182
  }
176
183
  const contentType = await deps.contentTypeRepo.findByKey({ workspaceId: input.workspaceId, key: input.type });
177
184
  if (!contentType || contentType.workspaceId !== input.workspaceId) {
178
- return { ok: false, error: new ContentTypeNotFoundError(`content type '${input.type}' was not found in workspace '${input.workspaceId}'`) };
185
+ return { ok: false, error: new ContentTypeNotFoundError({ message: `content type '${input.type}' was not found in workspace '${input.workspaceId}'` }) };
179
186
  }
180
187
  if (contentType.status === "tombstone") {
181
- return { ok: false, error: new ContentTypeNotActiveError(`content type '${input.type}' is tombstoned; entries cannot be imported into it`) };
188
+ return { ok: false, error: new ContentTypeNotActiveError({ message: `content type '${input.type}' is tombstoned; entries cannot be imported into it` }) };
182
189
  }
183
- const validation = validateFieldsAgainstSchema({ schema: contentType.fields, fieldsJson: input.fieldsJson, owner: input.owner });
190
+ const validation = validateFieldsAgainstSchema({ schema: contentType.fields, fieldsJson: input.fieldsJson }, { owner: input.owner });
184
191
  if (!validation.valid) {
185
- return { ok: false, error: new EntryFieldValidationError(validation.fieldErrors) };
192
+ return { ok: false, error: new EntryFieldValidationError({ fieldErrors: validation.fieldErrors }) };
186
193
  }
187
194
  const existing = await deps.entryRepo.findById({ workspaceId: input.workspaceId, id: input.id });
188
195
  if (input.expectedVersion === undefined) {
189
196
  if (existing) {
190
- return { ok: false, error: new VersionConflictError(`entry '${input.id}' already exists in workspace '${input.workspaceId}', but no expectedVersion was supplied for import`) };
197
+ return { ok: false, error: new VersionConflictError({ message: `entry '${input.id}' already exists in workspace '${input.workspaceId}', but no expectedVersion was supplied for import` }) };
191
198
  }
192
199
  }
193
200
  else {
194
201
  if (!existing) {
195
- return { ok: false, error: new VersionConflictError(`expected version ${input.expectedVersion} for entry '${input.id}', but no such entry exists`) };
202
+ return { ok: false, error: new VersionConflictError({ message: `expected version ${input.expectedVersion} for entry '${input.id}', but no such entry exists` }) };
196
203
  }
197
204
  if (existing.version !== input.expectedVersion) {
198
- return { ok: false, error: new VersionConflictError(`expected version ${input.expectedVersion} for entry '${input.id}', found ${existing.version}`) };
205
+ return { ok: false, error: new VersionConflictError({ message: `expected version ${input.expectedVersion} for entry '${input.id}', found ${existing.version}` }) };
199
206
  }
200
207
  // Same id, different type means this is not the row the caller's plan was made against; a
201
- // silent type move would also dodge the REQ-28 tombstone check on the entry's REAL type.
208
+ // silent type move would also dodge the tombstone check on the entry's REAL type. See docs/decisions/DR-002-content-lifecycle-and-cleanup.md.
202
209
  if (existing.type !== input.type) {
203
- return { ok: false, error: new VersionConflictError(`entry '${input.id}' is of type '${existing.type}', not '${input.type}'; an import cannot change an entry's type`) };
210
+ return { ok: false, error: new VersionConflictError({ message: `entry '${input.id}' is of type '${existing.type}', not '${input.type}'; an import cannot change an entry's type` }) };
204
211
  }
205
212
  }
206
- const now = deps.clock.nowIso();
213
+ const now = kernelNowIso({ clock: deps.clock });
207
214
  const entry = {
208
215
  id: input.id,
209
216
  workspaceId: input.workspaceId,
@@ -218,22 +225,22 @@ export async function importEntry(required) {
218
225
  updatedAt: now,
219
226
  version: existing ? existing.version + 1 : 1,
220
227
  };
221
- await deps.entryRepo.transaction(async () => {
222
- await deps.entryRepo.save(entry);
223
- await deps.entryRepo.appendRevision({
224
- entryId: entry.id,
225
- workspaceId: input.workspaceId,
226
- op: existing ? "update" : "create",
227
- stateJson: entry,
228
- actorId: input.actorId,
229
- ...delegationFields(input),
230
- recordedAt: now,
231
- });
232
- if (deps.watermark)
233
- await deps.watermark.stampWatermark({ workspaceId: input.workspaceId });
234
- if (deps.onWritten)
235
- await deps.onWritten(entry);
236
- });
228
+ await deps.entryRepo.transaction({ fn: async () => {
229
+ await deps.entryRepo.save(entry);
230
+ await deps.entryRepo.appendRevision({
231
+ entryId: entry.id,
232
+ workspaceId: input.workspaceId,
233
+ op: existing ? "update" : "create",
234
+ stateJson: entry,
235
+ actorId: input.actorId,
236
+ ...delegationFields(input),
237
+ recordedAt: now,
238
+ });
239
+ if (deps.watermark)
240
+ await deps.watermark.stampWatermark({ workspaceId: input.workspaceId });
241
+ if (deps.onWritten)
242
+ await deps.onWritten(entry);
243
+ } });
237
244
  await deps.outbox.enqueue({ name: "entry.imported", payload: { workspaceId: input.workspaceId, entryId: entry.id, type: input.type, slug: input.slug } });
238
245
  return { ok: true, value: { entry } };
239
246
  }
@@ -243,7 +250,7 @@ async function transitionEntryStatus(required, target) {
243
250
  if (!resolved.ok)
244
251
  return resolved;
245
252
  const { entry: current } = resolved.value;
246
- const now = deps.clock.nowIso();
253
+ const now = kernelNowIso({ clock: deps.clock });
247
254
  const updated = {
248
255
  ...current,
249
256
  status: target.status,
@@ -251,39 +258,41 @@ async function transitionEntryStatus(required, target) {
251
258
  updatedAt: now,
252
259
  version: current.version + 1,
253
260
  };
254
- await deps.entryRepo.transaction(async () => {
255
- await deps.entryRepo.save(updated);
256
- await deps.entryRepo.appendRevision({
257
- entryId: current.id,
258
- workspaceId: input.workspaceId,
259
- op: target.op,
260
- stateJson: updated,
261
- actorId: input.actorId,
262
- ...delegationFields(input),
263
- recordedAt: now,
264
- });
265
- if (deps.watermark)
266
- await deps.watermark.stampWatermark({ workspaceId: input.workspaceId });
267
- });
261
+ await deps.entryRepo.transaction({ fn: async () => {
262
+ await deps.entryRepo.save(updated);
263
+ await deps.entryRepo.appendRevision({
264
+ entryId: current.id,
265
+ workspaceId: input.workspaceId,
266
+ op: target.op,
267
+ stateJson: updated,
268
+ actorId: input.actorId,
269
+ ...delegationFields(input),
270
+ recordedAt: now,
271
+ });
272
+ if (deps.watermark)
273
+ await deps.watermark.stampWatermark({ workspaceId: input.workspaceId });
274
+ } });
268
275
  await deps.outbox.enqueue({ name: target.eventName, payload: { workspaceId: input.workspaceId, entryId: current.id } });
269
276
  return { ok: true, value: { entry: updated } };
270
277
  }
271
278
  /**
272
- * REQ-28 — flips an entry to `published`. Rejected `ContentTypeNotActiveError` only if the owning
273
- * type is `tombstone` (AC-45), with NO outbox event enqueued on rejection.
279
+ * — flips an entry to `published`. Rejected `ContentTypeNotActiveError` only if the owning
280
+ * type is `tombstone`, with NO outbox event enqueued on rejection.
274
281
  *
275
282
  * @complexity O(1) plus the shared resolve step and one same-tx write pair.
276
283
  * @overallScore 100
284
+ * See docs/decisions/DR-002-content-lifecycle-and-cleanup.md.
277
285
  */
278
286
  export async function publishEntry(required) {
279
287
  return transitionEntryStatus(required, { status: "published", op: "publish", eventName: "entry.published" });
280
288
  }
281
289
  /**
282
- * REQ-28 — flips an entry to `unpublished`. Rejected `ContentTypeNotActiveError` only if the
283
- * owning type is `tombstone` (AC-45), with NO outbox event enqueued on rejection.
290
+ * — flips an entry to `unpublished`. Rejected `ContentTypeNotActiveError` only if the
291
+ * owning type is `tombstone`, with NO outbox event enqueued on rejection.
284
292
  *
285
293
  * @complexity O(1) plus the shared resolve step and one same-tx write pair.
286
294
  * @overallScore 100
295
+ * See docs/decisions/DR-002-content-lifecycle-and-cleanup.md.
287
296
  */
288
297
  export async function unpublishEntry(required) {
289
298
  return transitionEntryStatus(required, { status: "unpublished", op: "unpublish", eventName: "entry.unpublished" });
@@ -0,0 +1,20 @@
1
+ import { type SettingsWriteServiceDeps, type SettingsRepoPort } from "../../settings/index.js";
2
+ import type { SettingsService, SettingsPermissions, SettingsChangeFeed } from "./contracts.js";
3
+ /** Keep the CMS write chokepoint while translating its permission vocabulary to host policy. */
4
+ /** Bind the CMS ledger and write chokepoint without copying their domain logic.
5
+ * Effective reads scan definitions and resolve each namespace key; mutations inherit CMS transactions/errors.
6
+ * @complexity O(1) setup. Per operation: O(definitions + keys) reads, or O(batch size) writes.
7
+ * @example createCmsSettingsService({ deps: cmsPorts, permissions });
8
+ */
9
+ export declare function createCmsSettingsService(required: {
10
+ deps: SettingsWriteServiceDeps;
11
+ permissions: SettingsPermissions;
12
+ }): SettingsService;
13
+ /** Adapt the ledger through CMS tenant/principal disclosure rules, returning names and cursors only.
14
+ * @complexity O(1) setup; collect is O(page size), with namespace lookup per visible revision.
15
+ * @example createCmsSettingsChangeFeed({ repo });
16
+ */
17
+ export declare function createCmsSettingsChangeFeed(required: {
18
+ repo: SettingsRepoPort;
19
+ }): SettingsChangeFeed;
20
+ //# sourceMappingURL=cms-adapter.d.ts.map