@cldmv/slothlet-types 3.16.1 → 3.16.3

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,7 @@ export class Lifecycle extends ComponentBase {
14
14
  */
15
15
  constructor(slothlet: object);
16
16
  subscribers: Map<any, any>;
17
+ internalSubscribers: Map<any, any>;
17
18
  eventLog: any[];
18
19
  maxLogSize: number;
19
20
  /**
@@ -45,6 +46,18 @@ export class Lifecycle extends ComponentBase {
45
46
  * });
46
47
  */
47
48
  public on(event: string, handler: Function): Function;
49
+ /**
50
+ * Subscribe to the INTERNAL lifecycle tier (#398) — the framework's own systems (metadata,
51
+ * routine manager, ownership) use this for the construction/contribution stream, which fires
52
+ * per contribution BEFORE collision resolution decides placement and carries the raw callable.
53
+ * Public consumers never reach this tier; they use {@link Lifecycle#subscribe} / `on`, which
54
+ * receives the sanitized post-placement PUBLIC events emitted via {@link Lifecycle#emit}.
55
+ * @param {string} event - Event name (e.g. `"impl:created"`, `"impl:changed"`).
56
+ * @param {Function} handler - Event handler function(eventData, token).
57
+ * @returns {Function} Unsubscribe function.
58
+ * @internal
59
+ */
60
+ subscribeInternal(event: string, handler: Function): Function;
48
61
  /**
49
62
  * Unsubscribe from lifecycle event - standard EventEmitter pattern
50
63
  * @param {string} event - Event name
@@ -89,5 +102,17 @@ export class Lifecycle extends ComponentBase {
89
102
  * });
90
103
  */
91
104
  private emit;
105
+ /**
106
+ * Emit an INTERNAL lifecycle event (#398) — delivered ONLY to {@link Lifecycle#subscribeInternal}
107
+ * subscribers (the framework's own metadata/routine/ownership systems), never to public
108
+ * consumers. Used for the construction/contribution stream (`impl:created` / `impl:changed`
109
+ * emitted per contribution, pre-placement, carrying the raw callable the internal systems need).
110
+ * @param {string} event - Event name.
111
+ * @param {object} data - Event data.
112
+ * @returns {Promise<void>}
113
+ * @internal
114
+ */
115
+ emitInternal(event: string, data: object): Promise<void>;
116
+ #private;
92
117
  }
93
118
  import { ComponentBase } from "#factories/component-base";
@@ -80,12 +80,12 @@ export class RoutineManager extends ComponentBase {
80
80
  * rebuild/cascade time (see the class-level description for why).
81
81
  *
82
82
  * @description
83
- * Reads `data.wrapper.__impl` (present on every such event, in both eager and lazy mode) rather
84
- * than `data.impl` — `impl:created` fires twice per leaf construction (once with `impl` set to
85
- * the wrapper itself, once with the raw value for eager-known impls), and `wrapper.__impl` is
86
- * the one consistent field across every variant. Fires BEFORE collision resolution decides
87
- * which contributor's value survives onto the composed tree, so every contributor is captured —
88
- * not just the merge winner.
83
+ * Subscribed to the INTERNAL contribution stream (#398), `emitInternal("impl:created"/"impl:changed")`,
84
+ * which fires once per contribution BEFORE collision resolution decides which contributor's value
85
+ * survives onto the composed tree — so every contributor is captured, not just the merge winner.
86
+ * Reads the leaf's callable from `data.wrapper.__impl` (present on every such event, eager and
87
+ * lazy); the raw `data.impl` field no longer exists (that was the enforcement-bypassing leak #398
88
+ * removed). The real `UnifiedWrapper` instance, when there is one, arrives on `data.__wrapperRef`.
89
89
  *
90
90
  * Also subscribed to `impl:changed` so a LATE, direct reassignment (`self.auth.shutdown = fn`,
91
91
  * done after the module that owns `auth` finished loading) is captured too, not just the
@@ -339,7 +339,7 @@ export class RoutineManager extends ComponentBase {
339
339
  * use only, for a caller (`#runModeRoutines`) that already force-materialized this exact
340
340
  * routine immediately beforehand and would otherwise re-walk the same tree for no new
341
341
  * information. Always leave this `false` for any externally-triggered cascade (the installed
342
- * `api[name]()` / `api.slothlet[name]()` callables never pass it), since those calls have no
342
+ * `api[name]()` callable never passes it), since those calls have no
343
343
  * such prior guarantee.
344
344
  * @returns {Promise<*>} The sole involved path's result, an ordered array of every involved
345
345
  * path's result when there are two or more, `[]` when the routine has no contributors
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cldmv/slothlet-types",
3
- "version": "3.16.1",
3
+ "version": "3.16.3",
4
4
  "description": "TypeScript declaration files (.d.mts) for @cldmv/slothlet. Install alongside @cldmv/slothlet for editor and type-checker support.",
5
5
  "keywords": [
6
6
  "slothlet",
@@ -79,7 +79,7 @@
79
79
  "LICENSE"
80
80
  ],
81
81
  "peerDependencies": {
82
- "@cldmv/slothlet": "3.16.1"
82
+ "@cldmv/slothlet": "3.16.3"
83
83
  },
84
84
  "peerDependenciesMeta": {
85
85
  "@cldmv/slothlet": {
package/slothlet.d.mts CHANGED
@@ -156,7 +156,7 @@ export type SlothletOptions = {
156
156
  */
157
157
  collectLifecycleHooks?: boolean | undefined;
158
158
  /**
159
- * - Stackable lifecycle routines (#341). Every mounted module exporting a function matching a configured routine name is composed into one callable at its exact composed api path, plus a root cascade (`self.<name>()` ≡ `api.slothlet.<name>()`) that runs every matching contribution anywhere. Entries: `"name"` (mode `"manual"`), `"name:mode"`, or `{ name, mode?, recursive?, order? }` (`recursive`/`order` only settable via the object form). `name` is mount-relative by default (a bare name matches only a mount's own top level; a dotted name matches a fixed relative sub-path, or with `recursive: true` any depth within the mount); a `^`-prefixed name is root-anchored, matched via glob (`*`, `**`, `{}`, `!`) against the full api path, crossing mount boundaries. `order` (`"mount"` | `"depth"`, mode-defaulted) controls the root cascade's grouping order. Providing `routines` at all REPLACES the built-in defaults (`slothlet.defaults.routines`: `initialize` → `startup`, `shutdown` → `shutdown`) — spread `slothlet.defaults.routines` to extend them instead, or pass `[]` to disable every routine. Every configured routine is always wrapped and directly callable regardless of `autoRoutines`. Whether two or more contributors colliding at the identical api path all run is governed by `stackRoutines` (#365), independent of `collisionMode` — by default only the single contribution that actually owns that path runs, matching ordinary collision behavior. A throwing contributor doesn't stop the chain — every contributor runs (best-effort), and one aggregate `ROUTINE_FAILED` error is thrown afterward if any failed. See [LIFECYCLE.md](docs/LIFECYCLE.md#routines).
159
+ * - Stackable lifecycle routines (#341). Every mounted module exporting a function matching a configured routine name is composed into one callable at its exact composed api path, plus a root cascade (`self.<name>()`, i.e. `api.<name>()`) that runs every matching contribution anywhere. Entries: `"name"` (mode `"manual"`), `"name:mode"`, or `{ name, mode?, recursive?, order? }` (`recursive`/`order` only settable via the object form). `name` is mount-relative by default (a bare name matches only a mount's own top level; a dotted name matches a fixed relative sub-path, or with `recursive: true` any depth within the mount); a `^`-prefixed name is root-anchored, matched via glob (`*`, `**`, `{}`, `!`) against the full api path, crossing mount boundaries. `order` (`"mount"` | `"depth"`, mode-defaulted) controls the root cascade's grouping order. Providing `routines` at all REPLACES the built-in defaults (`slothlet.defaults.routines`: `initialize` → `startup`, `shutdown` → `shutdown`) — spread `slothlet.defaults.routines` to extend them instead, or pass `[]` to disable every routine. Every configured routine is always wrapped and directly callable regardless of `autoRoutines`. Whether two or more contributors colliding at the identical api path all run is governed by `stackRoutines` (#365), independent of `collisionMode` — by default only the single contribution that actually owns that path runs, matching ordinary collision behavior. A throwing contributor doesn't stop the chain — every contributor runs (best-effort), and one aggregate `ROUTINE_FAILED` error is thrown afterward if any failed. See [LIFECYCLE.md](docs/LIFECYCLE.md#routines).
160
160
  */
161
161
  routines?: (string | {
162
162
  name: string;