@async/framework 0.10.1 → 0.11.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 +36 -0
- package/README.md +23 -7
- package/browser.d.ts +4 -7
- package/browser.js +143 -116
- package/browser.min.js +1 -1
- package/browser.ts +143 -116
- package/browser.umd.js +143 -116
- package/browser.umd.min.js +1 -1
- package/{server.d.ts → framework.d.ts} +4 -7
- package/framework.ts +5946 -0
- package/package.json +25 -17
- package/server.js +5945 -0
- package/examples/cache/index.html +0 -16
- package/examples/cache/main.js +0 -47
- package/examples/components/index.html +0 -11
- package/examples/components/main.js +0 -26
- package/examples/counter/index.html +0 -15
- package/examples/counter/main.js +0 -17
- package/examples/partials/index.html +0 -15
- package/examples/partials/main.js +0 -43
- package/examples/product/index.html +0 -32
- package/examples/product/main.js +0 -24
- package/examples/router/index.html +0 -18
- package/examples/router/main.js +0 -52
- package/examples/server-call/index.html +0 -21
- package/examples/server-call/main.js +0 -22
- package/examples/ssr/index.html +0 -12
- package/examples/ssr/main.js +0 -89
- package/examples/streaming/index.html +0 -16
- package/examples/streaming/main.js +0 -30
- package/src/app.js +0 -802
- package/src/async-signal.js +0 -277
- package/src/attributes.js +0 -52
- package/src/boundary-receiver.js +0 -302
- package/src/browser.js +0 -18
- package/src/cache.js +0 -189
- package/src/component.js +0 -373
- package/src/delay.js +0 -30
- package/src/elements.js +0 -63
- package/src/handlers.js +0 -219
- package/src/html.js +0 -158
- package/src/index.js +0 -20
- package/src/lazy-registry.js +0 -204
- package/src/loader.js +0 -765
- package/src/partials.js +0 -133
- package/src/registry-store.js +0 -267
- package/src/request-context.js +0 -40
- package/src/router.js +0 -571
- package/src/scheduler.js +0 -300
- package/src/server-entry.js +0 -20
- package/src/server-registry.js +0 -97
- package/src/server.js +0 -357
- package/src/signals.js +0 -592
package/src/partials.js
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import { isTemplateResult, renderTemplate } from "./html.js";
|
|
2
|
-
import { attachRegistryInspection, createRegistryStore } from "./registry-store.js";
|
|
3
|
-
import { createLazyRegistry, isLazyDescriptor } from "./lazy-registry.js";
|
|
4
|
-
|
|
5
|
-
export function createPartialRegistry(initialMap = {}, options = {}) {
|
|
6
|
-
const registryStore = options.registry ?? createRegistryStore();
|
|
7
|
-
const type = options.type ?? "partial";
|
|
8
|
-
const entries = registryStore._map(type);
|
|
9
|
-
const lazyRegistry = options.lazyRegistry ?? createLazyRegistry(options);
|
|
10
|
-
const lazyPartials = new Map();
|
|
11
|
-
|
|
12
|
-
const registry = attachRegistryInspection({
|
|
13
|
-
register(id, fn) {
|
|
14
|
-
assertId(id);
|
|
15
|
-
if (typeof fn !== "function" && !isLazyDescriptor(fn)) {
|
|
16
|
-
throw new TypeError(`Partial "${id}" must be a function.`);
|
|
17
|
-
}
|
|
18
|
-
if (entries.has(id)) {
|
|
19
|
-
throw new Error(`Partial "${id}" is already registered.`);
|
|
20
|
-
}
|
|
21
|
-
entries.set(id, fn);
|
|
22
|
-
return id;
|
|
23
|
-
},
|
|
24
|
-
|
|
25
|
-
registerMany(map) {
|
|
26
|
-
for (const [id, fn] of Object.entries(map ?? {})) {
|
|
27
|
-
registry.register(id, fn);
|
|
28
|
-
}
|
|
29
|
-
return registry;
|
|
30
|
-
},
|
|
31
|
-
|
|
32
|
-
unregister(id) {
|
|
33
|
-
assertId(id);
|
|
34
|
-
lazyPartials.delete(id);
|
|
35
|
-
return entries.delete(id);
|
|
36
|
-
},
|
|
37
|
-
|
|
38
|
-
resolve(id) {
|
|
39
|
-
assertId(id);
|
|
40
|
-
const partial = entries.get(id);
|
|
41
|
-
if (!isLazyDescriptor(partial)) {
|
|
42
|
-
return partial;
|
|
43
|
-
}
|
|
44
|
-
if (!lazyPartials.has(id)) {
|
|
45
|
-
lazyPartials.set(id, async function runLazyPartial(...args) {
|
|
46
|
-
const resolved = await lazyRegistry.resolve(type, id, partial);
|
|
47
|
-
if (typeof resolved !== "function") {
|
|
48
|
-
throw new TypeError(`Partial "${id}" did not resolve to a function.`);
|
|
49
|
-
}
|
|
50
|
-
return resolved.apply(this, args);
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
return lazyPartials.get(id);
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
async render(id, props = {}, context = {}) {
|
|
57
|
-
assertId(id);
|
|
58
|
-
const fn = registry.resolve(id);
|
|
59
|
-
if (!fn) {
|
|
60
|
-
throw new Error(`Partial "${id}" is not registered.`);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const partialContext = {
|
|
64
|
-
...context,
|
|
65
|
-
id,
|
|
66
|
-
props,
|
|
67
|
-
cache: context.cache,
|
|
68
|
-
partials: registry
|
|
69
|
-
};
|
|
70
|
-
const result = await fn.call(partialContext, props);
|
|
71
|
-
return normalizePartialResult(result, partialContext);
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
_adoptMany() {
|
|
75
|
-
return registry;
|
|
76
|
-
}
|
|
77
|
-
}, registryStore, type);
|
|
78
|
-
|
|
79
|
-
registry.registerMany(initialMap);
|
|
80
|
-
return registry;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function normalizePartialResult(result, context = {}) {
|
|
84
|
-
if (isPartialEnvelope(result)) {
|
|
85
|
-
return {
|
|
86
|
-
...result,
|
|
87
|
-
html: Object.hasOwn(result, "html") ? renderPartialValue(result.html, context) : result.html
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return { html: renderPartialValue(result, context) };
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function renderPartialValue(value, context) {
|
|
95
|
-
if (value?.nodeType) {
|
|
96
|
-
return value;
|
|
97
|
-
}
|
|
98
|
-
if (typeof value === "string") {
|
|
99
|
-
return value;
|
|
100
|
-
}
|
|
101
|
-
if (isTemplateResult(value)) {
|
|
102
|
-
return renderTemplate(value, templateRenderOptions(context));
|
|
103
|
-
}
|
|
104
|
-
return renderTemplate(value, templateRenderOptions(context));
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function templateRenderOptions(context) {
|
|
108
|
-
return {
|
|
109
|
-
attributes: context.loader?.attributes,
|
|
110
|
-
signals: context.signals,
|
|
111
|
-
bind: context.loader?._registerBinding?.bind(context.loader)
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function isPartialEnvelope(value) {
|
|
116
|
-
return Boolean(
|
|
117
|
-
value &&
|
|
118
|
-
typeof value === "object" &&
|
|
119
|
-
!Array.isArray(value) &&
|
|
120
|
-
(Object.hasOwn(value, "html") ||
|
|
121
|
-
Object.hasOwn(value, "signals") ||
|
|
122
|
-
Object.hasOwn(value, "boundary") ||
|
|
123
|
-
Object.hasOwn(value, "redirect") ||
|
|
124
|
-
Object.hasOwn(value, "status") ||
|
|
125
|
-
Object.hasOwn(value, "cache"))
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function assertId(id) {
|
|
130
|
-
if (typeof id !== "string" || id.length === 0) {
|
|
131
|
-
throw new TypeError("Partial id must be a non-empty string.");
|
|
132
|
-
}
|
|
133
|
-
}
|
package/src/registry-store.js
DELETED
|
@@ -1,267 +0,0 @@
|
|
|
1
|
-
import { publicRegistryValue } from "./lazy-registry.js";
|
|
2
|
-
|
|
3
|
-
const declarationTypes = new Set(["signal", "handler", "server", "partial", "route", "component", "asyncSignal"]);
|
|
4
|
-
const cacheTypes = new Set(["cache.browser", "cache.server"]);
|
|
5
|
-
const cacheEntryTypes = new Set(["cache.browser.entries", "cache.server.entries"]);
|
|
6
|
-
const allTypes = new Set([...declarationTypes, ...cacheTypes, ...cacheEntryTypes]);
|
|
7
|
-
|
|
8
|
-
export function createRegistryStore(initial = {}, options = {}) {
|
|
9
|
-
const backing = options.backing ?? createBacking();
|
|
10
|
-
const target = options.target ?? "server";
|
|
11
|
-
|
|
12
|
-
const registry = {
|
|
13
|
-
target,
|
|
14
|
-
|
|
15
|
-
register(type, id, value) {
|
|
16
|
-
const map = registry._map(type);
|
|
17
|
-
assertId(type, id);
|
|
18
|
-
if (map.has(id)) {
|
|
19
|
-
throw new Error(`${type} "${id}" is already registered.`);
|
|
20
|
-
}
|
|
21
|
-
map.set(id, value);
|
|
22
|
-
return id;
|
|
23
|
-
},
|
|
24
|
-
|
|
25
|
-
registerMany(type, map = {}) {
|
|
26
|
-
for (const [id, value] of Object.entries(map ?? {})) {
|
|
27
|
-
registry.register(type, id, value);
|
|
28
|
-
}
|
|
29
|
-
return registry;
|
|
30
|
-
},
|
|
31
|
-
|
|
32
|
-
set(type, id, value) {
|
|
33
|
-
const map = registry._map(type);
|
|
34
|
-
assertId(type, id);
|
|
35
|
-
map.set(id, value);
|
|
36
|
-
return value;
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
unregister(type, id) {
|
|
40
|
-
return registry.delete(type, id);
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
delete(type, id) {
|
|
44
|
-
return registry._map(type).delete(id);
|
|
45
|
-
},
|
|
46
|
-
|
|
47
|
-
keys(type) {
|
|
48
|
-
if (isHiddenInBrowser(type, target)) {
|
|
49
|
-
return [];
|
|
50
|
-
}
|
|
51
|
-
return [...registry._map(type).keys()];
|
|
52
|
-
},
|
|
53
|
-
|
|
54
|
-
entries(type, entryOptions = {}) {
|
|
55
|
-
const normalized = normalizeType(type);
|
|
56
|
-
if (isHiddenInBrowser(normalized, entryOptions.target ?? target)) {
|
|
57
|
-
return [];
|
|
58
|
-
}
|
|
59
|
-
return [...registry._map(normalized)].map(([id, value]) => [
|
|
60
|
-
id,
|
|
61
|
-
publicValue(normalized, id, value, { target, ...entryOptions })
|
|
62
|
-
]);
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
has(type, id) {
|
|
66
|
-
assertId(type, id);
|
|
67
|
-
if (isHiddenInBrowser(type, target)) {
|
|
68
|
-
return false;
|
|
69
|
-
}
|
|
70
|
-
return registry._map(type).has(id);
|
|
71
|
-
},
|
|
72
|
-
|
|
73
|
-
get(type, id, getOptions = {}) {
|
|
74
|
-
assertId(type, id);
|
|
75
|
-
const normalized = normalizeType(type);
|
|
76
|
-
if (isHiddenInBrowser(normalized, getOptions.target ?? target)) {
|
|
77
|
-
return undefined;
|
|
78
|
-
}
|
|
79
|
-
const value = registry._map(normalized).get(id);
|
|
80
|
-
if (value === undefined) {
|
|
81
|
-
return undefined;
|
|
82
|
-
}
|
|
83
|
-
return publicValue(normalized, id, value, { target, ...getOptions });
|
|
84
|
-
},
|
|
85
|
-
|
|
86
|
-
snapshot(snapshotOptions = {}) {
|
|
87
|
-
const snapshotTarget = snapshotOptions.target ?? target;
|
|
88
|
-
return {
|
|
89
|
-
signal: snapshotSignals(backing.signal),
|
|
90
|
-
handler: snapshotDescriptors(backing.handler),
|
|
91
|
-
server: snapshotDescriptors(backing.server),
|
|
92
|
-
partial: snapshotDescriptors(backing.partial),
|
|
93
|
-
route: snapshotPlain(backing.route),
|
|
94
|
-
component: snapshotDescriptors(backing.component),
|
|
95
|
-
asyncSignal: snapshotDescriptors(backing.asyncSignal),
|
|
96
|
-
cache: {
|
|
97
|
-
browser: snapshotPlain(backing.cache.browser),
|
|
98
|
-
server: snapshotPlain(backing.cache.server)
|
|
99
|
-
},
|
|
100
|
-
entries: {
|
|
101
|
-
browser: snapshotCacheEntries(backing.cacheEntries.browser),
|
|
102
|
-
server: snapshotTarget === "browser" ? {} : snapshotCacheEntries(backing.cacheEntries.server)
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
},
|
|
106
|
-
|
|
107
|
-
rawSnapshot() {
|
|
108
|
-
return {
|
|
109
|
-
signal: Object.fromEntries(backing.signal),
|
|
110
|
-
handler: Object.fromEntries(backing.handler),
|
|
111
|
-
server: Object.fromEntries(backing.server),
|
|
112
|
-
partial: Object.fromEntries(backing.partial),
|
|
113
|
-
route: Object.fromEntries(backing.route),
|
|
114
|
-
component: Object.fromEntries(backing.component),
|
|
115
|
-
asyncSignal: Object.fromEntries(backing.asyncSignal),
|
|
116
|
-
cache: {
|
|
117
|
-
browser: Object.fromEntries(backing.cache.browser),
|
|
118
|
-
server: Object.fromEntries(backing.cache.server)
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
},
|
|
122
|
-
|
|
123
|
-
view(viewOptions = {}) {
|
|
124
|
-
return createRegistryStore(undefined, {
|
|
125
|
-
backing,
|
|
126
|
-
target: viewOptions.target ?? target
|
|
127
|
-
});
|
|
128
|
-
},
|
|
129
|
-
|
|
130
|
-
_map(type) {
|
|
131
|
-
const normalized = normalizeType(type);
|
|
132
|
-
if (declarationTypes.has(normalized)) {
|
|
133
|
-
return backing[normalized];
|
|
134
|
-
}
|
|
135
|
-
if (normalized === "cache.browser") {
|
|
136
|
-
return backing.cache.browser;
|
|
137
|
-
}
|
|
138
|
-
if (normalized === "cache.server") {
|
|
139
|
-
return backing.cache.server;
|
|
140
|
-
}
|
|
141
|
-
if (normalized === "cache.browser.entries") {
|
|
142
|
-
return backing.cacheEntries.browser;
|
|
143
|
-
}
|
|
144
|
-
if (normalized === "cache.server.entries") {
|
|
145
|
-
return backing.cacheEntries.server;
|
|
146
|
-
}
|
|
147
|
-
throw new Error(`Unknown Async registry type "${type}".`);
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
applyInitial(registry, initial);
|
|
152
|
-
return registry;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
export function attachRegistryInspection(target, registry, type) {
|
|
156
|
-
Object.defineProperty(target, "registry", {
|
|
157
|
-
configurable: true,
|
|
158
|
-
enumerable: true,
|
|
159
|
-
value: registry
|
|
160
|
-
});
|
|
161
|
-
target.keys = () => registry.keys(type);
|
|
162
|
-
target.entries = () => registry.entries(type);
|
|
163
|
-
target.inspect = () => registry.entries(type);
|
|
164
|
-
return target;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function createBacking() {
|
|
168
|
-
return {
|
|
169
|
-
signal: new Map(),
|
|
170
|
-
handler: new Map(),
|
|
171
|
-
server: new Map(),
|
|
172
|
-
partial: new Map(),
|
|
173
|
-
route: new Map(),
|
|
174
|
-
component: new Map(),
|
|
175
|
-
asyncSignal: new Map(),
|
|
176
|
-
cache: {
|
|
177
|
-
browser: new Map(),
|
|
178
|
-
server: new Map()
|
|
179
|
-
},
|
|
180
|
-
cacheEntries: {
|
|
181
|
-
browser: new Map(),
|
|
182
|
-
server: new Map()
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
function applyInitial(registry, initial = {}) {
|
|
188
|
-
registry.registerMany("signal", initial.signal);
|
|
189
|
-
registry.registerMany("handler", initial.handler);
|
|
190
|
-
registry.registerMany("server", initial.server);
|
|
191
|
-
registry.registerMany("partial", initial.partial);
|
|
192
|
-
registry.registerMany("route", initial.route);
|
|
193
|
-
registry.registerMany("component", initial.component);
|
|
194
|
-
registry.registerMany("asyncSignal", initial.asyncSignal);
|
|
195
|
-
registry.registerMany("cache.browser", initial.cache?.browser);
|
|
196
|
-
registry.registerMany("cache.server", initial.cache?.server);
|
|
197
|
-
|
|
198
|
-
const entries = initial.entries ?? {};
|
|
199
|
-
for (const [key, value] of Object.entries(entries.browser ?? {})) {
|
|
200
|
-
registry.set("cache.browser.entries", key, cacheEntry(value));
|
|
201
|
-
}
|
|
202
|
-
for (const [key, value] of Object.entries(entries.server ?? {})) {
|
|
203
|
-
registry.set("cache.server.entries", key, cacheEntry(value));
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
function normalizeType(type) {
|
|
208
|
-
if (!allTypes.has(type)) {
|
|
209
|
-
throw new Error(`Unknown Async registry type "${type}".`);
|
|
210
|
-
}
|
|
211
|
-
return type;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
function assertId(type, id) {
|
|
215
|
-
if (typeof id !== "string" || id.length === 0) {
|
|
216
|
-
throw new TypeError(`${type} id must be a non-empty string.`);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
function publicValue(type, id, value, options) {
|
|
221
|
-
if (type === "server" && options.target === "browser") {
|
|
222
|
-
return publicRegistryValue(value, id);
|
|
223
|
-
}
|
|
224
|
-
if (cacheEntryTypes.has(type)) {
|
|
225
|
-
return value?.value;
|
|
226
|
-
}
|
|
227
|
-
return value;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
function isHiddenInBrowser(type, target) {
|
|
231
|
-
return type === "cache.server.entries" && target === "browser";
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
function snapshotSignals(map) {
|
|
235
|
-
const snapshot = {};
|
|
236
|
-
for (const [id, entry] of map) {
|
|
237
|
-
snapshot[id] = typeof entry?.snapshot === "function" ? entry.snapshot() : entry?.value ?? entry;
|
|
238
|
-
}
|
|
239
|
-
return snapshot;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
function snapshotDescriptors(map) {
|
|
243
|
-
const snapshot = {};
|
|
244
|
-
for (const [id, value] of map) {
|
|
245
|
-
snapshot[id] = publicRegistryValue(value, id);
|
|
246
|
-
}
|
|
247
|
-
return snapshot;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
function snapshotPlain(map) {
|
|
251
|
-
return Object.fromEntries(map);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
function snapshotCacheEntries(map) {
|
|
255
|
-
const snapshot = {};
|
|
256
|
-
for (const [id, entry] of map) {
|
|
257
|
-
snapshot[id] = entry?.value;
|
|
258
|
-
}
|
|
259
|
-
return snapshot;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
function cacheEntry(value) {
|
|
263
|
-
if (value && typeof value === "object" && Object.hasOwn(value, "value")) {
|
|
264
|
-
return value;
|
|
265
|
-
}
|
|
266
|
-
return { value };
|
|
267
|
-
}
|
package/src/request-context.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
-
|
|
3
|
-
export function createRequestContextStore() {
|
|
4
|
-
const storage = new AsyncLocalStorage();
|
|
5
|
-
|
|
6
|
-
return {
|
|
7
|
-
storage,
|
|
8
|
-
|
|
9
|
-
run(context, fn, ...args) {
|
|
10
|
-
if (typeof fn !== "function") {
|
|
11
|
-
throw new TypeError("requestContext.run(context, fn) requires a function.");
|
|
12
|
-
}
|
|
13
|
-
return storage.run(context ?? {}, fn, ...args);
|
|
14
|
-
},
|
|
15
|
-
|
|
16
|
-
get() {
|
|
17
|
-
return storage.getStore();
|
|
18
|
-
},
|
|
19
|
-
|
|
20
|
-
snapshot() {
|
|
21
|
-
return { ...(storage.getStore() ?? {}) };
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function readRequestContext(store) {
|
|
27
|
-
if (!store) {
|
|
28
|
-
return {};
|
|
29
|
-
}
|
|
30
|
-
if (typeof store.get === "function") {
|
|
31
|
-
return store.get() ?? {};
|
|
32
|
-
}
|
|
33
|
-
if (typeof store.getStore === "function") {
|
|
34
|
-
return store.getStore() ?? {};
|
|
35
|
-
}
|
|
36
|
-
if (typeof store === "object") {
|
|
37
|
-
return store;
|
|
38
|
-
}
|
|
39
|
-
return {};
|
|
40
|
-
}
|