@reventlessdev/reventless-spec 3.0.0-alpha.62 → 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.
@@ -130,6 +130,19 @@ function extractTagsFromProperties(properties, jsonDict) {
130
130
  });
131
131
  }
132
132
 
133
+ function variantTagName(items) {
134
+ return Stdlib_Option.flatMap(items.find(item => item.location === "TAG"), item => {
135
+ let match = item.schema;
136
+ if (match.type !== "string") {
137
+ return;
138
+ }
139
+ let $$const = match.const;
140
+ if ($$const !== undefined) {
141
+ return $$const;
142
+ }
143
+ });
144
+ }
145
+
133
146
  function extractTagsFromJson(schema, json) {
134
147
  switch (schema.type) {
135
148
  case "object" :
@@ -152,22 +165,12 @@ function extractTagsFromJson(schema, json) {
152
165
  return Stdlib_Array.reduce(schema.anyOf, [], (acc, variantSchema) => {
153
166
  if (acc.length !== 0) {
154
167
  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;
163
- }
164
- let $$const = match.const;
165
- if ($$const !== undefined) {
166
- return $$const;
168
+ } else if (variantSchema.type === "object") {
169
+ if (Primitive_object.equal(variantTagName(variantSchema.items), jsonTag)) {
170
+ return extractTagsFromProperties(variantSchema.properties, jsonDict$1);
171
+ } else {
172
+ return [];
167
173
  }
168
- });
169
- if (Primitive_object.equal(variantTag, jsonTag)) {
170
- return extractTagsFromProperties(variantSchema.properties, jsonDict$1);
171
174
  } else {
172
175
  return [];
173
176
  }
@@ -185,29 +188,11 @@ function extractTags(schema, value) {
185
188
  function extractVariantNames(schema) {
186
189
  switch (schema.type) {
187
190
  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
- }), []);
191
+ return Stdlib_Option.mapOr(variantTagName(schema.items), [], t => [t]);
198
192
  case "union" :
199
193
  return Stdlib_Array.filterMap(schema.anyOf, variantSchema => {
200
194
  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
- });
195
+ return variantTagName(variantSchema.items);
211
196
  }
212
197
  });
213
198
  default:
@@ -225,16 +210,7 @@ function extractAllVariantNames(schema) {
225
210
  return [];
226
211
  }
227
212
  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
- }), []);
213
+ return Stdlib_Option.mapOr(variantTagName(schema.items), [], t => [t]);
238
214
  case "union" :
239
215
  return Stdlib_Array.filterMap(schema.anyOf, variantSchema => {
240
216
  switch (variantSchema.type) {
@@ -246,16 +222,7 @@ function extractAllVariantNames(schema) {
246
222
  return;
247
223
  }
248
224
  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
- });
225
+ return variantTagName(variantSchema.items);
259
226
  default:
260
227
  return;
261
228
  }
@@ -272,29 +239,11 @@ function isVariantPayloadBearing(schema, name) {
272
239
  }
273
240
  switch (schema.type) {
274
241
  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);
242
+ return Stdlib_Option.mapOr(variantTagName(schema.items), false, t => t === name);
285
243
  case "union" :
286
244
  return schema.anyOf.some(variantSchema => {
287
245
  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);
246
+ return Stdlib_Option.mapOr(variantTagName(variantSchema.items), false, t => t === name);
298
247
  } else {
299
248
  return false;
300
249
  }
@@ -359,22 +308,12 @@ function extractTagsFromJsonExpanded(schema, json) {
359
308
  return Stdlib_Array.reduce(schema.anyOf, [], (acc, variantSchema) => {
360
309
  if (acc.length !== 0) {
361
310
  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;
370
- }
371
- let $$const = match.const;
372
- if ($$const !== undefined) {
373
- return $$const;
311
+ } else if (variantSchema.type === "object") {
312
+ if (Primitive_object.equal(variantTagName(variantSchema.items), jsonTag)) {
313
+ return extractTagsFromPropertiesExpanded(variantSchema.properties, jsonDict$1);
314
+ } else {
315
+ return [];
374
316
  }
375
- });
376
- if (Primitive_object.equal(variantTag, jsonTag)) {
377
- return extractTagsFromPropertiesExpanded(variantSchema.properties, jsonDict$1);
378
317
  } else {
379
318
  return [];
380
319
  }
@@ -427,16 +366,7 @@ function extractTagKeysByEventType(schema) {
427
366
  return;
428
367
  }
429
368
  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 => {
369
+ Stdlib_Option.forEach(variantTagName(variantSchema.items), eventType => {
440
370
  result[eventType] = tagKeysOfProperties(properties);
441
371
  });
442
372
  };
@@ -608,16 +538,7 @@ function eventShapesOfSchema(schema) {
608
538
  }
609
539
  case "object" :
610
540
  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 => ({
541
+ return Stdlib_Option.map(variantTagName(variantSchema.items), eventType => ({
621
542
  eventType: eventType,
622
543
  idFields: idFieldsOfProperties(properties)
623
544
  }));
@@ -702,16 +623,7 @@ function findMultiTagVariantNames(schema) {
702
623
  }
703
624
  let tagCount = Object.entries(variantSchema.properties).filter(param => isTagged(param[1])).length;
704
625
  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)");
626
+ return Stdlib_Option.getOr(variantTagName(variantSchema.items), "(unknown)");
715
627
  }
716
628
  };
717
629
  if (schema.type === "union") {
@@ -909,6 +821,7 @@ export {
909
821
  resolveArrayTagKey,
910
822
  jsonValueToString,
911
823
  extractTagsFromProperties,
824
+ variantTagName,
912
825
  extractTagsFromJson,
913
826
  extractTags,
914
827
  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
@@ -56,7 +47,10 @@ let extractAllVariants = (schema: S.t<unknown>): array<variantInfo> =>
56
47
  // Check if a variant has no payload fields (only TAG)
57
48
  let isPayloadLess = (info: variantInfo): bool => info.fields->Dict.toArray->Array.length == 0
58
49
 
59
- // Compare two sury schema types for structural compatibility
50
+ // Compare two sury schema types for structural compatibility. Objects and
51
+ // unions recurse: previously any (Object, Object) / (Union, Union) pair was
52
+ // declared compatible, so nested payload drift (a renamed/retyped nested field,
53
+ // a changed variant) passed validation undetected.
60
54
  let rec schemasAreCompatible = (a: S.t<unknown>, b: S.t<unknown>): bool =>
61
55
  switch (a, b) {
62
56
  | (String(_), String(_)) => true
@@ -65,10 +59,35 @@ let rec schemasAreCompatible = (a: S.t<unknown>, b: S.t<unknown>): bool =>
65
59
  | (BigInt(_), BigInt(_)) => true
66
60
  | (Array({additionalItems: Schema(aItem)}), Array({additionalItems: Schema(bItem)})) =>
67
61
  schemasAreCompatible(aItem, bItem)
68
- | (Union(_), Union(_)) => true
69
- | (Object(_), Object(_)) => true
62
+ | (Object({properties: aProps}), Object({properties: bProps})) => propsCompatible(aProps, bProps)
63
+ | (Union(_), Union(_)) =>
64
+ // Same set of variant tags, and each shared variant's payload compatible.
65
+ let av = extractAllVariants(a)
66
+ let bv = extractAllVariants(b)
67
+ let at = av->Array.map(v => v.tagName)->Array.toSorted(String.compare)
68
+ let bt = bv->Array.map(v => v.tagName)->Array.toSorted(String.compare)
69
+ at == bt &&
70
+ at->Array.every(tag =>
71
+ switch (av->Array.find(v => v.tagName == tag), bv->Array.find(v => v.tagName == tag)) {
72
+ | (Some(x), Some(y)) => propsCompatible(x.fields, y.fields)
73
+ | _ => false
74
+ }
75
+ )
70
76
  | _ => false
71
77
  }
78
+ // Two property maps are compatible when they carry the same field names and each
79
+ // field's schema is compatible.
80
+ and propsCompatible = (aProps: dict<S.t<unknown>>, bProps: dict<S.t<unknown>>): bool => {
81
+ let aKeys = aProps->Dict.keysToArray->Array.toSorted(String.compare)
82
+ let bKeys = bProps->Dict.keysToArray->Array.toSorted(String.compare)
83
+ aKeys == bKeys &&
84
+ aKeys->Array.every(k =>
85
+ switch (aProps->Dict.get(k), bProps->Dict.get(k)) {
86
+ | (Some(av), Some(bv)) => schemasAreCompatible(av, bv)
87
+ | _ => false
88
+ }
89
+ )
90
+ }
72
91
 
73
92
  // Get a human-readable type name for a schema
74
93
  let schemaTypeName = (schema: S.t<unknown>): string =>
@@ -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];
@@ -95,15 +85,56 @@ function schemasAreCompatible(_a, _b) {
95
85
  _a = aItem;
96
86
  continue;
97
87
  case "object" :
98
- return b.type === "object";
88
+ if (b.type === "object") {
89
+ return propsCompatible(a.properties, b.properties);
90
+ } else {
91
+ return false;
92
+ }
99
93
  case "union" :
100
- return b.type === "union";
94
+ if (b.type !== "union") {
95
+ return false;
96
+ }
97
+ let av = extractAllVariants(a);
98
+ let bv = extractAllVariants(b);
99
+ let at = av.map(v => v.tagName).toSorted(Primitive_string.compare);
100
+ let bt = bv.map(v => v.tagName).toSorted(Primitive_string.compare);
101
+ if (Primitive_object.equal(at, bt)) {
102
+ return at.every(tag => {
103
+ let match = av.find(v => v.tagName === tag);
104
+ let match$1 = bv.find(v => v.tagName === tag);
105
+ if (match !== undefined && match$1 !== undefined) {
106
+ return propsCompatible(match.fields, match$1.fields);
107
+ } else {
108
+ return false;
109
+ }
110
+ });
111
+ } else {
112
+ return false;
113
+ }
101
114
  default:
102
115
  return false;
103
116
  }
104
117
  };
105
118
  }
106
119
 
120
+ function propsCompatible(aProps, bProps) {
121
+ let aKeys = Object.keys(aProps).toSorted(Primitive_string.compare);
122
+ let bKeys = Object.keys(bProps).toSorted(Primitive_string.compare);
123
+ if (Primitive_object.equal(aKeys, bKeys)) {
124
+ return aKeys.every(k => {
125
+ let match = aProps[k];
126
+ let match$1 = bProps[k];
127
+ if (match !== undefined && match$1 !== undefined) {
128
+ return schemasAreCompatible(match, match$1);
129
+ } else {
130
+ return false;
131
+ }
132
+ });
133
+ } else {
134
+ return false;
135
+ }
136
+ }
137
+
107
138
  function schemaTypeName(schema) {
108
139
  switch (schema.type) {
109
140
  case "never" :
@@ -381,6 +412,7 @@ export {
381
412
  extractAllVariants,
382
413
  isPayloadLess,
383
414
  schemasAreCompatible,
415
+ propsCompatible,
384
416
  schemaTypeName,
385
417
  dedupeKeys,
386
418
  validateCompositeReads,
@@ -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. */
@@ -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"