@reventlessdev/reventless-core 3.0.0-alpha.166 → 3.0.0-alpha.168

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 (44) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/package.json +3 -3
  3. package/src/Projection.res +11 -6
  4. package/src/Projection.res.mjs +27 -25
  5. package/src/admin/AdminApi.res +9 -62
  6. package/src/admin/AdminApi.res.mjs +6 -28
  7. package/src/components/Api/GraphQL_Stitcher.res +4 -112
  8. package/src/components/Api/GraphQL_Stitcher.res.mjs +0 -90
  9. package/src/components/Dcb/Dcb_Builder.res +38 -21
  10. package/src/components/Dcb/Dcb_Builder.res.mjs +13 -4
  11. package/src/components/ReadModel/ReadModel_Callback.res +1 -1
  12. package/src/components/ReadModel/ReadModel_Callback.res.mjs +1 -1
  13. package/src/components/StateViewSlice/StateViewSlice_Builder.res +1 -1
  14. package/src/components/StateViewSlice/StateViewSlice_Builder.res.mjs +1 -1
  15. package/src/components/StateViewSlice/StateViewSlice_Callback.res +1 -1
  16. package/src/components/StateViewSlice/StateViewSlice_Callback.res.mjs +1 -1
  17. package/src/plugin/component/Plugin_Builder.res +5 -7
  18. package/src/plugin/component/Plugin_Builder.res.mjs +3 -6
  19. package/src/util/EffectLogger.res +5 -3
  20. package/src/util/EffectLogger.res.mjs +3 -10
  21. package/src/util/Logger.res +41 -11
  22. package/src/util/Logger.res.mjs +36 -10
  23. package/tests/api/GraphQL_StitcherTest.res +0 -198
  24. package/tests/api/GraphQL_StitcherTest.res.mjs +0 -168
  25. package/src/admin/ApiFragmentRegistry/ApiFragmentRegistryBehavior.res +0 -108
  26. package/src/admin/ApiFragmentRegistry/ApiFragmentRegistryBehavior.res.mjs +0 -190
  27. package/src/admin/ApiFragmentRegistry/ApiFragmentRegistrySpec.res +0 -71
  28. package/src/admin/ApiFragmentRegistry/ApiFragmentRegistrySpec.res.mjs +0 -92
  29. package/src/admin/ApiFragmentRegistry/ApiFragmentsProjection.res +0 -63
  30. package/src/admin/ApiFragmentRegistry/ApiFragmentsProjection.res.mjs +0 -108
  31. package/src/admin/ApiFragmentRegistry/ApiFragmentsReadModelSpec.res +0 -23
  32. package/src/admin/ApiFragmentRegistry/ApiFragmentsReadModelSpec.res.mjs +0 -43
  33. package/src/admin/Platform_ApiFragmentsApi.res +0 -32
  34. package/src/admin/Platform_ApiFragmentsApi.res.mjs +0 -52
  35. package/src/components/Api/Api_Builder.res +0 -40
  36. package/src/components/Api/Api_Builder.res.mjs +0 -33
  37. package/src/components/Api/Api_Operations.res +0 -13
  38. package/src/components/Api/Api_Operations.res.mjs +0 -12
  39. package/src/components/Api/GraphQL_PushPlanner.res +0 -65
  40. package/src/components/Api/GraphQL_PushPlanner.res.mjs +0 -46
  41. package/tests/admin/Platform_ApiFragmentsApiTest.res +0 -66
  42. package/tests/admin/Platform_ApiFragmentsApiTest.res.mjs +0 -68
  43. package/tests/api/GraphQL_PushPlannerTest.res +0 -62
  44. package/tests/api/GraphQL_PushPlannerTest.res.mjs +0 -80
package/CHANGELOG.md CHANGED
@@ -3,6 +3,26 @@
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.168 (2026-07-14)
7
+
8
+ ### Bug Fixes
9
+
10
+ * **aws:** create EC publishToAggregates SendMessage grants — cross-plugin extension→DCB publishes no longer AccessDenied ([c2126df](https://github.com/ReventlessDev/reventless-core/commit/c2126df0b9af4a79a980f2668ffc18a7760ef4c3))
11
+ * **aws:** create heartbeat SendMessage grant at top level; document the pulumi.all side-channel gotcha ([6ffa06a](https://github.com/ReventlessDev/reventless-core/commit/6ffa06ac87070af4027ba5753ac7c2cb216a76d0))
12
+ * show debug logs on the local platform (both launch paths) ([81837d7](https://github.com/ReventlessDev/reventless-core/commit/81837d7e02abe1065a722b43b195adef2c836794))
13
+ ### Features
14
+
15
+ * **core:** thread ~comp through Projection.handleAction for attributed action logging ([fa32d93](https://github.com/ReventlessDev/reventless-core/commit/fa32d93dedabea1b1f655f01a4ea769a5908b143))
16
+
17
+
18
+ # 3.0.0-alpha.167 (2026-07-14)
19
+
20
+ **Note:** Version bump only for package @reventlessdev/reventless-core
21
+
22
+
23
+
24
+
25
+
6
26
  # 3.0.0-alpha.166 (2026-07-14)
7
27
 
8
28
  ### Features
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reventlessdev/reventless-core",
3
- "version": "3.0.0-alpha.166",
3
+ "version": "3.0.0-alpha.168",
4
4
  "description": "Core package for Reventless framework",
5
5
  "license": "Apache-2.0",
6
6
  "jest": {
@@ -31,12 +31,12 @@
31
31
  "@reventlessdev/rescript-effect": "0.1.0-alpha.27",
32
32
  "@reventlessdev/rescript-fast-csv": "1.2.0-alpha.12",
33
33
  "@reventlessdev/rescript-hash-object": "1.2.0-alpha.11",
34
- "@reventlessdev/rescript-node-streams": "1.1.0-alpha.11",
35
34
  "@reventlessdev/rescript-jest": "1.0.0-alpha.7",
35
+ "@reventlessdev/rescript-node-streams": "1.1.0-alpha.11",
36
36
  "@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.15",
37
37
  "@reventlessdev/rescript-ssh2": "1.1.0-alpha.12",
38
38
  "@reventlessdev/rescript-uuid": "1.1.0-alpha.15",
39
- "@reventlessdev/reventless-infra": "3.0.0-alpha.98",
39
+ "@reventlessdev/reventless-infra": "3.0.0-alpha.99",
40
40
  "@reventlessdev/reventless-interop": "3.0.0-alpha.26",
41
41
  "@reventlessdev/reventless-spec": "3.0.0-alpha.76"
42
42
  },
@@ -133,10 +133,16 @@ let statesToString: array<'a> => string = states =>
133
133
  states->Array.map(stateToString)->Array.joinUnsafe(", ")
134
134
 
135
135
  let handleAction = async (
136
+ ~comp="Projection",
136
137
  action,
137
138
  {QueryDb.loadStream: loadStream, save, saveBatch, delete, deleteBatch} as operations,
138
139
  subIdConfig,
139
140
  ) => {
141
+ // Log each applied action at Debug with the full state it creates/changes,
142
+ // attributed to the owning component. Debug-lazy so the state is only
143
+ // serialized when debug logging is enabled; shadows the module-level
144
+ // `logAction` to carry the threaded `~comp` and the `handling action:` prefix.
145
+ let logAction = makeStr => log.debugLazy(~comp, () => `handling action: ${makeStr()}`)
140
146
  let loadAtMost = (n, id) =>
141
147
  loadStream(id)
142
148
  ->Stream.take(n)
@@ -210,7 +216,6 @@ let handleAction = async (
210
216
  | Error(err) => Error(err)
211
217
  }
212
218
  | UpdateWithDefault(id, default, update) =>
213
- logAction(() => `UpdateWithDefault(${id}, loading ...`)
214
219
  switch await loadAtMost(2, id) {
215
220
  | Ok(states) =>
216
221
  switch states {
@@ -424,19 +429,19 @@ let optimizeActions = actions => {
424
429
  })
425
430
  }
426
431
 
427
- let handleActions = async (actions, operations, subIdConfig) => {
432
+ let handleActions = async (~comp="Projection", actions, operations, subIdConfig) => {
428
433
  let handleActionsForId = async (actions, id) => {
429
434
  let actionCount = actions->Array.length
430
435
  if actionCount > 1 {
431
436
  log.debug(
432
- ~comp="Projection",
437
+ ~comp,
433
438
  `handleActions: optimizing ${actionCount->Int.toString} actions for id=${id}`,
434
439
  )
435
440
  }
436
441
 
437
442
  let optimizedActions = optimizeActions(actions)
438
443
  let optimizedActionCount = optimizedActions->Array.length
439
- log.info(~comp="Projection", `handleActions: id=${id} actions=${optimizedActionCount->Int.toString}`)
444
+ log.debug(~comp, `handleActions: id=${id} actions=${optimizedActionCount->Int.toString}`)
440
445
 
441
446
  // FIXME: handle errors!
442
447
  await optimizedActions->Array.reduce(Ok()->Promise.resolve, async (p, action) => {
@@ -444,11 +449,11 @@ let handleActions = async (actions, operations, subIdConfig) => {
444
449
  | Ok() => ()
445
450
  | Error(err) =>
446
451
  log.error(
447
- ~comp="Projection",
452
+ ~comp,
448
453
  `storage error: ${err->Message.encode(ReventlessInfra.QueryDb.storageErrorSchema)->JSON.stringify}`,
449
454
  )
450
455
  }
451
- await action->handleAction(operations, subIdConfig)
456
+ await action->handleAction(~comp, operations, subIdConfig)
452
457
  })
453
458
  }
454
459
 
@@ -202,10 +202,12 @@ function statesToString(states) {
202
202
  return states.map(stateToString).join(", ");
203
203
  }
204
204
 
205
- async function handleAction(action, operations, subIdConfig) {
205
+ async function handleAction($staropt$star, action, operations, subIdConfig) {
206
206
  let saveBatch = operations.saveBatch;
207
207
  let save = operations.save;
208
208
  let loadStream = operations.loadStream;
209
+ let comp = $staropt$star !== undefined ? $staropt$star : "Projection";
210
+ let logAction = makeStr => log.debugLazy(comp, () => `handling action: ` + makeStr());
209
211
  let loadAtMost = (n, id) => Effect.runPromise(Effect.catchAll(Effect.map(Stream.runCollect(Stream$1.take(loadStream(id), n)), states => ({
210
212
  TAG: "Ok",
211
213
  _0: states
@@ -221,7 +223,7 @@ async function handleAction(action, operations, subIdConfig) {
221
223
  _0: e
222
224
  })));
223
225
  if (typeof action !== "object") {
224
- log.debugLazy("Projection", () => "Ignore");
226
+ logAction(() => "Ignore");
225
227
  return {
226
228
  TAG: "Ok",
227
229
  _0: undefined
@@ -231,7 +233,7 @@ async function handleAction(action, operations, subIdConfig) {
231
233
  case "Create" :
232
234
  let state = action._1;
233
235
  let id = action._0;
234
- log.debugLazy("Projection", () => `Create(` + id + `, ` + stateToString(state) + `)`);
236
+ logAction(() => `Create(` + id + `, ` + stateToString(state) + `)`);
235
237
  return await save(id, state, "Init", undefined);
236
238
  case "CreateMany" :
237
239
  let batch = action._0.map(param => [
@@ -239,7 +241,7 @@ async function handleAction(action, operations, subIdConfig) {
239
241
  param[1],
240
242
  undefined
241
243
  ]);
242
- log.debugLazy("Projection", () => `CreateMany(` + batch.map(param => `(` + param[0] + `,` + stateToString(param[1]) + `)`).join(", ") + `)`);
244
+ logAction(() => `CreateMany(` + batch.map(param => `(` + param[0] + `,` + stateToString(param[1]) + `)`).join(", ") + `)`);
243
245
  return await saveBatch(batch);
244
246
  case "Update" :
245
247
  let id$1 = action._0;
@@ -254,13 +256,13 @@ async function handleAction(action, operations, subIdConfig) {
254
256
  let len = states$1.length;
255
257
  if (len !== 1) {
256
258
  if (len !== 0) {
257
- log.debugLazy("Projection", () => `Update Error: Multiple oldStates for ` + id$1 + `)`);
259
+ logAction(() => `Update Error: Multiple oldStates for ` + id$1 + `)`);
258
260
  return {
259
261
  TAG: "Error",
260
262
  _0: "StaleState"
261
263
  };
262
264
  } else {
263
- log.debugLazy("Projection", () => `Update Error: No oldState for ` + id$1 + `)`);
265
+ logAction(() => `Update Error: No oldState for ` + id$1 + `)`);
264
266
  return {
265
267
  TAG: "Error",
266
268
  _0: "StaleState"
@@ -269,35 +271,34 @@ async function handleAction(action, operations, subIdConfig) {
269
271
  }
270
272
  let oldState = states$1[0];
271
273
  let newState = action._1(oldState);
272
- log.debugLazy("Projection", () => `Update(` + id$1 + `, ` + stateToString(oldState) + ` => ` + stateToString(newState) + `)`);
274
+ logAction(() => `Update(` + id$1 + `, ` + stateToString(oldState) + ` => ` + stateToString(newState) + `)`);
273
275
  return await save(id$1, newState, "Overwrite", undefined);
274
276
  case "UpdateWithDefault" :
275
277
  let $$default = action._1;
276
278
  let id$2 = action._0;
277
- log.debugLazy("Projection", () => `UpdateWithDefault(` + id$2 + `, loading ...`);
278
279
  let states$2 = await loadAtMost(2, id$2);
279
280
  if (states$2.TAG === "Ok") {
280
281
  let states$3 = states$2._0;
281
282
  let len$1 = states$3.length;
282
283
  if (len$1 !== 1) {
283
284
  if (len$1 !== 0) {
284
- log.debugLazy("Projection", () => `UpdateWithDefault Error: Multiple oldStates for ` + id$2 + `)`);
285
+ logAction(() => `UpdateWithDefault Error: Multiple oldStates for ` + id$2 + `)`);
285
286
  return {
286
287
  TAG: "Error",
287
288
  _0: "StaleState"
288
289
  };
289
290
  } else {
290
- log.debugLazy("Projection", () => `UpdateWithDefault(` + id$2 + `, default: ` + stateToString($$default) + `)`);
291
+ logAction(() => `UpdateWithDefault(` + id$2 + `, default: ` + stateToString($$default) + `)`);
291
292
  return await save(id$2, $$default, "Init", undefined);
292
293
  }
293
294
  }
294
295
  let oldState$1 = states$3[0];
295
296
  let newState$1 = action._2(oldState$1);
296
- log.debugLazy("Projection", () => `UpdateWithDefault(` + id$2 + `, ` + stateToString(oldState$1) + ` => ` + stateToString(newState$1) + `)`);
297
+ logAction(() => `UpdateWithDefault(` + id$2 + `, ` + stateToString(oldState$1) + ` => ` + stateToString(newState$1) + `)`);
297
298
  return await save(id$2, newState$1, "Overwrite", undefined);
298
299
  }
299
300
  let err = states$2._0;
300
- log.debugLazy("Projection", () => `UpdateWithDefault Error: Couldn't load oldState(s) for ` + id$2 + `: ` + QueryDb$ReventlessCore.storageErrorToString(err) + `)`);
301
+ logAction(() => `UpdateWithDefault Error: Couldn't load oldState(s) for ` + id$2 + `: ` + QueryDb$ReventlessCore.storageErrorToString(err) + `)`);
301
302
  return {
302
303
  TAG: "Error",
303
304
  _0: err
@@ -305,7 +306,7 @@ async function handleAction(action, operations, subIdConfig) {
305
306
  case "Set" :
306
307
  let state$1 = action._1;
307
308
  let id$3 = action._0;
308
- log.debugLazy("Projection", () => `Set(` + id$3 + `, ` + stateToString(state$1) + `)`);
309
+ logAction(() => `Set(` + id$3 + `, ` + stateToString(state$1) + `)`);
309
310
  return await save(id$3, state$1, "Any", undefined);
310
311
  case "SetMany" :
311
312
  let set = action._1;
@@ -314,15 +315,15 @@ async function handleAction(action, operations, subIdConfig) {
314
315
  set(id),
315
316
  undefined
316
317
  ]);
317
- log.debugLazy("Projection", () => `SetMany(` + batch$1.map(param => `(` + param[0] + `,` + stateToString(param[1]) + `)`).join(", ") + `)`);
318
+ logAction(() => `SetMany(` + batch$1.map(param => `(` + param[0] + `,` + stateToString(param[1]) + `)`).join(", ") + `)`);
318
319
  return await saveBatch(batch$1);
319
320
  case "Delete" :
320
321
  let id$4 = action._0;
321
- log.debugLazy("Projection", () => `Delete(` + id$4 + `)`);
322
+ logAction(() => `Delete(` + id$4 + `)`);
322
323
  return await operations.delete(id$4, undefined);
323
324
  case "DeleteMany" :
324
325
  let ids = action._0;
325
- log.debugLazy("Projection", () => `DeleteMany(` + ids.join(", ") + `)`);
326
+ logAction(() => `DeleteMany(` + ids.join(", ") + `)`);
326
327
  return await operations.deleteBatch(ids.map(id => [
327
328
  id,
328
329
  undefined
@@ -330,7 +331,7 @@ async function handleAction(action, operations, subIdConfig) {
330
331
  case "CreateMultiState" :
331
332
  let states$4 = action._1;
332
333
  let id$5 = action._0;
333
- log.debugLazy("Projection", () => `CreateMultiState(` + id$5 + `, ` + states$4.map(stateToString).join(", ") + `)`);
334
+ logAction(() => `CreateMultiState(` + id$5 + `, ` + states$4.map(stateToString).join(", ") + `)`);
334
335
  let len$2 = states$4.length;
335
336
  if (len$2 !== 1) {
336
337
  if (len$2 === 0) {
@@ -359,19 +360,19 @@ async function handleAction(action, operations, subIdConfig) {
359
360
  }
360
361
  } else if (subIdConfig !== undefined) {
361
362
  let err$1 = match._0;
362
- log.debugLazy("Projection", () => `UpdateMultiState Error: Couldn't load states for ` + id$6 + `: ` + QueryDb$ReventlessCore.storageErrorToString(err$1) + `)`);
363
+ logAction(() => `UpdateMultiState Error: Couldn't load states for ` + id$6 + `: ` + QueryDb$ReventlessCore.storageErrorToString(err$1) + `)`);
363
364
  return {
364
365
  TAG: "Error",
365
366
  _0: err$1
366
367
  };
367
368
  }
368
- log.debugLazy("Projection", () => "UpdateMultiState Error: Missing SubIdConfig !");
369
+ logAction(() => "UpdateMultiState Error: Missing SubIdConfig !");
369
370
  return {
370
371
  TAG: "Error",
371
372
  _0: "MissingSubIdConfig"
372
373
  };
373
374
  default:
374
- log.debugLazy("Projection", () => "Error: projection action not supported");
375
+ logAction(() => "Error: projection action not supported");
375
376
  return {
376
377
  TAG: "Error",
377
378
  _0: {
@@ -668,24 +669,25 @@ function optimizeActions(actions) {
668
669
  });
669
670
  }
670
671
 
671
- async function handleActions(actions, operations, subIdConfig) {
672
+ async function handleActions(compOpt, actions, operations, subIdConfig) {
673
+ let comp = compOpt !== undefined ? compOpt : "Projection";
672
674
  let handleActionsForId = async (actions, id) => {
673
675
  let actionCount = actions.length;
674
676
  if (actionCount > 1) {
675
- log.debug("Projection", undefined, `handleActions: optimizing ` + actionCount.toString() + ` actions for id=` + id);
677
+ log.debug(comp, undefined, `handleActions: optimizing ` + actionCount.toString() + ` actions for id=` + id);
676
678
  }
677
679
  let optimizedActions = optimizeActions(actions);
678
680
  let optimizedActionCount = optimizedActions.length;
679
- log.info("Projection", undefined, `handleActions: id=` + id + ` actions=` + optimizedActionCount.toString());
681
+ log.debug(comp, undefined, `handleActions: id=` + id + ` actions=` + optimizedActionCount.toString());
680
682
  return await Stdlib_Array.reduce(optimizedActions, Promise.resolve({
681
683
  TAG: "Ok",
682
684
  _0: undefined
683
685
  }), async (p, action) => {
684
686
  let err = await p;
685
687
  if (err.TAG !== "Ok") {
686
- log.error("Projection", undefined, `storage error: ` + JSON.stringify(Message$ReventlessCore.encode(err._0, QueryDb$ReventlessInfra.storageErrorSchema)));
688
+ log.error(comp, undefined, `storage error: ` + JSON.stringify(Message$ReventlessCore.encode(err._0, QueryDb$ReventlessInfra.storageErrorSchema)));
687
689
  }
688
- return await handleAction(action, operations, subIdConfig);
690
+ return await handleAction(comp, action, operations, subIdConfig);
689
691
  });
690
692
  };
691
693
  let results = await Promise.all(groupActionsById(actions).map(param => handleActionsForId(param[1], param[0])));
@@ -9,46 +9,14 @@ let cloneMutationEntry: mutationSchemaEntry = {
9
9
  description: "Clone the system to a specific point in time",
10
10
  }
11
11
 
12
- // ApiFragmentRegistry admin mutations — the real GraphQL surface of the ApiFragmentRegistry
13
- // singleton aggregate: the plugin / standalone-service deploy calls
14
- // `Platform_ApiFragmentRegistry_RegisterApiFragment` / `..._DeregisterApiFragment` as a SigV4
15
- // system caller. Derived from the aggregate's `commandSchema` exactly like the Plugin aggregate's
16
- // entries (`PluginBaseFragment.pluginAggregateMutationEntries`) — one `Platform_<Spec>_<Command>`
17
- // field per non-`@noApi` variant (`RecordApiFragmentPush` is `@noApi`, filtered out). The matching
18
- // resolver wiring is fired by `Plugin_Helpers.registerAdminAggregateMutations` over the same
19
- // `~aggregates` list in `Platform_Admin.construct`, so the SDL field and the auto-bound resolver
20
- // carry byte-identical names.
21
- let apiFragmentRegistryMutationEntries: array<mutationSchemaEntry> = {
22
- let commandSchema = ApiFragmentRegistrySpec.commandSchema->S.castToUnknown
23
- let constructorNames = Reventless.DcbTag.extractAllVariantNames(ApiFragmentRegistrySpec.commandSchema)
24
- let filteredConstructorNames = ApiNoApiHelpers.filterNoApiVariants(constructorNames, commandSchema)
25
- let fieldNames =
26
- filteredConstructorNames->Array.map(cname =>
27
- Api_Naming.adminField(~name=ApiFragmentRegistrySpec.name ++ "_" ++ cname)
28
- )
29
- if fieldNames->Array.length === 0 {
30
- []
31
- } else {
32
- [
33
- {
34
- ReventlessInfra.Api.fieldNames,
35
- commandSchema,
36
- },
37
- ]
38
- }
39
- }
40
-
41
12
  // Aggregate-derived admin mutations come from `PluginBaseFragment.pluginAggregateMutationEntries`
42
- // (Plugin aggregate) + `apiFragmentRegistryMutationEntries` (ApiFragmentRegistry aggregate) so they
43
- // end up in the stitched SDL AND in the static `baseFragment` the AWS path pushes directly. The
44
- // corresponding resolver wiring is fired in parallel by
45
- // `Plugin_Helpers.registerAdminAggregateMutations` from `Platform_Admin.construct` over the same
46
- // `~aggregates` list.
13
+ // (Plugin aggregate) so they end up in the admin base document. The corresponding resolver wiring
14
+ // is fired in parallel by `Plugin_Helpers.registerAdminAggregateMutations` from
15
+ // `Platform_Admin.construct` over the same `~aggregates` list.
16
+ // (The ApiFragmentRegistry aggregate's entries were retired with the merged-API cutover —
17
+ // schema composition is push-free, so no deploy-time register/deregister surface exists.)
47
18
  let mutationEntries = (~cloner: bool) => {
48
- let base = Array.concat(
49
- PluginBaseFragment.pluginAggregateMutationEntries,
50
- apiFragmentRegistryMutationEntries,
51
- )
19
+ let base = PluginBaseFragment.pluginAggregateMutationEntries
52
20
  if cloner {
53
21
  Array.concat(base, [cloneMutationEntry])
54
22
  } else {
@@ -58,17 +26,6 @@ let mutationEntries = (~cloner: bool) => {
58
26
 
59
27
  let queryEntries = PluginBaseFragment.queryEntries
60
28
 
61
- // Admin fields a deploy-time system caller (machine credentials — SigV4/IAM on AWS) invokes: the
62
- // two ApiFragmentRegistry mutations (the deploy's register/deregister write path) and
63
- // `Platform_ApiFragments` (the deploy waiter's push-status poll). Provider-neutral by design — the
64
- // AWS adapter threads these into `injectAwsAuthAll`'s `~iamFieldNames` so only these fields carry
65
- // the dual-auth (`@aws_cognito_user_pools @aws_iam`) directive; every other admin field stays
66
- // Cognito-only. Derived from the same mutation entries so the names never drift from the SDL.
67
- let systemCallerFieldNames =
68
- apiFragmentRegistryMutationEntries
69
- ->Array.flatMap(e => e.fieldNames)
70
- ->Array.concat([Platform_ApiFragmentsApi.queryFieldName])
71
-
72
29
  // UIFragment lifecycle Source C subscriptions.
73
30
  // Mutations are called by the backend when UIFragment events occur; the
74
31
  // subscription→mutation fan-in is carried as neutral `subscriptionSource`
@@ -132,35 +89,25 @@ let baseFragment = (~cloner: bool) => {
132
89
  // matching SDL fields, AppSync's CreateResolver fails with "Type not found".
133
90
  let (pluginAggregateSubscriptionFields, pluginAggregateSubscriptionSources) =
134
91
  Plugin_SubscriptionSchema.sourceCFields(~mutationEntries=PluginBaseFragment.pluginAggregateMutationEntries)
135
- // The ApiFragmentRegistry aggregate's mutations go through the same CommandGenerator
136
- // auto-flow, which creates an `on<field>` subscription resolver per mutation. On the
137
- // static-push platform (AWS) those resolvers orphan unless the fields are declared in the
138
- // pushed baseFragment — so generate them here too, symmetric with the Plugin aggregate.
139
- let (apiFragmentAggregateSubscriptionFields, apiFragmentAggregateSubscriptionSources) =
140
- Plugin_SubscriptionSchema.sourceCFields(~mutationEntries=apiFragmentRegistryMutationEntries)
141
92
  GraphQL_Stitcher.encode({
142
93
  types: parts.types
143
94
  ->Array.concat(uiFragmentSubscriptionTypes)
144
95
  ->Array.concat(pluginStatusSubscriptionTypes)
145
96
  ->Array.concat(Platform_ComponentDefinitionsApi.sdlTypes)
146
- ->Array.concat(Platform_UIFragmentsApi.sdlTypes)
147
- ->Array.concat(Platform_ApiFragmentsApi.sdlTypes),
97
+ ->Array.concat(Platform_UIFragmentsApi.sdlTypes),
148
98
  queries: Array.concat(
149
99
  parts.queries,
150
100
  [
151
101
  Platform_ComponentDefinitionsApi.sdlQueryField,
152
102
  Platform_UIFragmentsApi.sdlQueryField,
153
- Platform_ApiFragmentsApi.sdlQueryField,
154
103
  ],
155
104
  ),
156
105
  mutations: parts.mutations
157
106
  ->Array.concat(uiFragmentMutationFields)
158
107
  ->Array.concat(pluginStatusMutationFields),
159
108
  subscriptions: [uiFragmentSubscriptionField, pluginStatusSubscriptionField]
160
- ->Array.concat(pluginAggregateSubscriptionFields)
161
- ->Array.concat(apiFragmentAggregateSubscriptionFields),
109
+ ->Array.concat(pluginAggregateSubscriptionFields),
162
110
  subscriptionSources: [uiFragmentSubscriptionSource, pluginStatusSubscriptionSource]
163
- ->Array.concat(pluginAggregateSubscriptionSources)
164
- ->Array.concat(apiFragmentAggregateSubscriptionSources),
111
+ ->Array.concat(pluginAggregateSubscriptionSources),
165
112
  })
166
113
  }
@@ -1,14 +1,10 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
3
  import * as S from "sury/src/S.res.mjs";
4
- import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
5
4
  import * as Api_Naming$ReventlessCore from "../components/Api/Api_Naming.res.mjs";
6
- import * as ApiNoApiHelpers$ReventlessCore from "../components/Api/ApiNoApiHelpers.res.mjs";
7
5
  import * as GraphQL_Stitcher$ReventlessCore from "../components/Api/GraphQL_Stitcher.res.mjs";
8
6
  import * as PluginBaseFragment$ReventlessCore from "../plugin/api/PluginBaseFragment.res.mjs";
9
- import * as ApiFragmentRegistrySpec$ReventlessCore from "./ApiFragmentRegistry/ApiFragmentRegistrySpec.res.mjs";
10
7
  import * as Platform_UIFragmentsApi$ReventlessCore from "./Platform_UIFragmentsApi.res.mjs";
11
- import * as Platform_ApiFragmentsApi$ReventlessCore from "./Platform_ApiFragmentsApi.res.mjs";
12
8
  import * as GraphQL_FragmentGenerator$ReventlessCore from "../components/Api/GraphQL_FragmentGenerator.res.mjs";
13
9
  import * as Plugin_SubscriptionSchema$ReventlessCore from "../plugin/component/Plugin_SubscriptionSchema.res.mjs";
14
10
  import * as Platform_ComponentDefinitionsApi$ReventlessCore from "./Platform_ComponentDefinitionsApi.res.mjs";
@@ -27,28 +23,14 @@ let cloneMutationEntry = {
27
23
  description: cloneMutationEntry_description
28
24
  };
29
25
 
30
- let constructorNames = DcbTag$Reventless.extractAllVariantNames(ApiFragmentRegistrySpec$ReventlessCore.commandSchema);
31
-
32
- let filteredConstructorNames = ApiNoApiHelpers$ReventlessCore.filterNoApiVariants(constructorNames, ApiFragmentRegistrySpec$ReventlessCore.commandSchema);
33
-
34
- let fieldNames = filteredConstructorNames.map(cname => Api_Naming$ReventlessCore.adminField(ApiFragmentRegistrySpec$ReventlessCore.name + "_" + cname));
35
-
36
- let apiFragmentRegistryMutationEntries = fieldNames.length === 0 ? [] : [{
37
- fieldNames: fieldNames,
38
- commandSchema: ApiFragmentRegistrySpec$ReventlessCore.commandSchema
39
- }];
40
-
41
26
  function mutationEntries(cloner) {
42
- let base = PluginBaseFragment$ReventlessCore.pluginAggregateMutationEntries.concat(apiFragmentRegistryMutationEntries);
43
27
  if (cloner) {
44
- return base.concat([cloneMutationEntry]);
28
+ return PluginBaseFragment$ReventlessCore.pluginAggregateMutationEntries.concat([cloneMutationEntry]);
45
29
  } else {
46
- return base;
30
+ return PluginBaseFragment$ReventlessCore.pluginAggregateMutationEntries;
47
31
  }
48
32
  }
49
33
 
50
- let systemCallerFieldNames = apiFragmentRegistryMutationEntries.flatMap(e => e.fieldNames).concat([Platform_ApiFragmentsApi$ReventlessCore.queryFieldName]);
51
-
52
34
  let uiFragmentSubscriptionTypes = [
53
35
  `enum UIFragmentChangeKind {\n Registered\n Updated\n Deregistered\n}`,
54
36
  `type UIFragmentChangeEvent {\n pluginId: ID!\n changeKind: UIFragmentChangeKind!\n manifest: String\n}`
@@ -93,23 +75,21 @@ function baseFragment(cloner) {
93
75
  let base = GraphQL_FragmentGenerator$ReventlessCore.generate(mutationEntries(cloner), PluginBaseFragment$ReventlessCore.queryEntries);
94
76
  let parts = GraphQL_Stitcher$ReventlessCore.decode(base);
95
77
  let match = Plugin_SubscriptionSchema$ReventlessCore.sourceCFields(PluginBaseFragment$ReventlessCore.pluginAggregateMutationEntries);
96
- let match$1 = Plugin_SubscriptionSchema$ReventlessCore.sourceCFields(apiFragmentRegistryMutationEntries);
97
78
  return GraphQL_Stitcher$ReventlessCore.encode({
98
- types: parts.types.concat(uiFragmentSubscriptionTypes).concat(pluginStatusSubscriptionTypes).concat(Platform_ComponentDefinitionsApi$ReventlessCore.sdlTypes).concat(Platform_UIFragmentsApi$ReventlessCore.sdlTypes).concat(Platform_ApiFragmentsApi$ReventlessCore.sdlTypes),
79
+ types: parts.types.concat(uiFragmentSubscriptionTypes).concat(pluginStatusSubscriptionTypes).concat(Platform_ComponentDefinitionsApi$ReventlessCore.sdlTypes).concat(Platform_UIFragmentsApi$ReventlessCore.sdlTypes),
99
80
  mutations: parts.mutations.concat(uiFragmentMutationFields).concat(pluginStatusMutationFields),
100
81
  queries: parts.queries.concat([
101
82
  Platform_ComponentDefinitionsApi$ReventlessCore.sdlQueryField,
102
- Platform_UIFragmentsApi$ReventlessCore.sdlQueryField,
103
- Platform_ApiFragmentsApi$ReventlessCore.sdlQueryField
83
+ Platform_UIFragmentsApi$ReventlessCore.sdlQueryField
104
84
  ]),
105
85
  subscriptions: [
106
86
  uiFragmentSubscriptionField,
107
87
  pluginStatusSubscriptionField
108
- ].concat(match[0]).concat(match$1[0]),
88
+ ].concat(match[0]),
109
89
  subscriptionSources: [
110
90
  uiFragmentSubscriptionSource,
111
91
  pluginStatusSubscriptionSource
112
- ].concat(match[1]).concat(match$1[1])
92
+ ].concat(match[1])
113
93
  });
114
94
  }
115
95
 
@@ -118,10 +98,8 @@ let queryEntries = PluginBaseFragment$ReventlessCore.queryEntries;
118
98
  export {
119
99
  cloneArgsSchema,
120
100
  cloneMutationEntry,
121
- apiFragmentRegistryMutationEntries,
122
101
  mutationEntries,
123
102
  queryEntries,
124
- systemCallerFieldNames,
125
103
  uiFragmentSubscriptionTypes,
126
104
  uiFragmentMutationFields,
127
105
  uiFragmentSubscriptionField,
@@ -317,115 +317,7 @@ document carries it (via `stitch`).
317
317
  let stitchStandalone = (~fragment: Reventless.Plugin.apiSchemaFragment): string =>
318
318
  assembleSdl(~fragments=[fragment], ~includeGlobalNodeQuery=false)
319
319
 
320
- let isIdentStart = (line: string): bool =>
321
- switch line->String.codePointAt(0) {
322
- // A-Z (65-90), a-z (97-122), or `_` (95)
323
- | Some(c) => (c >= 65 && c <= 90) || (c >= 97 && c <= 122) || c == 95
324
- | None => false
325
- }
326
-
327
- /**
328
- List the field NAMES defined inside a root object type (`Mutation` / `Query` /
329
- `Subscription`) of a full SDL string.
330
-
331
- This is the identity-aware primitive underlying every schema-clobber guard:
332
- `countRootTypeFields` is just its length, and the deploy-time repair / shrink
333
- guards compare the returned NAME SETS rather than cardinalities so they catch
334
- field *swaps* and equal-cardinality drift that a count comparison misses.
335
-
336
- Heuristic but adequate: root operation fields are flat single-line declarations
337
- (`name(args): T` or `name: T`), so we slice the `type <typeName> { … }` block at
338
- its first `{`/`}` and read the leading identifier of each indented line that
339
- begins with an identifier character, ignoring directive-only lines (`@…`),
340
- comments (`#…`) and braces.
341
- */
342
- let rootTypeFieldNames = (~sdl: string, ~typeName: string): array<string> => {
343
- let marker = `type ${typeName}`
344
- switch sdl->String.indexOfOpt(marker) {
345
- | None => []
346
- | Some(typeStart) =>
347
- let rest = sdl->String.slice(~start=typeStart)
348
- switch (rest->String.indexOfOpt("{"), rest->String.indexOfOpt("}")) {
349
- | (Some(openIdx), Some(closeIdx)) if closeIdx > openIdx =>
350
- rest
351
- ->String.slice(~start=openIdx + 1, ~end=closeIdx)
352
- ->String.split("\n")
353
- ->Array.filterMap(line => {
354
- let trimmed = line->String.trim
355
- if trimmed->String.length > 0 && isIdentStart(trimmed) {
356
- // `name(args): T` → extractLeadingName strips the arg list; `name: T`
357
- // (no args) leaves a trailing colon on the token — drop it so a field
358
- // reads the same whether or not it takes arguments.
359
- let name = extractLeadingName(trimmed)
360
- let name = name->String.endsWith(":")
361
- ? name->String.slice(~start=0, ~end=name->String.length - 1)
362
- : name
363
- name->String.length > 0 ? Some(name) : None
364
- } else {
365
- None
366
- }
367
- })
368
- | _ => []
369
- }
370
- }
371
- }
372
-
373
- /**
374
- Count the field definitions inside a root object type (`Mutation` / `Query`) of a
375
- full SDL string. Length of `rootTypeFieldNames`.
376
- */
377
- let countRootTypeFields = (~sdl: string, ~typeName: string): int =>
378
- rootTypeFieldNames(~sdl, ~typeName)->Array.length
379
-
380
- // The three GraphQL root operation types every clobber guard reasons over.
381
- let rootTypeNames = ["Mutation", "Query", "Subscription"]
382
-
383
- /**
384
- Union of every root-operation field name across `Mutation` + `Query` +
385
- `Subscription`. The identity set the deploy-time repair and shrink guards diff.
386
- */
387
- let allRootFieldNames = (~sdl: string): array<string> =>
388
- rootTypeNames->Array.flatMap(typeName => rootTypeFieldNames(~sdl, ~typeName))
389
-
390
- /**
391
- Root-operation field names present in `expectedSdl` but MISSING from `liveSdl`
392
- (across Mutation + Query + Subscription). Non-empty ⇒ the live schema is not a
393
- superset of what we expect and a repair push is warranted — this heals field
394
- *swaps* and equal-cardinality drift that a bare count comparison would skip.
395
- */
396
- let missingRootFields = (~expectedSdl: string, ~liveSdl: string): array<string> => {
397
- let liveSet = allRootFieldNames(~sdl=liveSdl)->Set.fromArray
398
- allRootFieldNames(~sdl=expectedSdl)->Array.filter(name => !(liveSet->Set.has(name)))
399
- }
400
-
401
- /**
402
- Decide whether replacing the live schema (`currentSdl`) with `newSdl` would drop
403
- root-operation fields the pushing stack does not carry — i.e. an almost-certainly
404
- transient/incomplete stitch rather than an intentional removal.
405
-
406
- Identity-based (across `Mutation` + `Query` + `Subscription`):
407
- - When `newSdl`'s field-name set is a SUPERSET of the live set — nothing is
408
- dropped — it is purely additive (or unchanged) and never a clobber, so this
409
- returns `false` even when the pushing stack is legitimately adding its own
410
- fields.
411
- - Otherwise it falls back to the cardinality threshold on the union of the three
412
- root types: `true` only when the new total drops below `threshold` × the
413
- current total. A small intentional removal (above threshold) is allowed.
414
-
415
- When the current schema has no countable root fields (e.g. first deploy, or
416
- introspection was unavailable so `currentSdl` is empty) it returns `false` so the
417
- initial push always proceeds.
418
- */
419
- let isCatastrophicSchemaShrink = (~currentSdl: string, ~newSdl: string, ~threshold: float): bool => {
420
- let currentNames = allRootFieldNames(~sdl=currentSdl)
421
- let newSet = allRootFieldNames(~sdl=newSdl)->Set.fromArray
422
- let dropped = currentNames->Array.filter(name => !(newSet->Set.has(name)))
423
- if dropped->Array.length == 0 {
424
- // Additive or unchanged push — the new schema keeps every live field.
425
- false
426
- } else {
427
- let current = currentNames->Array.length
428
- let next = allRootFieldNames(~sdl=newSdl)->Array.length
429
- current > 0 && next->Int.toFloat < current->Int.toFloat *. threshold
430
- }
431
- }
320
+ // (The schema-clobber guard family — rootTypeFieldNames / countRootTypeFields /
321
+ // missingRootFields / isCatastrophicSchemaShrink — was retired with the push
322
+ // machinery: under merged-API composition every source API is a single writer,
323
+ // so no whole-replace push exists to guard.)