@reventlessdev/reventless-spec 3.0.0-alpha.63 → 3.0.0-alpha.64
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.
- package/CHANGELOG.md +8 -0
- package/package.json +15 -3
- package/rescript.json +6 -1
- package/src/components/ComponentKind.res +99 -0
- package/src/components/ComponentKind.res.mjs +125 -0
- package/src/components/DcbDecode.res +2 -20
- package/src/components/DcbDecode.res.mjs +7 -25
- package/src/components/DcbTag.res +31 -104
- package/src/components/DcbTag.res.mjs +33 -120
- package/src/components/DcbValidation.res +1 -10
- package/src/components/DcbValidation.res.mjs +1 -11
- package/src/components/PluginName.res +39 -0
- package/src/components/PluginName.res.mjs +45 -0
- package/src/components/Snapshot.res +26 -0
- package/src/components/Snapshot.res.mjs +2 -0
- package/src/generator/Config.res +9 -26
- package/src/generator/Config.res.mjs +5 -30
- package/src/generator/Discovery.res +5 -26
- package/src/generator/Discovery.res.mjs +4 -54
- package/src/generator/Pairing.res +33 -29
- package/src/generator/Pairing.res.mjs +35 -29
- package/src/types/Behavior.res +8 -0
|
@@ -165,6 +165,38 @@ let hasAsyncAttribute = (filePath: string): bool => {
|
|
|
165
165
|
}
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
+
// Partition the ExtensionPoint mapping files into flat (ungrouped) and grouped
|
|
169
|
+
// `extensionPointDef`s: every mapping sharing an `epGroup` collects into one
|
|
170
|
+
// grouped entry; the ungrouped ones share a single flat (`group: None`) entry.
|
|
171
|
+
// Pure (no I/O) so the grouping is unit-testable — in particular the A8 fix:
|
|
172
|
+
// `Option.getOr`'s eager default previously re-created the group's array every
|
|
173
|
+
// iteration, so a group with ≥2 mappings collapsed to `[]` and the generator
|
|
174
|
+
// emitted a `Plugin.res` referencing a never-generated module.
|
|
175
|
+
let groupExtensionPoints = (epFiles: array<Discovery.discoveredFile>): array<extensionPointDef> => {
|
|
176
|
+
let epByGroup: Dict.t<array<string>> = Dict.make()
|
|
177
|
+
let flatEpMappings: array<string> = []
|
|
178
|
+
|
|
179
|
+
epFiles->Array.forEach(({stem, epGroup}) =>
|
|
180
|
+
switch epGroup {
|
|
181
|
+
| None => flatEpMappings->Array.push(stem)
|
|
182
|
+
| Some(g) =>
|
|
183
|
+
switch Dict.get(epByGroup, g) {
|
|
184
|
+
| Some(arr) => arr->Array.push(stem)
|
|
185
|
+
| None => Dict.set(epByGroup, g, [stem])
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
let extensionPoints: array<extensionPointDef> = []
|
|
191
|
+
if flatEpMappings->Array.length > 0 {
|
|
192
|
+
extensionPoints->Array.push({group: None, mappings: flatEpMappings->sortedStems})
|
|
193
|
+
}
|
|
194
|
+
Dict.toArray(epByGroup)->Array.forEach(((group, mappings)) =>
|
|
195
|
+
extensionPoints->Array.push({group: Some(group), mappings: mappings->sortedStems})
|
|
196
|
+
)
|
|
197
|
+
extensionPoints
|
|
198
|
+
}
|
|
199
|
+
|
|
168
200
|
let resolve = (discovered: array<Discovery.discoveredFile>, ~srcDir: string): resolved => {
|
|
169
201
|
let eventMappings = findEventMappings(~srcDir)
|
|
170
202
|
|
|
@@ -309,35 +341,7 @@ let resolve = (discovered: array<Discovery.discoveredFile>, ~srcDir: string): re
|
|
|
309
341
|
)
|
|
310
342
|
|
|
311
343
|
// ── ExtensionPoint grouping ────────────────────────────────────────────────
|
|
312
|
-
let
|
|
313
|
-
let flatEpMappings: array<string> = []
|
|
314
|
-
|
|
315
|
-
epFiles->Array.forEach(({stem, epGroup}) => {
|
|
316
|
-
switch epGroup {
|
|
317
|
-
| None => flatEpMappings->Array.push(stem)
|
|
318
|
-
| Some(g) =>
|
|
319
|
-
// `Option.getOr`'s default is evaluated eagerly, so the previous shape
|
|
320
|
-
// re-created and re-set a fresh empty array every iteration — overwriting
|
|
321
|
-
// the group's real entry and pushing onto a now-detached array. A group
|
|
322
|
-
// with ≥2 mappings ended up empty, emitting a Plugin.res that referenced a
|
|
323
|
-
// never-generated module (`Array.getUnsafe(0)` on `[]`). Use a switch so
|
|
324
|
-
// the create branch runs only when the group is genuinely absent.
|
|
325
|
-
switch Dict.get(epByGroup, g) {
|
|
326
|
-
| Some(arr) => arr->Array.push(stem)
|
|
327
|
-
| None => Dict.set(epByGroup, g, [stem])
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
})
|
|
331
|
-
|
|
332
|
-
let extensionPoints: array<extensionPointDef> = []
|
|
333
|
-
|
|
334
|
-
if flatEpMappings->Array.length > 0 {
|
|
335
|
-
extensionPoints->Array.push({group: None, mappings: flatEpMappings->sortedStems})
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
Dict.toArray(epByGroup)->Array.forEach(((group, mappings)) => {
|
|
339
|
-
extensionPoints->Array.push({group: Some(group), mappings: mappings->sortedStems})
|
|
340
|
-
})
|
|
344
|
+
let extensionPoints = groupExtensionPoints(epFiles)
|
|
341
345
|
|
|
342
346
|
// ── targetName extraction ──────────────────────────────────────────────────
|
|
343
347
|
let buildTargets = (stems: array<string>, relPaths: Dict.t<string>): Dict.t<option<string>> => {
|
|
@@ -131,6 +131,39 @@ function hasAsyncAttribute(filePath) {
|
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
function groupExtensionPoints(epFiles) {
|
|
135
|
+
let epByGroup = {};
|
|
136
|
+
let flatEpMappings = [];
|
|
137
|
+
epFiles.forEach(param => {
|
|
138
|
+
let epGroup = param.epGroup;
|
|
139
|
+
let stem = param.stem;
|
|
140
|
+
if (epGroup !== undefined) {
|
|
141
|
+
let arr = epByGroup[epGroup];
|
|
142
|
+
if (arr !== undefined) {
|
|
143
|
+
arr.push(stem);
|
|
144
|
+
} else {
|
|
145
|
+
epByGroup[epGroup] = [stem];
|
|
146
|
+
}
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
flatEpMappings.push(stem);
|
|
150
|
+
});
|
|
151
|
+
let extensionPoints = [];
|
|
152
|
+
if (flatEpMappings.length !== 0) {
|
|
153
|
+
extensionPoints.push({
|
|
154
|
+
group: undefined,
|
|
155
|
+
mappings: sortedStems(flatEpMappings)
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
Object.entries(epByGroup).forEach(param => {
|
|
159
|
+
extensionPoints.push({
|
|
160
|
+
group: param[0],
|
|
161
|
+
mappings: sortedStems(param[1])
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
return extensionPoints;
|
|
165
|
+
}
|
|
166
|
+
|
|
134
167
|
function resolve(discovered, srcDir) {
|
|
135
168
|
let eventMappings = findEventMappings(srcDir);
|
|
136
169
|
let stateChangeSlices = [];
|
|
@@ -275,35 +308,7 @@ function resolve(discovered, srcDir) {
|
|
|
275
308
|
}
|
|
276
309
|
};
|
|
277
310
|
let readModels = Stdlib_Array.filterMap(sortedStems(readModelStems), rm => pairReadModel(false, rm)).concat(Stdlib_Array.filterMap(sortedStems(readModelStreamStems), rm => pairReadModel(true, rm)));
|
|
278
|
-
let
|
|
279
|
-
let flatEpMappings = [];
|
|
280
|
-
epFiles.forEach(param => {
|
|
281
|
-
let epGroup = param.epGroup;
|
|
282
|
-
let stem = param.stem;
|
|
283
|
-
if (epGroup !== undefined) {
|
|
284
|
-
let arr = epByGroup[epGroup];
|
|
285
|
-
if (arr !== undefined) {
|
|
286
|
-
arr.push(stem);
|
|
287
|
-
} else {
|
|
288
|
-
epByGroup[epGroup] = [stem];
|
|
289
|
-
}
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
flatEpMappings.push(stem);
|
|
293
|
-
});
|
|
294
|
-
let extensionPoints = [];
|
|
295
|
-
if (flatEpMappings.length !== 0) {
|
|
296
|
-
extensionPoints.push({
|
|
297
|
-
group: undefined,
|
|
298
|
-
mappings: sortedStems(flatEpMappings)
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
Object.entries(epByGroup).forEach(param => {
|
|
302
|
-
extensionPoints.push({
|
|
303
|
-
group: param[0],
|
|
304
|
-
mappings: sortedStems(param[1])
|
|
305
|
-
});
|
|
306
|
-
});
|
|
311
|
+
let extensionPoints = groupExtensionPoints(epFiles);
|
|
307
312
|
let buildTargets = (stems, relPaths) => {
|
|
308
313
|
let dict = {};
|
|
309
314
|
stems.forEach(stem => {
|
|
@@ -350,6 +355,7 @@ export {
|
|
|
350
355
|
sortedStems,
|
|
351
356
|
extractTargetName,
|
|
352
357
|
hasAsyncAttribute,
|
|
358
|
+
groupExtensionPoints,
|
|
353
359
|
resolve,
|
|
354
360
|
}
|
|
355
361
|
/* node:fs Not a pure module */
|
package/src/types/Behavior.res
CHANGED
|
@@ -72,6 +72,14 @@ module type T = {
|
|
|
72
72
|
*/
|
|
73
73
|
let decide: (state, Spec.command) => result<array<Spec.event>, Spec.error>
|
|
74
74
|
|
|
75
|
+
/** Persisted-snapshot configuration (docs/plans/aggregate-snapshotting.md).
|
|
76
|
+
`None` — the default, auto-injected by `@@reventless.behavior` — keeps
|
|
77
|
+
full replay; `Some({interval, stateSchema})` writes a keep-one snapshot
|
|
78
|
+
every `interval` events and seeds cold replays from the latest one.
|
|
79
|
+
Enable with `@@reventless.snapshots(<interval>)` (requires
|
|
80
|
+
`@schema type state`) or a manual binding. */
|
|
81
|
+
let snapshot: option<Snapshot.config<state>>
|
|
82
|
+
|
|
75
83
|
/** File URL of this module (`import.meta.url`). Used by AWS builders to derive
|
|
76
84
|
the npm specifier for runtime dynamic imports. */
|
|
77
85
|
let moduleUrl: string
|