@spine-event-engine/server 2.0.0-snapshot.2 → 2.0.0-snapshot.21

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 (227) hide show
  1. package/README.md +225 -518
  2. package/REFERENCE.md +498 -49
  3. package/dist/browser/browser-server.d.ts +95 -0
  4. package/dist/browser/browser-server.d.ts.map +1 -0
  5. package/dist/{server → browser}/browser-server.js +93 -7
  6. package/dist/browser/browser-server.js.map +1 -0
  7. package/dist/browser/durable-subscription-bindings.d.ts.map +1 -0
  8. package/dist/browser/durable-subscription-bindings.js.map +1 -0
  9. package/dist/browser/index.d.ts +12 -0
  10. package/dist/browser/index.d.ts.map +1 -0
  11. package/dist/browser/index.js +24 -0
  12. package/dist/browser/index.js.map +1 -0
  13. package/dist/browser/options.d.ts +183 -0
  14. package/dist/browser/options.d.ts.map +1 -0
  15. package/dist/browser/options.js +15 -0
  16. package/dist/browser/options.js.map +1 -0
  17. package/dist/bus/command-bus.d.ts +2 -0
  18. package/dist/bus/command-bus.d.ts.map +1 -1
  19. package/dist/bus/command-bus.js +36 -1
  20. package/dist/bus/command-bus.js.map +1 -1
  21. package/dist/bus/event-dispatcher-registry.d.ts +2 -2
  22. package/dist/bus/event-dispatcher-registry.js +3 -3
  23. package/dist/bus/event-dispatcher-registry.js.map +1 -1
  24. package/dist/context/bounded-context.d.ts +238 -83
  25. package/dist/context/bounded-context.d.ts.map +1 -1
  26. package/dist/context/bounded-context.js +1083 -286
  27. package/dist/context/bounded-context.js.map +1 -1
  28. package/dist/context/effective-tenant.d.ts +9 -0
  29. package/dist/context/effective-tenant.d.ts.map +1 -0
  30. package/dist/context/effective-tenant.js +58 -0
  31. package/dist/context/effective-tenant.js.map +1 -0
  32. package/dist/context/entity-inbox.d.ts.map +1 -1
  33. package/dist/context/entity-inbox.js +24 -17
  34. package/dist/context/entity-inbox.js.map +1 -1
  35. package/dist/context/local-inbox-handoff.d.ts +7 -3
  36. package/dist/context/local-inbox-handoff.d.ts.map +1 -1
  37. package/dist/context/local-inbox-handoff.js +32 -26
  38. package/dist/context/local-inbox-handoff.js.map +1 -1
  39. package/dist/context/projection-handoff.d.ts.map +1 -1
  40. package/dist/context/projection-handoff.js +36 -31
  41. package/dist/context/projection-handoff.js.map +1 -1
  42. package/dist/context/tenant-index.d.ts.map +1 -1
  43. package/dist/context/tenant-index.js +72 -2
  44. package/dist/context/tenant-index.js.map +1 -1
  45. package/dist/delivery/delivery-ports.d.ts +14 -4
  46. package/dist/delivery/delivery-ports.d.ts.map +1 -1
  47. package/dist/delivery/delivery.d.ts +19 -21
  48. package/dist/delivery/delivery.d.ts.map +1 -1
  49. package/dist/delivery/delivery.js +541 -158
  50. package/dist/delivery/delivery.js.map +1 -1
  51. package/dist/delivery/inbox-storage.d.ts +12 -3
  52. package/dist/delivery/inbox-storage.d.ts.map +1 -1
  53. package/dist/delivery/inbox-storage.js +160 -67
  54. package/dist/delivery/inbox-storage.js.map +1 -1
  55. package/dist/delivery/inbox.d.ts +9 -0
  56. package/dist/delivery/inbox.d.ts.map +1 -1
  57. package/dist/delivery/inbox.js +11 -0
  58. package/dist/delivery/inbox.js.map +1 -1
  59. package/dist/delivery/sharded-work-registry.d.ts.map +1 -1
  60. package/dist/delivery/sharded-work-registry.js +2 -1
  61. package/dist/delivery/sharded-work-registry.js.map +1 -1
  62. package/dist/entity/entity-metadata.d.ts +14 -5
  63. package/dist/entity/entity-metadata.d.ts.map +1 -1
  64. package/dist/entity/entity-metadata.js +38 -2
  65. package/dist/entity/entity-metadata.js.map +1 -1
  66. package/dist/entity/entity-storage-descriptor.d.ts +25 -5
  67. package/dist/entity/entity-storage-descriptor.d.ts.map +1 -1
  68. package/dist/entity/entity-storage-descriptor.js +69 -23
  69. package/dist/entity/entity-storage-descriptor.js.map +1 -1
  70. package/dist/entity/entity-transaction.d.ts +46 -42
  71. package/dist/entity/entity-transaction.d.ts.map +1 -1
  72. package/dist/entity/entity-transaction.js +130 -35
  73. package/dist/entity/entity-transaction.js.map +1 -1
  74. package/dist/entity/entity.d.ts +243 -98
  75. package/dist/entity/entity.d.ts.map +1 -1
  76. package/dist/entity/entity.js +405 -226
  77. package/dist/entity/entity.js.map +1 -1
  78. package/dist/entity/spec-scanner.d.ts +13 -1
  79. package/dist/entity/spec-scanner.d.ts.map +1 -1
  80. package/dist/entity/spec-scanner.js +20 -3
  81. package/dist/entity/spec-scanner.js.map +1 -1
  82. package/dist/handler/command-registration-readiness.d.ts +6 -6
  83. package/dist/handler/command-registration-readiness.d.ts.map +1 -1
  84. package/dist/handler/command-registration-readiness.js +4 -2
  85. package/dist/handler/command-registration-readiness.js.map +1 -1
  86. package/dist/handler/declared-rejections.d.ts +11 -0
  87. package/dist/handler/declared-rejections.d.ts.map +1 -0
  88. package/dist/handler/declared-rejections.js +34 -0
  89. package/dist/handler/declared-rejections.js.map +1 -0
  90. package/dist/handler/event-registration-readiness.d.ts +13 -56
  91. package/dist/handler/event-registration-readiness.d.ts.map +1 -1
  92. package/dist/handler/event-registration-readiness.js +23 -43
  93. package/dist/handler/event-registration-readiness.js.map +1 -1
  94. package/dist/handler/generated-handler-registry.d.ts +72 -33
  95. package/dist/handler/generated-handler-registry.d.ts.map +1 -1
  96. package/dist/handler/generated-handler-registry.js +421 -43
  97. package/dist/handler/generated-handler-registry.js.map +1 -1
  98. package/dist/handler/generated-registry-discovery.d.ts.map +1 -1
  99. package/dist/handler/generated-registry-discovery.js +2 -4
  100. package/dist/handler/generated-registry-discovery.js.map +1 -1
  101. package/dist/handler/handler-decorators.d.ts +91 -37
  102. package/dist/handler/handler-decorators.d.ts.map +1 -1
  103. package/dist/handler/handler-decorators.js +124 -31
  104. package/dist/handler/handler-decorators.js.map +1 -1
  105. package/dist/handler/handler-metadata.d.ts +105 -60
  106. package/dist/handler/handler-metadata.d.ts.map +1 -1
  107. package/dist/handler/handler-metadata.js +275 -57
  108. package/dist/handler/handler-metadata.js.map +1 -1
  109. package/dist/handler/registration-readiness-metadata.d.ts +4 -0
  110. package/dist/handler/registration-readiness-metadata.d.ts.map +1 -1
  111. package/dist/handler/registration-readiness-metadata.js +84 -2
  112. package/dist/handler/registration-readiness-metadata.js.map +1 -1
  113. package/dist/handler/standalone.d.ts +25 -0
  114. package/dist/handler/standalone.d.ts.map +1 -0
  115. package/dist/handler/standalone.js +38 -0
  116. package/dist/handler/standalone.js.map +1 -0
  117. package/dist/index.d.ts +9 -9
  118. package/dist/index.d.ts.map +1 -1
  119. package/dist/index.js +3 -3
  120. package/dist/index.js.map +1 -1
  121. package/dist/repository/command-routing.d.ts +63 -10
  122. package/dist/repository/command-routing.d.ts.map +1 -1
  123. package/dist/repository/command-routing.js +41 -8
  124. package/dist/repository/command-routing.js.map +1 -1
  125. package/dist/repository/event-routing.d.ts +64 -9
  126. package/dist/repository/event-routing.d.ts.map +1 -1
  127. package/dist/repository/event-routing.js +42 -7
  128. package/dist/repository/event-routing.js.map +1 -1
  129. package/dist/repository/primitive-id.d.ts +12 -23
  130. package/dist/repository/primitive-id.d.ts.map +1 -1
  131. package/dist/repository/primitive-id.js +2 -27
  132. package/dist/repository/primitive-id.js.map +1 -1
  133. package/dist/repository/repository.d.ts +317 -87
  134. package/dist/repository/repository.d.ts.map +1 -1
  135. package/dist/repository/repository.js +3746 -856
  136. package/dist/repository/repository.js.map +1 -1
  137. package/dist/repository/state-update-routing.d.ts +67 -8
  138. package/dist/repository/state-update-routing.d.ts.map +1 -1
  139. package/dist/repository/state-update-routing.js +45 -6
  140. package/dist/repository/state-update-routing.js.map +1 -1
  141. package/dist/runtime/runtime.js +1 -1
  142. package/dist/runtime/runtime.js.map +1 -1
  143. package/dist/runtime/signal-metadata.d.ts +22 -47
  144. package/dist/runtime/signal-metadata.d.ts.map +1 -1
  145. package/dist/runtime/signal-metadata.js +34 -69
  146. package/dist/runtime/signal-metadata.js.map +1 -1
  147. package/dist/runtime/signal-publisher.d.ts +144 -0
  148. package/dist/runtime/signal-publisher.d.ts.map +1 -0
  149. package/dist/runtime/signal-publisher.js +248 -0
  150. package/dist/runtime/signal-publisher.js.map +1 -0
  151. package/dist/runtime/standalone-handler-runtime.d.ts +130 -0
  152. package/dist/runtime/standalone-handler-runtime.d.ts.map +1 -0
  153. package/dist/runtime/standalone-handler-runtime.js +382 -0
  154. package/dist/runtime/standalone-handler-runtime.js.map +1 -0
  155. package/dist/server/environment-attachment.d.ts.map +1 -1
  156. package/dist/server/environment-attachment.js +2 -1
  157. package/dist/server/environment-attachment.js.map +1 -1
  158. package/dist/server/environment-delivery-worker.d.ts.map +1 -1
  159. package/dist/server/environment-delivery-worker.js +21 -12
  160. package/dist/server/environment-delivery-worker.js.map +1 -1
  161. package/dist/server/managed-server-application.d.ts +4 -1
  162. package/dist/server/managed-server-application.d.ts.map +1 -1
  163. package/dist/server/managed-server-application.js +2 -2
  164. package/dist/server/managed-server-application.js.map +1 -1
  165. package/dist/server/node-coordinator.js +2 -2
  166. package/dist/server/node-coordinator.js.map +1 -1
  167. package/dist/server/server-log.d.ts.map +1 -1
  168. package/dist/server/server-log.js +4 -0
  169. package/dist/server/server-log.js.map +1 -1
  170. package/dist/server/server.d.ts +9 -177
  171. package/dist/server/server.d.ts.map +1 -1
  172. package/dist/server/server.js +428 -178
  173. package/dist/server/server.js.map +1 -1
  174. package/dist/services/query-reader.d.ts +19 -0
  175. package/dist/services/query-reader.d.ts.map +1 -0
  176. package/dist/services/query-reader.js +43 -0
  177. package/dist/services/query-reader.js.map +1 -0
  178. package/dist/services/registered-targets.d.ts +73 -0
  179. package/dist/services/registered-targets.d.ts.map +1 -0
  180. package/dist/services/registered-targets.js +127 -0
  181. package/dist/services/registered-targets.js.map +1 -0
  182. package/dist/services/spine-services.d.ts +26 -12
  183. package/dist/services/spine-services.d.ts.map +1 -1
  184. package/dist/services/spine-services.js +1047 -969
  185. package/dist/services/spine-services.js.map +1 -1
  186. package/dist/spi/delivery.d.ts +5 -0
  187. package/dist/spi/delivery.d.ts.map +1 -0
  188. package/dist/spi/delivery.js +18 -0
  189. package/dist/spi/delivery.js.map +1 -0
  190. package/dist/spi/handler-registry.d.ts +8 -0
  191. package/dist/spi/handler-registry.d.ts.map +1 -0
  192. package/dist/spi/handler-registry.js +15 -0
  193. package/dist/spi/handler-registry.js.map +1 -0
  194. package/dist/stand/stand.d.ts +73 -1
  195. package/dist/stand/stand.d.ts.map +1 -1
  196. package/dist/stand/stand.js +221 -48
  197. package/dist/stand/stand.js.map +1 -1
  198. package/dist/stand/subscription-observer.d.ts.map +1 -1
  199. package/dist/stand/subscription-observer.js +5 -12
  200. package/dist/stand/subscription-observer.js.map +1 -1
  201. package/dist/stand/subscription-registry.js +1 -1
  202. package/dist/stand/subscription-registry.js.map +1 -1
  203. package/dist/testing/index.d.ts +25 -3
  204. package/dist/testing/index.d.ts.map +1 -1
  205. package/dist/testing/index.js +23 -3
  206. package/dist/testing/index.js.map +1 -1
  207. package/dist/tsconfig.tsbuildinfo +1 -1
  208. package/package.json +33 -23
  209. package/dist/handler/build-time-handler-analyzer.d.ts +0 -150
  210. package/dist/handler/build-time-handler-analyzer.d.ts.map +0 -1
  211. package/dist/handler/build-time-handler-analyzer.js +0 -1101
  212. package/dist/handler/build-time-handler-analyzer.js.map +0 -1
  213. package/dist/handler/generated-registry-writer.d.ts +0 -58
  214. package/dist/handler/generated-registry-writer.d.ts.map +0 -1
  215. package/dist/handler/generated-registry-writer.js +0 -458
  216. package/dist/handler/generated-registry-writer.js.map +0 -1
  217. package/dist/handler/handler-codegen.d.ts +0 -48
  218. package/dist/handler/handler-codegen.d.ts.map +0 -1
  219. package/dist/handler/handler-codegen.js +0 -214
  220. package/dist/handler/handler-codegen.js.map +0 -1
  221. package/dist/server/browser-server.d.ts +0 -49
  222. package/dist/server/browser-server.d.ts.map +0 -1
  223. package/dist/server/browser-server.js.map +0 -1
  224. package/dist/server/durable-subscription-bindings.d.ts.map +0 -1
  225. package/dist/server/durable-subscription-bindings.js.map +0 -1
  226. /package/dist/{server → browser}/durable-subscription-bindings.d.ts +0 -0
  227. /package/dist/{server → browser}/durable-subscription-bindings.js +0 -0
@@ -11,10 +11,187 @@
11
11
  * or implied. See the License for the specific language governing permissions and limitations under
12
12
  * the License.
13
13
  */
14
- import { clone, fromBinary, toBinary } from "@bufbuild/protobuf";
15
- import { ValidationErrorSchema, } from "@spine-event-engine/proto";
14
+ import { clone, create, fromBinary, toBinary, } from "@bufbuild/protobuf";
15
+ import { EntityQuery, } from "@spine-event-engine/core";
16
+ import { EntityQueryDescription } from "@spine-event-engine/core/codegen";
17
+ import { VersionSchema, ActorContextSchema, ValidationErrorSchema, } from "@spine-event-engine/proto";
16
18
  import { describeEntityMetadata, } from "./entity-metadata.js";
17
19
  import { EntityTransaction, } from "./entity-transaction.js";
20
+ const processManagerQueries = new WeakMap();
21
+ /**
22
+ * Keeps Process Manager execution limits at the read boundary.
23
+ */
24
+ const ProcessManagerQueryLimits = Object.freeze({
25
+ /**
26
+ * Rejects plans that exceed Process Manager result or explicit-ID limits.
27
+ *
28
+ * @param plan Compiled query plan to execute.
29
+ */
30
+ check(plan) {
31
+ if (plan.limit !== undefined && plan.limit > 1_000) {
32
+ throw new TypeError("Process Manager query limit may be at most 1000.");
33
+ }
34
+ if (plan.predicate !== undefined && this.ids(plan.predicate) > 1_000) {
35
+ throw new TypeError("Process Manager query ID filter may contain at most 1000 IDs.");
36
+ }
37
+ },
38
+ /**
39
+ * Returns the number of explicit IDs in a compiled predicate tree.
40
+ *
41
+ * @param predicate Compiled filter node.
42
+ * @returns Number of explicit IDs in that node.
43
+ */
44
+ ids(predicate) {
45
+ if (predicate.kind === "ids")
46
+ return predicate.ids.length;
47
+ if (predicate.kind === "comparison")
48
+ return 0;
49
+ return predicate.predicates.reduce((total, child) => total + this.ids(child), 0);
50
+ },
51
+ });
52
+ /**
53
+ * Binds the repository-scoped query capability for one Process Manager invocation.
54
+ *
55
+ * @internal
56
+ */
57
+ export const processManagerQueryAccess = Object.freeze({
58
+ /**
59
+ * Enables read-side queries for the duration of one handler invocation.
60
+ *
61
+ * @param entity Process Manager receiving the query capability.
62
+ * @param execute Repository operation that runs queries.
63
+ * @param actorContext Actor and tenant of the incoming signal.
64
+ * @returns A function that disables and removes this capability.
65
+ */
66
+ bind(entity, execute, actorContext) {
67
+ const capability = {
68
+ execute,
69
+ actorContext: clone(ActorContextSchema, actorContext),
70
+ active: true,
71
+ };
72
+ processManagerQueries.set(entity, capability);
73
+ return () => {
74
+ capability.active = false;
75
+ processManagerQueries.delete(entity);
76
+ };
77
+ },
78
+ /**
79
+ * Gets the query capability of a currently executing Process Manager.
80
+ *
81
+ * @param entity Process Manager attempting a query.
82
+ * @returns The active repository query capability.
83
+ */
84
+ require(entity) {
85
+ const capability = processManagerQueries.get(entity);
86
+ if (capability?.active !== true) {
87
+ throw new Error("Process Manager queries are available only during repository handler execution.");
88
+ }
89
+ return capability;
90
+ },
91
+ });
92
+ /**
93
+ * A repository-scoped, read-only Entity query issued by a Process Manager.
94
+ *
95
+ * @typeParam Schema State schema read by the query.
96
+ * @typeParam Columns Registered descriptor-backed columns for `Schema`.
97
+ */
98
+ export class ProcessManagerQuery {
99
+ #entity;
100
+ #schema;
101
+ #builder;
102
+ /**
103
+ * Creates the repository-scoped query facade.
104
+ *
105
+ * @internal
106
+ * @param entity Process Manager using this query capability.
107
+ * @param schema State schema read by this query.
108
+ * @param builder Typed query builder used to create the wire query.
109
+ */
110
+ constructor(entity, schema, builder) {
111
+ this.#entity = entity;
112
+ this.#schema = schema;
113
+ this.#builder = builder;
114
+ }
115
+ /**
116
+ * Adds the supplied Entity IDs to the query target.
117
+ *
118
+ * @param ids Entity IDs to include.
119
+ * @returns This query for fluent configuration.
120
+ */
121
+ byId(...ids) {
122
+ this.#builder.byId(...ids);
123
+ return this;
124
+ }
125
+ /**
126
+ * Adds a typed state predicate to the query.
127
+ *
128
+ * @typeParam Predicate Comparison supported by the registered columns.
129
+ * @param predicate Predicate evaluated against registered state columns.
130
+ * @returns This query for fluent configuration.
131
+ */
132
+ where(predicate) {
133
+ this.#builder.where(predicate);
134
+ return this;
135
+ }
136
+ /**
137
+ * Sets the ordering for matching states by one registered column.
138
+ *
139
+ * @typeParam Column Registered column supplying the ordered values.
140
+ * @param column Registered orderable column used for sorting.
141
+ * @param direction Optional sort direction, ascending by default.
142
+ * @returns This query for fluent configuration.
143
+ */
144
+ orderBy(column, direction = "asc") {
145
+ this.#builder.orderBy(column, direction);
146
+ return this;
147
+ }
148
+ /**
149
+ * Sets the returned-state limit to at most 1,000 entries.
150
+ *
151
+ * @param value Maximum number of states to return.
152
+ * @returns This query for fluent configuration.
153
+ */
154
+ limit(value) {
155
+ if (value > 1_000) {
156
+ throw new TypeError("Process Manager query limit may be at most 1000.");
157
+ }
158
+ this.#builder.limit(value);
159
+ return this;
160
+ }
161
+ /**
162
+ * Reads matching state snapshots from the eventually consistent query projection.
163
+ *
164
+ * @returns Readonly state snapshots, subject to the configured result limit.
165
+ */
166
+ async read() {
167
+ const capability = processManagerQueryAccess.require(this.#entity);
168
+ const plan = this.#builder.buildPlan();
169
+ ProcessManagerQueryLimits.check(plan);
170
+ const states = await capability.execute(plan, this.#schema, this.#builder.build());
171
+ return Object.freeze(states.slice(0, 1_000));
172
+ }
173
+ /**
174
+ * Reads the first state snapshot for one Entity ID.
175
+ *
176
+ * @param id Entity ID to read.
177
+ * @returns The eventually consistent state snapshot, or `undefined` when it is absent.
178
+ */
179
+ async findById(id) {
180
+ const states = await this.byId(id).read();
181
+ return states[0];
182
+ }
183
+ /**
184
+ * Reads every matching state snapshot within the configured result limit.
185
+ *
186
+ * This can be more expensive than an ID-targeted read because the projection must evaluate all
187
+ * matching states.
188
+ *
189
+ * @returns Readonly eventually consistent state snapshots.
190
+ */
191
+ async all() {
192
+ return await this.read();
193
+ }
194
+ }
18
195
  const rejectedCommits = new WeakMap();
19
196
  /**
20
197
  * Error thrown when a transactional entity draft helper is used outside its scope.
@@ -45,15 +222,15 @@ export class TransactionalEntityScopeError extends Error {
45
222
  Object.setPrototypeOf(this, new.target.prototype);
46
223
  }
47
224
  }
48
- const isProxy = process.getBuiltinModule("node:util").types.isProxy;
49
225
  /**
50
- * Common in-memory OOP shell for one server-side entity state.
226
+ * Identity, state, version, and lifecycle of one server-side Entity.
227
+ *
228
+ * Keeps the Entity ID, state schema, state, Spine Version, and lifecycle flags.
229
+ * State and Version accessors return copies, and lifecycle access returns a
230
+ * separate flag object. Repositories run handlers and manage storage.
51
231
  *
52
- * The shell exposes identity, descriptor-derived metadata, cloned state
53
- * snapshots, caller-owned plain version metadata snapshots, and lifecycle flags. It does not
54
- * invoke handlers, create transactions, write repositories or storage, dispatch
55
- * messages, increment versions, route IDs, query read models, start buses, or
56
- * mutate process-wide runtime state.
232
+ * @typeParam Id Domain identifier type.
233
+ * @typeParam Schema Generated schema describing the Entity state.
57
234
  */
58
235
  export class Entity {
59
236
  #id;
@@ -64,7 +241,7 @@ export class Entity {
64
241
  #lifecycle;
65
242
  #lifecycleFlagsChanged = false;
66
243
  /**
67
- * Creates an entity shell from caller-provided state and metadata inputs.
244
+ * Initializes an Entity from its ID, schema, state, Version, and lifecycle flags.
68
245
  *
69
246
  * @param options Identity, schema, state, version, and lifecycle inputs.
70
247
  */
@@ -73,7 +250,7 @@ export class Entity {
73
250
  this.#schema = options.schema;
74
251
  this.#metadata = describeEntityMetadata(options.schema);
75
252
  this.#state = EntitySnapshots.clone(options.schema, options.state);
76
- this.#version = EntityVersions.clone(options.version);
253
+ this.#version = clone(VersionSchema, options.version ?? create(VersionSchema));
77
254
  this.#lifecycle = {
78
255
  archived: options.lifecycle?.archived ?? false,
79
256
  deleted: options.lifecycle?.deleted ?? false,
@@ -82,7 +259,7 @@ export class Entity {
82
259
  /**
83
260
  * Gets the stable entity identifier.
84
261
  *
85
- * @returns The caller-owned entity identifier.
262
+ * @returns The domain identifier supplied during construction.
86
263
  */
87
264
  get id() {
88
265
  return this.#id;
@@ -112,12 +289,12 @@ export class Entity {
112
289
  return EntitySnapshots.clone(this.#schema, this.#state);
113
290
  }
114
291
  /**
115
- * Gets the caller-owned plain version metadata snapshot.
292
+ * Gets the current Spine Version without exposing the stored message.
116
293
  *
117
- * @returns A validated clone of the version metadata.
294
+ * @returns A copy of the version number and timestamp.
118
295
  */
119
296
  get version() {
120
- return EntityVersions.clone(this.#version);
297
+ return clone(VersionSchema, this.#version);
121
298
  }
122
299
  /**
123
300
  * Gets the current lifecycle flag snapshot.
@@ -163,7 +340,7 @@ export class Entity {
163
340
  return this.#lifecycleFlagsChanged;
164
341
  }
165
342
  /**
166
- * Replaces stored state from framework-owned subclass or runtime code.
343
+ * Replaces stored state when framework transaction code accepts a draft.
167
344
  *
168
345
  * @param state Next entity state snapshot.
169
346
  */
@@ -171,15 +348,15 @@ export class Entity {
171
348
  this.#state = EntitySnapshots.clone(this.#schema, state);
172
349
  }
173
350
  /**
174
- * Replaces caller-owned version metadata from framework-owned subclass or runtime code.
351
+ * Applies the Version calculated by a framework transaction.
175
352
  *
176
- * @param version Next caller-owned version metadata.
353
+ * @param version Accepted version number and timestamp.
177
354
  */
178
- replaceVersionMetadata(version) {
179
- this.#version = EntityVersions.clone(version);
355
+ replaceVersion(version) {
356
+ this.#version = clone(VersionSchema, version);
180
357
  }
181
358
  /**
182
- * Replaces lifecycle flags from framework-owned subclass or runtime code.
359
+ * Applies lifecycle flags accepted by framework transaction code.
183
360
  *
184
361
  * @param lifecycle Lifecycle flag changes to apply.
185
362
  */
@@ -229,21 +406,60 @@ const boundEntityHistories = new WeakMap();
229
406
  * @internal
230
407
  */
231
408
  export const entityHistoryAccess = Object.freeze({
409
+ /**
410
+ * Associates an Entity instance with its repository history operations.
411
+ *
412
+ * @param entity Entity instance loaded by the repository.
413
+ * @param binding Operations bound to that Entity's history.
414
+ */
232
415
  bind(entity, binding) {
233
416
  boundEntityHistories.set(entity, binding);
234
417
  },
418
+ /**
419
+ * Reads the most recent retained state no later than the requested time.
420
+ *
421
+ * @param entity Entity whose state is requested.
422
+ * @param time Latest allowed state timestamp.
423
+ * @returns The retained state, or undefined when none matches.
424
+ */
235
425
  stateAt(entity, time) {
236
426
  return EntityHistory.require(entity).stateAt(time);
237
427
  },
428
+ /**
429
+ * Reads retained states after checking the history read limit.
430
+ *
431
+ * @param entity Entity whose history is requested.
432
+ * @param depth Maximum number of states to return.
433
+ * @returns Retained states in descending version order.
434
+ */
238
435
  states(entity, depth) {
239
436
  return EntityHistory.require(entity).states(EntityHistory.depth(depth));
240
437
  },
438
+ /**
439
+ * Reads diagnostic Events after checking the history read limit.
440
+ *
441
+ * @param entity Entity that produced the Events.
442
+ * @param depth Maximum number of Events to return.
443
+ * @returns Retained Events in descending producer-version order.
444
+ */
241
445
  events(entity, depth) {
242
446
  return EntityHistory.require(entity).events(EntityHistory.depth(depth));
243
447
  },
448
+ /**
449
+ * Gets the state-history storage attached by the repository.
450
+ *
451
+ * @param entity Entity whose retained states are maintained.
452
+ * @returns Its state-history storage.
453
+ */
244
454
  stateMaintenance(entity) {
245
455
  return EntityHistory.require(entity).stateMaintenance;
246
456
  },
457
+ /**
458
+ * Gets diagnostic Event storage attached by the repository.
459
+ *
460
+ * @param entity Entity whose retained Events are maintained.
461
+ * @returns Its diagnostic Event storage.
462
+ */
247
463
  eventMaintenance(entity) {
248
464
  return EntityHistory.require(entity).eventMaintenance;
249
465
  },
@@ -252,6 +468,12 @@ export const entityHistoryAccess = Object.freeze({
252
468
  * Validates repository-bound history lookups.
253
469
  */
254
470
  const EntityHistory = Object.freeze({
471
+ /**
472
+ * Gets history operations installed during repository execution.
473
+ *
474
+ * @param entity Entity instance whose binding is required.
475
+ * @returns Its repository history operations.
476
+ */
255
477
  require(entity) {
256
478
  const binding = boundEntityHistories.get(entity);
257
479
  if (binding === undefined) {
@@ -259,6 +481,12 @@ const EntityHistory = Object.freeze({
259
481
  }
260
482
  return binding;
261
483
  },
484
+ /**
485
+ * Rejects history read limits that are not positive safe integers.
486
+ *
487
+ * @param depth Requested history read limit.
488
+ * @returns The validated limit.
489
+ */
262
490
  depth(depth) {
263
491
  if (!Number.isSafeInteger(depth) || depth <= 0) {
264
492
  throw new RangeError("Entity history depth must be a positive safe integer.");
@@ -267,16 +495,15 @@ const EntityHistory = Object.freeze({
267
495
  },
268
496
  });
269
497
  /**
270
- * Common in-memory entity shell with a protected scoped transaction draft.
498
+ * Entity base with one active transaction draft.
499
+ *
500
+ * Repository dispatch starts and finishes each transaction. Entity handlers
501
+ * change the draft state or lifecycle through protected helpers. A successful
502
+ * commit updates state, Spine Version, and lifecycle flags. A rejected commit
503
+ * leaves the draft active until the framework rolls it back.
271
504
  *
272
- * The transaction scope is backed by {@link EntityTransaction}. Subclasses can
273
- * start one active draft, mutate draft state/version/lifecycle through protected
274
- * helpers, and then commit or roll back the scope. Accepted commits replace this
275
- * entity's in-memory state, explicit version metadata, and lifecycle flags.
276
- * Rejected commits leave the transaction active so subclass code can correct the
277
- * draft or roll it back explicitly. This base does not write repositories,
278
- * emit events, dispatch handlers, increment versions, or manage global
279
- * transaction state.
505
+ * @typeParam Id Domain identifier type.
506
+ * @typeParam Schema Generated schema describing the Entity state.
280
507
  */
281
508
  export class TransactionalEntity extends Entity {
282
509
  #transaction;
@@ -312,7 +539,7 @@ export class TransactionalEntity extends Entity {
312
539
  previous: this.state,
313
540
  version: {
314
541
  previous: previousVersion,
315
- draft: EntityVersions.clone(previousVersion),
542
+ draft: clone(VersionSchema, previousVersion),
316
543
  },
317
544
  lifecycle: this.lifecycle,
318
545
  });
@@ -326,19 +553,6 @@ export class TransactionalEntity extends Entity {
326
553
  currentDraft() {
327
554
  return this.#requireTransaction("currentDraft").currentDraft;
328
555
  }
329
- /**
330
- * Gets the current draft version metadata snapshot.
331
- *
332
- * @returns Cloned previous and draft version metadata.
333
- * @throws {@link TransactionalEntityScopeError} when no transaction is active.
334
- */
335
- draftVersionMetadata() {
336
- const version = this.#requireTransaction("draftVersionMetadata").version;
337
- return {
338
- previous: EntityVersions.clone(version.previous),
339
- draft: EntityVersions.clone(version.draft),
340
- };
341
- }
342
556
  /**
343
557
  * Gets the current draft lifecycle flag snapshot.
344
558
  *
@@ -371,17 +585,6 @@ export class TransactionalEntity extends Entity {
371
585
  tryUpdate(mutator) {
372
586
  return this.#requireTransaction("tryUpdate").tryUpdate(mutator);
373
587
  }
374
- /**
375
- * Updates the buffered draft version metadata without computing version increments.
376
- *
377
- * @param draft Caller-owned version metadata for the active draft.
378
- * @returns Cloned previous and draft version metadata.
379
- * @throws {@link TransactionalEntityScopeError} when no transaction is active.
380
- */
381
- updateDraftVersionMetadata(draft) {
382
- this.#requireTransaction("updateDraftVersionMetadata").updateVersionMetadata(EntityVersions.clone(draft));
383
- return this.draftVersionMetadata();
384
- }
385
588
  /**
386
589
  * Marks the buffered draft lifecycle as archived.
387
590
  *
@@ -421,23 +624,24 @@ export class TransactionalEntity extends Entity {
421
624
  /**
422
625
  * Commits the active draft transaction.
423
626
  *
424
- * Accepted commits apply state, version metadata, and lifecycle flags to this
627
+ * Accepted commits apply state, Spine Version, and lifecycle flags to this
425
628
  * entity and close the transaction. Rejected commits do not apply anything and
426
629
  * keep the transaction active for correction or explicit rollback.
427
630
  *
631
+ * @param producedEvents Whether handling returned Events, requiring a version advance.
428
632
  * @returns A cloned accepted or rejected transaction result.
429
633
  * @throws {@link TransactionalEntityScopeError} when no transaction is active.
430
634
  */
431
- commitTransaction() {
635
+ commitTransaction(producedEvents = false) {
432
636
  const transaction = this.#requireTransaction("commitTransaction");
433
- const result = transaction.commit();
637
+ const result = transaction.commit(producedEvents);
434
638
  if (result.status === "accepted") {
435
639
  if (result.previous === undefined ||
436
640
  !EntitySnapshots.equal(this.schema, result.previous, result.next)) {
437
641
  this.#stateChanged = true;
438
642
  }
439
643
  this.replaceState(result.next);
440
- this.replaceVersionMetadata(result.version.committed);
644
+ this.replaceVersion(result.version.committed);
441
645
  this.replaceLifecycleFlags(result.lifecycle);
442
646
  this.#transaction = undefined;
443
647
  rejectedCommits.delete(this);
@@ -458,6 +662,12 @@ export class TransactionalEntity extends Entity {
458
662
  this.#transaction = undefined;
459
663
  return result;
460
664
  }
665
+ /**
666
+ * Gets the active transaction or rejects an out-of-scope operation.
667
+ *
668
+ * @param operation Draft operation being attempted.
669
+ * @returns The currently active transaction.
670
+ */
461
671
  #requireTransaction(operation) {
462
672
  const transaction = this.#transaction;
463
673
  if (transaction?.status !== "active") {
@@ -472,12 +682,29 @@ export class TransactionalEntity extends Entity {
472
682
  * @internal
473
683
  */
474
684
  export const transactionalEntityAccess = Object.freeze({
685
+ /**
686
+ * Starts the Entity's protected transaction before invoking its handler.
687
+ *
688
+ * @param entity Entity about to handle a signal.
689
+ */
475
690
  start(entity) {
476
691
  TransactionAccess.call(entity, "startTransaction");
477
692
  },
478
- commit(entity) {
479
- return TransactionAccess.call(entity, "commitTransaction");
693
+ /**
694
+ * Commits the handler's draft and records whether it returned Events.
695
+ *
696
+ * @param entity Entity whose handler has completed.
697
+ * @param producedEvents Whether handling returned domain Events.
698
+ * @returns The accepted or validation-rejected transaction result.
699
+ */
700
+ commit(entity, producedEvents = false) {
701
+ return TransactionAccess.call(entity, "commitTransaction", producedEvents);
480
702
  },
703
+ /**
704
+ * Rolls back an active draft, ignoring a transaction that has already closed.
705
+ *
706
+ * @param entity Entity whose handling failed or was rejected.
707
+ */
481
708
  rollback(entity) {
482
709
  try {
483
710
  TransactionAccess.call(entity, "rollbackTransaction");
@@ -488,6 +715,12 @@ export const transactionalEntityAccess = Object.freeze({
488
715
  }
489
716
  }
490
717
  },
718
+ /**
719
+ * Reads the validation failure retained for the Entity's latest rejected commit.
720
+ *
721
+ * @param entity Entity whose rejected result is requested.
722
+ * @returns A copy of the rejected result, or undefined when none is retained.
723
+ */
491
724
  rejectedCommit(entity) {
492
725
  const rejected = rejectedCommits.get(entity);
493
726
  return rejected === undefined
@@ -499,28 +732,44 @@ export const transactionalEntityAccess = Object.freeze({
499
732
  * Bridges repository code to protected transactional entity methods.
500
733
  */
501
734
  const TransactionAccess = Object.freeze({
502
- call(entity, methodName) {
735
+ /**
736
+ * Invokes a protected transaction method from repository code.
737
+ *
738
+ * @param entity Instance receiving the method call.
739
+ * @param methodName Transaction method to invoke.
740
+ * @param args Arguments passed to the transaction method.
741
+ * @returns The method's result.
742
+ */
743
+ call(entity, methodName, ...args) {
503
744
  const method = entity[methodName];
504
745
  if (typeof method !== "function") {
505
746
  throw new TypeError(`Transactional entity access requires "${methodName}".`);
506
747
  }
507
- return Reflect.apply(method, entity, []);
748
+ return Reflect.apply(method, entity, args);
508
749
  },
750
+ /**
751
+ * Tests whether an operation failed because no transaction was active.
752
+ *
753
+ * @param error Failure returned by a transaction operation.
754
+ * @returns True only for a missing transaction scope.
755
+ */
509
756
  isMissing(error) {
510
757
  return error instanceof TransactionalEntityScopeError && error.reason === "missing";
511
758
  },
512
759
  });
513
760
  /**
514
- * Abstract aggregate family marker over the common transactional entity shell.
761
+ * Base class for Aggregates with transactional state and Event-history access.
762
+ *
763
+ * Provides Aggregate family identity and protected repository-backed history
764
+ * methods. Repositories and bounded contexts handle dispatch, persistence, and
765
+ * Event publication; application handlers change state through draft helpers.
515
766
  *
516
- * This class intentionally adds only stable family identity. It does not add
517
- * command dispatch, snapshots, repositories, idempotency guards, or handler
518
- * invocation. Repository-bound diagnostic event-history reads are declared
519
- * below for the Aggregate family.
767
+ * @typeParam Id Domain identifier type.
768
+ * @typeParam Schema Generated schema describing the Aggregate state.
520
769
  */
521
770
  export class Aggregate extends TransactionalEntity {
522
771
  /**
523
- * Creates an aggregate family shell from caller-provided state and metadata inputs.
772
+ * Creates an Aggregate from its identity, state, and metadata.
524
773
  *
525
774
  * @param options Identity, schema, state, version, and lifecycle inputs.
526
775
  */
@@ -557,15 +806,18 @@ export class Aggregate extends TransactionalEntity {
557
806
  }
558
807
  }
559
808
  /**
560
- * Abstract projection family marker over the common transactional entity shell.
809
+ * Base class for Projections with transactional state.
810
+ *
811
+ * Repositories and Bounded Contexts invoke Event handlers and persist state
812
+ * changes with the Projection's Version.
813
+ * Projections do not expose the diagnostic history methods of other families.
561
814
  *
562
- * This class intentionally adds only stable family identity. It does not add
563
- * event subscriptions, event playing, repositories, version columns, query
564
- * clients, or handler invocation.
815
+ * @typeParam Id Domain identifier type.
816
+ * @typeParam Schema Generated schema describing the Projection state.
565
817
  */
566
818
  export class Projection extends TransactionalEntity {
567
819
  /**
568
- * Creates a projection family shell from caller-provided state and metadata inputs.
820
+ * Creates a Projection from its identity, state, and metadata.
569
821
  *
570
822
  * @param options Identity, schema, state, version, and lifecycle inputs.
571
823
  */
@@ -575,15 +827,18 @@ export class Projection extends TransactionalEntity {
575
827
  }
576
828
  }
577
829
  /**
578
- * Abstract process manager family marker over the common transactional entity shell.
830
+ * Base class for Process Managers coordinating a workflow through signals.
579
831
  *
580
- * This class intentionally adds only stable family identity. It does not add
581
- * process workflow execution, command posting, query clients, repositories,
582
- * bounded-context injection, or handler invocation.
832
+ * Provides transactional state, protected Event-history access, and
833
+ * handler-scoped queryable Entity-state reads through `select()`. Repositories and bounded
834
+ * contexts invoke handlers, persist changes, and deliver returned signals.
835
+ *
836
+ * @typeParam Id Domain identifier type.
837
+ * @typeParam Schema Generated schema describing the Process Manager state.
583
838
  */
584
839
  export class ProcessManager extends TransactionalEntity {
585
840
  /**
586
- * Creates a process manager family shell from caller-provided state and metadata inputs.
841
+ * Creates a Process Manager from its identity, state, and metadata.
587
842
  *
588
843
  * @param options Identity, schema, state, version, and lifecycle inputs.
589
844
  */
@@ -618,11 +873,47 @@ export class ProcessManager extends TransactionalEntity {
618
873
  eventStorage() {
619
874
  return entityHistoryAccess.eventMaintenance(this);
620
875
  }
876
+ /**
877
+ * Binds either query form to the active handler capability.
878
+ *
879
+ * @typeParam QuerySchema Queried Entity state schema.
880
+ * @typeParam Columns Registered columns for the legacy builder.
881
+ * @typeParam Id Identifier type of a detached query.
882
+ * @param schemaOrQuery State schema or built context-free query.
883
+ * @param columns Columns required with a state schema.
884
+ * @returns Legacy builder or detached-query read facade.
885
+ */
886
+ select(schemaOrQuery, columns) {
887
+ const capability = processManagerQueryAccess.require(this);
888
+ if (schemaOrQuery instanceof EntityQueryDescription) {
889
+ const query = schemaOrQuery;
890
+ return Object.freeze({
891
+ read: async () => {
892
+ const active = processManagerQueryAccess.require(this);
893
+ const plan = query.buildPlan();
894
+ ProcessManagerQueryLimits.check(plan);
895
+ const wire = query.build();
896
+ wire.context = clone(ActorContextSchema, active.actorContext);
897
+ const states = await active.execute(plan, query.schema, wire);
898
+ return Object.freeze(states.slice(0, 1_000));
899
+ },
900
+ });
901
+ }
902
+ if (columns === undefined)
903
+ throw new TypeError("Process Manager query columns are required.");
904
+ return new ProcessManagerQuery(this, schemaOrQuery, EntityQuery.select({ schema: schemaOrQuery, columns, context: capability.actorContext }));
905
+ }
621
906
  }
622
907
  /**
623
908
  * Marks immutable entity families.
624
909
  */
625
910
  const EntityFamilies = Object.freeze({
911
+ /**
912
+ * Records whether an Entity is an Aggregate, Projection, or Process Manager.
913
+ *
914
+ * @param entity Instance being constructed.
915
+ * @param family Kind of Entity being constructed.
916
+ */
626
917
  mark(entity, family) {
627
918
  Object.defineProperty(entity, "entityFamily", {
628
919
  configurable: false,
@@ -636,9 +927,26 @@ const EntityFamilies = Object.freeze({
636
927
  * Creates entity-state snapshots and compares state bytes.
637
928
  */
638
929
  const EntitySnapshots = Object.freeze({
930
+ /**
931
+ * Copies state through its schema, discarding unknown wire fields.
932
+ *
933
+ * @typeParam Schema Generated schema describing the state.
934
+ * @param schema Schema used for encoding and decoding.
935
+ * @param state State snapshot to copy.
936
+ * @returns An independent state message containing known fields.
937
+ */
639
938
  clone(schema, state) {
640
939
  return fromBinary(schema, toBinary(schema, state, { writeUnknownFields: false }));
641
940
  },
941
+ /**
942
+ * Compares the encoded known fields of two state snapshots.
943
+ *
944
+ * @typeParam Schema Generated schema shared by both snapshots.
945
+ * @param schema Schema used to encode the states.
946
+ * @param previous State before handling.
947
+ * @param next State after handling.
948
+ * @returns True when their encoded known fields are identical.
949
+ */
642
950
  equal(schema, previous, next) {
643
951
  const previousBinary = toBinary(schema, previous, { writeUnknownFields: false });
644
952
  const nextBinary = toBinary(schema, next, { writeUnknownFields: false });
@@ -647,16 +955,23 @@ const EntitySnapshots = Object.freeze({
647
955
  },
648
956
  });
649
957
  /**
650
- * Creates immutable transaction-result snapshots.
958
+ * Copies transaction version, lifecycle, and validation snapshots.
651
959
  */
652
960
  const EntityCommits = Object.freeze({
961
+ /**
962
+ * Copies version, lifecycle, and validation messages in a transaction result.
963
+ *
964
+ * @typeParam Schema Generated schema describing the transaction's state.
965
+ * @param result Accepted or rejected transaction result.
966
+ * @returns A result with independent version and validation metadata.
967
+ */
653
968
  clone(result) {
654
969
  if (result.status === "accepted") {
655
970
  return {
656
971
  ...result,
657
972
  version: {
658
- previous: EntityVersions.clone(result.version.previous),
659
- committed: EntityVersions.clone(result.version.committed),
973
+ previous: clone(VersionSchema, result.version.previous),
974
+ committed: clone(VersionSchema, result.version.committed),
660
975
  },
661
976
  lifecycle: { archived: result.lifecycle.archived, deleted: result.lifecycle.deleted },
662
977
  validation: this.validation(result.validation),
@@ -665,13 +980,19 @@ const EntityCommits = Object.freeze({
665
980
  return {
666
981
  ...result,
667
982
  version: {
668
- previous: EntityVersions.clone(result.version.previous),
669
- draft: EntityVersions.clone(result.version.draft),
983
+ previous: clone(VersionSchema, result.version.previous),
984
+ draft: clone(VersionSchema, result.version.draft),
670
985
  },
671
986
  lifecycle: { archived: result.lifecycle.archived, deleted: result.lifecycle.deleted },
672
987
  validation: this.validation(result.validation),
673
988
  };
674
989
  },
990
+ /**
991
+ * Copies validation errors without exposing the stored violation messages.
992
+ *
993
+ * @param validation State-transition validation result.
994
+ * @returns An independent valid result or cloned validation error.
995
+ */
675
996
  validation(validation) {
676
997
  if (validation.valid) {
677
998
  return { valid: true, violations: [], error: undefined };
@@ -684,146 +1005,4 @@ const EntityCommits = Object.freeze({
684
1005
  };
685
1006
  },
686
1007
  });
687
- const maxVersionMetadataDepth = 1_000;
688
- /**
689
- * Validates and clones caller-provided plain version metadata.
690
- */
691
- const EntityVersions = Object.freeze({
692
- clone(version) {
693
- return this.value(version, "$", new WeakSet(), 0);
694
- },
695
- value(value, path, stack, depth) {
696
- if (depth > maxVersionMetadataDepth) {
697
- throw this.error(path, "excessive nesting depth");
698
- }
699
- if (value === null) {
700
- return value;
701
- }
702
- switch (typeof value) {
703
- case "string":
704
- case "number":
705
- case "boolean":
706
- case "bigint":
707
- case "symbol":
708
- case "undefined":
709
- return value;
710
- case "function":
711
- throw this.error(path, "function");
712
- case "object":
713
- return this.object(value, path, stack, depth);
714
- }
715
- },
716
- object(value, path, stack, depth) {
717
- if (isProxy(value))
718
- throw this.error(path, "Proxy");
719
- if (ArrayBuffer.isView(value))
720
- throw this.error(path, this.kind(value));
721
- if (value instanceof ArrayBuffer || this.isSharedBuffer(value)) {
722
- throw this.error(path, this.kind(value));
723
- }
724
- if (stack.has(value))
725
- throw this.error(path, "cyclic object");
726
- stack.add(value);
727
- try {
728
- if (Array.isArray(value))
729
- return this.array(value, path, stack, depth);
730
- if (!this.isPlainObject(value))
731
- throw this.error(path, this.kind(value));
732
- const clone = Object.create(this.prototype(value));
733
- const descriptors = Object.getOwnPropertyDescriptors(value);
734
- const [symbolKey] = Object.getOwnPropertySymbols(descriptors);
735
- if (symbolKey !== undefined) {
736
- throw this.error(`${path}[${String(symbolKey)}]`, "symbol-keyed property");
737
- }
738
- for (const [key, descriptor] of Object.entries(descriptors)) {
739
- const childPath = `${path}.${key}`;
740
- if (!descriptor.enumerable)
741
- throw this.error(childPath, "non-enumerable property");
742
- if (!("value" in descriptor))
743
- throw this.error(childPath, "accessor property");
744
- Object.defineProperty(clone, key, {
745
- configurable: true,
746
- enumerable: true,
747
- value: this.value(descriptor.value, childPath, stack, depth + 1),
748
- writable: true,
749
- });
750
- }
751
- return clone;
752
- }
753
- finally {
754
- stack.delete(value);
755
- }
756
- },
757
- array(value, path, stack, depth) {
758
- if (this.prototype(value) !== Array.prototype)
759
- throw this.error(path, "Array");
760
- const descriptors = Object.getOwnPropertyDescriptors(value);
761
- const [symbolKey] = Object.getOwnPropertySymbols(descriptors);
762
- if (symbolKey !== undefined) {
763
- throw this.error(`${path}[${String(symbolKey)}]`, "symbol-keyed property");
764
- }
765
- const lengthDescriptor = descriptors.length;
766
- if (lengthDescriptor === undefined || !("value" in lengthDescriptor)) {
767
- throw this.error(path, "array without data length");
768
- }
769
- const length = lengthDescriptor.value;
770
- const clone = new Array(length);
771
- for (const [key, descriptor] of Object.entries(descriptors)) {
772
- if (key === "length")
773
- continue;
774
- if (!this.isArrayKey(key, length))
775
- throw this.error(`${path}.${key}`, "custom array property");
776
- if (!descriptor.enumerable)
777
- throw this.error(`${path}[${key}]`, "non-enumerable property");
778
- if (!("value" in descriptor))
779
- throw this.error(`${path}[${key}]`, "accessor property");
780
- }
781
- for (let index = 0; index < length; index += 1) {
782
- const key = String(index);
783
- const descriptor = descriptors[key];
784
- if (descriptor === undefined || !("value" in descriptor)) {
785
- throw this.error(`${path}[${key}]`, "sparse array element");
786
- }
787
- Object.defineProperty(clone, index, {
788
- configurable: true,
789
- enumerable: true,
790
- value: this.value(descriptor.value, `${path}[${key}]`, stack, depth + 1),
791
- writable: true,
792
- });
793
- }
794
- return clone;
795
- },
796
- isArrayKey(key, length) {
797
- const index = Number(key);
798
- return Number.isInteger(index) && index >= 0 && index < length && String(index) === key;
799
- },
800
- isPlainObject(value) {
801
- const prototype = this.prototype(value);
802
- return prototype === Object.prototype || prototype === null;
803
- },
804
- prototype(value) {
805
- return Object.getPrototypeOf(value);
806
- },
807
- kind(value) {
808
- if (value instanceof Date)
809
- return "Date";
810
- if (value instanceof Map)
811
- return "Map";
812
- if (value instanceof Set)
813
- return "Set";
814
- if (ArrayBuffer.isView(value))
815
- return "typed array";
816
- if (value instanceof ArrayBuffer)
817
- return "ArrayBuffer";
818
- if (this.isSharedBuffer(value))
819
- return "SharedArrayBuffer";
820
- return "object";
821
- },
822
- isSharedBuffer(value) {
823
- return typeof SharedArrayBuffer !== "undefined" && value instanceof SharedArrayBuffer;
824
- },
825
- error(path, kind) {
826
- return new TypeError(`Entity version metadata must be plain snapshot data; ${path} contains ${kind}.`);
827
- },
828
- });
829
1008
  //# sourceMappingURL=entity.js.map