@getforma/core 0.3.0 → 0.6.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 +201 -13
- package/dist/{chunk-KX5WRZH7.js → chunk-DPSAVBCP.js} +3 -4
- package/dist/chunk-DPSAVBCP.js.map +1 -0
- package/dist/{chunk-FPSLC62A.cjs → chunk-KH3F5NRU.cjs} +2 -4
- package/dist/chunk-KH3F5NRU.cjs.map +1 -0
- package/dist/{chunk-VKKPX4YU.js → chunk-TKGUHASG.js} +79 -19
- package/dist/chunk-TKGUHASG.js.map +1 -0
- package/dist/{chunk-VP5EOGM5.cjs → chunk-YSKF3VRA.cjs} +87 -26
- package/dist/chunk-YSKF3VRA.cjs.map +1 -0
- package/dist/forma-runtime-csp.js +2 -0
- package/dist/forma-runtime.js +2 -0
- package/dist/formajs-runtime-hardened.global.js +1 -1
- package/dist/formajs-runtime-hardened.global.js.map +1 -1
- package/dist/formajs-runtime.global.js +1 -1
- package/dist/formajs-runtime.global.js.map +1 -1
- package/dist/formajs.global.js +1 -1
- package/dist/formajs.global.js.map +1 -1
- package/dist/index.cjs +154 -96
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +83 -35
- package/dist/index.d.ts +83 -35
- package/dist/index.js +99 -40
- package/dist/index.js.map +1 -1
- package/dist/runtime-hardened.cjs +224 -60
- package/dist/runtime-hardened.cjs.map +1 -1
- package/dist/runtime-hardened.d.cts +86 -0
- package/dist/runtime-hardened.d.ts +86 -0
- package/dist/runtime-hardened.js +225 -61
- package/dist/runtime-hardened.js.map +1 -1
- package/dist/runtime.cjs +248 -83
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.js +226 -61
- package/dist/runtime.js.map +1 -1
- package/dist/ssr/index.cjs +69 -73
- package/dist/ssr/index.cjs.map +1 -1
- package/dist/ssr/index.d.cts +4 -0
- package/dist/ssr/index.d.ts +4 -0
- package/dist/ssr/index.js +69 -73
- package/dist/ssr/index.js.map +1 -1
- package/dist/tc39-compat.cjs +3 -3
- package/dist/tc39-compat.js +1 -1
- package/package.json +24 -3
- package/dist/chunk-FPSLC62A.cjs.map +0 -1
- package/dist/chunk-KX5WRZH7.js.map +0 -1
- package/dist/chunk-VKKPX4YU.js.map +0 -1
- package/dist/chunk-VP5EOGM5.cjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { internalEffect, createRoot, hydrateIsland, untrack, createEffect, pushSuspenseContext, popSuspenseContext, batch } from './chunk-
|
|
2
|
-
export { Fragment, batch, cleanup, createEffect, createList, createMemo, createReducer, createRef, createResource, createRoot, createShow, fragment, h, hydrateIsland,
|
|
3
|
-
import { createSignal
|
|
4
|
-
export { createComputed, createSignal } from './chunk-
|
|
1
|
+
import { internalEffect, createRoot, hydrateIsland, untrack, createEffect, pushSuspenseContext, popSuspenseContext, __DEV__, reportError, batch } from './chunk-TKGUHASG.js';
|
|
2
|
+
export { Fragment, batch, cleanup, createEffect, createList, createMemo, createReducer, createRef, createResource, createRoot, createShow, fragment, h, hydrateIsland, on, onCleanup, onError, reconcileList, untrack } from './chunk-TKGUHASG.js';
|
|
3
|
+
import { createSignal } from './chunk-DPSAVBCP.js';
|
|
4
|
+
export { createComputed, createSignal } from './chunk-DPSAVBCP.js';
|
|
5
5
|
|
|
6
6
|
// src/dom/text.ts
|
|
7
7
|
function createText(value) {
|
|
@@ -238,14 +238,11 @@ function activateIslands(registry2) {
|
|
|
238
238
|
const componentName = root.getAttribute("data-forma-component");
|
|
239
239
|
const hydrateFn = registry2[componentName];
|
|
240
240
|
if (!hydrateFn) {
|
|
241
|
-
console.warn(`[forma] No hydrate function for island "${componentName}" (id=${id})`);
|
|
241
|
+
if (__DEV__) console.warn(`[forma] No hydrate function for island "${componentName}" (id=${id})`);
|
|
242
242
|
root.setAttribute("data-forma-status", "error");
|
|
243
243
|
continue;
|
|
244
244
|
}
|
|
245
245
|
const trigger = root.getAttribute("data-forma-hydrate") || "load";
|
|
246
|
-
if (trigger === "interaction" || trigger === "idle") {
|
|
247
|
-
console.warn(`[forma] Trigger "${trigger}" not yet implemented for island "${componentName}" (id=${id}), falling back to load`);
|
|
248
|
-
}
|
|
249
246
|
if (trigger === "visible") {
|
|
250
247
|
const observer = new IntersectionObserver(
|
|
251
248
|
(entries) => {
|
|
@@ -258,23 +255,52 @@ function activateIslands(registry2) {
|
|
|
258
255
|
{ rootMargin: "200px" }
|
|
259
256
|
);
|
|
260
257
|
observer.observe(root);
|
|
258
|
+
} else if (trigger === "idle") {
|
|
259
|
+
const hydrate = () => hydrateIslandRoot(root, id, componentName, hydrateFn, sharedProps);
|
|
260
|
+
if (typeof requestIdleCallback === "function") {
|
|
261
|
+
requestIdleCallback(hydrate);
|
|
262
|
+
} else {
|
|
263
|
+
setTimeout(hydrate, 200);
|
|
264
|
+
}
|
|
265
|
+
} else if (trigger === "interaction") {
|
|
266
|
+
const hydrate = () => {
|
|
267
|
+
root.removeEventListener("pointerdown", hydrate, true);
|
|
268
|
+
root.removeEventListener("focusin", hydrate, true);
|
|
269
|
+
hydrateIslandRoot(root, id, componentName, hydrateFn, sharedProps);
|
|
270
|
+
};
|
|
271
|
+
root.addEventListener("pointerdown", hydrate, { capture: true, once: true });
|
|
272
|
+
root.addEventListener("focusin", hydrate, { capture: true, once: true });
|
|
261
273
|
} else {
|
|
262
274
|
hydrateIslandRoot(root, id, componentName, hydrateFn, sharedProps);
|
|
263
275
|
}
|
|
264
276
|
}
|
|
265
277
|
}
|
|
278
|
+
function deactivateIsland(el) {
|
|
279
|
+
const dispose = el.__formaDispose;
|
|
280
|
+
if (typeof dispose === "function") {
|
|
281
|
+
dispose();
|
|
282
|
+
delete el.__formaDispose;
|
|
283
|
+
el.setAttribute("data-forma-status", "disposed");
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
function deactivateAllIslands(root = document) {
|
|
287
|
+
const islands = root.querySelectorAll('[data-forma-status="active"]');
|
|
288
|
+
for (const island of islands) {
|
|
289
|
+
deactivateIsland(island);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
266
292
|
function hydrateIslandRoot(root, id, componentName, hydrateFn, sharedProps) {
|
|
267
293
|
try {
|
|
268
294
|
const props = loadIslandProps(root, id, sharedProps);
|
|
269
295
|
root.setAttribute("data-forma-status", "hydrating");
|
|
270
296
|
let activeRoot = root;
|
|
271
297
|
createRoot((dispose) => {
|
|
272
|
-
activeRoot = hydrateIsland(() => hydrateFn(props), root);
|
|
298
|
+
activeRoot = hydrateIsland(() => hydrateFn(root, props), root);
|
|
273
299
|
activeRoot.__formaDispose = dispose;
|
|
274
300
|
});
|
|
275
301
|
activeRoot.setAttribute("data-forma-status", "active");
|
|
276
302
|
} catch (err) {
|
|
277
|
-
console.error(`[forma] Island "${componentName}" (id=${id}) failed:`, err);
|
|
303
|
+
if (__DEV__) console.error(`[forma] Island "${componentName}" (id=${id}) failed:`, err);
|
|
278
304
|
root.setAttribute("data-forma-status", "error");
|
|
279
305
|
}
|
|
280
306
|
}
|
|
@@ -322,13 +348,15 @@ function defineComponent(setupOrDef) {
|
|
|
322
348
|
for (const cb of ctx.unmountCallbacks) {
|
|
323
349
|
try {
|
|
324
350
|
cb();
|
|
325
|
-
} catch {
|
|
351
|
+
} catch (e) {
|
|
352
|
+
reportError(e, "onUnmount");
|
|
326
353
|
}
|
|
327
354
|
}
|
|
328
355
|
for (const d of ctx.disposers) {
|
|
329
356
|
try {
|
|
330
357
|
d();
|
|
331
|
-
} catch {
|
|
358
|
+
} catch (e) {
|
|
359
|
+
reportError(e, "component disposer");
|
|
332
360
|
}
|
|
333
361
|
}
|
|
334
362
|
ctx.disposers.length = 0;
|
|
@@ -342,7 +370,8 @@ function defineComponent(setupOrDef) {
|
|
|
342
370
|
if (typeof cleanup2 === "function") {
|
|
343
371
|
ctx.unmountCallbacks.push(cleanup2);
|
|
344
372
|
}
|
|
345
|
-
} catch {
|
|
373
|
+
} catch (e) {
|
|
374
|
+
reportError(e, "onMount");
|
|
346
375
|
}
|
|
347
376
|
}
|
|
348
377
|
return dom;
|
|
@@ -616,9 +645,9 @@ function createHistory(source, options) {
|
|
|
616
645
|
const maxLength = options?.maxLength ?? 100;
|
|
617
646
|
let _stack = [sourceGet()];
|
|
618
647
|
let _cursor = 0;
|
|
619
|
-
const [stackSignal, setStackSignal] =
|
|
620
|
-
const [cursorSignal, setCursorSignal] =
|
|
621
|
-
const [stackLenSignal, setStackLenSignal] =
|
|
648
|
+
const [stackSignal, setStackSignal] = createSignal([..._stack]);
|
|
649
|
+
const [cursorSignal, setCursorSignal] = createSignal(_cursor);
|
|
650
|
+
const [stackLenSignal, setStackLenSignal] = createSignal(_stack.length);
|
|
622
651
|
function syncSignals() {
|
|
623
652
|
batch(() => {
|
|
624
653
|
setStackSignal([..._stack]);
|
|
@@ -685,11 +714,14 @@ function persist(source, key, options) {
|
|
|
685
714
|
const storage = options?.storage ?? globalThis.localStorage;
|
|
686
715
|
const serialize = options?.serialize ?? JSON.stringify;
|
|
687
716
|
const deserialize = options?.deserialize ?? JSON.parse;
|
|
717
|
+
const validate = options?.validate;
|
|
688
718
|
try {
|
|
689
719
|
const stored = storage.getItem(key);
|
|
690
720
|
if (stored !== null) {
|
|
691
721
|
const value = deserialize(stored);
|
|
692
|
-
|
|
722
|
+
if (!validate || validate(value)) {
|
|
723
|
+
sourceSet(value);
|
|
724
|
+
}
|
|
693
725
|
}
|
|
694
726
|
} catch {
|
|
695
727
|
}
|
|
@@ -870,6 +902,9 @@ function setText(el, text) {
|
|
|
870
902
|
function setHTML(el, html) {
|
|
871
903
|
el.innerHTML = html;
|
|
872
904
|
}
|
|
905
|
+
function setHTMLUnsafe(el, html) {
|
|
906
|
+
el.innerHTML = html;
|
|
907
|
+
}
|
|
873
908
|
|
|
874
909
|
// src/dom-utils/traverse.ts
|
|
875
910
|
function closest(el, selector) {
|
|
@@ -953,20 +988,26 @@ function onMutation(el, handler, options) {
|
|
|
953
988
|
function createLocalStorage(key, options) {
|
|
954
989
|
const serialize = options?.serialize ?? JSON.stringify;
|
|
955
990
|
const deserialize = options?.deserialize ?? JSON.parse;
|
|
991
|
+
const validate = options?.validate;
|
|
956
992
|
return {
|
|
957
993
|
key,
|
|
958
994
|
get() {
|
|
959
995
|
try {
|
|
960
996
|
const raw = localStorage.getItem(key);
|
|
961
997
|
if (raw === null) return null;
|
|
962
|
-
|
|
998
|
+
const value = deserialize(raw);
|
|
999
|
+
if (validate && !validate(value)) return null;
|
|
1000
|
+
return value;
|
|
963
1001
|
} catch {
|
|
964
1002
|
return null;
|
|
965
1003
|
}
|
|
966
1004
|
},
|
|
967
1005
|
set(value) {
|
|
968
|
-
|
|
969
|
-
|
|
1006
|
+
try {
|
|
1007
|
+
const serialized = serialize(value);
|
|
1008
|
+
localStorage.setItem(key, serialized);
|
|
1009
|
+
} catch {
|
|
1010
|
+
}
|
|
970
1011
|
},
|
|
971
1012
|
remove() {
|
|
972
1013
|
localStorage.removeItem(key);
|
|
@@ -978,20 +1019,26 @@ function createLocalStorage(key, options) {
|
|
|
978
1019
|
function createSessionStorage(key, options) {
|
|
979
1020
|
const serialize = options?.serialize ?? JSON.stringify;
|
|
980
1021
|
const deserialize = options?.deserialize ?? JSON.parse;
|
|
1022
|
+
const validate = options?.validate;
|
|
981
1023
|
return {
|
|
982
1024
|
key,
|
|
983
1025
|
get() {
|
|
984
1026
|
try {
|
|
985
1027
|
const raw = sessionStorage.getItem(key);
|
|
986
1028
|
if (raw === null) return null;
|
|
987
|
-
|
|
1029
|
+
const value = deserialize(raw);
|
|
1030
|
+
if (validate && !validate(value)) return null;
|
|
1031
|
+
return value;
|
|
988
1032
|
} catch {
|
|
989
1033
|
return null;
|
|
990
1034
|
}
|
|
991
1035
|
},
|
|
992
1036
|
set(value) {
|
|
993
|
-
|
|
994
|
-
|
|
1037
|
+
try {
|
|
1038
|
+
const serialized = serialize(value);
|
|
1039
|
+
sessionStorage.setItem(key, serialized);
|
|
1040
|
+
} catch {
|
|
1041
|
+
}
|
|
995
1042
|
},
|
|
996
1043
|
remove() {
|
|
997
1044
|
sessionStorage.removeItem(key);
|
|
@@ -1122,7 +1169,7 @@ function createFetch(url, options) {
|
|
|
1122
1169
|
const transformed = transform ? transform(json) : json;
|
|
1123
1170
|
setData(transformed);
|
|
1124
1171
|
} catch (err) {
|
|
1125
|
-
if (err
|
|
1172
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
1126
1173
|
return;
|
|
1127
1174
|
}
|
|
1128
1175
|
setError(err instanceof Error ? err : new Error(String(err)));
|
|
@@ -1174,13 +1221,15 @@ function createSSE(url, options) {
|
|
|
1174
1221
|
setConnected(true);
|
|
1175
1222
|
setError(null);
|
|
1176
1223
|
};
|
|
1177
|
-
|
|
1224
|
+
const parseMessage = options?.parse ?? ((raw) => {
|
|
1178
1225
|
try {
|
|
1179
|
-
|
|
1180
|
-
setData(parsed);
|
|
1226
|
+
return JSON.parse(raw);
|
|
1181
1227
|
} catch {
|
|
1182
|
-
|
|
1228
|
+
return raw;
|
|
1183
1229
|
}
|
|
1230
|
+
});
|
|
1231
|
+
source.onmessage = (event) => {
|
|
1232
|
+
setData(parseMessage(event.data));
|
|
1184
1233
|
};
|
|
1185
1234
|
source.onerror = (event) => {
|
|
1186
1235
|
setError(event);
|
|
@@ -1195,12 +1244,15 @@ function createSSE(url, options) {
|
|
|
1195
1244
|
setConnected(false);
|
|
1196
1245
|
},
|
|
1197
1246
|
on(event, handler) {
|
|
1198
|
-
const
|
|
1247
|
+
const parseEvent = options?.parse ?? ((raw) => {
|
|
1199
1248
|
try {
|
|
1200
|
-
|
|
1249
|
+
return JSON.parse(raw);
|
|
1201
1250
|
} catch {
|
|
1202
|
-
|
|
1251
|
+
return raw;
|
|
1203
1252
|
}
|
|
1253
|
+
});
|
|
1254
|
+
const listener = (e) => {
|
|
1255
|
+
handler(parseEvent(e.data));
|
|
1204
1256
|
};
|
|
1205
1257
|
source.addEventListener(event, listener);
|
|
1206
1258
|
return () => {
|
|
@@ -1230,13 +1282,15 @@ function createWebSocket(url, options) {
|
|
|
1230
1282
|
setStatus("open");
|
|
1231
1283
|
reconnectCount = 0;
|
|
1232
1284
|
};
|
|
1233
|
-
|
|
1234
|
-
let parsed;
|
|
1285
|
+
const parseMessage = options?.parse ?? ((raw) => {
|
|
1235
1286
|
try {
|
|
1236
|
-
|
|
1287
|
+
return JSON.parse(raw);
|
|
1237
1288
|
} catch {
|
|
1238
|
-
|
|
1289
|
+
return raw;
|
|
1239
1290
|
}
|
|
1291
|
+
});
|
|
1292
|
+
socket.onmessage = (event) => {
|
|
1293
|
+
const parsed = parseMessage(event.data);
|
|
1240
1294
|
setData(parsed);
|
|
1241
1295
|
for (const handler of handlers) {
|
|
1242
1296
|
handler(parsed);
|
|
@@ -1290,8 +1344,8 @@ function createWebSocket(url, options) {
|
|
|
1290
1344
|
|
|
1291
1345
|
// src/server/action.ts
|
|
1292
1346
|
function createAction(serverFn, options) {
|
|
1293
|
-
const [pending, setPending] =
|
|
1294
|
-
const [error, setError] =
|
|
1347
|
+
const [pending, setPending] = createSignal(false);
|
|
1348
|
+
const [error, setError] = createSignal(void 0);
|
|
1295
1349
|
const action = async (...args) => {
|
|
1296
1350
|
setPending(true);
|
|
1297
1351
|
setError(void 0);
|
|
@@ -1349,6 +1403,10 @@ function applyRevalidation(revalidateData) {
|
|
|
1349
1403
|
}
|
|
1350
1404
|
}
|
|
1351
1405
|
function enableAutoRevalidation() {
|
|
1406
|
+
if (typeof window === "undefined") {
|
|
1407
|
+
return () => {
|
|
1408
|
+
};
|
|
1409
|
+
}
|
|
1352
1410
|
const handler = (event) => {
|
|
1353
1411
|
const detail = event.detail;
|
|
1354
1412
|
if (detail && typeof detail === "object") {
|
|
@@ -1417,9 +1475,10 @@ async function handleRPC(endpoint, body, revalidateData) {
|
|
|
1417
1475
|
if (revalidateData) {
|
|
1418
1476
|
return { data: result, __revalidate: revalidateData };
|
|
1419
1477
|
}
|
|
1420
|
-
return result;
|
|
1478
|
+
return { data: result };
|
|
1421
1479
|
} catch (err) {
|
|
1422
|
-
const
|
|
1480
|
+
const isDev = typeof process !== "undefined" && process.env?.NODE_ENV === "development";
|
|
1481
|
+
const message = isDev && err instanceof Error ? err.message : "Internal server error";
|
|
1423
1482
|
return { error: message };
|
|
1424
1483
|
}
|
|
1425
1484
|
}
|
|
@@ -1477,6 +1536,6 @@ async function renderIsland(slotsJson, islandId) {
|
|
|
1477
1536
|
return wasm.render_island(ir, slotsJson, islandId);
|
|
1478
1537
|
}
|
|
1479
1538
|
|
|
1480
|
-
export { $, $$, $$serverFunction, activateIslands, addClass, applyRevalidation, children, closest, createAction, createBus, createContext, createErrorBoundary, createFetch, createHistory, createIndexedDB, createLocalStorage, createPortal, createRPCMiddleware, createSSE, createSessionStorage, createStore, createSuspense, createSwitch, createText, createWebSocket, defineComponent, delegate, disposeComponent, enableAutoRevalidation, fetchJSON, getRegisteredEndpoints, getServerFunction, handleRPC, inject, mount, nextSibling, onIntersect, onKey, onMount, onMutation, onResize, onUnmount, parent, persist, prevSibling, provide, registerResource, registerServerFunction, removeClass, renderIsland, renderLocal, setAttr, setHTML, setStyle, setText, siblings, toggleClass, trackDisposer, unprovide, unregisterResource, withRevalidation };
|
|
1539
|
+
export { $, $$, $$serverFunction, activateIslands, addClass, applyRevalidation, children, closest, createAction, createBus, createContext, createErrorBoundary, createFetch, createHistory, createIndexedDB, createLocalStorage, createPortal, createRPCMiddleware, createSSE, createSessionStorage, createStore, createSuspense, createSwitch, createText, createWebSocket, deactivateAllIslands, deactivateIsland, defineComponent, delegate, disposeComponent, enableAutoRevalidation, fetchJSON, getRegisteredEndpoints, getServerFunction, handleRPC, inject, mount, nextSibling, onIntersect, onKey, onMount, onMutation, onResize, onUnmount, parent, persist, prevSibling, provide, registerResource, registerServerFunction, removeClass, renderIsland, renderLocal, setAttr, setHTML, setHTMLUnsafe, setStyle, setText, siblings, toggleClass, trackDisposer, unprovide, unregisterResource, withRevalidation };
|
|
1481
1540
|
//# sourceMappingURL=index.js.map
|
|
1482
1541
|
//# sourceMappingURL=index.js.map
|