@reventlessdev/reventless-spec 3.0.0-alpha.63 → 3.0.0-alpha.65

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.
@@ -14,6 +14,10 @@ let tagSchema = S.schema(s => ({
14
14
  value: s.m(S.string)
15
15
  }));
16
16
 
17
+ let partitionTagSchema = S.schema(s => ({
18
+ key: s.m(S.string)
19
+ }));
20
+
17
21
  let dcbTagId = S.Metadata.Id.make("dcb", "tag");
18
22
 
19
23
  let dcbPartitionTagId = S.Metadata.Id.make("dcb", "partitionTag");
@@ -48,6 +52,22 @@ function isCompositePartitionMember(fieldSchema) {
48
52
  return Stdlib_Option.isSome(S.Metadata.get(fieldSchema, dcbCompositePartitionMemberId));
49
53
  }
50
54
 
55
+ let compositePartitionSpecSchema = S.schema(s => ({
56
+ keys: s.m(S.array(S.string)),
57
+ seps: s.m(S.array(S.string))
58
+ }));
59
+
60
+ let derivedPartitionTagSchema = S.union([
61
+ S.schema(s => ({
62
+ TAG: "Simple",
63
+ _0: s.m(partitionTagSchema)
64
+ })),
65
+ S.schema(s => ({
66
+ TAG: "Composite",
67
+ _0: s.m(compositePartitionSpecSchema)
68
+ }))
69
+ ]);
70
+
51
71
  function isTagged(fieldSchema) {
52
72
  return Stdlib_Option.isSome(S.Metadata.get(fieldSchema, dcbTagId));
53
73
  }
@@ -130,6 +150,19 @@ function extractTagsFromProperties(properties, jsonDict) {
130
150
  });
131
151
  }
132
152
 
153
+ function variantTagName(items) {
154
+ return Stdlib_Option.flatMap(items.find(item => item.location === "TAG"), item => {
155
+ let match = item.schema;
156
+ if (match.type !== "string") {
157
+ return;
158
+ }
159
+ let $$const = match.const;
160
+ if ($$const !== undefined) {
161
+ return $$const;
162
+ }
163
+ });
164
+ }
165
+
133
166
  function extractTagsFromJson(schema, json) {
134
167
  switch (schema.type) {
135
168
  case "object" :
@@ -152,22 +185,12 @@ function extractTagsFromJson(schema, json) {
152
185
  return Stdlib_Array.reduce(schema.anyOf, [], (acc, variantSchema) => {
153
186
  if (acc.length !== 0) {
154
187
  return acc;
155
- }
156
- if (variantSchema.type !== "object") {
157
- return [];
158
- }
159
- let variantTag = Stdlib_Option.flatMap(variantSchema.items.find(item => item.location === "TAG"), item => {
160
- let match = item.schema;
161
- if (match.type !== "string") {
162
- return;
188
+ } else if (variantSchema.type === "object") {
189
+ if (Primitive_object.equal(variantTagName(variantSchema.items), jsonTag)) {
190
+ return extractTagsFromProperties(variantSchema.properties, jsonDict$1);
191
+ } else {
192
+ return [];
163
193
  }
164
- let $$const = match.const;
165
- if ($$const !== undefined) {
166
- return $$const;
167
- }
168
- });
169
- if (Primitive_object.equal(variantTag, jsonTag)) {
170
- return extractTagsFromProperties(variantSchema.properties, jsonDict$1);
171
194
  } else {
172
195
  return [];
173
196
  }
@@ -185,29 +208,11 @@ function extractTags(schema, value) {
185
208
  function extractVariantNames(schema) {
186
209
  switch (schema.type) {
187
210
  case "object" :
188
- return Stdlib_Option.getOr(Stdlib_Option.flatMap(schema.items.find(item => item.location === "TAG"), item => {
189
- let match = item.schema;
190
- if (match.type !== "string") {
191
- return;
192
- }
193
- let $$const = match.const;
194
- if ($$const !== undefined) {
195
- return [$$const];
196
- }
197
- }), []);
211
+ return Stdlib_Option.mapOr(variantTagName(schema.items), [], t => [t]);
198
212
  case "union" :
199
213
  return Stdlib_Array.filterMap(schema.anyOf, variantSchema => {
200
214
  if (variantSchema.type === "object") {
201
- return Stdlib_Option.flatMap(variantSchema.items.find(item => item.location === "TAG"), item => {
202
- let match = item.schema;
203
- if (match.type !== "string") {
204
- return;
205
- }
206
- let $$const = match.const;
207
- if ($$const !== undefined) {
208
- return $$const;
209
- }
210
- });
215
+ return variantTagName(variantSchema.items);
211
216
  }
212
217
  });
213
218
  default:
@@ -225,16 +230,7 @@ function extractAllVariantNames(schema) {
225
230
  return [];
226
231
  }
227
232
  case "object" :
228
- return Stdlib_Option.getOr(Stdlib_Option.flatMap(schema.items.find(item => item.location === "TAG"), item => {
229
- let match = item.schema;
230
- if (match.type !== "string") {
231
- return;
232
- }
233
- let $$const = match.const;
234
- if ($$const !== undefined) {
235
- return [$$const];
236
- }
237
- }), []);
233
+ return Stdlib_Option.mapOr(variantTagName(schema.items), [], t => [t]);
238
234
  case "union" :
239
235
  return Stdlib_Array.filterMap(schema.anyOf, variantSchema => {
240
236
  switch (variantSchema.type) {
@@ -246,16 +242,7 @@ function extractAllVariantNames(schema) {
246
242
  return;
247
243
  }
248
244
  case "object" :
249
- return Stdlib_Option.flatMap(variantSchema.items.find(item => item.location === "TAG"), item => {
250
- let match = item.schema;
251
- if (match.type !== "string") {
252
- return;
253
- }
254
- let $$const = match.const;
255
- if ($$const !== undefined) {
256
- return $$const;
257
- }
258
- });
245
+ return variantTagName(variantSchema.items);
259
246
  default:
260
247
  return;
261
248
  }
@@ -272,29 +259,11 @@ function isVariantPayloadBearing(schema, name) {
272
259
  }
273
260
  switch (schema.type) {
274
261
  case "object" :
275
- return Stdlib_Option.getOr(Stdlib_Option.flatMap(schema.items.find(item => item.location === "TAG"), item => {
276
- let match = item.schema;
277
- if (match.type !== "string") {
278
- return;
279
- }
280
- let $$const = match.const;
281
- if ($$const !== undefined) {
282
- return $$const === name;
283
- }
284
- }), false);
262
+ return Stdlib_Option.mapOr(variantTagName(schema.items), false, t => t === name);
285
263
  case "union" :
286
264
  return schema.anyOf.some(variantSchema => {
287
265
  if (variantSchema.type === "object") {
288
- return Stdlib_Option.getOr(Stdlib_Option.flatMap(variantSchema.items.find(item => item.location === "TAG"), item => {
289
- let match = item.schema;
290
- if (match.type !== "string") {
291
- return;
292
- }
293
- let $$const = match.const;
294
- if ($$const !== undefined) {
295
- return $$const === name;
296
- }
297
- }), false);
266
+ return Stdlib_Option.mapOr(variantTagName(variantSchema.items), false, t => t === name);
298
267
  } else {
299
268
  return false;
300
269
  }
@@ -359,22 +328,12 @@ function extractTagsFromJsonExpanded(schema, json) {
359
328
  return Stdlib_Array.reduce(schema.anyOf, [], (acc, variantSchema) => {
360
329
  if (acc.length !== 0) {
361
330
  return acc;
362
- }
363
- if (variantSchema.type !== "object") {
364
- return [];
365
- }
366
- let variantTag = Stdlib_Option.flatMap(variantSchema.items.find(item => item.location === "TAG"), item => {
367
- let match = item.schema;
368
- if (match.type !== "string") {
369
- return;
331
+ } else if (variantSchema.type === "object") {
332
+ if (Primitive_object.equal(variantTagName(variantSchema.items), jsonTag)) {
333
+ return extractTagsFromPropertiesExpanded(variantSchema.properties, jsonDict$1);
334
+ } else {
335
+ return [];
370
336
  }
371
- let $$const = match.const;
372
- if ($$const !== undefined) {
373
- return $$const;
374
- }
375
- });
376
- if (Primitive_object.equal(variantTag, jsonTag)) {
377
- return extractTagsFromPropertiesExpanded(variantSchema.properties, jsonDict$1);
378
337
  } else {
379
338
  return [];
380
339
  }
@@ -427,16 +386,7 @@ function extractTagKeysByEventType(schema) {
427
386
  return;
428
387
  }
429
388
  let properties = variantSchema.properties;
430
- Stdlib_Option.forEach(Stdlib_Option.flatMap(variantSchema.items.find(item => item.location === "TAG"), item => {
431
- let match = item.schema;
432
- if (match.type !== "string") {
433
- return;
434
- }
435
- let $$const = match.const;
436
- if ($$const !== undefined) {
437
- return $$const;
438
- }
439
- }), eventType => {
389
+ Stdlib_Option.forEach(variantTagName(variantSchema.items), eventType => {
440
390
  result[eventType] = tagKeysOfProperties(properties);
441
391
  });
442
392
  };
@@ -608,16 +558,7 @@ function eventShapesOfSchema(schema) {
608
558
  }
609
559
  case "object" :
610
560
  let properties = variantSchema.properties;
611
- return Stdlib_Option.map(Stdlib_Option.flatMap(variantSchema.items.find(item => item.location === "TAG"), item => {
612
- let match = item.schema;
613
- if (match.type !== "string") {
614
- return;
615
- }
616
- let $$const = match.const;
617
- if ($$const !== undefined) {
618
- return $$const;
619
- }
620
- }), eventType => ({
561
+ return Stdlib_Option.map(variantTagName(variantSchema.items), eventType => ({
621
562
  eventType: eventType,
622
563
  idFields: idFieldsOfProperties(properties)
623
564
  }));
@@ -702,16 +643,7 @@ function findMultiTagVariantNames(schema) {
702
643
  }
703
644
  let tagCount = Object.entries(variantSchema.properties).filter(param => isTagged(param[1])).length;
704
645
  if (tagCount > 1) {
705
- return Stdlib_Option.getOr(Stdlib_Option.flatMap(variantSchema.items.find(item => item.location === "TAG"), item => {
706
- let match = item.schema;
707
- if (match.type !== "string") {
708
- return;
709
- }
710
- let $$const = match.const;
711
- if ($$const !== undefined) {
712
- return $$const;
713
- }
714
- }), "(unknown)");
646
+ return Stdlib_Option.getOr(variantTagName(variantSchema.items), "(unknown)");
715
647
  }
716
648
  };
717
649
  if (schema.type === "union") {
@@ -888,6 +820,7 @@ function getPartitionTagValue(query, pt) {
888
820
 
889
821
  export {
890
822
  tagSchema,
823
+ partitionTagSchema,
891
824
  dcbTagId,
892
825
  dcbPartitionTagId,
893
826
  dcbCrossPartitionId,
@@ -900,6 +833,8 @@ export {
900
833
  crossPartition,
901
834
  compositePartitionMember,
902
835
  isCompositePartitionMember,
836
+ compositePartitionSpecSchema,
837
+ derivedPartitionTagSchema,
903
838
  isTagged,
904
839
  isTaggedArray,
905
840
  isPartitionTag,
@@ -909,6 +844,7 @@ export {
909
844
  resolveArrayTagKey,
910
845
  jsonValueToString,
911
846
  extractTagsFromProperties,
847
+ variantTagName,
912
848
  extractTagsFromJson,
913
849
  extractTags,
914
850
  extractVariantNames,
@@ -13,16 +13,7 @@ type variantInfo = {
13
13
  let extractVariantInfo = (variantSchema: S.t<unknown>): option<variantInfo> =>
14
14
  switch variantSchema {
15
15
  | Object({items, properties}) =>
16
- let tagName =
17
- items
18
- ->Array.find(item => item.location == "TAG")
19
- ->Option.flatMap(item =>
20
- switch item.schema {
21
- | String({const}) => Some(const)
22
- | _ => None
23
- }
24
- )
25
- tagName->Option.map(tagName => {
16
+ DcbTag.variantTagName(items)->Option.map(tagName => {
26
17
  let taggedFields =
27
18
  properties
28
19
  ->Dict.toArray
@@ -11,17 +11,7 @@ function extractVariantInfo(variantSchema) {
11
11
  return;
12
12
  }
13
13
  let properties = variantSchema.properties;
14
- let tagName = Stdlib_Option.flatMap(variantSchema.items.find(item => item.location === "TAG"), item => {
15
- let match = item.schema;
16
- if (match.type !== "string") {
17
- return;
18
- }
19
- let $$const = match.const;
20
- if ($$const !== undefined) {
21
- return $$const;
22
- }
23
- });
24
- return Stdlib_Option.map(tagName, tagName => {
14
+ return Stdlib_Option.map(DcbTag$Reventless.variantTagName(variantSchema.items), tagName => {
25
15
  let taggedFields = Stdlib_Array.filterMap(Object.entries(properties), param => {
26
16
  if (DcbTag$Reventless.isTagged(param[1])) {
27
17
  return param[0];
@@ -0,0 +1,39 @@
1
+ // Single source of truth for deriving a plugin's PascalCase name from its npm
2
+ // package name, and for resolving the final plugin name from the (optional)
3
+ // plugin.json `name` and package.json `name`. The plugin generator
4
+ // (`generator/Config`) and the external tooling that reconstructs the domain
5
+ // graph (`reventless-gwt`'s `LocalHost`) both derive from this, so the two can't
6
+ // drift — a drift here silently breaks graph plugin keys (the graph would key
7
+ // plugins under names that don't match the ones the generator bakes into
8
+ // `Plugin.res`). See [[reference_ppx_spec_name_single_strip]] for the sibling
9
+ // spec-name derivation.
10
+
11
+ // "@scope/my-catalog" → "MyCatalog", "online-shop" → "OnlineShop".
12
+ let fromPackageName = (packageName: string): string => {
13
+ let base = switch packageName->String.split("/") {
14
+ | [_scope, local] => local
15
+ | [local] => local
16
+ | parts => parts->Array.getUnsafe(parts->Array.length - 1)
17
+ }
18
+ base
19
+ ->String.split("-")
20
+ ->Array.flatMap(part => part->String.split("_"))
21
+ ->Array.map(word =>
22
+ if word === "" {
23
+ ""
24
+ } else {
25
+ word->String.slice(~start=0, ~end=1)->String.toUpperCase ++
26
+ word->String.slice(~start=1, ~end=word->String.length)
27
+ }
28
+ )
29
+ ->Array.join("")
30
+ }
31
+
32
+ // plugin.json `name` wins; else PascalCase(package.json `name`); else "Plugin".
33
+ // The two callers each read the raw fields with their own node bindings, then
34
+ // share this precedence so the resolution can never diverge.
35
+ let resolve = (~pluginJsonName: option<string>, ~packageJsonName: option<string>): string =>
36
+ switch pluginJsonName {
37
+ | Some(name) => name
38
+ | None => packageJsonName->Option.map(fromPackageName)->Option.getOr("Plugin")
39
+ }
@@ -0,0 +1,45 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
4
+
5
+ function fromPackageName(packageName) {
6
+ let parts = packageName.split("/");
7
+ let len = parts.length;
8
+ let base;
9
+ if (len >= 3) {
10
+ base = parts[parts.length - 1 | 0];
11
+ } else {
12
+ switch (len) {
13
+ case 0 :
14
+ base = parts[parts.length - 1 | 0];
15
+ break;
16
+ case 1 :
17
+ base = parts[0];
18
+ break;
19
+ case 2 :
20
+ base = parts[1];
21
+ break;
22
+ }
23
+ }
24
+ return base.split("-").flatMap(part => part.split("_")).map(word => {
25
+ if (word === "") {
26
+ return "";
27
+ } else {
28
+ return word.slice(0, 1).toUpperCase() + word.slice(1, word.length);
29
+ }
30
+ }).join("");
31
+ }
32
+
33
+ function resolve(pluginJsonName, packageJsonName) {
34
+ if (pluginJsonName !== undefined) {
35
+ return pluginJsonName;
36
+ } else {
37
+ return Stdlib_Option.getOr(Stdlib_Option.map(packageJsonName, fromPackageName), "Plugin");
38
+ }
39
+ }
40
+
41
+ export {
42
+ fromPackageName,
43
+ resolve,
44
+ }
45
+ /* No side effect */
@@ -0,0 +1,26 @@
1
+ // Per-aggregate persisted-snapshot configuration
2
+ // (docs/plans/aggregate-snapshotting.md).
3
+ //
4
+ // Snapshotting is opt-in and lives on the Behavior module (where `state` is
5
+ // defined): `Behavior.T.snapshot = None` (the default, auto-injected by
6
+ // `@@reventless.behavior`) keeps full replay; `Some(config)` makes the
7
+ // aggregate write a keep-one snapshot every `interval` events and seed cold
8
+ // replays from the latest one. Snapshots are a read optimization only — the
9
+ // OCC append remains the sole consistency primitive, and a missing, corrupt,
10
+ // or schema-drifted snapshot degrades to full replay.
11
+ //
12
+ // Enable via the file-level attribute on a behavior file:
13
+ //
14
+ // @@reventless.snapshots(100)
15
+ //
16
+ // which injects `let snapshot = Some({interval: 100, stateSchema})` (requires
17
+ // `@schema type state` so sury generates the schema), or hand-write the
18
+ // binding for full control.
19
+
20
+ type config<'state> = {
21
+ /** Write a snapshot after every N appended events. Required — no default. */
22
+ interval: int,
23
+ /** Sury schema for the behavior's state — serializes the persisted snapshot
24
+ and (hashed) gates staleness across state-shape changes. */
25
+ stateSchema: S.t<'state>,
26
+ }
@@ -0,0 +1,2 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+ /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
@@ -672,6 +672,16 @@ let renderComposition = (~config: Config.config, ~resolved: Pairing.resolved): s
672
672
  ~moduleSuffix="Slice",
673
673
  ),
674
674
  hasPluginStructure ? Some(" ~pluginStructure=pluginStructure,") : None,
675
+ // Components carrying `@@reventless.systemCallable` — only emitted when at
676
+ // least one opts in, so existing generated Plugin.res files stay identical.
677
+ resolved.systemCallableComponents->Array.length > 0
678
+ ? Some(
679
+ " ~systemCallableComponents=[" ++
680
+ resolved.systemCallableComponents
681
+ ->Array.map(n => "\"" ++ n ++ "\"")
682
+ ->Array.join(", ") ++ "],",
683
+ )
684
+ : None,
675
685
  ]
676
686
 
677
687
  makeParams->Array.filterMap(x => x)->Array.forEach(line => lines->Array.push(line))
@@ -428,7 +428,8 @@ function renderComposition(config, resolved) {
428
428
  renderMakeParam("automationSlices", resolved.automationSlices, "Slice"),
429
429
  renderMakeParam("outboundTranslationSlices", resolved.outboundTranslationSlices, "Slice"),
430
430
  renderMakeParam("inboundTranslationSlices", resolved.inboundTranslationSlices, "Slice"),
431
- hasPluginStructure ? " ~pluginStructure=pluginStructure," : undefined
431
+ hasPluginStructure ? " ~pluginStructure=pluginStructure," : undefined,
432
+ resolved.systemCallableComponents.length !== 0 ? " ~systemCallableComponents=[" + resolved.systemCallableComponents.map(n => "\"" + n + "\"").join(", ") + "]," : undefined
432
433
  ];
433
434
  Stdlib_Array.filterMap(makeParams, x => x).forEach(line => {
434
435
  lines.push(line);
@@ -12,25 +12,9 @@ type config = {
12
12
 
13
13
  // Convert npm package name to PascalCase plugin name.
14
14
  // "@scope/my-catalog" → "MyCatalog", "online-shop" → "OnlineShop"
15
- let packageNameToPluginName = (packageName: string): string => {
16
- let base = switch packageName->String.split("/") {
17
- | [_scope, local] => local
18
- | [local] => local
19
- | parts => parts->Array.getUnsafe(parts->Array.length - 1)
20
- }
21
- base
22
- ->String.split("-")
23
- ->Array.flatMap(part => part->String.split("_"))
24
- ->Array.map(word =>
25
- if word === "" {
26
- ""
27
- } else {
28
- word->String.slice(~start=0, ~end=1)->String.toUpperCase ++
29
- word->String.slice(~start=1, ~end=word->String.length)
30
- }
31
- )
32
- ->Array.join("")
33
- }
15
+ // Single-sourced with reventless-gwt's LocalHost via `PluginName` so the two
16
+ // can't drift (a drift silently breaks graph plugin keys).
17
+ let packageNameToPluginName = PluginName.fromPackageName
34
18
 
35
19
  let readJson = (path: string): option<JSON.t> =>
36
20
  try Some(Generator_Node.readFileSync(path)->JSON.parseOrThrow) catch {
@@ -58,13 +42,9 @@ let getStrArrayField = (json: JSON.t, key: string): option<array<string>> =>
58
42
  ->Option.map(arr => arr->Array.filterMap(JSON.Decode.string))
59
43
 
60
44
  let read = (~srcDir: string): config => {
61
- // Derive plugin name from package.json in parent of srcDir
45
+ // Read package.json `name` from the parent of srcDir
62
46
  let packageJsonPath = Generator_Node.join([Generator_Node.dirname(srcDir), "package.json"])
63
- let derivedName =
64
- readJson(packageJsonPath)
65
- ->Option.flatMap(j => getStrField(j, "name"))
66
- ->Option.map(packageNameToPluginName)
67
- ->Option.getOr("Plugin")
47
+ let packageJsonName = readJson(packageJsonPath)->Option.flatMap(j => getStrField(j, "name"))
68
48
 
69
49
  // Read plugin.json from srcDir (optional)
70
50
  let pluginJsonPath = Generator_Node.join([srcDir, "plugin.json"])
@@ -75,7 +55,10 @@ let read = (~srcDir: string): config => {
75
55
  }
76
56
 
77
57
  {
78
- name: pluginJson->Option.flatMap(j => getStrField(j, "name"))->Option.getOr(derivedName),
58
+ name: PluginName.resolve(
59
+ ~pluginJsonName=pluginJson->Option.flatMap(j => getStrField(j, "name")),
60
+ ~packageJsonName,
61
+ ),
79
62
  heartbeatInterval: pluginJson
80
63
  ->Option.flatMap(j => getIntField(j, "heartbeatInterval"))
81
64
  ->Option.getOr(5),
@@ -5,34 +5,7 @@ import * as Nodepath from "node:path";
5
5
  import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
6
6
  import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
7
7
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
8
-
9
- function packageNameToPluginName(packageName) {
10
- let parts = packageName.split("/");
11
- let len = parts.length;
12
- let base;
13
- if (len >= 3) {
14
- base = parts[parts.length - 1 | 0];
15
- } else {
16
- switch (len) {
17
- case 0 :
18
- base = parts[parts.length - 1 | 0];
19
- break;
20
- case 1 :
21
- base = parts[0];
22
- break;
23
- case 2 :
24
- base = parts[1];
25
- break;
26
- }
27
- }
28
- return base.split("-").flatMap(part => part.split("_")).map(word => {
29
- if (word === "") {
30
- return "";
31
- } else {
32
- return word.slice(0, 1).toUpperCase() + word.slice(1, word.length);
33
- }
34
- }).join("");
35
- }
8
+ import * as PluginName$Reventless from "../components/PluginName.res.mjs";
36
9
 
37
10
  function readJson(path) {
38
11
  try {
@@ -56,17 +29,19 @@ function getStrArrayField(json, key) {
56
29
 
57
30
  function read(srcDir) {
58
31
  let packageJsonPath = Nodepath.join(Nodepath.dirname(srcDir), "package.json");
59
- let derivedName = Stdlib_Option.getOr(Stdlib_Option.map(Stdlib_Option.flatMap(readJson(packageJsonPath), j => getStrField(j, "name")), packageNameToPluginName), "Plugin");
32
+ let packageJsonName = Stdlib_Option.flatMap(readJson(packageJsonPath), j => getStrField(j, "name"));
60
33
  let pluginJsonPath = Nodepath.join(srcDir, "plugin.json");
61
34
  let pluginJson = Nodefs.existsSync(pluginJsonPath) ? readJson(pluginJsonPath) : undefined;
62
35
  return {
63
- name: Stdlib_Option.getOr(Stdlib_Option.flatMap(pluginJson, j => getStrField(j, "name")), derivedName),
36
+ name: PluginName$Reventless.resolve(Stdlib_Option.flatMap(pluginJson, j => getStrField(j, "name")), packageJsonName),
64
37
  heartbeatInterval: Stdlib_Option.getOr(Stdlib_Option.flatMap(pluginJson, j => getIntField(j, "heartbeatInterval")), 5),
65
38
  exclude: Stdlib_Option.getOr(Stdlib_Option.flatMap(pluginJson, j => getStrArrayField(j, "exclude")), []),
66
39
  variant: "Composition"
67
40
  };
68
41
  }
69
42
 
43
+ let packageNameToPluginName = PluginName$Reventless.fromPackageName;
44
+
70
45
  export {
71
46
  packageNameToPluginName,
72
47
  readJson,
@@ -1,6 +1,9 @@
1
1
  // Directory scanner: walks src/, classifies .res files by parent folder name.
2
2
 
3
- type componentType =
3
+ // Re-export the single-source `ComponentKind.t` (same constructors, so the bare
4
+ // pattern matches in `Pairing` keep resolving via type inference) and derive the
5
+ // folder classifier from it — one vocabulary shared with the gwt discovery.
6
+ type componentType = ComponentKind.t =
4
7
  | StateChangeSlice
5
8
  | StateViewSlice
6
9
  | StateViewSliceStream
@@ -17,31 +20,7 @@ type componentType =
17
20
  // relPath: path relative to srcDir (e.g. "ReadModel/ProductsProjections.res")
18
21
  type discoveredFile = {stem: string, componentType: componentType, epGroup: option<string>, relPath: string}
19
22
 
20
- let folderToComponentType = (folder: string): option<componentType> =>
21
- switch folder {
22
- | "StateChange" | "StateChanges" | "StateChangeSlice" | "StateChangeSlices" =>
23
- Some(StateChangeSlice)
24
- | "StateView" | "StateViews" | "StateViewSlice" | "StateViewSlices" => Some(StateViewSlice)
25
- | "StateViewSliceStream" | "StateViewSliceStreams" => Some(StateViewSliceStream)
26
- | "Automation" | "Automations" | "AutomationSlice" | "AutomationSlices" => Some(AutomationSlice)
27
- | "InboundTranslation"
28
- | "InboundTranslations"
29
- | "InboundTranslationSlice"
30
- | "InboundTranslationSlices" =>
31
- Some(InboundTranslationSlice)
32
- | "OutboundTranslation"
33
- | "OutboundTranslations"
34
- | "OutboundTranslationSlice"
35
- | "OutboundTranslationSlices" =>
36
- Some(OutboundTranslationSlice)
37
- | "Aggregate" | "Aggregates" => Some(Aggregate)
38
- | "ReadModel" | "ReadModels" => Some(ReadModel)
39
- | "ReadModelStream" | "ReadModelStreams" => Some(ReadModelStream)
40
- | "Task" | "Tasks" => Some(Task)
41
- | "ExtensionPoint" | "ExtensionPoints" => Some(ExtensionPoint)
42
- | "Extension" | "Extensions" => Some(Extension)
43
- | _ => None
44
- }
23
+ let folderToComponentType = ComponentKind.folderToKind
45
24
 
46
25
  let isAlwaysExcludedDir = (name: string): bool =>
47
26
  name === "Plugin" || name === "tests" || name === "lib"