@async/framework 0.9.0 → 0.10.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 +12 -0
- package/README.md +115 -0
- package/browser.d.ts +69 -18
- package/browser.js +733 -71
- package/browser.min.js +1 -1
- package/browser.ts +733 -71
- package/browser.umd.js +733 -71
- package/browser.umd.min.js +1 -1
- package/package.json +1 -1
- package/server.d.ts +69 -18
- package/src/app.js +314 -46
- package/src/browser.js +2 -0
- package/src/component.js +19 -2
- package/src/elements.js +63 -0
- package/src/handlers.js +19 -2
- package/src/index.js +2 -0
- package/src/lazy-registry.js +204 -0
- package/src/loader.js +23 -5
- package/src/partials.js +19 -2
- package/src/registry-store.js +15 -9
- package/src/signals.js +46 -4
package/src/signals.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { asyncSignal as createAsyncSignal, isAsyncSignal } from "./async-signal.js";
|
|
2
2
|
import { attachRegistryInspection, createRegistryStore } from "./registry-store.js";
|
|
3
|
+
import { createLazyRegistry, isLazyDescriptor } from "./lazy-registry.js";
|
|
3
4
|
|
|
4
5
|
const signalKind = Symbol.for("@async/framework.signal");
|
|
5
6
|
const computedKind = Symbol.for("@async/framework.computed");
|
|
@@ -122,6 +123,8 @@ export function createSignalRegistry(initialMap = {}, options = {}) {
|
|
|
122
123
|
const registryStore = options.registry ?? createRegistryStore();
|
|
123
124
|
const type = options.type ?? "signal";
|
|
124
125
|
const entries = registryStore._map(type);
|
|
126
|
+
const asyncDescriptors = registryStore._map("asyncSignal");
|
|
127
|
+
const lazyRegistry = options.lazyRegistry ?? createLazyRegistry(options);
|
|
125
128
|
const registryCleanups = new Map();
|
|
126
129
|
const runtimeContext = {};
|
|
127
130
|
const boundEntries = new Set();
|
|
@@ -162,6 +165,7 @@ export function createSignalRegistry(initialMap = {}, options = {}) {
|
|
|
162
165
|
|
|
163
166
|
ensure(id, initial) {
|
|
164
167
|
assertId(id);
|
|
168
|
+
materializeAsyncSignal(id);
|
|
165
169
|
if (!entries.has(id)) {
|
|
166
170
|
registry.register(id, createSignal(initial));
|
|
167
171
|
}
|
|
@@ -169,18 +173,18 @@ export function createSignalRegistry(initialMap = {}, options = {}) {
|
|
|
169
173
|
},
|
|
170
174
|
|
|
171
175
|
has(id) {
|
|
172
|
-
return entries.has(id);
|
|
176
|
+
return entries.has(id) || asyncDescriptors.has(id);
|
|
173
177
|
},
|
|
174
178
|
|
|
175
179
|
get(path) {
|
|
176
|
-
const parsed =
|
|
180
|
+
const parsed = parseRegistryPath(path);
|
|
177
181
|
track(parsed.path);
|
|
178
182
|
const entry = requireEntry(entries, parsed.id);
|
|
179
183
|
return readEntry(entry, parsed.parts);
|
|
180
184
|
},
|
|
181
185
|
|
|
182
186
|
set(path, value) {
|
|
183
|
-
const parsed =
|
|
187
|
+
const parsed = parseRegistryPath(path);
|
|
184
188
|
const entry = requireEntry(entries, parsed.id);
|
|
185
189
|
if (parsed.parts.length === 0) {
|
|
186
190
|
return entry.set(value);
|
|
@@ -199,6 +203,7 @@ export function createSignalRegistry(initialMap = {}, options = {}) {
|
|
|
199
203
|
|
|
200
204
|
ref(id) {
|
|
201
205
|
assertId(id);
|
|
206
|
+
materializeAsyncSignal(id);
|
|
202
207
|
return createRef(registry, id);
|
|
203
208
|
},
|
|
204
209
|
|
|
@@ -206,7 +211,7 @@ export function createSignalRegistry(initialMap = {}, options = {}) {
|
|
|
206
211
|
if (typeof fn !== "function") {
|
|
207
212
|
throw new TypeError("subscribe(path, fn) requires a function.");
|
|
208
213
|
}
|
|
209
|
-
const parsed =
|
|
214
|
+
const parsed = parseRegistryPath(path);
|
|
210
215
|
const entry = requireEntry(entries, parsed.id);
|
|
211
216
|
const subscriptionId = ++subscriptionCounter;
|
|
212
217
|
return entry.subscribe(() => {
|
|
@@ -312,6 +317,7 @@ export function createSignalRegistry(initialMap = {}, options = {}) {
|
|
|
312
317
|
},
|
|
313
318
|
|
|
314
319
|
_entry(id) {
|
|
320
|
+
materializeAsyncSignal(id);
|
|
315
321
|
return requireEntry(entries, id);
|
|
316
322
|
},
|
|
317
323
|
|
|
@@ -351,6 +357,42 @@ export function createSignalRegistry(initialMap = {}, options = {}) {
|
|
|
351
357
|
}
|
|
352
358
|
}
|
|
353
359
|
|
|
360
|
+
function parseRegistryPath(path) {
|
|
361
|
+
if (typeof path !== "string" || path.length === 0) {
|
|
362
|
+
throw new TypeError("Signal path must be a non-empty string.");
|
|
363
|
+
}
|
|
364
|
+
const segments = path.split(".");
|
|
365
|
+
for (let end = segments.length; end > 0; end -= 1) {
|
|
366
|
+
const id = segments.slice(0, end).join(".");
|
|
367
|
+
if (entries.has(id) || asyncDescriptors.has(id)) {
|
|
368
|
+
materializeAsyncSignal(id);
|
|
369
|
+
return { id, parts: segments.slice(end), path };
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
const [id, ...parts] = segments;
|
|
373
|
+
return { id, parts, path };
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function materializeAsyncSignal(id) {
|
|
377
|
+
if (entries.has(id) || !asyncDescriptors.has(id)) {
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
const descriptor = asyncDescriptors.get(id);
|
|
381
|
+
if (!isLazyDescriptor(descriptor) && typeof descriptor !== "function") {
|
|
382
|
+
throw new TypeError(`Async signal "${id}" must be a function or lazy descriptor.`);
|
|
383
|
+
}
|
|
384
|
+
const loader = async function runLazyAsyncSignal(...args) {
|
|
385
|
+
const resolved = await lazyRegistry.resolve("asyncSignal", id, descriptor);
|
|
386
|
+
if (typeof resolved !== "function") {
|
|
387
|
+
throw new TypeError(`Async signal "${id}" did not resolve to a function.`);
|
|
388
|
+
}
|
|
389
|
+
return resolved.apply(this, args);
|
|
390
|
+
};
|
|
391
|
+
const entry = createAsyncSignal(id, loader);
|
|
392
|
+
entries.set(id, entry);
|
|
393
|
+
bindEntry(id, entry);
|
|
394
|
+
}
|
|
395
|
+
|
|
354
396
|
function scheduleCallback(fn, options = {}) {
|
|
355
397
|
const scheduler = options.scheduler;
|
|
356
398
|
if (!scheduler || options.phase === "sync") {
|