@getforma/core 0.9.1 → 1.0.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.
Files changed (44) hide show
  1. package/README.md +20 -1
  2. package/dist/chunk-DCTOXHPF.cjs +399 -0
  3. package/dist/chunk-DCTOXHPF.cjs.map +1 -0
  4. package/dist/chunk-OUVOAYIO.js +359 -0
  5. package/dist/chunk-OUVOAYIO.js.map +1 -0
  6. package/dist/{chunk-GDULJFJO.cjs → chunk-V732ZBCU.cjs} +119 -511
  7. package/dist/chunk-V732ZBCU.cjs.map +1 -0
  8. package/dist/{chunk-CN56FSDT.js → chunk-VTPFK5TJ.js} +89 -442
  9. package/dist/chunk-VTPFK5TJ.js.map +1 -0
  10. package/dist/formajs.global.js +1 -1
  11. package/dist/formajs.global.js.map +1 -1
  12. package/dist/http.cjs +225 -0
  13. package/dist/http.cjs.map +1 -0
  14. package/dist/http.d.cts +108 -0
  15. package/dist/http.d.ts +108 -0
  16. package/dist/http.js +220 -0
  17. package/dist/http.js.map +1 -0
  18. package/dist/index.cjs +71 -607
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +2 -456
  21. package/dist/index.d.ts +2 -456
  22. package/dist/index.js +7 -523
  23. package/dist/index.js.map +1 -1
  24. package/dist/resource-Cd0cGOxS.d.ts +62 -0
  25. package/dist/resource-DK98lW5e.d.cts +62 -0
  26. package/dist/runtime.cjs +23 -22
  27. package/dist/runtime.cjs.map +1 -1
  28. package/dist/runtime.js +2 -1
  29. package/dist/runtime.js.map +1 -1
  30. package/dist/server.cjs +179 -0
  31. package/dist/server.cjs.map +1 -0
  32. package/dist/server.d.cts +217 -0
  33. package/dist/server.d.ts +217 -0
  34. package/dist/server.js +166 -0
  35. package/dist/server.js.map +1 -0
  36. package/dist/storage.cjs +151 -0
  37. package/dist/storage.cjs.map +1 -0
  38. package/dist/storage.d.cts +77 -0
  39. package/dist/storage.d.ts +77 -0
  40. package/dist/storage.js +147 -0
  41. package/dist/storage.js.map +1 -0
  42. package/package.json +31 -1
  43. package/dist/chunk-CN56FSDT.js.map +0 -1
  44. package/dist/chunk-GDULJFJO.cjs.map +0 -1
package/dist/index.js CHANGED
@@ -1,5 +1,7 @@
1
- import { internalEffect, createRoot, hydrateIsland, untrack, createEffect, pushSuspenseContext, popSuspenseContext, __DEV__, reportError, batch } from './chunk-CN56FSDT.js';
2
- export { Fragment, batch, cleanup, createEffect, createList, createMemo, createReducer, createRef, createResource, createRoot, createShow, fragment, getBatchDepth, h, hydrateIsland, isComputed, isEffect, isEffectScope, isSignal, on, onCleanup, onError, reconcileList, trigger, untrack } from './chunk-CN56FSDT.js';
1
+ import { hydrateIsland } from './chunk-VTPFK5TJ.js';
2
+ export { Fragment, cleanup, createList, createShow, fragment, h, hydrateIsland, reconcileList } from './chunk-VTPFK5TJ.js';
3
+ import { internalEffect, createRoot, untrack, createEffect, pushSuspenseContext, popSuspenseContext, __DEV__, reportError, batch } from './chunk-OUVOAYIO.js';
4
+ export { batch, createEffect, createMemo, createReducer, createRef, createResource, createRoot, getBatchDepth, isComputed, isEffect, isEffectScope, isSignal, on, onCleanup, onError, trigger, untrack } from './chunk-OUVOAYIO.js';
3
5
  import { createSignal } from './chunk-OZCHIVAZ.js';
4
6
  export { createComputed, createSignal } from './chunk-OZCHIVAZ.js';
5
7
 
@@ -236,14 +238,14 @@ function loadIslandProps(root, id, sharedProps) {
236
238
  }
237
239
  return null;
238
240
  }
239
- function activateIslands(registry2) {
241
+ function activateIslands(registry) {
240
242
  const scriptBlock = document.getElementById("__forma_islands");
241
243
  const sharedProps = scriptBlock ? JSON.parse(scriptBlock.textContent) : null;
242
244
  const islands = document.querySelectorAll("[data-forma-island]");
243
245
  for (const root of islands) {
244
246
  const id = parseInt(root.getAttribute("data-forma-island"), 10);
245
247
  const componentName = root.getAttribute("data-forma-component");
246
- const hydrateFn = registry2[componentName];
248
+ const hydrateFn = registry[componentName];
247
249
  if (!hydrateFn) {
248
250
  if (__DEV__) console.warn(`[forma] No hydrate function for island "${componentName}" (id=${id})`);
249
251
  root.setAttribute("data-forma-status", "error");
@@ -993,524 +995,6 @@ function onMutation(el, handler, options) {
993
995
  };
994
996
  }
995
997
 
996
- // src/storage/local.ts
997
- function createLocalStorage(key, options) {
998
- const serialize = options?.serialize ?? JSON.stringify;
999
- const deserialize = options?.deserialize ?? JSON.parse;
1000
- const validate = options?.validate;
1001
- return {
1002
- key,
1003
- get() {
1004
- try {
1005
- const raw = localStorage.getItem(key);
1006
- if (raw === null) return null;
1007
- const value = deserialize(raw);
1008
- if (validate && !validate(value)) return null;
1009
- return value;
1010
- } catch {
1011
- return null;
1012
- }
1013
- },
1014
- set(value) {
1015
- try {
1016
- const serialized = serialize(value);
1017
- localStorage.setItem(key, serialized);
1018
- } catch {
1019
- }
1020
- },
1021
- remove() {
1022
- localStorage.removeItem(key);
1023
- }
1024
- };
1025
- }
1026
-
1027
- // src/storage/session.ts
1028
- function createSessionStorage(key, options) {
1029
- const serialize = options?.serialize ?? JSON.stringify;
1030
- const deserialize = options?.deserialize ?? JSON.parse;
1031
- const validate = options?.validate;
1032
- return {
1033
- key,
1034
- get() {
1035
- try {
1036
- const raw = sessionStorage.getItem(key);
1037
- if (raw === null) return null;
1038
- const value = deserialize(raw);
1039
- if (validate && !validate(value)) return null;
1040
- return value;
1041
- } catch {
1042
- return null;
1043
- }
1044
- },
1045
- set(value) {
1046
- try {
1047
- const serialized = serialize(value);
1048
- sessionStorage.setItem(key, serialized);
1049
- } catch {
1050
- }
1051
- },
1052
- remove() {
1053
- sessionStorage.removeItem(key);
1054
- }
1055
- };
1056
- }
1057
-
1058
- // src/storage/indexed.ts
1059
- var dbCache = /* @__PURE__ */ new Map();
1060
- function openDB(dbName, storeName) {
1061
- const cacheKey = `${dbName}::${storeName}`;
1062
- const cached = dbCache.get(cacheKey);
1063
- if (cached) return cached;
1064
- const promise = new Promise((resolve, reject) => {
1065
- const probe = indexedDB.open(dbName);
1066
- probe.onerror = () => reject(probe.error);
1067
- probe.onsuccess = () => {
1068
- const db = probe.result;
1069
- if (db.objectStoreNames.contains(storeName)) {
1070
- resolve(db);
1071
- return;
1072
- }
1073
- const nextVersion = db.version + 1;
1074
- db.close();
1075
- const upgrade = indexedDB.open(dbName, nextVersion);
1076
- upgrade.onerror = () => reject(upgrade.error);
1077
- upgrade.onupgradeneeded = () => {
1078
- const upgradedDB = upgrade.result;
1079
- if (!upgradedDB.objectStoreNames.contains(storeName)) {
1080
- upgradedDB.createObjectStore(storeName);
1081
- }
1082
- };
1083
- upgrade.onsuccess = () => resolve(upgrade.result);
1084
- };
1085
- probe.onupgradeneeded = () => {
1086
- const db = probe.result;
1087
- if (!db.objectStoreNames.contains(storeName)) {
1088
- db.createObjectStore(storeName);
1089
- }
1090
- };
1091
- });
1092
- dbCache.set(cacheKey, promise);
1093
- promise.catch(() => {
1094
- dbCache.delete(cacheKey);
1095
- });
1096
- return promise;
1097
- }
1098
- function createIndexedDB(dbName, storeName = "default") {
1099
- function withStore(mode, fn) {
1100
- return openDB(dbName, storeName).then(
1101
- (db) => new Promise((resolve, reject) => {
1102
- const tx = db.transaction(storeName, mode);
1103
- const store = tx.objectStore(storeName);
1104
- const request = fn(store);
1105
- request.onsuccess = () => resolve(request.result);
1106
- request.onerror = () => reject(request.error);
1107
- })
1108
- );
1109
- }
1110
- return {
1111
- get(key) {
1112
- return withStore("readonly", (store) => store.get(key));
1113
- },
1114
- set(key, value) {
1115
- return withStore("readwrite", (store) => store.put(value, key)).then(
1116
- () => void 0
1117
- );
1118
- },
1119
- delete(key) {
1120
- return withStore("readwrite", (store) => store.delete(key)).then(
1121
- () => void 0
1122
- );
1123
- },
1124
- getAll() {
1125
- return withStore("readonly", (store) => store.getAll());
1126
- },
1127
- keys() {
1128
- return withStore("readonly", (store) => store.getAllKeys()).then(
1129
- (keys) => keys.map(String)
1130
- );
1131
- },
1132
- clear() {
1133
- return withStore("readwrite", (store) => store.clear()).then(
1134
- () => void 0
1135
- );
1136
- }
1137
- };
1138
- }
1139
-
1140
- // src/http/fetch.ts
1141
- function createFetch(url, options) {
1142
- const [data, setData] = createSignal(null);
1143
- const [error, setError] = createSignal(null);
1144
- const [loading, setLoading] = createSignal(false);
1145
- let currentController = null;
1146
- function resolveURL() {
1147
- const raw = typeof url === "function" ? url() : url;
1148
- const base = options?.base ?? "";
1149
- const fullURL = new URL(raw, base || void 0);
1150
- if (options?.params) {
1151
- for (const [key, value] of Object.entries(options.params)) {
1152
- fullURL.searchParams.set(key, value);
1153
- }
1154
- }
1155
- return fullURL.toString();
1156
- }
1157
- async function execute() {
1158
- if (currentController) {
1159
- currentController.abort();
1160
- }
1161
- currentController = new AbortController();
1162
- const controller = currentController;
1163
- const timeoutMs = options?.timeout ?? 3e4;
1164
- const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
1165
- setLoading(true);
1166
- setError(null);
1167
- try {
1168
- const resolvedURL = resolveURL();
1169
- const { base: _base, params: _params, timeout: _timeout, transform, ...fetchInit } = options ?? {};
1170
- const response = await fetch(resolvedURL, {
1171
- ...fetchInit,
1172
- signal: controller.signal
1173
- });
1174
- if (!response.ok) {
1175
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
1176
- }
1177
- const json = await response.json();
1178
- const transformed = transform ? transform(json) : json;
1179
- setData(transformed);
1180
- } catch (err) {
1181
- if (err instanceof Error && err.name === "AbortError") {
1182
- return;
1183
- }
1184
- setError(err instanceof Error ? err : new Error(String(err)));
1185
- } finally {
1186
- clearTimeout(timeoutId);
1187
- if (currentController === controller) {
1188
- currentController = null;
1189
- setLoading(false);
1190
- }
1191
- }
1192
- }
1193
- if (typeof url === "function") {
1194
- internalEffect(() => {
1195
- url();
1196
- execute();
1197
- });
1198
- } else {
1199
- execute();
1200
- }
1201
- return {
1202
- data,
1203
- error,
1204
- loading,
1205
- refetch: execute,
1206
- abort() {
1207
- if (currentController) {
1208
- currentController.abort();
1209
- }
1210
- }
1211
- };
1212
- }
1213
- async function fetchJSON(url, options) {
1214
- const response = await fetch(url, options);
1215
- if (!response.ok) {
1216
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
1217
- }
1218
- return await response.json();
1219
- }
1220
-
1221
- // src/http/sse.ts
1222
- function createSSE(url, options) {
1223
- const [data, setData] = createSignal(null);
1224
- const [error, setError] = createSignal(null);
1225
- const [connected, setConnected] = createSignal(false);
1226
- const source = new EventSource(url, {
1227
- withCredentials: options?.withCredentials ?? false
1228
- });
1229
- source.onopen = () => {
1230
- setConnected(true);
1231
- setError(null);
1232
- };
1233
- const parseMessage = options?.parse ?? ((raw) => {
1234
- try {
1235
- return JSON.parse(raw);
1236
- } catch {
1237
- return raw;
1238
- }
1239
- });
1240
- source.onmessage = (event) => {
1241
- setData(parseMessage(event.data));
1242
- };
1243
- source.onerror = (event) => {
1244
- setError(event);
1245
- setConnected(false);
1246
- };
1247
- return {
1248
- data,
1249
- error,
1250
- connected,
1251
- close() {
1252
- source.close();
1253
- setConnected(false);
1254
- },
1255
- on(event, handler) {
1256
- const parseEvent = options?.parse ?? ((raw) => {
1257
- try {
1258
- return JSON.parse(raw);
1259
- } catch {
1260
- return raw;
1261
- }
1262
- });
1263
- const listener = (e) => {
1264
- handler(parseEvent(e.data));
1265
- };
1266
- source.addEventListener(event, listener);
1267
- return () => {
1268
- source.removeEventListener(event, listener);
1269
- };
1270
- }
1271
- };
1272
- }
1273
-
1274
- // src/http/ws.ts
1275
- function createWebSocket(url, options) {
1276
- const shouldReconnect = options?.reconnect ?? true;
1277
- const baseInterval = options?.reconnectInterval ?? 1e3;
1278
- const maxReconnects = options?.maxReconnects ?? 5;
1279
- const [data, setData] = createSignal(null);
1280
- const [status, setStatus] = createSignal("connecting");
1281
- const handlers = /* @__PURE__ */ new Set();
1282
- let socket = null;
1283
- let reconnectCount = 0;
1284
- let reconnectTimer = null;
1285
- let permanentlyClosed = false;
1286
- function connect() {
1287
- if (permanentlyClosed) return;
1288
- setStatus("connecting");
1289
- socket = new WebSocket(url, options?.protocols);
1290
- socket.onopen = () => {
1291
- setStatus("open");
1292
- reconnectCount = 0;
1293
- };
1294
- const parseMessage = options?.parse ?? ((raw) => {
1295
- try {
1296
- return JSON.parse(raw);
1297
- } catch {
1298
- return raw;
1299
- }
1300
- });
1301
- socket.onmessage = (event) => {
1302
- const parsed = parseMessage(event.data);
1303
- setData(parsed);
1304
- for (const handler of handlers) {
1305
- handler(parsed);
1306
- }
1307
- };
1308
- socket.onerror = () => {
1309
- setStatus("error");
1310
- };
1311
- socket.onclose = () => {
1312
- if (permanentlyClosed) {
1313
- setStatus("closed");
1314
- return;
1315
- }
1316
- setStatus("closed");
1317
- if (shouldReconnect && reconnectCount < maxReconnects) {
1318
- const delay = baseInterval * Math.pow(2, reconnectCount);
1319
- reconnectCount++;
1320
- reconnectTimer = setTimeout(connect, delay);
1321
- }
1322
- };
1323
- }
1324
- connect();
1325
- return {
1326
- data,
1327
- status,
1328
- send(value) {
1329
- if (socket && socket.readyState === WebSocket.OPEN) {
1330
- socket.send(JSON.stringify(value));
1331
- }
1332
- },
1333
- close() {
1334
- permanentlyClosed = true;
1335
- if (reconnectTimer !== null) {
1336
- clearTimeout(reconnectTimer);
1337
- reconnectTimer = null;
1338
- }
1339
- if (socket) {
1340
- socket.close();
1341
- socket = null;
1342
- }
1343
- setStatus("closed");
1344
- },
1345
- on(handler) {
1346
- handlers.add(handler);
1347
- return () => {
1348
- handlers.delete(handler);
1349
- };
1350
- }
1351
- };
1352
- }
1353
-
1354
- // src/server/action.ts
1355
- function createAction(serverFn, options) {
1356
- const [pending, setPending] = createSignal(false);
1357
- const [error, setError] = createSignal(void 0);
1358
- const action = async (...args) => {
1359
- setPending(true);
1360
- setError(void 0);
1361
- if (options?.optimistic) {
1362
- try {
1363
- batch(() => options.optimistic(...args));
1364
- } catch {
1365
- }
1366
- }
1367
- try {
1368
- const result = await serverFn(...args);
1369
- if (options?.onSuccess) {
1370
- batch(() => options.onSuccess(result, ...args));
1371
- }
1372
- if (options?.invalidates) {
1373
- for (const resource of options.invalidates) {
1374
- resource.refetch();
1375
- }
1376
- }
1377
- setPending(false);
1378
- return result;
1379
- } catch (err) {
1380
- if (options?.onError) {
1381
- try {
1382
- batch(() => options.onError(err, ...args));
1383
- } catch {
1384
- }
1385
- }
1386
- setError(err);
1387
- setPending(false);
1388
- throw err;
1389
- }
1390
- };
1391
- const typedAction = action;
1392
- typedAction.pending = pending;
1393
- typedAction.error = error;
1394
- typedAction.clearError = () => setError(void 0);
1395
- return typedAction;
1396
- }
1397
-
1398
- // src/server/mutation.ts
1399
- var resourceRegistry = /* @__PURE__ */ new Map();
1400
- function registerResource(key, resource) {
1401
- resourceRegistry.set(key, resource);
1402
- }
1403
- function unregisterResource(key) {
1404
- resourceRegistry.delete(key);
1405
- }
1406
- function applyRevalidation(revalidateData) {
1407
- for (const [key, freshData] of Object.entries(revalidateData)) {
1408
- const resource = resourceRegistry.get(key);
1409
- if (resource) {
1410
- resource.mutate(freshData);
1411
- }
1412
- }
1413
- }
1414
- function enableAutoRevalidation() {
1415
- if (typeof window === "undefined") {
1416
- return () => {
1417
- };
1418
- }
1419
- const handler = (event) => {
1420
- const detail = event.detail;
1421
- if (detail && typeof detail === "object") {
1422
- applyRevalidation(detail);
1423
- }
1424
- };
1425
- window.addEventListener("forma:revalidate", handler);
1426
- return () => window.removeEventListener("forma:revalidate", handler);
1427
- }
1428
- function withRevalidation(data, revalidate) {
1429
- return { data, __revalidate: revalidate };
1430
- }
1431
-
1432
- // src/server/rpc-client.ts
1433
- function $$serverFunction(endpoint) {
1434
- const rpcFn = async (...args) => {
1435
- const response = await fetch(endpoint, {
1436
- method: "POST",
1437
- headers: {
1438
- "Content-Type": "application/json",
1439
- "X-Forma-RPC": "1"
1440
- },
1441
- body: JSON.stringify({ args })
1442
- });
1443
- if (!response.ok) {
1444
- const errorText = await response.text();
1445
- throw new Error(`Server function failed (${response.status}): ${errorText}`);
1446
- }
1447
- const result = await response.json();
1448
- if (result && typeof result === "object" && "__revalidate" in result) {
1449
- if (typeof window !== "undefined") {
1450
- window.dispatchEvent(new CustomEvent("forma:revalidate", {
1451
- detail: result.__revalidate
1452
- }));
1453
- }
1454
- return result.data;
1455
- }
1456
- return result;
1457
- };
1458
- return rpcFn;
1459
- }
1460
-
1461
- // src/server/rpc-handler.ts
1462
- var registry = /* @__PURE__ */ new Map();
1463
- function registerServerFunction(endpoint, fn) {
1464
- registry.set(endpoint, fn);
1465
- }
1466
- function getServerFunction(endpoint) {
1467
- return registry.get(endpoint);
1468
- }
1469
- function getRegisteredEndpoints() {
1470
- return [...registry.keys()];
1471
- }
1472
- var FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
1473
- async function handleRPC(endpoint, body, revalidateData) {
1474
- const endpointName = endpoint.split("/").pop() ?? "";
1475
- if (FORBIDDEN_KEYS.has(endpointName)) {
1476
- return { error: "Forbidden endpoint name" };
1477
- }
1478
- const fn = registry.get(endpoint);
1479
- if (!fn) {
1480
- return { error: `Unknown server function: ${endpoint}` };
1481
- }
1482
- try {
1483
- const result = await fn(...body.args);
1484
- if (revalidateData) {
1485
- return { data: result, __revalidate: revalidateData };
1486
- }
1487
- return { data: result };
1488
- } catch (err) {
1489
- const isDev = typeof process !== "undefined" && process.env?.NODE_ENV === "development";
1490
- const message = isDev && err instanceof Error ? err.message : "Internal server error";
1491
- return { error: message };
1492
- }
1493
- }
1494
- function createRPCMiddleware() {
1495
- return async (req, res) => {
1496
- if (req.method !== "POST") {
1497
- res.status(405).json({ error: "Method not allowed" });
1498
- return;
1499
- }
1500
- const body = req.body;
1501
- if (!body || !Array.isArray(body.args)) {
1502
- res.status(400).json({ error: "Invalid RPC request: missing args array" });
1503
- return;
1504
- }
1505
- const result = await handleRPC(req.url, body);
1506
- if (result.error) {
1507
- res.status(500).json(result);
1508
- } else {
1509
- res.json(result);
1510
- }
1511
- };
1512
- }
1513
-
1514
- 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, setAttr, setHTML, setHTMLUnsafe, setStyle, setText, siblings, toggleClass, trackDisposer, unprovide, unregisterResource, withRevalidation };
998
+ export { $, $$, activateIslands, addClass, children, closest, createBus, createContext, createErrorBoundary, createHistory, createPortal, createStore, createSuspense, createSwitch, createText, deactivateAllIslands, deactivateIsland, defineComponent, delegate, disposeComponent, inject, mount, nextSibling, onIntersect, onKey, onMount, onMutation, onResize, onUnmount, parent, persist, prevSibling, provide, removeClass, setAttr, setHTML, setHTMLUnsafe, setStyle, setText, siblings, toggleClass, trackDisposer, unprovide };
1515
999
  //# sourceMappingURL=index.js.map
1516
1000
  //# sourceMappingURL=index.js.map