@spearwolf/shadow-objects 0.32.0 → 0.34.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/CHANGELOG.md +333 -10
- package/README.md +100 -20
- package/bundle.js +5 -54
- package/package.json +7 -3
- package/src/ChangeTrailRefusedError.d.ts +27 -0
- package/src/ChangeTrailRefusedError.d.ts.map +1 -0
- package/src/ChangeTrailRefusedError.js +12 -0
- package/src/ChangeTrailRefusedError.js.map +7 -0
- package/src/EntityUuidInUseError.d.ts +19 -0
- package/src/EntityUuidInUseError.d.ts.map +1 -0
- package/src/EntityUuidInUseError.js +11 -0
- package/src/EntityUuidInUseError.js.map +7 -0
- package/src/WorkerTimeoutError.d.ts +25 -0
- package/src/WorkerTimeoutError.d.ts.map +1 -0
- package/src/WorkerTimeoutError.js +12 -0
- package/src/WorkerTimeoutError.js.map +7 -0
- package/src/bundle.d.ts +1 -1
- package/src/bundle.d.ts.map +1 -1
- package/src/bundle.js +1 -1
- package/src/bundle.js.map +2 -2
- package/src/constants.d.ts +9 -2
- package/src/constants.d.ts.map +1 -1
- package/src/constants.js +1 -1
- package/src/constants.js.map +2 -2
- package/src/create-worker.bundle.d.ts +1 -1
- package/src/create-worker.bundle.d.ts.map +1 -1
- package/src/create-worker.bundle.js.map +1 -1
- package/src/create-worker.d.ts +1 -1
- package/src/create-worker.d.ts.map +1 -1
- package/src/create-worker.js.map +1 -1
- package/src/elements/ShaeElement.d.ts +70 -2
- package/src/elements/ShaeElement.d.ts.map +1 -1
- package/src/elements/ShaeElement.js +129 -25
- package/src/elements/ShaeElement.js.map +3 -3
- package/src/elements/ShaeEntElement.d.ts +43 -5
- package/src/elements/ShaeEntElement.d.ts.map +1 -1
- package/src/elements/ShaeEntElement.js +399 -170
- package/src/elements/ShaeEntElement.js.map +2 -2
- package/src/elements/ShaeLifecycleElement.d.ts +71 -0
- package/src/elements/ShaeLifecycleElement.d.ts.map +1 -0
- package/src/elements/ShaeLifecycleElement.js +83 -0
- package/src/elements/ShaeLifecycleElement.js.map +7 -0
- package/src/elements/ShaePropElement.d.ts +57 -7
- package/src/elements/ShaePropElement.d.ts.map +1 -1
- package/src/elements/ShaePropElement.js +241 -220
- package/src/elements/ShaePropElement.js.map +2 -2
- package/src/elements/ShaeWorkerElement.d.ts +49 -5
- package/src/elements/ShaeWorkerElement.d.ts.map +1 -1
- package/src/elements/ShaeWorkerElement.js +230 -74
- package/src/elements/ShaeWorkerElement.js.map +2 -2
- package/src/elements/constants.d.ts +6 -0
- package/src/elements/constants.d.ts.map +1 -1
- package/src/elements/constants.js +12 -0
- package/src/elements/constants.js.map +2 -2
- package/src/elements/deferredTeardown.d.ts +24 -0
- package/src/elements/deferredTeardown.d.ts.map +1 -0
- package/src/elements/deferredTeardown.js +30 -0
- package/src/elements/deferredTeardown.js.map +7 -0
- package/src/elements/displayContentsRule.d.ts +25 -0
- package/src/elements/displayContentsRule.d.ts.map +1 -0
- package/src/elements/displayContentsRule.js +37 -0
- package/src/elements/displayContentsRule.js.map +7 -0
- package/src/elements/events.d.ts +10 -7
- package/src/elements/events.d.ts.map +1 -1
- package/src/elements/forwardCustomEvents.d.ts +19 -0
- package/src/elements/forwardCustomEvents.d.ts.map +1 -0
- package/src/elements/forwardCustomEvents.js +47 -0
- package/src/elements/forwardCustomEvents.js.map +7 -0
- package/src/elements/hostedSlots.d.ts +36 -0
- package/src/elements/hostedSlots.d.ts.map +1 -0
- package/src/elements/hostedSlots.js +118 -0
- package/src/elements/hostedSlots.js.map +7 -0
- package/src/elements/parentRemoval.d.ts +18 -0
- package/src/elements/parentRemoval.d.ts.map +1 -0
- package/src/elements/parentRemoval.js +60 -0
- package/src/elements/parentRemoval.js.map +7 -0
- package/src/elements/propValueConverters.d.ts +3 -0
- package/src/elements/propValueConverters.d.ts.map +1 -0
- package/src/elements/propValueConverters.js +54 -0
- package/src/elements/propValueConverters.js.map +7 -0
- package/src/elements/requestEntAncestor.d.ts +32 -0
- package/src/elements/requestEntAncestor.d.ts.map +1 -0
- package/src/elements/requestEntAncestor.js +16 -0
- package/src/elements/requestEntAncestor.js.map +7 -0
- package/src/elements.js.map +1 -1
- package/src/in-the-dark/Entity.d.ts +113 -3
- package/src/in-the-dark/Entity.d.ts.map +1 -1
- package/src/in-the-dark/Entity.js +292 -63
- package/src/in-the-dark/Entity.js.map +3 -3
- package/src/in-the-dark/Kernel.d.ts +81 -17
- package/src/in-the-dark/Kernel.d.ts.map +1 -1
- package/src/in-the-dark/Kernel.js +449 -392
- package/src/in-the-dark/Kernel.js.map +3 -3
- package/src/in-the-dark/Registry.d.ts +1 -1
- package/src/in-the-dark/Registry.d.ts.map +1 -1
- package/src/in-the-dark/Registry.js +99 -26
- package/src/in-the-dark/Registry.js.map +2 -2
- package/src/in-the-dark/ShadowObject.d.ts +1 -1
- package/src/in-the-dark/ShadowObject.d.ts.map +1 -1
- package/src/in-the-dark/ShadowObject.js +3 -2
- package/src/in-the-dark/ShadowObject.js.map +2 -2
- package/src/in-the-dark/ShadowObjectCreationScope.d.ts +126 -0
- package/src/in-the-dark/ShadowObjectCreationScope.d.ts.map +1 -0
- package/src/in-the-dark/ShadowObjectCreationScope.js +596 -0
- package/src/in-the-dark/ShadowObjectCreationScope.js.map +7 -0
- package/src/in-the-dark/SignalsPath.d.ts.map +1 -1
- package/src/in-the-dark/SignalsPath.js +2 -2
- package/src/in-the-dark/SignalsPath.js.map +2 -2
- package/src/in-the-dark/events.js.map +1 -1
- package/src/in-the-dark/importModule.d.ts +7 -0
- package/src/in-the-dark/importModule.d.ts.map +1 -1
- package/src/in-the-dark/importModule.js +8 -5
- package/src/in-the-dark/importModule.js.map +2 -2
- package/src/index.d.ts +7 -1
- package/src/index.d.ts.map +1 -1
- package/src/index.js +5 -1
- package/src/index.js.map +2 -2
- package/src/shadow-objects.d.ts +2 -0
- package/src/shadow-objects.d.ts.map +1 -1
- package/src/shadow-objects.js +2 -0
- package/src/shadow-objects.js.map +2 -2
- package/src/shadow-objects.worker.js +0 -1
- package/src/shadow-objects.worker.js.map +2 -2
- package/src/shae-ent.js.map +1 -1
- package/src/shae-prop.js +2 -2
- package/src/shae-prop.js.map +2 -2
- package/src/shae-worker.js.map +1 -1
- package/src/types.d.ts +39 -8
- package/src/types.d.ts.map +1 -1
- package/src/utils/ConsoleLogger.d.ts +45 -10
- package/src/utils/ConsoleLogger.d.ts.map +1 -1
- package/src/utils/ConsoleLogger.js +54 -28
- package/src/utils/ConsoleLogger.js.map +2 -2
- package/src/utils/FrameLoop.d.ts +42 -3
- package/src/utils/FrameLoop.d.ts.map +1 -1
- package/src/utils/FrameLoop.js +71 -12
- package/src/utils/FrameLoop.js.map +2 -2
- package/src/utils/MicrotaskCollector.d.ts +45 -0
- package/src/utils/MicrotaskCollector.d.ts.map +1 -0
- package/src/utils/MicrotaskCollector.js +33 -0
- package/src/utils/MicrotaskCollector.js.map +7 -0
- package/src/utils/MicrotaskGate.d.ts +17 -0
- package/src/utils/MicrotaskGate.d.ts.map +1 -0
- package/src/utils/MicrotaskGate.js +20 -0
- package/src/utils/MicrotaskGate.js.map +7 -0
- package/src/utils/array-utils.js.map +1 -1
- package/src/utils/attr-utils.d.ts +6 -0
- package/src/utils/attr-utils.d.ts.map +1 -1
- package/src/utils/attr-utils.js +4 -2
- package/src/utils/attr-utils.js.map +2 -2
- package/src/utils/constants.js.map +1 -1
- package/src/utils/generateUUID.d.ts +12 -1
- package/src/utils/generateUUID.d.ts.map +1 -1
- package/src/utils/generateUUID.js +31 -266
- package/src/utils/generateUUID.js.map +2 -2
- package/src/utils/props-utils.d.ts +3 -2
- package/src/utils/props-utils.d.ts.map +1 -1
- package/src/utils/props-utils.js +13 -24
- package/src/utils/props-utils.js.map +2 -2
- package/src/utils/runGuarded.d.ts +27 -0
- package/src/utils/runGuarded.d.ts.map +1 -0
- package/src/utils/runGuarded.js +11 -0
- package/src/utils/runGuarded.js.map +7 -0
- package/src/utils/toMaybe.d.ts.map +1 -1
- package/src/utils/toMaybe.js.map +1 -1
- package/src/utils/toNamespace.d.ts.map +1 -1
- package/src/utils/toNamespace.js.map +1 -1
- package/src/utils/toUrlString.d.ts +12 -0
- package/src/utils/toUrlString.d.ts.map +1 -1
- package/src/utils/toUrlString.js.map +2 -2
- package/src/utils/waitForMessageOfType.d.ts +16 -1
- package/src/utils/waitForMessageOfType.d.ts.map +1 -1
- package/src/utils/waitForMessageOfType.js +28 -3
- package/src/utils/waitForMessageOfType.js.map +2 -2
- package/src/view/ComponentChanges.d.ts +91 -1
- package/src/view/ComponentChanges.d.ts.map +1 -1
- package/src/view/ComponentChanges.js +253 -69
- package/src/view/ComponentChanges.js.map +2 -2
- package/src/view/ComponentContext.d.ts +239 -7
- package/src/view/ComponentContext.d.ts.map +1 -1
- package/src/view/ComponentContext.js +648 -115
- package/src/view/ComponentContext.js.map +2 -2
- package/src/view/ComponentMemory.d.ts +3 -3
- package/src/view/ComponentMemory.d.ts.map +1 -1
- package/src/view/ComponentMemory.js +3 -1
- package/src/view/ComponentMemory.js.map +2 -2
- package/src/view/IShadowObjectEnvProxy.d.ts +33 -1
- package/src/view/IShadowObjectEnvProxy.d.ts.map +1 -1
- package/src/view/LocalShadowObjectEnv.d.ts +2 -2
- package/src/view/LocalShadowObjectEnv.d.ts.map +1 -1
- package/src/view/LocalShadowObjectEnv.js +18 -11
- package/src/view/LocalShadowObjectEnv.js.map +2 -2
- package/src/view/RemoteWorkerEnv.d.ts +129 -3
- package/src/view/RemoteWorkerEnv.d.ts.map +1 -1
- package/src/view/RemoteWorkerEnv.js +290 -60
- package/src/view/RemoteWorkerEnv.js.map +2 -2
- package/src/view/ShadowEnv.d.ts +73 -2
- package/src/view/ShadowEnv.d.ts.map +1 -1
- package/src/view/ShadowEnv.js +301 -64
- package/src/view/ShadowEnv.js.map +2 -2
- package/src/view/ViewComponent.d.ts +93 -8
- package/src/view/ViewComponent.d.ts.map +1 -1
- package/src/view/ViewComponent.js +148 -28
- package/src/view/ViewComponent.js.map +2 -2
- package/src/view/cloneChangeTrail.js.map +2 -2
- package/src/worker/MessageRouter.d.ts +14 -0
- package/src/worker/MessageRouter.d.ts.map +1 -1
- package/src/worker/MessageRouter.js +80 -18
- package/src/worker/MessageRouter.js.map +2 -2
- package/src/worker/WorkerRuntime.d.ts +22 -1
- package/src/worker/WorkerRuntime.d.ts.map +1 -1
- package/src/worker/WorkerRuntime.js +60 -8
- package/src/worker/WorkerRuntime.js.map +2 -2
package/README.md
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@spearwolf/shadow-objects)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
*a reactive entity-component framework that feels at home in the shadows*
|
|
6
|
+
|
|
7
|
+
Shadow Objects is an Entity Component System (ECS) for the browser platform. It separates application logic from its presentation, and not just logically: the logic runs in a Shadow Environment, which lives either on the main thread (`LocalShadowObjectEnv`) or inside a web worker (`RemoteWorkerEnv`). Your Shadow Object code is identical in both cases. Only the proxy gets swapped.
|
|
8
|
+
|
|
9
|
+
Entities are lightweight nodes in a tree. Shadow Objects are ECS components that attach behavior to them. The View is authoritative for structure, not for behavior: it decides which entities exist and which properties they carry, while the Registry decides which Shadow Objects land on them.
|
|
6
10
|
|
|
7
11
|
## Installation
|
|
8
12
|
|
|
@@ -10,33 +14,109 @@ Shadow Objects is a reactive ECS (Entity Component System) library that decouple
|
|
|
10
14
|
npm install @spearwolf/shadow-objects
|
|
11
15
|
```
|
|
12
16
|
|
|
17
|
+
Exactly one copy of `@spearwolf/signalize` and one of `@spearwolf/eventize` may stand in the dependency tree. Both key their marker slots with realm-wide symbols, so two majors of either share one slot per object and fail at the boundary between them. You do not have to install signalize for this: the reactivity primitives reach a Shadow Object as arguments — `createSignal`, `createEffect` and `createMemo` come in through the creation API, and nothing here asks you to import them yourself. eventize is the other way round: its surface is reached through that package's free functions — `on`, `once`, `off`, `emit` — imported from it directly, so code that imports those functions, in the view or in a Shadow Object, needs eventize in your own manifest, at the range this package declares. Whoever does put signalize next to this package takes the range this package declares, `^1.0.0`. The `latest` tag of signalize sits inside that range today, so a plain `npm install @spearwolf/signalize` currently lands on the one copy — and stops doing so the day a signalize 2.0 takes the tag over, without anything in your manifest changing. `npm ls @spearwolf/signalize` — or `pnpm why @spearwolf/signalize` — says whether it stayed at one.
|
|
18
|
+
|
|
13
19
|
## Quick Example
|
|
14
20
|
|
|
15
|
-
```
|
|
16
|
-
|
|
21
|
+
```html
|
|
22
|
+
<!-- index.html -- the view layer -->
|
|
23
|
+
<script type="module">
|
|
24
|
+
import '@spearwolf/shadow-objects/elements.js';
|
|
25
|
+
</script>
|
|
17
26
|
|
|
18
|
-
|
|
19
|
-
function MyComponent({ entity, useSignals }) {
|
|
20
|
-
const [count, setCount] = useSignals('count', 0);
|
|
27
|
+
<shae-worker src="./my-logic.js"></shae-worker>
|
|
21
28
|
|
|
22
|
-
|
|
29
|
+
<shae-ent token="my-component">
|
|
30
|
+
<shae-prop name="step" value="1" type="int"></shae-prop>
|
|
31
|
+
</shae-ent>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
// my-logic.js -- runs in the shadow environment
|
|
36
|
+
// A shadow object is an ECS component: the body is the setup phase, after that it only reacts.
|
|
37
|
+
// It runs once, for as long as this shadow object stays on the entity.
|
|
38
|
+
function MyComponent({useProperty, createSignal, onViewEvent, dispatchMessageToView}) {
|
|
39
|
+
const step = useProperty('step');
|
|
40
|
+
const count = createSignal(0);
|
|
23
41
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
42
|
+
onViewEvent((type) => {
|
|
43
|
+
if (type === 'increment') {
|
|
44
|
+
count.set(count.value + (step() ?? 1));
|
|
45
|
+
dispatchMessageToView('count-changed', {value: count.value});
|
|
46
|
+
}
|
|
47
|
+
});
|
|
27
48
|
}
|
|
28
49
|
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
|
|
50
|
+
// The module exports the registry (component manifest) under the name `shadowObjects` --
|
|
51
|
+
// the loader reads exactly that named export. A view node with the token 'my-component'
|
|
52
|
+
// gets this shadow object.
|
|
53
|
+
export const shadowObjects = {
|
|
54
|
+
define: {
|
|
55
|
+
'my-component': MyComponent,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Need to register a shadow object at runtime instead? `@spearwolf/shadow-objects/shadow-objects.js` exports a helper object of the same name for that, with a `define(token, constructor)` method. It is a separate thing from the registry a module exports: the helper writes into a `Registry`, the export declares one.
|
|
61
|
+
|
|
62
|
+
`@spearwolf/shadow-objects/FrameLoop.js` is the same kind of subpath: it carries the `FrameLoop` class without the view layer, for code that runs inside a worker.
|
|
63
|
+
|
|
64
|
+
## Element Lifecycle
|
|
65
|
+
|
|
66
|
+
The custom elements clean up after themselves — no teardown call for you to make, because a
|
|
67
|
+
framework re-rendering a subtree would not make one either.
|
|
68
|
+
|
|
69
|
+
All three elements take their subscriptions up when they first connect, not when they are built —
|
|
70
|
+
an element created with `document.createElement()` and never put into a document holds no effect and
|
|
71
|
+
no event subscription, so nothing on the module level points at it and it can be collected. A
|
|
72
|
+
`<shae-worker>` does own its `ShadowEnv` from the moment it is built; what it does not own is
|
|
73
|
+
anything that listens.
|
|
74
|
+
|
|
75
|
+
`<shae-ent>` and `<shae-prop>` release their subscriptions again one microtask after they leave the
|
|
76
|
+
document, which makes them collectable once more. A move within a single task never reaches that
|
|
77
|
+
point, so a re-render costs nothing. And the release is reversible: an element put back into the
|
|
78
|
+
document takes its subscriptions up again and carries the same `ViewComponent` and the same uuid it
|
|
79
|
+
left with. `destroy()` does it by hand, `isDestroyed` reads the current state.
|
|
80
|
+
|
|
81
|
+
What a released element is written in the meantime is where the two part company. `<shae-ent>` keeps
|
|
82
|
+
it — `token`, `ns` and `forward-custom-events` stand in the signals and are written out to the
|
|
83
|
+
attributes as the element reconnects. `<shae-prop>` re-reads its attributes and looks its host up
|
|
84
|
+
again on every connect, released or not, so a `prop.value` written in that window is replaced rather
|
|
85
|
+
than applied.
|
|
86
|
+
|
|
87
|
+
`<shae-worker>` uses the same two names for something stronger. Its teardown takes the Shadow
|
|
88
|
+
Environment with it, and an environment cannot be rebuilt — a released `<shae-worker>` stays
|
|
89
|
+
released, and a new one is the way back. See the
|
|
90
|
+
[API Reference](https://github.com/spearwolf/shadow-objects/blob/main/packages/shadow-objects/docs/api-reference.md#web-components) for all three in detail.
|
|
91
|
+
|
|
92
|
+
## The Five Domains
|
|
93
|
+
|
|
94
|
+
| # | Domain | Responsibility | Where it lives |
|
|
95
|
+
|---|---|---|---|
|
|
96
|
+
| 1 | **View** | Structure, properties, input | always the main thread |
|
|
97
|
+
| 2 | **Environment** | Place of execution, transport | main thread or worker |
|
|
98
|
+
| 3 | **Kernel** | Lifecycle, entity tree | inside the environment |
|
|
99
|
+
| 4 | **Composition** | Registry, token, routing | inside the environment |
|
|
100
|
+
| 5 | **Shadow Object** | Application logic, reactivity, communication | inside the environment |
|
|
101
|
+
|
|
102
|
+
Each domain, what it owns, what it must not touch, and the invariants that hold the whole thing together are written up in the [project README](https://github.com/spearwolf/shadow-objects#the-five-domains) and in [Concepts](https://github.com/spearwolf/shadow-objects/blob/main/packages/shadow-objects/docs/concepts.md).
|
|
103
|
+
|
|
104
|
+
## Security
|
|
105
|
+
|
|
106
|
+
The `src` of a `<shae-worker>` is a module URL, resolved against the document and run with a dynamic `import()`; the loaded module acts as the application's origin. Set it only from values the application trusts, and constrain it in production with a Content Security Policy delivered on every response of the origin — a policy scoped to only the document's response, or set through `<meta>`, never reaches a worker script loaded from a network URL.
|
|
107
|
+
|
|
32
108
|
```
|
|
109
|
+
Content-Security-Policy: script-src 'self'; worker-src 'self' blob:
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Full detail — why `worker-src` needs `blob:` for the `@spearwolf/shadow-objects/bundle.js` entry point, and which response has to carry the header for every other one — is in the [API Reference](https://github.com/spearwolf/shadow-objects/blob/main/packages/shadow-objects/docs/api-reference.md#security).
|
|
33
113
|
|
|
34
114
|
## Documentation
|
|
35
115
|
|
|
36
|
-
- [Overview](
|
|
37
|
-
- [Getting Started](
|
|
38
|
-
- [Concepts](
|
|
39
|
-
- [Guides](
|
|
40
|
-
- [API Reference](
|
|
41
|
-
- [Cheat Sheet](
|
|
42
|
-
- [Best Practices](
|
|
116
|
+
- [Overview](https://github.com/spearwolf/shadow-objects/blob/main/packages/shadow-objects/docs/README.md)
|
|
117
|
+
- [Getting Started](https://github.com/spearwolf/shadow-objects/blob/main/packages/shadow-objects/docs/getting-started.md)
|
|
118
|
+
- [Concepts](https://github.com/spearwolf/shadow-objects/blob/main/packages/shadow-objects/docs/concepts.md)
|
|
119
|
+
- [Guides](https://github.com/spearwolf/shadow-objects/blob/main/packages/shadow-objects/docs/guides.md)
|
|
120
|
+
- [API Reference](https://github.com/spearwolf/shadow-objects/blob/main/packages/shadow-objects/docs/api-reference.md)
|
|
121
|
+
- [Cheat Sheet](https://github.com/spearwolf/shadow-objects/blob/main/packages/shadow-objects/docs/cheat-sheet.md)
|
|
122
|
+
- [Best Practices](https://github.com/spearwolf/shadow-objects/blob/main/packages/shadow-objects/docs/best-practices.md)
|