@vesk/runtime 0.0.1
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 +23 -0
- package/dist/action.d.ts +43 -0
- package/dist/action.d.ts.map +1 -0
- package/dist/action.js +84 -0
- package/dist/bindings.d.ts +4 -0
- package/dist/bindings.d.ts.map +1 -0
- package/dist/bindings.js +137 -0
- package/dist/context.d.ts +15 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +34 -0
- package/dist/experiment.d.ts +17 -0
- package/dist/experiment.d.ts.map +1 -0
- package/dist/experiment.js +71 -0
- package/dist/form.d.ts +36 -0
- package/dist/form.d.ts.map +1 -0
- package/dist/form.js +278 -0
- package/dist/hmr-client.d.ts +1 -0
- package/dist/hmr-client.d.ts.map +1 -0
- package/dist/hmr-client.js +273 -0
- package/dist/hydrate.d.ts +34 -0
- package/dist/hydrate.d.ts.map +1 -0
- package/dist/hydrate.js +248 -0
- package/dist/image.d.ts +19 -0
- package/dist/image.d.ts.map +1 -0
- package/dist/image.js +51 -0
- package/dist/index-client.d.ts +16 -0
- package/dist/index-client.d.ts.map +1 -0
- package/dist/index-client.js +15 -0
- package/dist/index-server.d.ts +15 -0
- package/dist/index-server.d.ts.map +1 -0
- package/dist/index-server.js +14 -0
- package/dist/isr.d.ts +27 -0
- package/dist/isr.d.ts.map +1 -0
- package/dist/isr.js +143 -0
- package/dist/md.d.ts +17 -0
- package/dist/md.d.ts.map +1 -0
- package/dist/md.js +507 -0
- package/dist/package.json +23 -0
- package/dist/portal.d.ts +8 -0
- package/dist/portal.d.ts.map +1 -0
- package/dist/portal.js +20 -0
- package/dist/reconcile.d.ts +3 -0
- package/dist/reconcile.d.ts.map +1 -0
- package/dist/reconcile.js +66 -0
- package/dist/request.d.ts +188 -0
- package/dist/request.d.ts.map +1 -0
- package/dist/request.js +624 -0
- package/dist/resource.d.ts +47 -0
- package/dist/resource.d.ts.map +1 -0
- package/dist/resource.js +502 -0
- package/dist/ripple-blocks.d.ts +18 -0
- package/dist/ripple-blocks.d.ts.map +1 -0
- package/dist/ripple-blocks.js +184 -0
- package/dist/ripple-constants.d.ts +42 -0
- package/dist/ripple-constants.d.ts.map +1 -0
- package/dist/ripple-constants.js +41 -0
- package/dist/ripple-runtime.d.ts +125 -0
- package/dist/ripple-runtime.d.ts.map +1 -0
- package/dist/ripple-runtime.js +891 -0
- package/dist/ripple-utils.d.ts +12 -0
- package/dist/ripple-utils.d.ts.map +1 -0
- package/dist/ripple-utils.js +10 -0
- package/dist/router-components.d.ts +83 -0
- package/dist/router-components.d.ts.map +1 -0
- package/dist/router-components.js +320 -0
- package/dist/router-match.d.ts +40 -0
- package/dist/router-match.d.ts.map +1 -0
- package/dist/router-match.js +158 -0
- package/dist/router.d.ts +56 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +1330 -0
- package/dist/seo.d.ts +94 -0
- package/dist/seo.d.ts.map +1 -0
- package/dist/seo.js +138 -0
- package/dist/suspense.d.ts +1 -0
- package/dist/suspense.d.ts.map +1 -0
- package/dist/suspense.js +14 -0
- package/dist/track.d.ts +20 -0
- package/dist/track.d.ts.map +1 -0
- package/dist/track.js +124 -0
- package/package.json +55 -0
package/dist/resource.js
ADDED
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
import { tracked, get, set, scope, on_destroy } from '@vesk/runtime/src/ripple-runtime';
|
|
2
|
+
import { is_destroyed } from '@vesk/runtime/src/ripple-blocks';
|
|
3
|
+
export class HttpError extends Error {
|
|
4
|
+
status;
|
|
5
|
+
constructor(status, statusText) {
|
|
6
|
+
super(`HTTP ${status}: ${statusText}`);
|
|
7
|
+
this.status = status;
|
|
8
|
+
this.name = 'HttpError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export class TimeoutError extends Error {
|
|
12
|
+
constructor(timeout) {
|
|
13
|
+
super(`Request timed out after ${timeout}ms`);
|
|
14
|
+
this.name = 'TimeoutError';
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const g = () => globalThis;
|
|
18
|
+
const isServer = () => !!g().__vsk_ssr;
|
|
19
|
+
let ssrSink = null;
|
|
20
|
+
export function setSsrSink(sink) {
|
|
21
|
+
ssrSink = sink;
|
|
22
|
+
}
|
|
23
|
+
function getClientCache() {
|
|
24
|
+
const value = g().__vsk_fetch_cache;
|
|
25
|
+
if (value)
|
|
26
|
+
return value;
|
|
27
|
+
const map = new Map();
|
|
28
|
+
g().__vsk_fetch_cache = map;
|
|
29
|
+
return map;
|
|
30
|
+
}
|
|
31
|
+
function getInflight() {
|
|
32
|
+
const value = g().__vsk_fetch_inflight;
|
|
33
|
+
if (value)
|
|
34
|
+
return value;
|
|
35
|
+
const map = new Map();
|
|
36
|
+
g().__vsk_fetch_inflight = map;
|
|
37
|
+
return map;
|
|
38
|
+
}
|
|
39
|
+
function getRegistry() {
|
|
40
|
+
const value = g().__vsk_fetch_registry;
|
|
41
|
+
if (value)
|
|
42
|
+
return value;
|
|
43
|
+
const map = new Map();
|
|
44
|
+
g().__vsk_fetch_registry = map;
|
|
45
|
+
return map;
|
|
46
|
+
}
|
|
47
|
+
function getSsrData(key) {
|
|
48
|
+
const sink = ssrSink;
|
|
49
|
+
if (sink)
|
|
50
|
+
return sink.get(key);
|
|
51
|
+
const store = g().__vsk_ssr_data;
|
|
52
|
+
if (!store)
|
|
53
|
+
return undefined;
|
|
54
|
+
return store[key];
|
|
55
|
+
}
|
|
56
|
+
export function setSsrData(key, value) {
|
|
57
|
+
const sink = ssrSink;
|
|
58
|
+
if (sink) {
|
|
59
|
+
sink.set(key, value);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (!g().__vsk_ssr_data)
|
|
63
|
+
g().__vsk_ssr_data = {};
|
|
64
|
+
g().__vsk_ssr_data[key] = value;
|
|
65
|
+
}
|
|
66
|
+
export function clearSsrData() {
|
|
67
|
+
const sink = ssrSink;
|
|
68
|
+
if (sink) {
|
|
69
|
+
sink.clear();
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
delete g().__vsk_ssr_data;
|
|
73
|
+
}
|
|
74
|
+
function setInto(into, data) {
|
|
75
|
+
if (into && typeof into === 'object' && typeof into.f === 'number') {
|
|
76
|
+
set(into, data);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function isAbortError(error) {
|
|
80
|
+
if (typeof DOMException !== 'undefined' && error instanceof DOMException && error.name === 'AbortError') {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
return error instanceof Error && error.name === 'AbortError';
|
|
84
|
+
}
|
|
85
|
+
function makeAbortError() {
|
|
86
|
+
if (typeof DOMException !== 'undefined')
|
|
87
|
+
return new DOMException('aborted', 'AbortError');
|
|
88
|
+
const error = new Error('aborted');
|
|
89
|
+
error.name = 'AbortError';
|
|
90
|
+
return error;
|
|
91
|
+
}
|
|
92
|
+
function normalizeHeaders(headers) {
|
|
93
|
+
const out = {};
|
|
94
|
+
if (!headers)
|
|
95
|
+
return out;
|
|
96
|
+
if (typeof Headers !== 'undefined' && headers instanceof Headers) {
|
|
97
|
+
headers.forEach((value, key) => (out[key] = value));
|
|
98
|
+
}
|
|
99
|
+
else if (Array.isArray(headers)) {
|
|
100
|
+
for (const [key, value] of headers)
|
|
101
|
+
out[key] = value;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
Object.assign(out, headers);
|
|
105
|
+
}
|
|
106
|
+
return out;
|
|
107
|
+
}
|
|
108
|
+
function prepareBody(body, headers) {
|
|
109
|
+
if (body === undefined || body === null)
|
|
110
|
+
return { headers };
|
|
111
|
+
if (typeof body === 'string' ||
|
|
112
|
+
typeof body === 'boolean' ||
|
|
113
|
+
typeof body === 'number' ||
|
|
114
|
+
(typeof FormData !== 'undefined' && body instanceof FormData) ||
|
|
115
|
+
(typeof URLSearchParams !== 'undefined' && body instanceof URLSearchParams) ||
|
|
116
|
+
(typeof Blob !== 'undefined' && body instanceof Blob) ||
|
|
117
|
+
(typeof ArrayBuffer !== 'undefined' && (body instanceof ArrayBuffer || ArrayBuffer.isView(body)))) {
|
|
118
|
+
return { body: body, headers };
|
|
119
|
+
}
|
|
120
|
+
if (!headers['content-type'] && !headers['Content-Type']) {
|
|
121
|
+
headers['Content-Type'] = 'application/json';
|
|
122
|
+
}
|
|
123
|
+
return { body: JSON.stringify(body), headers };
|
|
124
|
+
}
|
|
125
|
+
function buildRequestInit(options) {
|
|
126
|
+
const { method, credentials, cache, mode, redirect, referrer, referrerPolicy, integrity, keepalive, } = options;
|
|
127
|
+
const init = { method, credentials, cache, mode, redirect, referrer, referrerPolicy, integrity, keepalive };
|
|
128
|
+
const prepared = prepareBody(options.body, normalizeHeaders(options.headers));
|
|
129
|
+
init.headers = prepared.headers;
|
|
130
|
+
if (prepared.body !== undefined)
|
|
131
|
+
init.body = prepared.body;
|
|
132
|
+
return init;
|
|
133
|
+
}
|
|
134
|
+
function resolveFetchUrl(url) {
|
|
135
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(url) || url.startsWith('//'))
|
|
136
|
+
return url;
|
|
137
|
+
const reqUrl = g().__vesk_request?.url;
|
|
138
|
+
const base = typeof reqUrl === 'string' && /^https?:\/\//i.test(reqUrl)
|
|
139
|
+
? reqUrl
|
|
140
|
+
: g().__vesk_ssr_base_url || '';
|
|
141
|
+
if (base)
|
|
142
|
+
return new URL(url, base).href;
|
|
143
|
+
return url;
|
|
144
|
+
}
|
|
145
|
+
function doFetch(url, init) {
|
|
146
|
+
const hook = g().__vesk_ssr_fetch;
|
|
147
|
+
if (isServer() && typeof hook === 'function') {
|
|
148
|
+
return hook(url, init);
|
|
149
|
+
}
|
|
150
|
+
return fetch(url, init);
|
|
151
|
+
}
|
|
152
|
+
function createFetcher(url, options) {
|
|
153
|
+
const init = buildRequestInit(options);
|
|
154
|
+
return async (signal) => {
|
|
155
|
+
const res = await doFetch(resolveFetchUrl(url), signal ? { ...init, signal } : init);
|
|
156
|
+
if (!res.ok)
|
|
157
|
+
throw new HttpError(res.status, res.statusText);
|
|
158
|
+
return res.json();
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function linkSignal(userSignal, controller) {
|
|
162
|
+
if (!userSignal)
|
|
163
|
+
return;
|
|
164
|
+
if (userSignal.aborted)
|
|
165
|
+
controller.abort();
|
|
166
|
+
else
|
|
167
|
+
userSignal.addEventListener('abort', () => controller.abort(), { once: true });
|
|
168
|
+
}
|
|
169
|
+
async function runFetcher(handle, timeout) {
|
|
170
|
+
const { retry = 0, retryDelay = 1000, method, signal } = handle.options;
|
|
171
|
+
const maxAttempts = retry + 1;
|
|
172
|
+
const canRetry = !method || method.toUpperCase() === 'GET';
|
|
173
|
+
let attempt = 0;
|
|
174
|
+
let lastError;
|
|
175
|
+
while (true) {
|
|
176
|
+
if (handle.block !== null && is_destroyed(handle.block))
|
|
177
|
+
throw makeAbortError();
|
|
178
|
+
const controller = new AbortController();
|
|
179
|
+
handle.controller = controller;
|
|
180
|
+
linkSignal(signal, controller);
|
|
181
|
+
let timer = null;
|
|
182
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
183
|
+
if (timeout <= 0)
|
|
184
|
+
return;
|
|
185
|
+
timer = setTimeout(() => {
|
|
186
|
+
controller.abort();
|
|
187
|
+
reject(new TimeoutError(timeout));
|
|
188
|
+
}, timeout);
|
|
189
|
+
});
|
|
190
|
+
try {
|
|
191
|
+
const result = await Promise.race([handle.fetcher(controller.signal), timeoutPromise]);
|
|
192
|
+
return result;
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
if (isAbortError(error))
|
|
196
|
+
throw error;
|
|
197
|
+
lastError = error;
|
|
198
|
+
const retriable = canRetry &&
|
|
199
|
+
attempt < maxAttempts - 1 &&
|
|
200
|
+
!(error instanceof HttpError && error.status >= 400 && error.status < 500);
|
|
201
|
+
if (!retriable)
|
|
202
|
+
throw error;
|
|
203
|
+
if (retryDelay > 0)
|
|
204
|
+
await sleep(retryDelay * (isServer() ? 1 : Math.pow(2, attempt)));
|
|
205
|
+
attempt++;
|
|
206
|
+
}
|
|
207
|
+
finally {
|
|
208
|
+
if (timer !== null)
|
|
209
|
+
clearTimeout(timer);
|
|
210
|
+
if (handle.controller === controller)
|
|
211
|
+
handle.controller = null;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function sleep(ms) {
|
|
216
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
217
|
+
}
|
|
218
|
+
function settle(handle, data) {
|
|
219
|
+
if (handle.block !== null && is_destroyed(handle.block))
|
|
220
|
+
return;
|
|
221
|
+
if (handle.into)
|
|
222
|
+
setInto(handle.into, data);
|
|
223
|
+
const current = get(handle.state);
|
|
224
|
+
if (!(current.data === data && !current.loading && current.error === null)) {
|
|
225
|
+
set(handle.state, { loading: false, error: null, data });
|
|
226
|
+
}
|
|
227
|
+
handle.settleNotify();
|
|
228
|
+
}
|
|
229
|
+
function settleError(handle, error) {
|
|
230
|
+
if (handle.block !== null && is_destroyed(handle.block))
|
|
231
|
+
return;
|
|
232
|
+
if (isAbortError(error)) {
|
|
233
|
+
if (handle.controller !== null)
|
|
234
|
+
return;
|
|
235
|
+
const current = get(handle.state);
|
|
236
|
+
if (current.loading)
|
|
237
|
+
set(handle.state, { loading: false, error: null, data: current.data });
|
|
238
|
+
handle.settleNotify();
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
const current = get(handle.state);
|
|
242
|
+
set(handle.state, { loading: false, error, data: current.data });
|
|
243
|
+
handle.settleNotify();
|
|
244
|
+
}
|
|
245
|
+
function markRefetching(handle) {
|
|
246
|
+
const current = get(handle.state);
|
|
247
|
+
if (current.loading)
|
|
248
|
+
return;
|
|
249
|
+
set(handle.state, {
|
|
250
|
+
loading: true,
|
|
251
|
+
error: null,
|
|
252
|
+
data: handle.options.keepPreviousData ? current.data : undefined,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
function attachSettle(handle, promise) {
|
|
256
|
+
promise.then(data => settle(handle, data), error => settleError(handle, error));
|
|
257
|
+
}
|
|
258
|
+
function writeCache(key, data) {
|
|
259
|
+
if (isServer())
|
|
260
|
+
return;
|
|
261
|
+
const entry = getClientCache().get(key);
|
|
262
|
+
if (!entry || entry.data !== data)
|
|
263
|
+
getClientCache().set(key, { data, fetchedAt: Date.now() });
|
|
264
|
+
}
|
|
265
|
+
function trackSsrPromise(promise) {
|
|
266
|
+
const tk = g().__vsk_ssr_token || '';
|
|
267
|
+
const promisesKey = tk ? `__vsk_ssr_promises_${tk}` : '__vsk_ssr_promises';
|
|
268
|
+
if (!g()[promisesKey])
|
|
269
|
+
g()[promisesKey] = [];
|
|
270
|
+
g()[promisesKey].push(promise);
|
|
271
|
+
}
|
|
272
|
+
function registerDestroyAbort(handle) {
|
|
273
|
+
if (isServer() || handle.block === null)
|
|
274
|
+
return;
|
|
275
|
+
on_destroy(() => {
|
|
276
|
+
if (is_destroyed(handle.block)) {
|
|
277
|
+
handle.controller?.abort();
|
|
278
|
+
const registry = getRegistry().get(handle.key);
|
|
279
|
+
if (registry)
|
|
280
|
+
registry.delete(handle);
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
function startRequest(handle, skipCache) {
|
|
285
|
+
const key = handle.key;
|
|
286
|
+
const options = handle.options;
|
|
287
|
+
if (isServer()) {
|
|
288
|
+
const existing = getInflight().get(key);
|
|
289
|
+
const prom = existing ?? runFetcher(handle, options.timeout || 0);
|
|
290
|
+
if (!existing) {
|
|
291
|
+
getInflight().set(key, prom);
|
|
292
|
+
prom.then(data => {
|
|
293
|
+
setSsrData(key, data);
|
|
294
|
+
settle(handle, data);
|
|
295
|
+
}, error => settleError(handle, error)).finally(() => {
|
|
296
|
+
if (getInflight().get(key) === prom)
|
|
297
|
+
getInflight().delete(key);
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
attachSettle(handle, prom);
|
|
302
|
+
}
|
|
303
|
+
trackSsrPromise(prom);
|
|
304
|
+
return prom;
|
|
305
|
+
}
|
|
306
|
+
if (!skipCache && options.staleTime && options.staleTime > 0) {
|
|
307
|
+
const entry = getClientCache().get(key);
|
|
308
|
+
if (entry && Date.now() - entry.fetchedAt < options.staleTime) {
|
|
309
|
+
settle(handle, entry.data);
|
|
310
|
+
return Promise.resolve(entry.data);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (options.dedupe !== false) {
|
|
314
|
+
const existing = getInflight().get(key);
|
|
315
|
+
if (existing) {
|
|
316
|
+
attachSettle(handle, existing);
|
|
317
|
+
return existing;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
markRefetching(handle);
|
|
321
|
+
const controller = new AbortController();
|
|
322
|
+
handle.controller = controller;
|
|
323
|
+
linkSignal(options.signal, controller);
|
|
324
|
+
const prom = runFetcher(handle, options.timeout || 0);
|
|
325
|
+
prom.then(data => {
|
|
326
|
+
writeCache(key, data);
|
|
327
|
+
settle(handle, data);
|
|
328
|
+
}, error => settleError(handle, error)).finally(() => {
|
|
329
|
+
if (options.dedupe !== false && getInflight().get(key) === prom)
|
|
330
|
+
getInflight().delete(key);
|
|
331
|
+
});
|
|
332
|
+
if (options.dedupe !== false)
|
|
333
|
+
getInflight().set(key, prom);
|
|
334
|
+
registerDestroyAbort(handle);
|
|
335
|
+
return prom;
|
|
336
|
+
}
|
|
337
|
+
function revalidate(handle) {
|
|
338
|
+
if (!isServer()) {
|
|
339
|
+
const registry = getRegistry().get(handle.key);
|
|
340
|
+
if (registry && registry.size > 0) {
|
|
341
|
+
const prev = getInflight().get(handle.key);
|
|
342
|
+
if (prev) {
|
|
343
|
+
getInflight().delete(handle.key);
|
|
344
|
+
registry.forEach(h => h.controller?.abort());
|
|
345
|
+
}
|
|
346
|
+
registry.forEach(h => startRequest(h, true));
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
const prev = getInflight().get(handle.key);
|
|
351
|
+
if (prev)
|
|
352
|
+
getInflight().delete(handle.key);
|
|
353
|
+
handle.controller?.abort();
|
|
354
|
+
startRequest(handle, true);
|
|
355
|
+
}
|
|
356
|
+
export function mutate(key, data) {
|
|
357
|
+
if (isServer())
|
|
358
|
+
return;
|
|
359
|
+
const registry = getRegistry().get(key);
|
|
360
|
+
const prev = getInflight().get(key);
|
|
361
|
+
if (data !== undefined) {
|
|
362
|
+
getClientCache().set(key, { data, fetchedAt: Date.now() });
|
|
363
|
+
if (prev) {
|
|
364
|
+
getInflight().delete(key);
|
|
365
|
+
if (registry)
|
|
366
|
+
registry.forEach(h => h.controller?.abort());
|
|
367
|
+
}
|
|
368
|
+
if (registry) {
|
|
369
|
+
registry.forEach(h => {
|
|
370
|
+
if (h.into)
|
|
371
|
+
setInto(h.into, data);
|
|
372
|
+
set(h.state, { loading: false, error: null, data });
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
if (registry && registry.size > 0) {
|
|
378
|
+
if (prev) {
|
|
379
|
+
getInflight().delete(key);
|
|
380
|
+
registry.forEach(h => h.controller?.abort());
|
|
381
|
+
}
|
|
382
|
+
registry.forEach(h => startRequest(h, true));
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
function createResourceAccessor(handle) {
|
|
386
|
+
const state = handle.state;
|
|
387
|
+
const accessor = {};
|
|
388
|
+
Object.defineProperty(accessor, 'loading', {
|
|
389
|
+
get() { return get(state).loading; },
|
|
390
|
+
});
|
|
391
|
+
Object.defineProperty(accessor, 'error', {
|
|
392
|
+
get() { return get(state).error; },
|
|
393
|
+
});
|
|
394
|
+
Object.defineProperty(accessor, 'data', {
|
|
395
|
+
get() { return get(state).data; },
|
|
396
|
+
});
|
|
397
|
+
accessor._state = state;
|
|
398
|
+
const toData = async () => {
|
|
399
|
+
for (;;) {
|
|
400
|
+
const s = get(state);
|
|
401
|
+
if (!s.loading) {
|
|
402
|
+
if (s.error)
|
|
403
|
+
throw s.error;
|
|
404
|
+
return s.data;
|
|
405
|
+
}
|
|
406
|
+
await handle.settled;
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
accessor.then = (onFulfilled, onRejected) => toData().then(onFulfilled, onRejected);
|
|
410
|
+
accessor.catch = (onRejected) => toData().catch(onRejected);
|
|
411
|
+
accessor.finally = (onFinally) => toData().finally(onFinally);
|
|
412
|
+
accessor.refresh = () => revalidate(handle);
|
|
413
|
+
accessor.abort = () => {
|
|
414
|
+
if (!isServer())
|
|
415
|
+
handle.controller?.abort();
|
|
416
|
+
};
|
|
417
|
+
return accessor;
|
|
418
|
+
}
|
|
419
|
+
export function createResource(fn, key, into, options = {}) {
|
|
420
|
+
const resourceKey = key || options.key || fn._ssrKey || fn.toString().slice(0, 64);
|
|
421
|
+
let notify = () => { };
|
|
422
|
+
const handle = {
|
|
423
|
+
key: resourceKey,
|
|
424
|
+
state: tracked({ loading: true, error: null, data: undefined }),
|
|
425
|
+
into,
|
|
426
|
+
fetcher: fn,
|
|
427
|
+
options,
|
|
428
|
+
block: scope(),
|
|
429
|
+
controller: null,
|
|
430
|
+
settled: new Promise((res) => { notify = res; }),
|
|
431
|
+
settleNotify: () => {
|
|
432
|
+
notify();
|
|
433
|
+
handle.settled = new Promise((res) => { notify = res; });
|
|
434
|
+
},
|
|
435
|
+
};
|
|
436
|
+
const accessor = createResourceAccessor(handle);
|
|
437
|
+
accessor.refresh = () => revalidate(handle);
|
|
438
|
+
accessor.abort = () => {
|
|
439
|
+
if (!isServer())
|
|
440
|
+
handle.controller?.abort();
|
|
441
|
+
};
|
|
442
|
+
if (options.enabled === false) {
|
|
443
|
+
set(handle.state, { loading: false, error: null, data: undefined });
|
|
444
|
+
return accessor;
|
|
445
|
+
}
|
|
446
|
+
if (!isServer()) {
|
|
447
|
+
const registry = getRegistry();
|
|
448
|
+
const set = registry.get(resourceKey) ?? new Set();
|
|
449
|
+
set.add(handle);
|
|
450
|
+
registry.set(resourceKey, set);
|
|
451
|
+
if (handle.block !== null) {
|
|
452
|
+
on_destroy(() => {
|
|
453
|
+
if (is_destroyed(handle.block)) {
|
|
454
|
+
handle.controller?.abort();
|
|
455
|
+
const current = getRegistry().get(resourceKey);
|
|
456
|
+
if (current)
|
|
457
|
+
current.delete(handle);
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
const ssrData = getSsrData(resourceKey);
|
|
463
|
+
if (ssrData !== undefined) {
|
|
464
|
+
settle(handle, ssrData);
|
|
465
|
+
writeCache(resourceKey, ssrData);
|
|
466
|
+
return accessor;
|
|
467
|
+
}
|
|
468
|
+
startRequest(handle, false);
|
|
469
|
+
return accessor;
|
|
470
|
+
}
|
|
471
|
+
export function useFetch(urlOrFn, options = {}) {
|
|
472
|
+
const fetcher = typeof urlOrFn === 'function'
|
|
473
|
+
? urlOrFn
|
|
474
|
+
: createFetcher(urlOrFn, options);
|
|
475
|
+
const key = options.key || (typeof urlOrFn === 'string' ? urlOrFn : undefined);
|
|
476
|
+
const resource = createResource(fetcher, key, options.into, options);
|
|
477
|
+
return resource;
|
|
478
|
+
}
|
|
479
|
+
useFetch.text = (url, options) => useFetch(() => doFetch(resolveFetchUrl(url), buildRequestInit(options ?? {})).then(r => r.text()), {
|
|
480
|
+
...options,
|
|
481
|
+
key: options?.key ?? url,
|
|
482
|
+
});
|
|
483
|
+
useFetch.json = (url, options) => useFetch(() => doFetch(resolveFetchUrl(url), buildRequestInit(options ?? {})).then(r => r.json()), {
|
|
484
|
+
...options,
|
|
485
|
+
key: options?.key ?? url,
|
|
486
|
+
});
|
|
487
|
+
useFetch.arrayBuffer = (url, options) => useFetch(() => doFetch(resolveFetchUrl(url), buildRequestInit(options ?? {})).then(r => r.arrayBuffer()), {
|
|
488
|
+
...options,
|
|
489
|
+
key: options?.key ?? url,
|
|
490
|
+
});
|
|
491
|
+
export async function resolveSsrResources() {
|
|
492
|
+
const sink = ssrSink;
|
|
493
|
+
if (sink)
|
|
494
|
+
return { ...sink.snapshot() };
|
|
495
|
+
const promises = (g().__vsk_ssr_promises || []);
|
|
496
|
+
if (promises.length === 0)
|
|
497
|
+
return {};
|
|
498
|
+
await Promise.allSettled(promises);
|
|
499
|
+
const data = (g().__vsk_ssr_data || {});
|
|
500
|
+
delete g().__vsk_ssr_promises;
|
|
501
|
+
return data;
|
|
502
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Block, Component } from '@vesk/runtime/src/ripple-runtime';
|
|
2
|
+
export declare function user_effect(fn: () => void): Block | void;
|
|
3
|
+
export declare function effect(fn: () => void): Block;
|
|
4
|
+
export declare function pre_effect(fn: () => void): Block;
|
|
5
|
+
export declare function render(fn: (state: unknown) => unknown, state?: unknown, flags?: number): Block;
|
|
6
|
+
export declare function branch(fn: (state: unknown) => unknown, flags?: number, state?: unknown): Block;
|
|
7
|
+
export declare function root(fn: () => void | (() => void)): Block;
|
|
8
|
+
export declare function create_try_block(fn: (state: unknown) => unknown, state?: unknown): Block;
|
|
9
|
+
export declare function boundary_fn_running_block(fn: (state: unknown) => unknown, flags?: number, state?: unknown): Block;
|
|
10
|
+
export declare function block(flags: number, fn: (state: unknown) => unknown, state?: unknown, co?: Component): Block;
|
|
11
|
+
export declare function destroy_block_children(parent: Block, remove_dom?: boolean): void;
|
|
12
|
+
export declare function destroy_non_branch_children(parent: Block, remove_dom?: boolean): void;
|
|
13
|
+
export declare function unlink_block(block: Block): void;
|
|
14
|
+
export declare function pause_block(block: Block): void;
|
|
15
|
+
export declare function resume_block(block: Block): void;
|
|
16
|
+
export declare function is_destroyed(target_block: Block): boolean;
|
|
17
|
+
export declare function destroy_block(block: Block, remove_dom?: boolean): void;
|
|
18
|
+
//# sourceMappingURL=ripple-blocks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ripple-blocks.d.ts","sourceRoot":"","sources":["../src/ripple-blocks.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAW,MAAM,kCAAkC,CAAC;AAGlF,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,KAAK,GAAG,IAAI,CAoBxD;AAED,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,KAAK,CAE5C;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,KAAK,CAEhD;AAED,wBAAgB,MAAM,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,SAAI,GAAG,KAAK,CAEzF;AAED,wBAAgB,MAAM,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,EAAE,KAAK,SAAI,EAAE,KAAK,GAAE,OAAc,GAAG,KAAK,CAE/F;AAED,wBAAgB,IAAI,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,KAAK,CAEzD;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,KAAK,CAExF;AAED,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,EAAE,KAAK,SAAI,EAAE,KAAK,GAAE,OAAc,GAAG,KAAK,CAElH;AAkBD,wBAAgB,KAAK,CACpB,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,EAC/B,KAAK,GAAE,OAAc,EACrB,EAAE,CAAC,EAAE,SAAS,GACZ,KAAK,CAgCP;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,KAAK,EAAE,UAAU,UAAQ,GAAG,IAAI,CAW9E;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,KAAK,EAAE,UAAU,UAAQ,GAAG,IAAI,CAkBnF;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAY/C;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAe9C;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAiB/C;AAED,wBAAgB,YAAY,CAAC,YAAY,EAAE,KAAK,GAAG,OAAO,CAezD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,UAAO,GAAG,IAAI,CA2BnE"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { BLOCK_HAS_RUN, BRANCH_BLOCK, DERIVED, CONTAINS_TEARDOWN, DESTROYED, EFFECT_BLOCK, PAUSED, PRE_EFFECT_BLOCK, RENDER_BLOCK, ROOT_BLOCK, TRY_BLOCK, HEAD_BLOCK, DIRECT_CHILD_BLOCK, } from '@vesk/runtime/src/ripple-constants';
|
|
2
|
+
import { active_block, active_component, active_reaction, create_component_ctx, is_block_dirty, run_block, run_teardown, schedule_update, } from '@vesk/runtime/src/ripple-runtime';
|
|
3
|
+
export function user_effect(fn) {
|
|
4
|
+
if (active_block === null) {
|
|
5
|
+
throw new Error('effect() must be called within an active context, such as a component or effect');
|
|
6
|
+
}
|
|
7
|
+
const component = active_component;
|
|
8
|
+
if (component !== null && !component.m) {
|
|
9
|
+
const e = (component.e ??= []);
|
|
10
|
+
e.push({
|
|
11
|
+
b: active_block,
|
|
12
|
+
fn,
|
|
13
|
+
r: active_reaction,
|
|
14
|
+
});
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
return block(EFFECT_BLOCK, fn);
|
|
18
|
+
}
|
|
19
|
+
export function effect(fn) {
|
|
20
|
+
return block(EFFECT_BLOCK, fn);
|
|
21
|
+
}
|
|
22
|
+
export function pre_effect(fn) {
|
|
23
|
+
return block(PRE_EFFECT_BLOCK, fn);
|
|
24
|
+
}
|
|
25
|
+
export function render(fn, state, flags = 0) {
|
|
26
|
+
return block(RENDER_BLOCK | flags, fn, state);
|
|
27
|
+
}
|
|
28
|
+
export function branch(fn, flags = 0, state = null) {
|
|
29
|
+
return block(BRANCH_BLOCK | flags, fn, state);
|
|
30
|
+
}
|
|
31
|
+
export function root(fn) {
|
|
32
|
+
return block(ROOT_BLOCK, fn, { start: null, end: null }, create_component_ctx());
|
|
33
|
+
}
|
|
34
|
+
export function create_try_block(fn, state) {
|
|
35
|
+
return block(TRY_BLOCK, fn, state);
|
|
36
|
+
}
|
|
37
|
+
export function boundary_fn_running_block(fn, flags = 0, state = null) {
|
|
38
|
+
return branch(fn, DIRECT_CHILD_BLOCK | flags, state);
|
|
39
|
+
}
|
|
40
|
+
function push_block(block, parent_block) {
|
|
41
|
+
const parent_last = parent_block.last;
|
|
42
|
+
if (parent_last === null) {
|
|
43
|
+
parent_block.last = parent_block.first = block;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
parent_last.next = block;
|
|
47
|
+
block.prev = parent_last;
|
|
48
|
+
parent_block.last = block;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export function block(flags, fn, state = null, co) {
|
|
52
|
+
const newBlock = {
|
|
53
|
+
co: co || active_component,
|
|
54
|
+
d: null,
|
|
55
|
+
first: null,
|
|
56
|
+
f: flags,
|
|
57
|
+
fn,
|
|
58
|
+
last: null,
|
|
59
|
+
next: null,
|
|
60
|
+
p: active_block,
|
|
61
|
+
prev: null,
|
|
62
|
+
s: state,
|
|
63
|
+
t: null,
|
|
64
|
+
tc: null,
|
|
65
|
+
};
|
|
66
|
+
if (active_reaction !== null && (active_reaction.f & DERIVED) !== 0) {
|
|
67
|
+
(active_reaction.blocks ??= []).push(newBlock);
|
|
68
|
+
}
|
|
69
|
+
if (active_block !== null) {
|
|
70
|
+
push_block(newBlock, active_block);
|
|
71
|
+
}
|
|
72
|
+
if ((flags & EFFECT_BLOCK) !== 0) {
|
|
73
|
+
schedule_update(newBlock);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
run_block(newBlock);
|
|
77
|
+
newBlock.f ^= BLOCK_HAS_RUN;
|
|
78
|
+
}
|
|
79
|
+
return newBlock;
|
|
80
|
+
}
|
|
81
|
+
export function destroy_block_children(parent, remove_dom = false) {
|
|
82
|
+
let block = parent.first;
|
|
83
|
+
parent.first = parent.last = null;
|
|
84
|
+
if (remove_dom || (parent.f & CONTAINS_TEARDOWN) !== 0) {
|
|
85
|
+
while (block !== null) {
|
|
86
|
+
const next = block.next;
|
|
87
|
+
destroy_block(block, remove_dom);
|
|
88
|
+
block = next;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
export function destroy_non_branch_children(parent, remove_dom = false) {
|
|
93
|
+
let block = parent.first;
|
|
94
|
+
if ((parent.f & CONTAINS_TEARDOWN) === 0 &&
|
|
95
|
+
parent.first !== null &&
|
|
96
|
+
(parent.first.f & BRANCH_BLOCK) === 0) {
|
|
97
|
+
parent.first = parent.last = null;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
while (block !== null) {
|
|
101
|
+
const next = block.next;
|
|
102
|
+
if ((block.f & BRANCH_BLOCK) === 0) {
|
|
103
|
+
destroy_block(block, remove_dom);
|
|
104
|
+
}
|
|
105
|
+
block = next;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
export function unlink_block(block) {
|
|
110
|
+
const parent = block.p;
|
|
111
|
+
const prev = block.prev;
|
|
112
|
+
const next = block.next;
|
|
113
|
+
if (prev !== null)
|
|
114
|
+
prev.next = next;
|
|
115
|
+
if (next !== null)
|
|
116
|
+
next.prev = prev;
|
|
117
|
+
if (parent !== null) {
|
|
118
|
+
if (parent.first === block)
|
|
119
|
+
parent.first = next;
|
|
120
|
+
if (parent.last === block)
|
|
121
|
+
parent.last = prev;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
export function pause_block(block) {
|
|
125
|
+
if ((block.f & PAUSED) !== 0) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
block.f ^= PAUSED;
|
|
129
|
+
let child = block.first;
|
|
130
|
+
while (child !== null) {
|
|
131
|
+
const next = child.next;
|
|
132
|
+
pause_block(child);
|
|
133
|
+
child = next;
|
|
134
|
+
}
|
|
135
|
+
run_teardown(block);
|
|
136
|
+
}
|
|
137
|
+
export function resume_block(block) {
|
|
138
|
+
if ((block.f & PAUSED) === 0) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
block.f ^= PAUSED;
|
|
142
|
+
if (is_block_dirty(block)) {
|
|
143
|
+
schedule_update(block);
|
|
144
|
+
}
|
|
145
|
+
let child = block.first;
|
|
146
|
+
while (child !== null) {
|
|
147
|
+
const next = child.next;
|
|
148
|
+
resume_block(child);
|
|
149
|
+
child = next;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
export function is_destroyed(target_block) {
|
|
153
|
+
let block = target_block;
|
|
154
|
+
while (block !== null) {
|
|
155
|
+
const flags = block.f;
|
|
156
|
+
if ((flags & DESTROYED) !== 0) {
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
if ((flags & ROOT_BLOCK) !== 0) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
block = block.p;
|
|
163
|
+
}
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
export function destroy_block(block, remove_dom = true) {
|
|
167
|
+
block.f ^= DESTROYED;
|
|
168
|
+
let removed = false;
|
|
169
|
+
const f = block.f;
|
|
170
|
+
if ((remove_dom && (f & (BRANCH_BLOCK | ROOT_BLOCK)) !== 0 && (f & TRY_BLOCK) === 0) ||
|
|
171
|
+
(f & HEAD_BLOCK) !== 0) {
|
|
172
|
+
const s = block.s;
|
|
173
|
+
if (s !== null && s.start !== null) {
|
|
174
|
+
removed = true;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
destroy_block_children(block, remove_dom && !removed);
|
|
178
|
+
run_teardown(block);
|
|
179
|
+
const parent = block.p;
|
|
180
|
+
if (parent !== null && parent.first !== null) {
|
|
181
|
+
unlink_block(block);
|
|
182
|
+
}
|
|
183
|
+
block.fn = block.s = block.d = block.p = block.co = block.t = null;
|
|
184
|
+
}
|