@reventlessdev/reventless-core 3.0.0-alpha.148 → 3.0.0-alpha.149

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 CHANGED
@@ -3,6 +3,13 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # 3.0.0-alpha.149 (2026-07-09)
7
+
8
+ ### Bug Fixes
9
+
10
+ * **reventless-core:** DCB StateChangeSlice mutations use ${plugin}_${command}, not ${plugin}_${slice}_${command} ([c5874d2](https://github.com/ReventlessDev/reventless-core/commit/c5874d27ad63e6af5c639c8b6c6f8596fd7f682b))
11
+
12
+
6
13
  # 3.0.0-alpha.148 (2026-07-09)
7
14
 
8
15
  ### Bug Fixes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reventlessdev/reventless-core",
3
- "version": "3.0.0-alpha.148",
3
+ "version": "3.0.0-alpha.149",
4
4
  "description": "Core package for Reventless framework",
5
5
  "license": "Apache-2.0",
6
6
  "jest": {
@@ -30,15 +30,15 @@
30
30
  "uuid": "^13.0.0",
31
31
  "@reventlessdev/rescript-effect": "0.1.0-alpha.25",
32
32
  "@reventlessdev/rescript-hash-object": "1.2.0-alpha.10",
33
- "@reventlessdev/rescript-fast-csv": "1.2.0-alpha.11",
34
33
  "@reventlessdev/rescript-jest": "1.0.0-alpha.6",
34
+ "@reventlessdev/rescript-fast-csv": "1.2.0-alpha.11",
35
35
  "@reventlessdev/rescript-node-streams": "1.1.0-alpha.10",
36
36
  "@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.14",
37
- "@reventlessdev/rescript-uuid": "1.1.0-alpha.14",
38
- "@reventlessdev/reventless-infra": "3.0.0-alpha.91",
39
- "@reventlessdev/reventless-interop": "3.0.0-alpha.24",
40
37
  "@reventlessdev/rescript-ssh2": "1.1.0-alpha.11",
41
- "@reventlessdev/reventless-spec": "3.0.0-alpha.69"
38
+ "@reventlessdev/reventless-infra": "3.0.0-alpha.91",
39
+ "@reventlessdev/reventless-spec": "3.0.0-alpha.69",
40
+ "@reventlessdev/rescript-uuid": "1.1.0-alpha.14",
41
+ "@reventlessdev/reventless-interop": "3.0.0-alpha.24"
42
42
  },
43
43
  "devDependencies": {
44
44
  "rescript": "^12.3.0",
@@ -1,5 +1,3 @@
1
- open ReventlessInfra.Api
2
-
3
1
  type queryNames = {
4
2
  singleFieldName: string,
5
3
  listFieldName: string,
@@ -41,13 +39,43 @@ let aggregateMutationField = (~plugin: string, ~aggregate: string, ~command: str
41
39
 
42
40
  let sliceMutationField = (~plugin: string, ~slice: string) => `${plugin}_${slice}`
43
41
 
42
+ // DCB StateChangeSlice per-command mutation field. Unlike aggregates — where multiple
43
+ // aggregates coexist under a plugin so the aggregate name must namespace the command —
44
+ // a DCB slice's command constructor already names the operation, and callers/plans
45
+ // treat the mutation as `${plugin}_${command}`. Doubling in the slice name
46
+ // (`${plugin}_${slice}_${command}`) both renames the primary command out from under
47
+ // existing callers and overflows AppSync's 50-char subscription-field cap once the
48
+ // `on` prefix is added.
49
+ let dcbCommandMutationField = (~plugin: string, ~command: string) => `${plugin}_${command}`
50
+
51
+ // AppSync hard limit: subscription field names may be at most 50 chars. Each mutation
52
+ // field `f` produces a `@aws_subscribe` subscription `on${f}` (see
53
+ // Plugin_SubscriptionSchema.sourceCFields), so the real cap on a mutation field is 48.
54
+ // Fail at build with an actionable message rather than letting AppSync reject the
55
+ // schema push at deploy time with an opaque 500.
56
+ let appSyncSubscriptionMaxLen = 50
57
+
58
+ let assertSubscriptionNameFits = (~fieldName: string) => {
59
+ let subscriptionName = `on${fieldName}`
60
+ if subscriptionName->String.length > appSyncSubscriptionMaxLen {
61
+ JsError.throwWithMessage(
62
+ `Generated subscription field \`${subscriptionName}\` is ${subscriptionName
63
+ ->String.length
64
+ ->Int.toString} chars, over AppSync's ${appSyncSubscriptionMaxLen->Int.toString}-char limit. ` ++
65
+ `Shorten the plugin, slice, or command name behind mutation field \`${fieldName}\`.`,
66
+ )
67
+ }
68
+ fieldName
69
+ }
70
+
44
71
  // DCB StateChangeSlice mutation fields — one per API-exposed command constructor,
45
72
  // mirroring the aggregate path (which emits one field per constructor). A slice whose
46
73
  // command union has a single API-exposed constructor keeps the byte-identical
47
- // `Plugin_Slice` name (no schema churn); a multi-command slice uses aggregate-style
48
- // `Plugin_Slice_Ctor` per constructor so the SDL generator and command resolvers
49
- // derive the constructor from the trailing `_` segment. @noApi variants are filtered
50
- // out. Returns [(fieldName, constructorName)] in declaration order.
74
+ // `Plugin_Slice` name (no schema churn); a multi-command slice names each mutation
75
+ // `${plugin}_${command}` — the constructor already names the operation, and callers/plans
76
+ // expect that shape (not aggregate-style `${plugin}_${slice}_${command}`). @noApi
77
+ // variants are filtered out. Every emitted name is guarded against the 50-char AppSync
78
+ // subscription cap at build time. Returns [(fieldName, constructorName)] in declaration order.
51
79
  let sliceMutationFields = (
52
80
  ~plugin: string,
53
81
  ~slice: string,
@@ -57,10 +85,10 @@ let sliceMutationFields = (
57
85
  let filtered = ApiNoApiHelpers.filterNoApiVariants(allNames, commandSchema)
58
86
  switch filtered {
59
87
  | [] => []
60
- | [single] => [(sliceMutationField(~plugin, ~slice), single)]
88
+ | [single] => [(assertSubscriptionNameFits(~fieldName=sliceMutationField(~plugin, ~slice)), single)]
61
89
  | _ =>
62
90
  filtered->Array.map(ctor => (
63
- aggregateMutationField(~plugin, ~aggregate=slice, ~command=ctor),
91
+ assertSubscriptionNameFits(~fieldName=dcbCommandMutationField(~plugin, ~command=ctor)),
64
92
  ctor,
65
93
  ))
66
94
  }
@@ -68,7 +96,7 @@ let sliceMutationFields = (
68
96
 
69
97
  // The mutation field name for a single command constructor of a DCB StateChangeSlice,
70
98
  // consistent with `sliceMutationFields`: single-command slices resolve every variant
71
- // to the slice name, multi-command slices to the aggregate-style per-constructor name.
99
+ // to the slice name, multi-command slices to the per-constructor `${plugin}_${command}`.
72
100
  let sliceMutationFieldFor = (
73
101
  ~plugin: string,
74
102
  ~slice: string,
@@ -78,7 +106,7 @@ let sliceMutationFieldFor = (
78
106
  if sliceMutationFields(~plugin, ~slice, ~commandSchema)->Array.length <= 1 {
79
107
  sliceMutationField(~plugin, ~slice)
80
108
  } else {
81
- aggregateMutationField(~plugin, ~aggregate=slice, ~command=variant)
109
+ dcbCommandMutationField(~plugin, ~command=variant)
82
110
  }
83
111
 
84
112
  // Pluralize via the singular stem so already-plural names normalise correctly:
@@ -1,5 +1,6 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
+ import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
3
4
  import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
4
5
  import * as ApiNoApiHelpers$ReventlessCore from "./ApiNoApiHelpers.res.mjs";
5
6
 
@@ -41,6 +42,18 @@ function sliceMutationField(plugin, slice) {
41
42
  return plugin + `_` + slice;
42
43
  }
43
44
 
45
+ function dcbCommandMutationField(plugin, command) {
46
+ return plugin + `_` + command;
47
+ }
48
+
49
+ function assertSubscriptionNameFits(fieldName) {
50
+ let subscriptionName = `on` + fieldName;
51
+ if (subscriptionName.length > 50) {
52
+ Stdlib_JsError.throwWithMessage(`Generated subscription field \`` + subscriptionName + `\` is ` + subscriptionName.length.toString() + ` chars, over AppSync's ` + (50).toString() + `-char limit. ` + (`Shorten the plugin, slice, or command name behind mutation field \`` + fieldName + `\`.`));
53
+ }
54
+ return fieldName;
55
+ }
56
+
44
57
  function sliceMutationFields(plugin, slice, commandSchema) {
45
58
  let allNames = DcbTag$Reventless.extractAllVariantNames(commandSchema);
46
59
  let filtered = ApiNoApiHelpers$ReventlessCore.filterNoApiVariants(allNames, commandSchema);
@@ -48,7 +61,7 @@ function sliceMutationFields(plugin, slice, commandSchema) {
48
61
  if (len !== 1) {
49
62
  if (len !== 0) {
50
63
  return filtered.map(ctor => [
51
- aggregateMutationField(plugin, slice, ctor),
64
+ assertSubscriptionNameFits(dcbCommandMutationField(plugin, ctor)),
52
65
  ctor
53
66
  ]);
54
67
  } else {
@@ -57,7 +70,7 @@ function sliceMutationFields(plugin, slice, commandSchema) {
57
70
  }
58
71
  let single = filtered[0];
59
72
  return [[
60
- sliceMutationField(plugin, slice),
73
+ assertSubscriptionNameFits(sliceMutationField(plugin, slice)),
61
74
  single
62
75
  ]];
63
76
  }
@@ -66,7 +79,7 @@ function sliceMutationFieldFor(plugin, slice, commandSchema, variant) {
66
79
  if (sliceMutationFields(plugin, slice, commandSchema).length <= 1) {
67
80
  return sliceMutationField(plugin, slice);
68
81
  } else {
69
- return aggregateMutationField(plugin, slice, variant);
82
+ return dcbCommandMutationField(plugin, variant);
70
83
  }
71
84
  }
72
85
 
@@ -119,12 +132,17 @@ function adminField(name) {
119
132
  return `Platform_` + name;
120
133
  }
121
134
 
135
+ let appSyncSubscriptionMaxLen = 50;
136
+
122
137
  export {
123
138
  pluralize,
124
139
  singularize,
125
140
  stripViewSuffix,
126
141
  aggregateMutationField,
127
142
  sliceMutationField,
143
+ dcbCommandMutationField,
144
+ appSyncSubscriptionMaxLen,
145
+ assertSubscriptionNameFits,
128
146
  sliceMutationFields,
129
147
  sliceMutationFieldFor,
130
148
  canonicalPlural,