@bian-womp/spark-graph 0.1.21 → 0.1.23
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/lib/cjs/index.cjs +436 -6
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/misc/base.d.ts.map +1 -1
- package/lib/esm/index.js +436 -6
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/misc/base.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/misc/base.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,KAAK,EAEV,eAAe,EAEhB,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/misc/base.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,KAAK,EAEV,eAAe,EAEhB,MAAM,eAAe,CAAC;AA2HvB,wBAAgB,uBAAuB,IAAI,QAAQ,CA+zBlD;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,QA+BnD;AAqBD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,QA6BvD;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,eAAe,6BAUrE"}
|
package/lib/esm/index.js
CHANGED
|
@@ -1784,6 +1784,96 @@ const lcg = (seed) => {
|
|
|
1784
1784
|
let s = seed >>> 0 || 1;
|
|
1785
1785
|
return () => (s = (s * 1664525 + 1013904223) >>> 0) / 0xffffffff;
|
|
1786
1786
|
};
|
|
1787
|
+
// JSON Pointer helpers (RFC 6901 subset)
|
|
1788
|
+
function jsonPointerGet(obj, pointer) {
|
|
1789
|
+
if (!pointer || pointer === "/")
|
|
1790
|
+
return obj;
|
|
1791
|
+
if (!pointer.startsWith("/"))
|
|
1792
|
+
return undefined;
|
|
1793
|
+
const parts = pointer
|
|
1794
|
+
.split("/")
|
|
1795
|
+
.slice(1)
|
|
1796
|
+
.map((p) => p.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
1797
|
+
let cur = obj;
|
|
1798
|
+
for (const key of parts) {
|
|
1799
|
+
if (cur === undefined || cur === null)
|
|
1800
|
+
return undefined;
|
|
1801
|
+
cur = cur[key];
|
|
1802
|
+
}
|
|
1803
|
+
return cur;
|
|
1804
|
+
}
|
|
1805
|
+
function jsonPointerSet(obj, pointer, value) {
|
|
1806
|
+
if (!pointer || pointer === "/")
|
|
1807
|
+
return value;
|
|
1808
|
+
if (!pointer.startsWith("/"))
|
|
1809
|
+
return obj;
|
|
1810
|
+
const parts = pointer
|
|
1811
|
+
.split("/")
|
|
1812
|
+
.slice(1)
|
|
1813
|
+
.map((p) => p.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
1814
|
+
const root = structuredClone(obj);
|
|
1815
|
+
let cur = root;
|
|
1816
|
+
for (let i = 0; i < parts.length; i++) {
|
|
1817
|
+
const key = parts[i];
|
|
1818
|
+
if (i === parts.length - 1) {
|
|
1819
|
+
if (Array.isArray(cur) && key === "-")
|
|
1820
|
+
cur.push(value);
|
|
1821
|
+
else
|
|
1822
|
+
cur[key] = value;
|
|
1823
|
+
}
|
|
1824
|
+
else {
|
|
1825
|
+
const next = cur[key];
|
|
1826
|
+
if (next === undefined || next === null) {
|
|
1827
|
+
// create container heuristically
|
|
1828
|
+
const nextKey = parts[i + 1];
|
|
1829
|
+
cur[key] =
|
|
1830
|
+
typeof nextKey === "string" && /^[0-9]+$/.test(nextKey) ? [] : {};
|
|
1831
|
+
}
|
|
1832
|
+
cur = cur[key];
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1835
|
+
return root;
|
|
1836
|
+
}
|
|
1837
|
+
function jsonPointerRemove(obj, pointer) {
|
|
1838
|
+
if (!pointer || pointer === "/")
|
|
1839
|
+
return undefined;
|
|
1840
|
+
if (!pointer.startsWith("/"))
|
|
1841
|
+
return obj;
|
|
1842
|
+
const parts = pointer
|
|
1843
|
+
.split("/")
|
|
1844
|
+
.slice(1)
|
|
1845
|
+
.map((p) => p.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
1846
|
+
const root = structuredClone(obj);
|
|
1847
|
+
let cur = root;
|
|
1848
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
1849
|
+
const key = parts[i];
|
|
1850
|
+
if (cur === undefined || cur === null)
|
|
1851
|
+
return root;
|
|
1852
|
+
cur = cur[key];
|
|
1853
|
+
}
|
|
1854
|
+
const last = parts[parts.length - 1];
|
|
1855
|
+
if (Array.isArray(cur)) {
|
|
1856
|
+
const idx = last === "-" ? cur.length - 1 : Number(last);
|
|
1857
|
+
if (Number.isFinite(idx))
|
|
1858
|
+
cur.splice(idx, 1);
|
|
1859
|
+
}
|
|
1860
|
+
else if (cur && typeof cur === "object") {
|
|
1861
|
+
delete cur[last];
|
|
1862
|
+
}
|
|
1863
|
+
return root;
|
|
1864
|
+
}
|
|
1865
|
+
function deepMerge(a, b) {
|
|
1866
|
+
if (Array.isArray(a) && Array.isArray(b))
|
|
1867
|
+
return [...a, ...b];
|
|
1868
|
+
if (isPlainObject(a) && isPlainObject(b)) {
|
|
1869
|
+
const out = { ...a };
|
|
1870
|
+
for (const [k, v] of Object.entries(b)) {
|
|
1871
|
+
out[k] = k in out ? deepMerge(out[k], v) : v;
|
|
1872
|
+
}
|
|
1873
|
+
return out;
|
|
1874
|
+
}
|
|
1875
|
+
return b;
|
|
1876
|
+
}
|
|
1787
1877
|
// JSON helpers
|
|
1788
1878
|
const isPlainObject = (v) => {
|
|
1789
1879
|
if (v === null || typeof v !== "object")
|
|
@@ -1822,7 +1912,7 @@ function setupBasicGraphRegistry() {
|
|
|
1822
1912
|
registry.registerType({
|
|
1823
1913
|
id: "base.object",
|
|
1824
1914
|
validate: (v) => isJson(v),
|
|
1825
|
-
}, { withArray:
|
|
1915
|
+
}, { withArray: false });
|
|
1826
1916
|
registry.registerType({
|
|
1827
1917
|
id: "base.vec3",
|
|
1828
1918
|
validate: (v) => Array.isArray(v) &&
|
|
@@ -1881,7 +1971,7 @@ function setupBasicGraphRegistry() {
|
|
|
1881
1971
|
});
|
|
1882
1972
|
// Enums: Math Operation
|
|
1883
1973
|
registry.registerEnum({
|
|
1884
|
-
id: "base.
|
|
1974
|
+
id: "enum:base.math.operation",
|
|
1885
1975
|
options: [
|
|
1886
1976
|
{ value: 0, label: "Add" },
|
|
1887
1977
|
{ value: 1, label: "Subtract" },
|
|
@@ -1891,11 +1981,20 @@ function setupBasicGraphRegistry() {
|
|
|
1891
1981
|
{ value: 5, label: "Max" },
|
|
1892
1982
|
{ value: 6, label: "Modulo" },
|
|
1893
1983
|
{ value: 7, label: "Power" },
|
|
1984
|
+
// Unary / aggregate operations on A only
|
|
1985
|
+
{ value: 8, label: "Round" },
|
|
1986
|
+
{ value: 9, label: "Floor" },
|
|
1987
|
+
{ value: 10, label: "Ceil" },
|
|
1988
|
+
{ value: 11, label: "Abs" },
|
|
1989
|
+
{ value: 12, label: "Sum" },
|
|
1990
|
+
{ value: 13, label: "Avg" },
|
|
1991
|
+
{ value: 14, label: "MinAll" },
|
|
1992
|
+
{ value: 15, label: "MaxAll" },
|
|
1894
1993
|
],
|
|
1895
1994
|
});
|
|
1896
1995
|
// Enums: Compare Operation
|
|
1897
1996
|
registry.registerEnum({
|
|
1898
|
-
id: "base.
|
|
1997
|
+
id: "enum:base.compare.operation",
|
|
1899
1998
|
options: [
|
|
1900
1999
|
{ value: 0, label: "LessThan" },
|
|
1901
2000
|
{ value: 1, label: "LessThanOrEqual" },
|
|
@@ -2020,7 +2119,7 @@ function setupBasicGraphRegistry() {
|
|
|
2020
2119
|
id: "base.math",
|
|
2021
2120
|
categoryId: "compute",
|
|
2022
2121
|
inputs: {
|
|
2023
|
-
Operation: "base.
|
|
2122
|
+
Operation: "enum:base.math.operation",
|
|
2024
2123
|
A: "base.float[]",
|
|
2025
2124
|
B: "base.float[]",
|
|
2026
2125
|
},
|
|
@@ -2031,8 +2130,34 @@ function setupBasicGraphRegistry() {
|
|
|
2031
2130
|
// Gracefully handle missing inputs by treating them as zeros
|
|
2032
2131
|
const a = ins.A === undefined ? [] : asArray(ins.A);
|
|
2033
2132
|
const b = ins.B === undefined ? [] : asArray(ins.B);
|
|
2034
|
-
const len = Math.max(a.length, b.length);
|
|
2035
2133
|
const op = Number(ins.Operation ?? 0) | 0;
|
|
2134
|
+
// Unary ops on A
|
|
2135
|
+
if (op === 8)
|
|
2136
|
+
return { Result: a.map((x) => Math.round(Number(x))) };
|
|
2137
|
+
if (op === 9)
|
|
2138
|
+
return { Result: a.map((x) => Math.floor(Number(x))) };
|
|
2139
|
+
if (op === 10)
|
|
2140
|
+
return { Result: a.map((x) => Math.ceil(Number(x))) };
|
|
2141
|
+
if (op === 11)
|
|
2142
|
+
return { Result: a.map((x) => Math.abs(Number(x))) };
|
|
2143
|
+
// Aggregate ops on A -> single-element array
|
|
2144
|
+
if (op === 12)
|
|
2145
|
+
return { Result: [a.reduce((s, x) => s + Number(x || 0), 0)] };
|
|
2146
|
+
if (op === 13) {
|
|
2147
|
+
const sum = a.reduce((s, x) => s + Number(x || 0), 0);
|
|
2148
|
+
const avg = a.length ? sum / a.length : 0;
|
|
2149
|
+
return { Result: [avg] };
|
|
2150
|
+
}
|
|
2151
|
+
if (op === 14)
|
|
2152
|
+
return {
|
|
2153
|
+
Result: [a.length ? Math.min(...a.map((x) => Number(x))) : 0],
|
|
2154
|
+
};
|
|
2155
|
+
if (op === 15)
|
|
2156
|
+
return {
|
|
2157
|
+
Result: [a.length ? Math.max(...a.map((x) => Number(x))) : 0],
|
|
2158
|
+
};
|
|
2159
|
+
// Binary ops A (broadcast) B
|
|
2160
|
+
const len = Math.max(a.length, b.length);
|
|
2036
2161
|
const ops = [
|
|
2037
2162
|
(x, y) => x + y,
|
|
2038
2163
|
(x, y) => x - y,
|
|
@@ -2057,7 +2182,7 @@ function setupBasicGraphRegistry() {
|
|
|
2057
2182
|
id: "base.compare",
|
|
2058
2183
|
categoryId: "compute",
|
|
2059
2184
|
inputs: {
|
|
2060
|
-
Operation: "base.
|
|
2185
|
+
Operation: "enum:base.compare.operation",
|
|
2061
2186
|
A: "base.float[]",
|
|
2062
2187
|
B: "base.float[]",
|
|
2063
2188
|
},
|
|
@@ -2077,6 +2202,122 @@ function setupBasicGraphRegistry() {
|
|
|
2077
2202
|
return { Result: a.map((x, i) => fn(Number(x), Number(b[i] ?? 0))) };
|
|
2078
2203
|
},
|
|
2079
2204
|
});
|
|
2205
|
+
// Logic
|
|
2206
|
+
registry.registerNode({
|
|
2207
|
+
id: "base.logic",
|
|
2208
|
+
categoryId: "compute",
|
|
2209
|
+
inputs: { Operation: "base.string", A: "base.bool", B: "base.bool" },
|
|
2210
|
+
outputs: { Result: "base.bool" },
|
|
2211
|
+
impl: (ins) => {
|
|
2212
|
+
const op = String(ins.Operation || "not").toLowerCase();
|
|
2213
|
+
const a = !!ins.A;
|
|
2214
|
+
const b = !!ins.B;
|
|
2215
|
+
if (op === "not")
|
|
2216
|
+
return { Result: !a };
|
|
2217
|
+
if (op === "and")
|
|
2218
|
+
return { Result: a && b };
|
|
2219
|
+
if (op === "or")
|
|
2220
|
+
return { Result: a || b };
|
|
2221
|
+
return { Result: false };
|
|
2222
|
+
},
|
|
2223
|
+
});
|
|
2224
|
+
// Strings
|
|
2225
|
+
registry.registerNode({
|
|
2226
|
+
id: "base.string.length",
|
|
2227
|
+
categoryId: "compute",
|
|
2228
|
+
inputs: { Text: "base.string" },
|
|
2229
|
+
outputs: { Length: "base.float" },
|
|
2230
|
+
impl: (ins) => ({
|
|
2231
|
+
Length: String(ins.Text || "").length,
|
|
2232
|
+
}),
|
|
2233
|
+
});
|
|
2234
|
+
registry.registerNode({
|
|
2235
|
+
id: "base.string.op",
|
|
2236
|
+
categoryId: "compute",
|
|
2237
|
+
inputs: { Op: "base.string", Text: "base.string" },
|
|
2238
|
+
outputs: { Text: "base.string" },
|
|
2239
|
+
impl: (ins) => {
|
|
2240
|
+
const op = String(ins.Op || "trim").toLowerCase();
|
|
2241
|
+
const t = String(ins.Text || "");
|
|
2242
|
+
if (op === "lower")
|
|
2243
|
+
return { Text: t.toLowerCase() };
|
|
2244
|
+
if (op === "upper")
|
|
2245
|
+
return { Text: t.toUpperCase() };
|
|
2246
|
+
return { Text: t.trim() };
|
|
2247
|
+
},
|
|
2248
|
+
});
|
|
2249
|
+
registry.registerNode({
|
|
2250
|
+
id: "base.string.split",
|
|
2251
|
+
categoryId: "compute",
|
|
2252
|
+
inputs: { Text: "base.string", Sep: "base.string" },
|
|
2253
|
+
outputs: { Parts: "base.string[]" },
|
|
2254
|
+
impl: (ins) => {
|
|
2255
|
+
const t = String(ins.Text || "");
|
|
2256
|
+
const sep = String(ins.Sep || ",");
|
|
2257
|
+
return { Parts: t.split(sep) };
|
|
2258
|
+
},
|
|
2259
|
+
});
|
|
2260
|
+
registry.registerNode({
|
|
2261
|
+
id: "base.string.join",
|
|
2262
|
+
categoryId: "compute",
|
|
2263
|
+
inputs: { Parts: "base.string[]", Sep: "base.string" },
|
|
2264
|
+
outputs: { Text: "base.string" },
|
|
2265
|
+
impl: (ins) => {
|
|
2266
|
+
const parts = Array.isArray(ins.Parts) ? ins.Parts.map(String) : [];
|
|
2267
|
+
const sep = String(ins.Sep || "");
|
|
2268
|
+
return { Text: parts.join(sep) };
|
|
2269
|
+
},
|
|
2270
|
+
});
|
|
2271
|
+
registry.registerNode({
|
|
2272
|
+
id: "base.string.replace",
|
|
2273
|
+
categoryId: "compute",
|
|
2274
|
+
inputs: {
|
|
2275
|
+
Text: "base.string",
|
|
2276
|
+
Search: "base.string",
|
|
2277
|
+
Replace: "base.string",
|
|
2278
|
+
},
|
|
2279
|
+
outputs: { Text: "base.string" },
|
|
2280
|
+
impl: (ins) => {
|
|
2281
|
+
const t = String(ins.Text || "");
|
|
2282
|
+
const s = String(ins.Search || "");
|
|
2283
|
+
const r = String(ins.Replace || "");
|
|
2284
|
+
return { Text: t.split(s).join(r) };
|
|
2285
|
+
},
|
|
2286
|
+
});
|
|
2287
|
+
// Arrays (carried as base.object)
|
|
2288
|
+
registry.registerNode({
|
|
2289
|
+
id: "base.array.length",
|
|
2290
|
+
categoryId: "compute",
|
|
2291
|
+
inputs: { Items: "base.object" },
|
|
2292
|
+
outputs: { Length: "base.float" },
|
|
2293
|
+
impl: (ins) => ({
|
|
2294
|
+
Length: Array.isArray(ins.Items) ? ins.Items.length : 0,
|
|
2295
|
+
}),
|
|
2296
|
+
});
|
|
2297
|
+
registry.registerNode({
|
|
2298
|
+
id: "base.array.slice",
|
|
2299
|
+
categoryId: "compute",
|
|
2300
|
+
inputs: { Items: "base.object", Start: "base.float", End: "base.float" },
|
|
2301
|
+
outputs: { Result: "base.object" },
|
|
2302
|
+
impl: (ins) => {
|
|
2303
|
+
const arr = Array.isArray(ins.Items) ? ins.Items : [];
|
|
2304
|
+
const s = Math.trunc(Number(ins.Start ?? 0));
|
|
2305
|
+
const e = Number.isFinite(Number(ins.End))
|
|
2306
|
+
? Math.trunc(Number(ins.End))
|
|
2307
|
+
: undefined;
|
|
2308
|
+
return { Result: arr.slice(s, e) };
|
|
2309
|
+
},
|
|
2310
|
+
});
|
|
2311
|
+
// Select
|
|
2312
|
+
registry.registerNode({
|
|
2313
|
+
id: "base.select",
|
|
2314
|
+
categoryId: "compute",
|
|
2315
|
+
inputs: { Cond: "base.bool", Then: "base.object", Else: "base.object" },
|
|
2316
|
+
outputs: { Result: "base.object" },
|
|
2317
|
+
impl: (ins) => ({
|
|
2318
|
+
Result: ins.Cond ? ins.Then : ins.Else,
|
|
2319
|
+
}),
|
|
2320
|
+
});
|
|
2080
2321
|
// Combine XYZ
|
|
2081
2322
|
registry.registerNode({
|
|
2082
2323
|
id: "base.compareXYZ",
|
|
@@ -2215,6 +2456,195 @@ function setupBasicGraphRegistry() {
|
|
|
2215
2456
|
},
|
|
2216
2457
|
},
|
|
2217
2458
|
});
|
|
2459
|
+
// ------------------------- JSON/object utilities -------------------------
|
|
2460
|
+
registry.registerNode({
|
|
2461
|
+
id: "base.object.get",
|
|
2462
|
+
categoryId: "compute",
|
|
2463
|
+
inputs: { Object: "base.object", Pointers: "base.string[]" },
|
|
2464
|
+
outputs: { Values: "base.object" },
|
|
2465
|
+
impl: (ins) => {
|
|
2466
|
+
const obj = ins.Object;
|
|
2467
|
+
const pointers = (ins.Pointers || []).map(String);
|
|
2468
|
+
const out = {};
|
|
2469
|
+
for (const p of pointers)
|
|
2470
|
+
out[p] = jsonPointerGet(obj, p);
|
|
2471
|
+
return { Values: out };
|
|
2472
|
+
},
|
|
2473
|
+
});
|
|
2474
|
+
registry.registerNode({
|
|
2475
|
+
id: "base.object.set",
|
|
2476
|
+
categoryId: "compute",
|
|
2477
|
+
inputs: {
|
|
2478
|
+
Object: "base.object",
|
|
2479
|
+
Pointers: "base.string[]",
|
|
2480
|
+
NewValues: "base.string[]",
|
|
2481
|
+
},
|
|
2482
|
+
outputs: { Result: "base.object" },
|
|
2483
|
+
impl: (ins) => {
|
|
2484
|
+
const pointers = (ins.Pointers || []).map(String);
|
|
2485
|
+
const values = (ins.NewValues || []).map(String);
|
|
2486
|
+
let cur = structuredClone(ins.Object);
|
|
2487
|
+
for (let i = 0; i < pointers.length; i++) {
|
|
2488
|
+
const p = pointers[i];
|
|
2489
|
+
const raw = values[i];
|
|
2490
|
+
let val = raw;
|
|
2491
|
+
if (typeof raw === "string") {
|
|
2492
|
+
try {
|
|
2493
|
+
val = JSON.parse(raw);
|
|
2494
|
+
}
|
|
2495
|
+
catch {
|
|
2496
|
+
/* keep as string */
|
|
2497
|
+
}
|
|
2498
|
+
}
|
|
2499
|
+
cur = jsonPointerSet(cur, p, val);
|
|
2500
|
+
}
|
|
2501
|
+
return { Result: cur };
|
|
2502
|
+
},
|
|
2503
|
+
});
|
|
2504
|
+
registry.registerNode({
|
|
2505
|
+
id: "base.object.remove",
|
|
2506
|
+
categoryId: "compute",
|
|
2507
|
+
inputs: { Object: "base.object", Pointers: "base.string[]" },
|
|
2508
|
+
outputs: { Result: "base.object" },
|
|
2509
|
+
impl: (ins) => {
|
|
2510
|
+
const pointers = (ins.Pointers || []).map(String);
|
|
2511
|
+
let cur = structuredClone(ins.Object);
|
|
2512
|
+
for (const p of pointers)
|
|
2513
|
+
cur = jsonPointerRemove(cur, p);
|
|
2514
|
+
return { Result: cur };
|
|
2515
|
+
},
|
|
2516
|
+
});
|
|
2517
|
+
registry.registerNode({
|
|
2518
|
+
id: "base.object.merge",
|
|
2519
|
+
categoryId: "compute",
|
|
2520
|
+
inputs: { A: "base.object", B: "base.object" },
|
|
2521
|
+
outputs: { Result: "base.object" },
|
|
2522
|
+
impl: (ins) => ({
|
|
2523
|
+
Result: deepMerge(ins.A, ins.B),
|
|
2524
|
+
}),
|
|
2525
|
+
});
|
|
2526
|
+
registry.registerNode({
|
|
2527
|
+
id: "base.object.keys",
|
|
2528
|
+
categoryId: "compute",
|
|
2529
|
+
inputs: { Object: "base.object" },
|
|
2530
|
+
outputs: { Keys: "base.string[]" },
|
|
2531
|
+
impl: (ins) => {
|
|
2532
|
+
const obj = ins.Object;
|
|
2533
|
+
const keys = isPlainObject(obj)
|
|
2534
|
+
? Object.keys(obj)
|
|
2535
|
+
: Array.isArray(obj)
|
|
2536
|
+
? Object.keys(obj)
|
|
2537
|
+
: [];
|
|
2538
|
+
return { Keys: keys };
|
|
2539
|
+
},
|
|
2540
|
+
});
|
|
2541
|
+
registry.registerNode({
|
|
2542
|
+
id: "base.object.values",
|
|
2543
|
+
categoryId: "compute",
|
|
2544
|
+
inputs: { Object: "base.object" },
|
|
2545
|
+
outputs: { Values: "base.object" },
|
|
2546
|
+
impl: (ins) => {
|
|
2547
|
+
const obj = ins.Object;
|
|
2548
|
+
const vals = isPlainObject(obj)
|
|
2549
|
+
? Object.values(obj)
|
|
2550
|
+
: Array.isArray(obj)
|
|
2551
|
+
? Object.values(obj)
|
|
2552
|
+
: [];
|
|
2553
|
+
return { Values: vals };
|
|
2554
|
+
},
|
|
2555
|
+
});
|
|
2556
|
+
registry.registerNode({
|
|
2557
|
+
id: "base.object.patch",
|
|
2558
|
+
categoryId: "compute",
|
|
2559
|
+
inputs: { Object: "base.object", Ops: "base.object" },
|
|
2560
|
+
outputs: { Result: "base.object" },
|
|
2561
|
+
impl: (ins) => {
|
|
2562
|
+
const root = structuredClone(ins.Object);
|
|
2563
|
+
const opsRaw = ins.Ops;
|
|
2564
|
+
const ops = Array.isArray(opsRaw)
|
|
2565
|
+
? opsRaw
|
|
2566
|
+
: opsRaw
|
|
2567
|
+
? [opsRaw]
|
|
2568
|
+
: [];
|
|
2569
|
+
let cur = root;
|
|
2570
|
+
for (const op of ops) {
|
|
2571
|
+
if (!op || typeof op !== "object")
|
|
2572
|
+
continue;
|
|
2573
|
+
const kind = String(op.op || "");
|
|
2574
|
+
const path = String(op.path || "");
|
|
2575
|
+
if (kind === "add" || kind === "replace") {
|
|
2576
|
+
cur = jsonPointerSet(cur, path, op.value);
|
|
2577
|
+
}
|
|
2578
|
+
else if (kind === "remove") {
|
|
2579
|
+
cur = jsonPointerRemove(cur, path);
|
|
2580
|
+
}
|
|
2581
|
+
else if (kind === "test") {
|
|
2582
|
+
const got = jsonPointerGet(cur, path);
|
|
2583
|
+
const expected = op.value;
|
|
2584
|
+
const ok = JSON.stringify(got) === JSON.stringify(expected);
|
|
2585
|
+
if (!ok)
|
|
2586
|
+
throw new Error(`objectPatch test failed at ${path}`);
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
return { Result: cur };
|
|
2590
|
+
},
|
|
2591
|
+
});
|
|
2592
|
+
registry.registerNode({
|
|
2593
|
+
id: "base.array.concat",
|
|
2594
|
+
categoryId: "compute",
|
|
2595
|
+
inputs: { A: "base.object", B: "base.object" },
|
|
2596
|
+
outputs: { Result: "base.object" },
|
|
2597
|
+
impl: (ins) => {
|
|
2598
|
+
const a = Array.isArray(ins.A) ? ins.A : [];
|
|
2599
|
+
const b = Array.isArray(ins.B) ? ins.B : [];
|
|
2600
|
+
return { Result: [...a, ...b] };
|
|
2601
|
+
},
|
|
2602
|
+
});
|
|
2603
|
+
registry.registerNode({
|
|
2604
|
+
id: "base.array.flatten",
|
|
2605
|
+
categoryId: "compute",
|
|
2606
|
+
inputs: { Objects: "base.object" },
|
|
2607
|
+
outputs: { Result: "base.object" },
|
|
2608
|
+
impl: (ins) => {
|
|
2609
|
+
const arr = Array.isArray(ins.Objects) ? ins.Objects : [];
|
|
2610
|
+
const out = [];
|
|
2611
|
+
for (const v of arr) {
|
|
2612
|
+
if (Array.isArray(v))
|
|
2613
|
+
out.push(...v);
|
|
2614
|
+
else
|
|
2615
|
+
out.push(v);
|
|
2616
|
+
}
|
|
2617
|
+
return { Result: out };
|
|
2618
|
+
},
|
|
2619
|
+
});
|
|
2620
|
+
registry.registerNode({
|
|
2621
|
+
id: "base.array.sortBy",
|
|
2622
|
+
categoryId: "compute",
|
|
2623
|
+
inputs: { Objects: "base.object", Pointers: "base.string[]" },
|
|
2624
|
+
outputs: { Result: "base.object" },
|
|
2625
|
+
impl: (ins) => {
|
|
2626
|
+
const arr = Array.isArray(ins.Objects) ? ins.Objects : [];
|
|
2627
|
+
const pointers = (ins.Pointers || []).map(String);
|
|
2628
|
+
const out = [...arr].sort((a, b) => {
|
|
2629
|
+
for (const p of pointers) {
|
|
2630
|
+
const av = jsonPointerGet(a, p);
|
|
2631
|
+
const bv = jsonPointerGet(b, p);
|
|
2632
|
+
if (av === bv)
|
|
2633
|
+
continue;
|
|
2634
|
+
if (av === undefined)
|
|
2635
|
+
return 1;
|
|
2636
|
+
if (bv === undefined)
|
|
2637
|
+
return -1;
|
|
2638
|
+
if (av < bv)
|
|
2639
|
+
return -1;
|
|
2640
|
+
if (av > bv)
|
|
2641
|
+
return 1;
|
|
2642
|
+
}
|
|
2643
|
+
return 0;
|
|
2644
|
+
});
|
|
2645
|
+
return { Result: out };
|
|
2646
|
+
},
|
|
2647
|
+
});
|
|
2218
2648
|
return registry;
|
|
2219
2649
|
}
|
|
2220
2650
|
function registerDelayNode(registry) {
|