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