@directive-run/core 0.1.1 → 0.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 +153 -9
- package/dist/adapter-utils.d.cts +1 -1
- package/dist/adapter-utils.d.ts +1 -1
- package/dist/index.cjs +20 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -35
- package/dist/index.d.ts +9 -35
- package/dist/index.js +20 -20
- package/dist/index.js.map +1 -1
- package/dist/migration.cjs +12 -12
- package/dist/migration.cjs.map +1 -1
- package/dist/migration.js +12 -12
- package/dist/migration.js.map +1 -1
- package/dist/plugins/index.d.cts +1 -1
- package/dist/plugins/index.d.ts +1 -1
- package/dist/{plugins-CcwEXXMS.d.cts → plugins-KKRG7lDP.d.cts} +11 -1
- package/dist/{plugins-CcwEXXMS.d.ts → plugins-KKRG7lDP.d.ts} +11 -1
- package/dist/testing.cjs +3 -3
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +3 -3
- package/dist/testing.js.map +1 -1
- package/dist/worker.cjs +3 -3
- package/dist/worker.cjs.map +1 -1
- package/dist/worker.d.cts +1 -1
- package/dist/worker.d.ts +1 -1
- package/dist/worker.js +3 -3
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
1
|
# @directive-run/core
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@directive-run/core)
|
|
4
|
+
[](https://www.npmjs.com/package/@directive-run/core)
|
|
5
|
+
[](https://bundlephobia.com/package/@directive-run/core)
|
|
6
|
+
[](https://github.com/directive-run/directive/actions)
|
|
7
|
+
[](https://github.com/directive-run/directive/blob/main/LICENSE)
|
|
8
|
+
|
|
3
9
|
Constraint-driven runtime for TypeScript. Declare requirements, let the runtime resolve them.
|
|
4
10
|
|
|
11
|
+
- **Auto-tracking derivations** – computed values that track their own dependencies, no manual dep arrays
|
|
12
|
+
- **Typed constraint/resolver cycle** – constraints declare what must be true, resolvers make it true
|
|
13
|
+
- **Events** – typed event handlers with payloads for imperative actions
|
|
14
|
+
- **Plugin architecture** – logging, devtools, persistence, and custom lifecycle hooks
|
|
15
|
+
- **Framework adapters** – first-class bindings for React, Vue, Svelte, Solid, and Lit
|
|
16
|
+
|
|
5
17
|
## Install
|
|
6
18
|
|
|
7
19
|
```bash
|
|
8
20
|
npm install @directive-run/core
|
|
9
21
|
```
|
|
10
22
|
|
|
11
|
-
##
|
|
23
|
+
## Quick Start
|
|
12
24
|
|
|
13
25
|
```typescript
|
|
14
26
|
import { createModule, createSystem, t } from "@directive-run/core";
|
|
@@ -17,19 +29,25 @@ const counter = createModule("counter", {
|
|
|
17
29
|
schema: {
|
|
18
30
|
facts: { count: t.number() },
|
|
19
31
|
derivations: { doubled: t.number() },
|
|
20
|
-
events: { increment: {} },
|
|
32
|
+
events: { increment: {}, reset: {} },
|
|
21
33
|
requirements: {},
|
|
22
34
|
},
|
|
35
|
+
|
|
23
36
|
init: (facts) => {
|
|
24
37
|
facts.count = 0;
|
|
25
38
|
},
|
|
39
|
+
|
|
26
40
|
derive: {
|
|
27
41
|
doubled: (facts) => facts.count * 2,
|
|
28
42
|
},
|
|
29
|
-
|
|
43
|
+
|
|
44
|
+
events: {
|
|
30
45
|
increment: (facts) => {
|
|
31
46
|
facts.count += 1;
|
|
32
47
|
},
|
|
48
|
+
reset: (facts) => {
|
|
49
|
+
facts.count = 0;
|
|
50
|
+
},
|
|
33
51
|
},
|
|
34
52
|
});
|
|
35
53
|
|
|
@@ -37,21 +55,147 @@ const system = createSystem({ module: counter });
|
|
|
37
55
|
system.start();
|
|
38
56
|
|
|
39
57
|
system.events.increment();
|
|
40
|
-
console.log(system.facts.count);
|
|
58
|
+
console.log(system.facts.count); // 1
|
|
41
59
|
console.log(system.read("doubled")); // 2
|
|
42
60
|
```
|
|
43
61
|
|
|
62
|
+
## Derived State
|
|
63
|
+
|
|
64
|
+
Derivations auto-track which facts they read. No dependency arrays, no manual subscriptions. Derivations can depend on other derivations for composition:
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
const app = createModule("app", {
|
|
68
|
+
schema: {
|
|
69
|
+
facts: { items: t.array<string>(), filter: t.string() },
|
|
70
|
+
derivations: {
|
|
71
|
+
filtered: t.array<string>(),
|
|
72
|
+
count: t.number(),
|
|
73
|
+
summary: t.string(),
|
|
74
|
+
},
|
|
75
|
+
events: {},
|
|
76
|
+
requirements: {},
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
init: (facts) => {
|
|
80
|
+
facts.items = ["apple", "banana", "avocado"];
|
|
81
|
+
facts.filter = "a";
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
derive: {
|
|
85
|
+
filtered: (facts) => facts.items.filter((i) => i.startsWith(facts.filter)),
|
|
86
|
+
count: (_facts, derive) => derive.filtered.length,
|
|
87
|
+
summary: (_facts, derive) => `${derive.count} items match`,
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Constraints and Resolvers
|
|
93
|
+
|
|
94
|
+
The constraint/resolver cycle is the core of Directive. Constraints declare _what_ must be true. Resolvers declare _how_ to make it true. The runtime connects them automatically.
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import { createModule, createSystem, t } from "@directive-run/core";
|
|
98
|
+
|
|
99
|
+
const userModule = createModule("user", {
|
|
100
|
+
schema: {
|
|
101
|
+
facts: {
|
|
102
|
+
userId: t.string().nullable(),
|
|
103
|
+
profile: t.object<{ name: string }>().nullable(),
|
|
104
|
+
},
|
|
105
|
+
derivations: {},
|
|
106
|
+
events: { login: { userId: t.string() } },
|
|
107
|
+
requirements: { FETCH_PROFILE: { userId: t.string() } },
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
init: (facts) => {
|
|
111
|
+
facts.userId = null;
|
|
112
|
+
facts.profile = null;
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
events: {
|
|
116
|
+
login: (facts, payload) => {
|
|
117
|
+
facts.userId = payload.userId;
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
constraints: {
|
|
122
|
+
needsProfile: {
|
|
123
|
+
when: (facts) => facts.userId !== null && facts.profile === null,
|
|
124
|
+
require: (facts) => ({ type: "FETCH_PROFILE", userId: facts.userId! }),
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
resolvers: {
|
|
129
|
+
fetchProfile: {
|
|
130
|
+
requirement: "FETCH_PROFILE",
|
|
131
|
+
retry: { attempts: 3, backoff: "exponential" },
|
|
132
|
+
resolve: async (req, context) => {
|
|
133
|
+
const res = await fetch(`/api/users/${req.userId}`);
|
|
134
|
+
context.facts.profile = await res.json();
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
const system = createSystem({ module: userModule });
|
|
141
|
+
system.start();
|
|
142
|
+
|
|
143
|
+
// Dispatching login sets userId, which triggers the constraint,
|
|
144
|
+
// which emits the requirement, which the resolver fulfills automatically.
|
|
145
|
+
system.events.login({ userId: "u-123" });
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Events
|
|
149
|
+
|
|
150
|
+
Events provide typed imperative actions with payloads. Define them in your schema and handle them with `events`:
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
events: {
|
|
154
|
+
addItem: (facts, payload: { name: string; price: number }) => {
|
|
155
|
+
facts.items = [...facts.items, { name: payload.name, price: payload.price }];
|
|
156
|
+
},
|
|
157
|
+
removeItem: (facts, payload: { id: string }) => {
|
|
158
|
+
facts.items = facts.items.filter((i) => i.id !== payload.id);
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
|
|
162
|
+
// Typed and autocompleted:
|
|
163
|
+
system.events.addItem({ name: "Widget", price: 9.99 });
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Framework Adapters
|
|
167
|
+
|
|
168
|
+
| Package | Framework | Reactivity Model |
|
|
169
|
+
|---------|-----------|-----------------|
|
|
170
|
+
| [`@directive-run/react`](https://www.npmjs.com/package/@directive-run/react) | React 18+ | `useSyncExternalStore` hooks |
|
|
171
|
+
| [`@directive-run/vue`](https://www.npmjs.com/package/@directive-run/vue) | Vue 3+ | `Ref` / `ShallowRef` composables |
|
|
172
|
+
| [`@directive-run/svelte`](https://www.npmjs.com/package/@directive-run/svelte) | Svelte 4+ | `Readable` stores |
|
|
173
|
+
| [`@directive-run/solid`](https://www.npmjs.com/package/@directive-run/solid) | Solid.js 1+ | `Accessor` signals |
|
|
174
|
+
| [`@directive-run/lit`](https://www.npmjs.com/package/@directive-run/lit) | Lit 3+ | `ReactiveController` classes |
|
|
175
|
+
|
|
44
176
|
## Subpath Exports
|
|
45
177
|
|
|
46
178
|
| Import | Purpose |
|
|
47
179
|
|--------|---------|
|
|
48
|
-
| `@directive-run/core` | Core runtime
|
|
49
|
-
| `@directive-run/core/plugins` | Logging, devtools, persistence
|
|
50
|
-
| `@directive-run/core/testing` | Mock resolvers, fake timers,
|
|
180
|
+
| `@directive-run/core` | Core runtime – modules, systems, schema types |
|
|
181
|
+
| `@directive-run/core/plugins` | Logging, devtools, persistence, observability, circuit breaker |
|
|
182
|
+
| `@directive-run/core/testing` | Mock resolvers, fake timers, assertion helpers |
|
|
51
183
|
| `@directive-run/core/migration` | Redux/Zustand/XState migration helpers |
|
|
184
|
+
| `@directive-run/core/worker` | Web Worker support |
|
|
185
|
+
|
|
186
|
+
## Why Directive?
|
|
187
|
+
|
|
188
|
+
- **Declarative over imperative** – describe what your system needs, not how to wire it up. Constraints and resolvers replace manual data-fetching orchestration.
|
|
189
|
+
- **Auto-tracking over manual subscriptions** – derivations detect their own dependencies at runtime. No selector functions, no dependency arrays, no stale closures.
|
|
190
|
+
- **Constraint-driven over event-driven** – instead of chaining events to coordinate async work, declare constraints that the runtime satisfies automatically with retry, batching, and error boundaries.
|
|
191
|
+
- **Framework-agnostic core** – one state layer, five framework adapters. Move between React, Vue, Svelte, Solid, and Lit without rewriting your state logic.
|
|
192
|
+
|
|
193
|
+
## Documentation
|
|
194
|
+
|
|
195
|
+
- [Getting Started](https://directive.run/docs/getting-started)
|
|
196
|
+
- [API Reference](https://directive.run/docs/api)
|
|
197
|
+
- [GitHub](https://github.com/directive-run/directive)
|
|
52
198
|
|
|
53
199
|
## License
|
|
54
200
|
|
|
55
201
|
MIT
|
|
56
|
-
|
|
57
|
-
[Full documentation](https://directive.run/docs)
|
package/dist/adapter-utils.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as Requirement, P as Plugin, F as Facts, S as Schema, Y as TimeTravelAPI, aE as SystemInspection, aH as TimeTravelState } from './plugins-
|
|
1
|
+
import { R as Requirement, P as Plugin, F as Facts, S as Schema, Y as TimeTravelAPI, aE as SystemInspection, aH as TimeTravelState } from './plugins-KKRG7lDP.cjs';
|
|
2
2
|
export { s as shallowEqual } from './utils-4JrY5fk9.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
package/dist/adapter-utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as Requirement, P as Plugin, F as Facts, S as Schema, Y as TimeTravelAPI, aE as SystemInspection, aH as TimeTravelState } from './plugins-
|
|
1
|
+
import { R as Requirement, P as Plugin, F as Facts, S as Schema, Y as TimeTravelAPI, aE as SystemInspection, aH as TimeTravelState } from './plugins-KKRG7lDP.js';
|
|
2
2
|
export { s as shallowEqual } from './utils-4JrY5fk9.js';
|
|
3
3
|
|
|
4
4
|
/**
|