@k8slens/injectable 26.0.0 → 26.2.0

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/README.md CHANGED
@@ -358,6 +358,25 @@ const someLoggerInjectable = getInjectable({
358
358
 
359
359
  Be aware it is `undefined` for anything resolved through `injectMany`, where the token stands in as the injecting party rather than the consumer.
360
360
 
361
+ - **`di.id`, `di.scopeIds` and `di.scopedId`** (on the `di` of a `getInjectable2`) are your *own* identity and place in the tree, as opposed to the consumer's: your id, the ids of the scopes you were registered under, outermost first and the immediate owner last, and the two together — the segments of your namespaced id. The scope pair walks the registration tree on every read and hands back a fresh array, so read them once. Two scopes registering an injectable of the same bare id get two instances, and this is how each tells which one it is, no matter who injects it:
362
+
363
+ ```ts
364
+ const someLoggerInjectable = getInjectable2({
365
+ id: "some-logger",
366
+ instantiate: (di) => () => createLogger({ prefix: di.scopedId.join(":") }),
367
+ });
368
+ ```
369
+
370
+ - **A registration can key its token by its scope.** `injectionToken` may be a function of the scope the injectable is registered under, `({ scopeIds }) => someToken.for(...)`, resolved once at registration with the same `scopeIds` the injectable's own `di.scopeIds` will read as. This is for token families whose specifier must be unique per scope without the scope's author spelling it: two scopes registering the same shape of injectable end up under two different specific tokens, and neither had to invent a globally unique name. The function is called once per registration and must return a token; deregistering forgets the resolution, so registering again elsewhere resolves afresh. Registration and deregistration callbacks receive the resolved token as their second argument, since the injectable alone would only show them the function.
371
+
372
+ ```ts
373
+ const bookmarkHotbarItemInjectable = getInjectable2({
374
+ id: "bookmark-hotbar-item",
375
+ instantiate: (di) => () => createBookmarkItem(),
376
+ injectionToken: ({ scopeIds }) => hotbarItemInjectionToken.for([...scopeIds, "bookmark"].join(":")),
377
+ });
378
+ ```
379
+
361
380
  - **`di.purge` means two different things.** On the container it purges instances globally. On the `di` inside an `instantiate` it is restricted to the scope: the owner's own instances and those of the injectables it registered directly, and it throws `Tried to purge "some-id" from "some-owner", but it is not within its registration context tree.` for anything else. Neither form removes registrations — only instances.
362
381
  - **Footgun: a scope belongs to the injectable, not to the instance.** The owner's identity is the injectable object, so a `transient` or `keyedSingleton` owner does not get a fresh scope per instantiation. Its second instantiation re-runs the same `di.register` calls and throws `Tried to register same injectable multiple times: "some-owner:some-id"`. The same happens after `di.purge` of a singleton owner, since purging drops the instance but keeps the registrations, so re-injecting re-runs `instantiate`. Scopes are a structural mechanism for features, not a per-instance one.
363
382
  - **Footgun: cardinality bounds are container-wide.** Two scopes cannot each register their own implementation of a token declared `one` or `zero-or-one`; the second registration is rejected regardless of which scope it is in.