@getforma/core 0.9.0 → 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.
- package/README.md +20 -1
- package/dist/chunk-DCTOXHPF.cjs +399 -0
- package/dist/chunk-DCTOXHPF.cjs.map +1 -0
- package/dist/chunk-OUVOAYIO.js +359 -0
- package/dist/chunk-OUVOAYIO.js.map +1 -0
- package/dist/{chunk-YMIMKO4W.cjs → chunk-V732ZBCU.cjs} +119 -511
- package/dist/chunk-V732ZBCU.cjs.map +1 -0
- package/dist/{chunk-N522P3G6.js → chunk-VTPFK5TJ.js} +89 -442
- package/dist/chunk-VTPFK5TJ.js.map +1 -0
- package/dist/forma-runtime-csp.js +1 -1
- package/dist/forma-runtime.js +1 -1
- 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/http.cjs +225 -0
- package/dist/http.cjs.map +1 -0
- package/dist/http.d.cts +108 -0
- package/dist/http.d.ts +108 -0
- package/dist/http.js +220 -0
- package/dist/http.js.map +1 -0
- package/dist/index.cjs +71 -607
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -458
- package/dist/index.d.ts +4 -458
- package/dist/index.js +7 -523
- package/dist/index.js.map +1 -1
- package/dist/resource-Cd0cGOxS.d.ts +62 -0
- package/dist/resource-DK98lW5e.d.cts +62 -0
- package/dist/runtime-hardened.cjs +3 -111
- package/dist/runtime-hardened.cjs.map +1 -1
- package/dist/runtime-hardened.js +4 -112
- package/dist/runtime-hardened.js.map +1 -1
- package/dist/runtime.cjs +23 -22
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.js +2 -1
- package/dist/runtime.js.map +1 -1
- package/dist/server.cjs +179 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +217 -0
- package/dist/server.d.ts +217 -0
- package/dist/server.js +166 -0
- package/dist/server.js.map +1 -0
- package/dist/{signal-B4_wQJHs.d.cts → signal-YlS1kgfh.d.cts} +1 -1
- package/dist/{signal-B4_wQJHs.d.ts → signal-YlS1kgfh.d.ts} +1 -1
- package/dist/storage.cjs +151 -0
- package/dist/storage.cjs.map +1 -0
- package/dist/storage.d.cts +77 -0
- package/dist/storage.d.ts +77 -0
- package/dist/storage.js +147 -0
- package/dist/storage.js.map +1 -0
- package/dist/tc39-compat.d.cts +1 -1
- package/dist/tc39-compat.d.ts +1 -1
- package/package.json +31 -1
- package/dist/chunk-N522P3G6.js.map +0 -1
- package/dist/chunk-YMIMKO4W.cjs.map +0 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { S as SignalGetter } from './signal-YlS1kgfh.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Forma Reactive - Resource
|
|
5
|
+
*
|
|
6
|
+
* Async data fetching primitive with reactive loading/error state.
|
|
7
|
+
* Tracks a source signal and refetches when it changes.
|
|
8
|
+
*
|
|
9
|
+
* SolidJS equivalent: createResource
|
|
10
|
+
* React equivalent: use() + Suspense (React 19), or useSWR/react-query
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
interface Resource<T> {
|
|
14
|
+
/** The resolved data (or undefined while loading). */
|
|
15
|
+
(): T | undefined;
|
|
16
|
+
/** True while the fetcher is running. */
|
|
17
|
+
loading: SignalGetter<boolean>;
|
|
18
|
+
/** The error if the fetcher rejected (or undefined). */
|
|
19
|
+
error: SignalGetter<unknown>;
|
|
20
|
+
/** Manually refetch with the current source value. */
|
|
21
|
+
refetch: () => void;
|
|
22
|
+
/** Manually set the data (overrides fetcher result). */
|
|
23
|
+
mutate: (value: T | undefined) => void;
|
|
24
|
+
}
|
|
25
|
+
interface ResourceOptions<T> {
|
|
26
|
+
/** Initial value before first fetch resolves. */
|
|
27
|
+
initialValue?: T;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Create an async resource that fetches data reactively.
|
|
31
|
+
*
|
|
32
|
+
* When `source` changes, the fetcher re-runs automatically.
|
|
33
|
+
* Provides reactive `loading` and `error` signals.
|
|
34
|
+
*
|
|
35
|
+
* ```ts
|
|
36
|
+
* const [userId, setUserId] = createSignal(1);
|
|
37
|
+
*
|
|
38
|
+
* const user = createResource(
|
|
39
|
+
* userId, // source signal
|
|
40
|
+
* (id) => fetch(`/api/users/${id}`).then(r => r.json()), // fetcher
|
|
41
|
+
* );
|
|
42
|
+
*
|
|
43
|
+
* internalEffect(() => {
|
|
44
|
+
* if (user.loading()) console.log('Loading...');
|
|
45
|
+
* else if (user.error()) console.log('Error:', user.error());
|
|
46
|
+
* else console.log('User:', user());
|
|
47
|
+
* });
|
|
48
|
+
*
|
|
49
|
+
* setUserId(2); // automatically refetches
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* Without a source signal (static fetch):
|
|
53
|
+
* ```ts
|
|
54
|
+
* const posts = createResource(
|
|
55
|
+
* () => true, // constant source — fetches once
|
|
56
|
+
* () => fetch('/api/posts').then(r => r.json()),
|
|
57
|
+
* );
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
declare function createResource<T, S = true>(source: SignalGetter<S>, fetcher: (source: S) => Promise<T>, options?: ResourceOptions<T>): Resource<T>;
|
|
61
|
+
|
|
62
|
+
export { type Resource as R, type ResourceOptions as a, createResource as c };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { S as SignalGetter } from './signal-YlS1kgfh.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Forma Reactive - Resource
|
|
5
|
+
*
|
|
6
|
+
* Async data fetching primitive with reactive loading/error state.
|
|
7
|
+
* Tracks a source signal and refetches when it changes.
|
|
8
|
+
*
|
|
9
|
+
* SolidJS equivalent: createResource
|
|
10
|
+
* React equivalent: use() + Suspense (React 19), or useSWR/react-query
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
interface Resource<T> {
|
|
14
|
+
/** The resolved data (or undefined while loading). */
|
|
15
|
+
(): T | undefined;
|
|
16
|
+
/** True while the fetcher is running. */
|
|
17
|
+
loading: SignalGetter<boolean>;
|
|
18
|
+
/** The error if the fetcher rejected (or undefined). */
|
|
19
|
+
error: SignalGetter<unknown>;
|
|
20
|
+
/** Manually refetch with the current source value. */
|
|
21
|
+
refetch: () => void;
|
|
22
|
+
/** Manually set the data (overrides fetcher result). */
|
|
23
|
+
mutate: (value: T | undefined) => void;
|
|
24
|
+
}
|
|
25
|
+
interface ResourceOptions<T> {
|
|
26
|
+
/** Initial value before first fetch resolves. */
|
|
27
|
+
initialValue?: T;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Create an async resource that fetches data reactively.
|
|
31
|
+
*
|
|
32
|
+
* When `source` changes, the fetcher re-runs automatically.
|
|
33
|
+
* Provides reactive `loading` and `error` signals.
|
|
34
|
+
*
|
|
35
|
+
* ```ts
|
|
36
|
+
* const [userId, setUserId] = createSignal(1);
|
|
37
|
+
*
|
|
38
|
+
* const user = createResource(
|
|
39
|
+
* userId, // source signal
|
|
40
|
+
* (id) => fetch(`/api/users/${id}`).then(r => r.json()), // fetcher
|
|
41
|
+
* );
|
|
42
|
+
*
|
|
43
|
+
* internalEffect(() => {
|
|
44
|
+
* if (user.loading()) console.log('Loading...');
|
|
45
|
+
* else if (user.error()) console.log('Error:', user.error());
|
|
46
|
+
* else console.log('User:', user());
|
|
47
|
+
* });
|
|
48
|
+
*
|
|
49
|
+
* setUserId(2); // automatically refetches
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* Without a source signal (static fetch):
|
|
53
|
+
* ```ts
|
|
54
|
+
* const posts = createResource(
|
|
55
|
+
* () => true, // constant source — fetches once
|
|
56
|
+
* () => fetch('/api/posts').then(r => r.json()),
|
|
57
|
+
* );
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
declare function createResource<T, S = true>(source: SignalGetter<S>, fetcher: (source: S) => Promise<T>, options?: ResourceOptions<T>): Resource<T>;
|
|
61
|
+
|
|
62
|
+
export { type Resource as R, type ResourceOptions as a, createResource as c };
|
|
@@ -890,7 +890,7 @@ var UNSAFE_METHOD_NAMES = /* @__PURE__ */ new Set([
|
|
|
890
890
|
"eval",
|
|
891
891
|
"Function"
|
|
892
892
|
]);
|
|
893
|
-
|
|
893
|
+
(() => {
|
|
894
894
|
const result = [];
|
|
895
895
|
for (const name of UNSAFE_METHOD_NAMES) {
|
|
896
896
|
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -904,44 +904,6 @@ var BLOCKED_METHOD_REGEXES = (() => {
|
|
|
904
904
|
}
|
|
905
905
|
return result;
|
|
906
906
|
})();
|
|
907
|
-
function findBlockedMethod(expr) {
|
|
908
|
-
let cleaned = expr.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
909
|
-
cleaned = cleaned.replace(/\/\/[^\n]*/g, "");
|
|
910
|
-
cleaned = cleaned.replace(/\s*\.\s*/g, ".");
|
|
911
|
-
for (const { name, dotRe, bracketRe } of BLOCKED_METHOD_REGEXES) {
|
|
912
|
-
if (dotRe.test(cleaned)) return name;
|
|
913
|
-
if (bracketRe.test(cleaned)) return name;
|
|
914
|
-
}
|
|
915
|
-
if (cleaned.includes("[")) {
|
|
916
|
-
const bracketContents = extractBracketContents(cleaned);
|
|
917
|
-
for (const content of bracketContents) {
|
|
918
|
-
if (!content.includes("+")) continue;
|
|
919
|
-
const fragments = content.match(/['"`]([^'"`]*?)['"`]/g);
|
|
920
|
-
if (!fragments) continue;
|
|
921
|
-
const joined = fragments.map((f) => f.slice(1, -1)).join("");
|
|
922
|
-
if (UNSAFE_METHOD_NAMES.has(joined)) return joined;
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
return null;
|
|
926
|
-
}
|
|
927
|
-
function extractBracketContents(expr) {
|
|
928
|
-
const results = [];
|
|
929
|
-
let depth = 0;
|
|
930
|
-
let start = -1;
|
|
931
|
-
for (let i = 0; i < expr.length; i++) {
|
|
932
|
-
if (expr[i] === "[") {
|
|
933
|
-
if (depth === 0) start = i + 1;
|
|
934
|
-
depth++;
|
|
935
|
-
} else if (expr[i] === "]") {
|
|
936
|
-
depth--;
|
|
937
|
-
if (depth === 0 && start >= 0) {
|
|
938
|
-
results.push(expr.slice(start, i));
|
|
939
|
-
start = -1;
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
return results;
|
|
944
|
-
}
|
|
945
907
|
var TEXT_BINDING_SYM = /* @__PURE__ */ Symbol.for("forma-text-binding-cache");
|
|
946
908
|
function toTextValue(value2) {
|
|
947
909
|
if (value2 == null) return "";
|
|
@@ -1945,40 +1907,13 @@ function buildEvaluator(expr, scope) {
|
|
|
1945
1907
|
cache.set(cleaned, cspFn);
|
|
1946
1908
|
return cspFn;
|
|
1947
1909
|
}
|
|
1948
|
-
|
|
1910
|
+
{
|
|
1949
1911
|
dbg("buildEvaluator: blocked unsafe eval fallback for expression:", cleaned);
|
|
1950
1912
|
reportDiagnostic("expression-unsupported", cleaned, cspExpressionHint(cleaned));
|
|
1951
1913
|
const blocked = () => void 0;
|
|
1952
1914
|
cache.set(cleaned, blocked);
|
|
1953
1915
|
return blocked;
|
|
1954
1916
|
}
|
|
1955
|
-
const blockedMethod = findBlockedMethod(cleaned);
|
|
1956
|
-
if (blockedMethod) {
|
|
1957
|
-
const msg = `Blocked unsafe method "${blockedMethod}" in expression`;
|
|
1958
|
-
reportDiagnostic("expression-unsupported", cleaned, msg);
|
|
1959
|
-
throw new Error(`[FormaJS] ${msg}: ${cleaned}`);
|
|
1960
|
-
}
|
|
1961
|
-
try {
|
|
1962
|
-
const fn = new Function("__scope", `with(__scope) { return (${cleaned}); }`);
|
|
1963
|
-
const proxy = new Proxy(/* @__PURE__ */ Object.create(null), {
|
|
1964
|
-
has(_, key) {
|
|
1965
|
-
return key in scope.getters;
|
|
1966
|
-
},
|
|
1967
|
-
get(_, key) {
|
|
1968
|
-
if (UNSAFE_METHOD_NAMES.has(key)) return void 0;
|
|
1969
|
-
const g = scope.getters[key];
|
|
1970
|
-
return g ? g() : void 0;
|
|
1971
|
-
}
|
|
1972
|
-
});
|
|
1973
|
-
const unsafe = () => fn(proxy);
|
|
1974
|
-
cache.set(cleaned, unsafe);
|
|
1975
|
-
return unsafe;
|
|
1976
|
-
} catch {
|
|
1977
|
-
reportDiagnostic("expression-unsupported", cleaned, "Expression too complex for CSP-safe mode. Enable unsafe-eval via FormaRuntime.unsafeEval = true, or use the standard (non-hardened) build.");
|
|
1978
|
-
const failed = () => void 0;
|
|
1979
|
-
cache.set(cleaned, failed);
|
|
1980
|
-
return failed;
|
|
1981
|
-
}
|
|
1982
1917
|
}
|
|
1983
1918
|
function parseHandler(expr, scope) {
|
|
1984
1919
|
const normalized = expr.trim().replace(/;+$/g, "").trim();
|
|
@@ -2096,7 +2031,7 @@ function buildHandler(expr, scope) {
|
|
|
2096
2031
|
cache.set(cleaned, result);
|
|
2097
2032
|
return result;
|
|
2098
2033
|
}
|
|
2099
|
-
|
|
2034
|
+
{
|
|
2100
2035
|
dbg("buildHandler: blocked unsafe eval fallback for expression:", cleaned);
|
|
2101
2036
|
reportDiagnostic("handler-unsupported", cleaned, cspExpressionHint(cleaned));
|
|
2102
2037
|
const result = {
|
|
@@ -2107,49 +2042,6 @@ function buildHandler(expr, scope) {
|
|
|
2107
2042
|
cache.set(cleaned, result);
|
|
2108
2043
|
return result;
|
|
2109
2044
|
}
|
|
2110
|
-
const blockedMethod = findBlockedMethod(cleaned);
|
|
2111
|
-
if (blockedMethod) {
|
|
2112
|
-
const msg = `Blocked unsafe method "${blockedMethod}" in handler`;
|
|
2113
|
-
reportDiagnostic("handler-unsupported", cleaned, msg);
|
|
2114
|
-
throw new Error(`[FormaJS] ${msg}: ${cleaned}`);
|
|
2115
|
-
}
|
|
2116
|
-
try {
|
|
2117
|
-
const fn = new Function("__scope", "$event", "event", `with(__scope) { ${cleaned} }`);
|
|
2118
|
-
const proxy = new Proxy(/* @__PURE__ */ Object.create(null), {
|
|
2119
|
-
has(_, key) {
|
|
2120
|
-
if (key === "$event" || key === "event") return false;
|
|
2121
|
-
return key in scope.getters || key in scope.setters;
|
|
2122
|
-
},
|
|
2123
|
-
get(_, key) {
|
|
2124
|
-
if (UNSAFE_METHOD_NAMES.has(key)) return void 0;
|
|
2125
|
-
const g = scope.getters[key];
|
|
2126
|
-
return g ? g() : void 0;
|
|
2127
|
-
},
|
|
2128
|
-
set(_, key, value2) {
|
|
2129
|
-
const s = scope.setters[key];
|
|
2130
|
-
if (s) s(value2);
|
|
2131
|
-
return true;
|
|
2132
|
-
}
|
|
2133
|
-
});
|
|
2134
|
-
const unsafeHandler = (e) => {
|
|
2135
|
-
batch(() => fn(proxy, e, e));
|
|
2136
|
-
};
|
|
2137
|
-
const result = {
|
|
2138
|
-
handler: unsafeHandler,
|
|
2139
|
-
supported: true
|
|
2140
|
-
};
|
|
2141
|
-
cache.set(cleaned, result);
|
|
2142
|
-
return result;
|
|
2143
|
-
} catch {
|
|
2144
|
-
reportDiagnostic("handler-unsupported", cleaned, "Expression too complex for CSP-safe mode. Enable unsafe-eval via FormaRuntime.unsafeEval = true, or use the standard (non-hardened) build.");
|
|
2145
|
-
const result = {
|
|
2146
|
-
handler: () => {
|
|
2147
|
-
},
|
|
2148
|
-
supported: false
|
|
2149
|
-
};
|
|
2150
|
-
cache.set(cleaned, result);
|
|
2151
|
-
return result;
|
|
2152
|
-
}
|
|
2153
2045
|
}
|
|
2154
2046
|
var FORBIDDEN_STATE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
2155
2047
|
function parseState(raw) {
|