@typicalday/firegraph 0.4.0 → 0.6.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 +114 -1
- package/dist/codegen/index.d.cts +1 -1
- package/dist/codegen/index.d.ts +1 -1
- package/dist/editor/client/assets/index-B1nKCPMa.js +411 -0
- package/dist/editor/client/assets/index-CJJR5qe5.css +1 -0
- package/dist/editor/client/index.html +2 -2
- package/dist/editor/server/index.mjs +1395 -346
- package/dist/{index-DR3jF5_b.d.cts → index-B9aodfYD.d.cts} +101 -1
- package/dist/{index-DR3jF5_b.d.ts → index-B9aodfYD.d.ts} +101 -1
- package/dist/index.cjs +794 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +164 -4
- package/dist/index.d.ts +164 -4
- package/dist/index.js +776 -41
- package/dist/index.js.map +1 -1
- package/package.json +27 -24
- package/dist/editor/client/assets/index-DJJ_b0jI.js +0 -411
- package/dist/editor/client/assets/index-Q0QBYrMV.css +0 -1
|
@@ -1295,8 +1295,8 @@ var require_node = __commonJS({
|
|
|
1295
1295
|
}
|
|
1296
1296
|
break;
|
|
1297
1297
|
case "FILE":
|
|
1298
|
-
var
|
|
1299
|
-
stream2 = new
|
|
1298
|
+
var fs3 = __require("fs");
|
|
1299
|
+
stream2 = new fs3.SyncWriteStream(fd2, { autoClose: false });
|
|
1300
1300
|
stream2._type = "fs";
|
|
1301
1301
|
break;
|
|
1302
1302
|
case "PIPE":
|
|
@@ -14083,11 +14083,11 @@ var require_mime_types = __commonJS({
|
|
|
14083
14083
|
}
|
|
14084
14084
|
return exts[0];
|
|
14085
14085
|
}
|
|
14086
|
-
function lookup(
|
|
14087
|
-
if (!
|
|
14086
|
+
function lookup(path5) {
|
|
14087
|
+
if (!path5 || typeof path5 !== "string") {
|
|
14088
14088
|
return false;
|
|
14089
14089
|
}
|
|
14090
|
-
var extension2 = extname("x." +
|
|
14090
|
+
var extension2 = extname("x." + path5).toLowerCase().substr(1);
|
|
14091
14091
|
if (!extension2) {
|
|
14092
14092
|
return false;
|
|
14093
14093
|
}
|
|
@@ -17602,7 +17602,7 @@ var require_path_to_regexp = __commonJS({
|
|
|
17602
17602
|
"editor/node_modules/.pnpm/path-to-regexp@0.1.12/node_modules/path-to-regexp/index.js"(exports, module) {
|
|
17603
17603
|
module.exports = pathToRegexp;
|
|
17604
17604
|
var MATCHING_GROUP_REGEXP = /\\.|\((?:\?<(.*?)>)?(?!\?)/g;
|
|
17605
|
-
function pathToRegexp(
|
|
17605
|
+
function pathToRegexp(path5, keys, options) {
|
|
17606
17606
|
options = options || {};
|
|
17607
17607
|
keys = keys || [];
|
|
17608
17608
|
var strict = options.strict;
|
|
@@ -17616,8 +17616,8 @@ var require_path_to_regexp = __commonJS({
|
|
|
17616
17616
|
var pos = 0;
|
|
17617
17617
|
var backtrack = "";
|
|
17618
17618
|
var m;
|
|
17619
|
-
if (
|
|
17620
|
-
while (m = MATCHING_GROUP_REGEXP.exec(
|
|
17619
|
+
if (path5 instanceof RegExp) {
|
|
17620
|
+
while (m = MATCHING_GROUP_REGEXP.exec(path5.source)) {
|
|
17621
17621
|
if (m[0][0] === "\\") continue;
|
|
17622
17622
|
keys.push({
|
|
17623
17623
|
name: m[1] || name++,
|
|
@@ -17625,18 +17625,18 @@ var require_path_to_regexp = __commonJS({
|
|
|
17625
17625
|
offset: m.index
|
|
17626
17626
|
});
|
|
17627
17627
|
}
|
|
17628
|
-
return
|
|
17628
|
+
return path5;
|
|
17629
17629
|
}
|
|
17630
|
-
if (Array.isArray(
|
|
17631
|
-
|
|
17630
|
+
if (Array.isArray(path5)) {
|
|
17631
|
+
path5 = path5.map(function(value) {
|
|
17632
17632
|
return pathToRegexp(value, keys, options).source;
|
|
17633
17633
|
});
|
|
17634
|
-
return new RegExp(
|
|
17634
|
+
return new RegExp(path5.join("|"), flags);
|
|
17635
17635
|
}
|
|
17636
|
-
if (typeof
|
|
17636
|
+
if (typeof path5 !== "string") {
|
|
17637
17637
|
throw new TypeError("path must be a string, array of strings, or regular expression");
|
|
17638
17638
|
}
|
|
17639
|
-
|
|
17639
|
+
path5 = path5.replace(
|
|
17640
17640
|
/\\.|(\/)?(\.)?:(\w+)(\(.*?\))?(\*)?(\?)?|[.*]|\/\(/g,
|
|
17641
17641
|
function(match, slash, format, key, capture, star, optional2, offset) {
|
|
17642
17642
|
if (match[0] === "\\") {
|
|
@@ -17653,7 +17653,7 @@ var require_path_to_regexp = __commonJS({
|
|
|
17653
17653
|
if (slash || format) {
|
|
17654
17654
|
backtrack = "";
|
|
17655
17655
|
} else {
|
|
17656
|
-
backtrack +=
|
|
17656
|
+
backtrack += path5.slice(pos, offset);
|
|
17657
17657
|
}
|
|
17658
17658
|
pos = offset + match.length;
|
|
17659
17659
|
if (match === "*") {
|
|
@@ -17681,7 +17681,7 @@ var require_path_to_regexp = __commonJS({
|
|
|
17681
17681
|
return result;
|
|
17682
17682
|
}
|
|
17683
17683
|
);
|
|
17684
|
-
while (m = MATCHING_GROUP_REGEXP.exec(
|
|
17684
|
+
while (m = MATCHING_GROUP_REGEXP.exec(path5)) {
|
|
17685
17685
|
if (m[0][0] === "\\") continue;
|
|
17686
17686
|
if (keysOffset + i === keys.length || keys[keysOffset + i].offset > m.index) {
|
|
17687
17687
|
keys.splice(keysOffset + i, 0, {
|
|
@@ -17693,13 +17693,13 @@ var require_path_to_regexp = __commonJS({
|
|
|
17693
17693
|
}
|
|
17694
17694
|
i++;
|
|
17695
17695
|
}
|
|
17696
|
-
|
|
17696
|
+
path5 += strict ? "" : path5[path5.length - 1] === "/" ? "?" : "/?";
|
|
17697
17697
|
if (end) {
|
|
17698
|
-
|
|
17699
|
-
} else if (
|
|
17700
|
-
|
|
17698
|
+
path5 += "$";
|
|
17699
|
+
} else if (path5[path5.length - 1] !== "/") {
|
|
17700
|
+
path5 += lookahead ? "(?=/|$)" : "(?:/|$)";
|
|
17701
17701
|
}
|
|
17702
|
-
return new RegExp("^" +
|
|
17702
|
+
return new RegExp("^" + path5, flags);
|
|
17703
17703
|
}
|
|
17704
17704
|
}
|
|
17705
17705
|
});
|
|
@@ -17712,19 +17712,19 @@ var require_layer = __commonJS({
|
|
|
17712
17712
|
var debug = require_src()("express:router:layer");
|
|
17713
17713
|
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
17714
17714
|
module.exports = Layer;
|
|
17715
|
-
function Layer(
|
|
17715
|
+
function Layer(path5, options, fn) {
|
|
17716
17716
|
if (!(this instanceof Layer)) {
|
|
17717
|
-
return new Layer(
|
|
17717
|
+
return new Layer(path5, options, fn);
|
|
17718
17718
|
}
|
|
17719
|
-
debug("new %o",
|
|
17719
|
+
debug("new %o", path5);
|
|
17720
17720
|
var opts = options || {};
|
|
17721
17721
|
this.handle = fn;
|
|
17722
17722
|
this.name = fn.name || "<anonymous>";
|
|
17723
17723
|
this.params = void 0;
|
|
17724
17724
|
this.path = void 0;
|
|
17725
|
-
this.regexp = pathRegexp(
|
|
17726
|
-
this.regexp.fast_star =
|
|
17727
|
-
this.regexp.fast_slash =
|
|
17725
|
+
this.regexp = pathRegexp(path5, this.keys = [], opts);
|
|
17726
|
+
this.regexp.fast_star = path5 === "*";
|
|
17727
|
+
this.regexp.fast_slash = path5 === "/" && opts.end === false;
|
|
17728
17728
|
}
|
|
17729
17729
|
Layer.prototype.handle_error = function handle_error(error48, req, res, next) {
|
|
17730
17730
|
var fn = this.handle;
|
|
@@ -17748,20 +17748,20 @@ var require_layer = __commonJS({
|
|
|
17748
17748
|
next(err);
|
|
17749
17749
|
}
|
|
17750
17750
|
};
|
|
17751
|
-
Layer.prototype.match = function match(
|
|
17751
|
+
Layer.prototype.match = function match(path5) {
|
|
17752
17752
|
var match2;
|
|
17753
|
-
if (
|
|
17753
|
+
if (path5 != null) {
|
|
17754
17754
|
if (this.regexp.fast_slash) {
|
|
17755
17755
|
this.params = {};
|
|
17756
17756
|
this.path = "";
|
|
17757
17757
|
return true;
|
|
17758
17758
|
}
|
|
17759
17759
|
if (this.regexp.fast_star) {
|
|
17760
|
-
this.params = { "0": decode_param(
|
|
17761
|
-
this.path =
|
|
17760
|
+
this.params = { "0": decode_param(path5) };
|
|
17761
|
+
this.path = path5;
|
|
17762
17762
|
return true;
|
|
17763
17763
|
}
|
|
17764
|
-
match2 = this.regexp.exec(
|
|
17764
|
+
match2 = this.regexp.exec(path5);
|
|
17765
17765
|
}
|
|
17766
17766
|
if (!match2) {
|
|
17767
17767
|
this.params = void 0;
|
|
@@ -17854,10 +17854,10 @@ var require_route = __commonJS({
|
|
|
17854
17854
|
var slice = Array.prototype.slice;
|
|
17855
17855
|
var toString = Object.prototype.toString;
|
|
17856
17856
|
module.exports = Route;
|
|
17857
|
-
function Route(
|
|
17858
|
-
this.path =
|
|
17857
|
+
function Route(path5) {
|
|
17858
|
+
this.path = path5;
|
|
17859
17859
|
this.stack = [];
|
|
17860
|
-
debug("new %o",
|
|
17860
|
+
debug("new %o", path5);
|
|
17861
17861
|
this.methods = {};
|
|
17862
17862
|
}
|
|
17863
17863
|
Route.prototype._handles_method = function _handles_method(method) {
|
|
@@ -18069,8 +18069,8 @@ var require_router = __commonJS({
|
|
|
18069
18069
|
if (++sync > 100) {
|
|
18070
18070
|
return setImmediate(next, err);
|
|
18071
18071
|
}
|
|
18072
|
-
var
|
|
18073
|
-
if (
|
|
18072
|
+
var path5 = getPathname(req);
|
|
18073
|
+
if (path5 == null) {
|
|
18074
18074
|
return done(layerError);
|
|
18075
18075
|
}
|
|
18076
18076
|
var layer;
|
|
@@ -18078,7 +18078,7 @@ var require_router = __commonJS({
|
|
|
18078
18078
|
var route;
|
|
18079
18079
|
while (match !== true && idx < stack.length) {
|
|
18080
18080
|
layer = stack[idx++];
|
|
18081
|
-
match = matchLayer(layer,
|
|
18081
|
+
match = matchLayer(layer, path5);
|
|
18082
18082
|
route = layer.route;
|
|
18083
18083
|
if (typeof match !== "boolean") {
|
|
18084
18084
|
layerError = layerError || match;
|
|
@@ -18116,18 +18116,18 @@ var require_router = __commonJS({
|
|
|
18116
18116
|
} else if (route) {
|
|
18117
18117
|
layer.handle_request(req, res, next);
|
|
18118
18118
|
} else {
|
|
18119
|
-
trim_prefix(layer, layerError, layerPath,
|
|
18119
|
+
trim_prefix(layer, layerError, layerPath, path5);
|
|
18120
18120
|
}
|
|
18121
18121
|
sync = 0;
|
|
18122
18122
|
});
|
|
18123
18123
|
}
|
|
18124
|
-
function trim_prefix(layer, layerError, layerPath,
|
|
18124
|
+
function trim_prefix(layer, layerError, layerPath, path5) {
|
|
18125
18125
|
if (layerPath.length !== 0) {
|
|
18126
|
-
if (layerPath !==
|
|
18126
|
+
if (layerPath !== path5.slice(0, layerPath.length)) {
|
|
18127
18127
|
next(layerError);
|
|
18128
18128
|
return;
|
|
18129
18129
|
}
|
|
18130
|
-
var c =
|
|
18130
|
+
var c = path5[layerPath.length];
|
|
18131
18131
|
if (c && c !== "/" && c !== ".") return next(layerError);
|
|
18132
18132
|
debug("trim prefix (%s) from url %s", layerPath, req.url);
|
|
18133
18133
|
removed = layerPath;
|
|
@@ -18205,7 +18205,7 @@ var require_router = __commonJS({
|
|
|
18205
18205
|
};
|
|
18206
18206
|
proto.use = function use(fn) {
|
|
18207
18207
|
var offset = 0;
|
|
18208
|
-
var
|
|
18208
|
+
var path5 = "/";
|
|
18209
18209
|
if (typeof fn !== "function") {
|
|
18210
18210
|
var arg = fn;
|
|
18211
18211
|
while (Array.isArray(arg) && arg.length !== 0) {
|
|
@@ -18213,7 +18213,7 @@ var require_router = __commonJS({
|
|
|
18213
18213
|
}
|
|
18214
18214
|
if (typeof arg !== "function") {
|
|
18215
18215
|
offset = 1;
|
|
18216
|
-
|
|
18216
|
+
path5 = fn;
|
|
18217
18217
|
}
|
|
18218
18218
|
}
|
|
18219
18219
|
var callbacks = flatten(slice.call(arguments, offset));
|
|
@@ -18225,8 +18225,8 @@ var require_router = __commonJS({
|
|
|
18225
18225
|
if (typeof fn !== "function") {
|
|
18226
18226
|
throw new TypeError("Router.use() requires a middleware function but got a " + gettype(fn));
|
|
18227
18227
|
}
|
|
18228
|
-
debug("use %o %s",
|
|
18229
|
-
var layer = new Layer(
|
|
18228
|
+
debug("use %o %s", path5, fn.name || "<anonymous>");
|
|
18229
|
+
var layer = new Layer(path5, {
|
|
18230
18230
|
sensitive: this.caseSensitive,
|
|
18231
18231
|
strict: false,
|
|
18232
18232
|
end: false
|
|
@@ -18236,9 +18236,9 @@ var require_router = __commonJS({
|
|
|
18236
18236
|
}
|
|
18237
18237
|
return this;
|
|
18238
18238
|
};
|
|
18239
|
-
proto.route = function route(
|
|
18240
|
-
var route2 = new Route(
|
|
18241
|
-
var layer = new Layer(
|
|
18239
|
+
proto.route = function route(path5) {
|
|
18240
|
+
var route2 = new Route(path5);
|
|
18241
|
+
var layer = new Layer(path5, {
|
|
18242
18242
|
sensitive: this.caseSensitive,
|
|
18243
18243
|
strict: this.strict,
|
|
18244
18244
|
end: true
|
|
@@ -18248,8 +18248,8 @@ var require_router = __commonJS({
|
|
|
18248
18248
|
return route2;
|
|
18249
18249
|
};
|
|
18250
18250
|
methods.concat("all").forEach(function(method) {
|
|
18251
|
-
proto[method] = function(
|
|
18252
|
-
var route = this.route(
|
|
18251
|
+
proto[method] = function(path5) {
|
|
18252
|
+
var route = this.route(path5);
|
|
18253
18253
|
route[method].apply(route, slice.call(arguments, 1));
|
|
18254
18254
|
return this;
|
|
18255
18255
|
};
|
|
@@ -18285,9 +18285,9 @@ var require_router = __commonJS({
|
|
|
18285
18285
|
}
|
|
18286
18286
|
return toString.call(obj).replace(objectRegExp, "$1");
|
|
18287
18287
|
}
|
|
18288
|
-
function matchLayer(layer,
|
|
18288
|
+
function matchLayer(layer, path5) {
|
|
18289
18289
|
try {
|
|
18290
|
-
return layer.match(
|
|
18290
|
+
return layer.match(path5);
|
|
18291
18291
|
} catch (err) {
|
|
18292
18292
|
return err;
|
|
18293
18293
|
}
|
|
@@ -18405,13 +18405,13 @@ var require_view = __commonJS({
|
|
|
18405
18405
|
"editor/node_modules/.pnpm/express@4.22.1/node_modules/express/lib/view.js"(exports, module) {
|
|
18406
18406
|
"use strict";
|
|
18407
18407
|
var debug = require_src()("express:view");
|
|
18408
|
-
var
|
|
18409
|
-
var
|
|
18410
|
-
var dirname =
|
|
18411
|
-
var basename =
|
|
18412
|
-
var extname =
|
|
18413
|
-
var join3 =
|
|
18414
|
-
var resolve2 =
|
|
18408
|
+
var path5 = __require("path");
|
|
18409
|
+
var fs3 = __require("fs");
|
|
18410
|
+
var dirname = path5.dirname;
|
|
18411
|
+
var basename = path5.basename;
|
|
18412
|
+
var extname = path5.extname;
|
|
18413
|
+
var join3 = path5.join;
|
|
18414
|
+
var resolve2 = path5.resolve;
|
|
18415
18415
|
module.exports = View;
|
|
18416
18416
|
function View(name, options) {
|
|
18417
18417
|
var opts = options || {};
|
|
@@ -18440,17 +18440,17 @@ var require_view = __commonJS({
|
|
|
18440
18440
|
this.path = this.lookup(fileName);
|
|
18441
18441
|
}
|
|
18442
18442
|
View.prototype.lookup = function lookup(name) {
|
|
18443
|
-
var
|
|
18443
|
+
var path6;
|
|
18444
18444
|
var roots = [].concat(this.root);
|
|
18445
18445
|
debug('lookup "%s"', name);
|
|
18446
|
-
for (var i = 0; i < roots.length && !
|
|
18446
|
+
for (var i = 0; i < roots.length && !path6; i++) {
|
|
18447
18447
|
var root = roots[i];
|
|
18448
18448
|
var loc = resolve2(root, name);
|
|
18449
18449
|
var dir = dirname(loc);
|
|
18450
18450
|
var file2 = basename(loc);
|
|
18451
|
-
|
|
18451
|
+
path6 = this.resolve(dir, file2);
|
|
18452
18452
|
}
|
|
18453
|
-
return
|
|
18453
|
+
return path6;
|
|
18454
18454
|
};
|
|
18455
18455
|
View.prototype.render = function render(options, callback) {
|
|
18456
18456
|
debug('render "%s"', this.path);
|
|
@@ -18458,21 +18458,21 @@ var require_view = __commonJS({
|
|
|
18458
18458
|
};
|
|
18459
18459
|
View.prototype.resolve = function resolve3(dir, file2) {
|
|
18460
18460
|
var ext = this.ext;
|
|
18461
|
-
var
|
|
18462
|
-
var stat = tryStat(
|
|
18461
|
+
var path6 = join3(dir, file2);
|
|
18462
|
+
var stat = tryStat(path6);
|
|
18463
18463
|
if (stat && stat.isFile()) {
|
|
18464
|
-
return
|
|
18464
|
+
return path6;
|
|
18465
18465
|
}
|
|
18466
|
-
|
|
18467
|
-
stat = tryStat(
|
|
18466
|
+
path6 = join3(dir, basename(file2, ext), "index" + ext);
|
|
18467
|
+
stat = tryStat(path6);
|
|
18468
18468
|
if (stat && stat.isFile()) {
|
|
18469
|
-
return
|
|
18469
|
+
return path6;
|
|
18470
18470
|
}
|
|
18471
18471
|
};
|
|
18472
|
-
function tryStat(
|
|
18473
|
-
debug('stat "%s"',
|
|
18472
|
+
function tryStat(path6) {
|
|
18473
|
+
debug('stat "%s"', path6);
|
|
18474
18474
|
try {
|
|
18475
|
-
return
|
|
18475
|
+
return fs3.statSync(path6);
|
|
18476
18476
|
} catch (e) {
|
|
18477
18477
|
return void 0;
|
|
18478
18478
|
}
|
|
@@ -18826,8 +18826,8 @@ var require_types = __commonJS({
|
|
|
18826
18826
|
// editor/node_modules/.pnpm/mime@1.6.0/node_modules/mime/mime.js
|
|
18827
18827
|
var require_mime = __commonJS({
|
|
18828
18828
|
"editor/node_modules/.pnpm/mime@1.6.0/node_modules/mime/mime.js"(exports, module) {
|
|
18829
|
-
var
|
|
18830
|
-
var
|
|
18829
|
+
var path5 = __require("path");
|
|
18830
|
+
var fs3 = __require("fs");
|
|
18831
18831
|
function Mime() {
|
|
18832
18832
|
this.types = /* @__PURE__ */ Object.create(null);
|
|
18833
18833
|
this.extensions = /* @__PURE__ */ Object.create(null);
|
|
@@ -18848,7 +18848,7 @@ var require_mime = __commonJS({
|
|
|
18848
18848
|
};
|
|
18849
18849
|
Mime.prototype.load = function(file2) {
|
|
18850
18850
|
this._loading = file2;
|
|
18851
|
-
var map2 = {}, content =
|
|
18851
|
+
var map2 = {}, content = fs3.readFileSync(file2, "ascii"), lines = content.split(/[\r\n]+/);
|
|
18852
18852
|
lines.forEach(function(line) {
|
|
18853
18853
|
var fields = line.replace(/\s*#.*|^\s*|\s*$/g, "").split(/\s+/);
|
|
18854
18854
|
map2[fields.shift()] = fields;
|
|
@@ -18856,8 +18856,8 @@ var require_mime = __commonJS({
|
|
|
18856
18856
|
this.define(map2);
|
|
18857
18857
|
this._loading = null;
|
|
18858
18858
|
};
|
|
18859
|
-
Mime.prototype.lookup = function(
|
|
18860
|
-
var ext =
|
|
18859
|
+
Mime.prototype.lookup = function(path6, fallback) {
|
|
18860
|
+
var ext = path6.replace(/^.*[\.\/\\]/, "").toLowerCase();
|
|
18861
18861
|
return this.types[ext] || fallback || this.default_type;
|
|
18862
18862
|
};
|
|
18863
18863
|
Mime.prototype.extension = function(mimeType) {
|
|
@@ -19086,33 +19086,33 @@ var require_send = __commonJS({
|
|
|
19086
19086
|
var escapeHtml = require_escape_html();
|
|
19087
19087
|
var etag = require_etag();
|
|
19088
19088
|
var fresh = require_fresh();
|
|
19089
|
-
var
|
|
19089
|
+
var fs3 = __require("fs");
|
|
19090
19090
|
var mime = require_mime();
|
|
19091
19091
|
var ms = require_ms2();
|
|
19092
19092
|
var onFinished = require_on_finished();
|
|
19093
19093
|
var parseRange = require_range_parser();
|
|
19094
|
-
var
|
|
19094
|
+
var path5 = __require("path");
|
|
19095
19095
|
var statuses = require_statuses();
|
|
19096
19096
|
var Stream = __require("stream");
|
|
19097
19097
|
var util = __require("util");
|
|
19098
|
-
var extname =
|
|
19099
|
-
var join3 =
|
|
19100
|
-
var normalize =
|
|
19101
|
-
var resolve2 =
|
|
19102
|
-
var sep =
|
|
19098
|
+
var extname = path5.extname;
|
|
19099
|
+
var join3 = path5.join;
|
|
19100
|
+
var normalize = path5.normalize;
|
|
19101
|
+
var resolve2 = path5.resolve;
|
|
19102
|
+
var sep = path5.sep;
|
|
19103
19103
|
var BYTES_RANGE_REGEXP = /^ *bytes=/;
|
|
19104
19104
|
var MAX_MAXAGE = 60 * 60 * 24 * 365 * 1e3;
|
|
19105
19105
|
var UP_PATH_REGEXP = /(?:^|[\\/])\.\.(?:[\\/]|$)/;
|
|
19106
19106
|
module.exports = send;
|
|
19107
19107
|
module.exports.mime = mime;
|
|
19108
|
-
function send(req,
|
|
19109
|
-
return new SendStream(req,
|
|
19108
|
+
function send(req, path6, options) {
|
|
19109
|
+
return new SendStream(req, path6, options);
|
|
19110
19110
|
}
|
|
19111
|
-
function SendStream(req,
|
|
19111
|
+
function SendStream(req, path6, options) {
|
|
19112
19112
|
Stream.call(this);
|
|
19113
19113
|
var opts = options || {};
|
|
19114
19114
|
this.options = opts;
|
|
19115
|
-
this.path =
|
|
19115
|
+
this.path = path6;
|
|
19116
19116
|
this.req = req;
|
|
19117
19117
|
this._acceptRanges = opts.acceptRanges !== void 0 ? Boolean(opts.acceptRanges) : true;
|
|
19118
19118
|
this._cacheControl = opts.cacheControl !== void 0 ? Boolean(opts.cacheControl) : true;
|
|
@@ -19158,8 +19158,8 @@ var require_send = __commonJS({
|
|
|
19158
19158
|
this._index = index2;
|
|
19159
19159
|
return this;
|
|
19160
19160
|
}, "send.index: pass index as option");
|
|
19161
|
-
SendStream.prototype.root = function root(
|
|
19162
|
-
this._root = resolve2(String(
|
|
19161
|
+
SendStream.prototype.root = function root(path6) {
|
|
19162
|
+
this._root = resolve2(String(path6));
|
|
19163
19163
|
debug("root %s", this._root);
|
|
19164
19164
|
return this;
|
|
19165
19165
|
};
|
|
@@ -19272,10 +19272,10 @@ var require_send = __commonJS({
|
|
|
19272
19272
|
var lastModified = this.res.getHeader("Last-Modified");
|
|
19273
19273
|
return parseHttpDate(lastModified) <= parseHttpDate(ifRange);
|
|
19274
19274
|
};
|
|
19275
|
-
SendStream.prototype.redirect = function redirect(
|
|
19275
|
+
SendStream.prototype.redirect = function redirect(path6) {
|
|
19276
19276
|
var res = this.res;
|
|
19277
19277
|
if (hasListeners(this, "directory")) {
|
|
19278
|
-
this.emit("directory", res,
|
|
19278
|
+
this.emit("directory", res, path6);
|
|
19279
19279
|
return;
|
|
19280
19280
|
}
|
|
19281
19281
|
if (this.hasTrailingSlash()) {
|
|
@@ -19295,42 +19295,42 @@ var require_send = __commonJS({
|
|
|
19295
19295
|
SendStream.prototype.pipe = function pipe2(res) {
|
|
19296
19296
|
var root = this._root;
|
|
19297
19297
|
this.res = res;
|
|
19298
|
-
var
|
|
19299
|
-
if (
|
|
19298
|
+
var path6 = decode3(this.path);
|
|
19299
|
+
if (path6 === -1) {
|
|
19300
19300
|
this.error(400);
|
|
19301
19301
|
return res;
|
|
19302
19302
|
}
|
|
19303
|
-
if (~
|
|
19303
|
+
if (~path6.indexOf("\0")) {
|
|
19304
19304
|
this.error(400);
|
|
19305
19305
|
return res;
|
|
19306
19306
|
}
|
|
19307
19307
|
var parts;
|
|
19308
19308
|
if (root !== null) {
|
|
19309
|
-
if (
|
|
19310
|
-
|
|
19309
|
+
if (path6) {
|
|
19310
|
+
path6 = normalize("." + sep + path6);
|
|
19311
19311
|
}
|
|
19312
|
-
if (UP_PATH_REGEXP.test(
|
|
19313
|
-
debug('malicious path "%s"',
|
|
19312
|
+
if (UP_PATH_REGEXP.test(path6)) {
|
|
19313
|
+
debug('malicious path "%s"', path6);
|
|
19314
19314
|
this.error(403);
|
|
19315
19315
|
return res;
|
|
19316
19316
|
}
|
|
19317
|
-
parts =
|
|
19318
|
-
|
|
19317
|
+
parts = path6.split(sep);
|
|
19318
|
+
path6 = normalize(join3(root, path6));
|
|
19319
19319
|
} else {
|
|
19320
|
-
if (UP_PATH_REGEXP.test(
|
|
19321
|
-
debug('malicious path "%s"',
|
|
19320
|
+
if (UP_PATH_REGEXP.test(path6)) {
|
|
19321
|
+
debug('malicious path "%s"', path6);
|
|
19322
19322
|
this.error(403);
|
|
19323
19323
|
return res;
|
|
19324
19324
|
}
|
|
19325
|
-
parts = normalize(
|
|
19326
|
-
|
|
19325
|
+
parts = normalize(path6).split(sep);
|
|
19326
|
+
path6 = resolve2(path6);
|
|
19327
19327
|
}
|
|
19328
19328
|
if (containsDotFile(parts)) {
|
|
19329
19329
|
var access = this._dotfiles;
|
|
19330
19330
|
if (access === void 0) {
|
|
19331
19331
|
access = parts[parts.length - 1][0] === "." ? this._hidden ? "allow" : "ignore" : "allow";
|
|
19332
19332
|
}
|
|
19333
|
-
debug('%s dotfile "%s"', access,
|
|
19333
|
+
debug('%s dotfile "%s"', access, path6);
|
|
19334
19334
|
switch (access) {
|
|
19335
19335
|
case "allow":
|
|
19336
19336
|
break;
|
|
@@ -19344,13 +19344,13 @@ var require_send = __commonJS({
|
|
|
19344
19344
|
}
|
|
19345
19345
|
}
|
|
19346
19346
|
if (this._index.length && this.hasTrailingSlash()) {
|
|
19347
|
-
this.sendIndex(
|
|
19347
|
+
this.sendIndex(path6);
|
|
19348
19348
|
return res;
|
|
19349
19349
|
}
|
|
19350
|
-
this.sendFile(
|
|
19350
|
+
this.sendFile(path6);
|
|
19351
19351
|
return res;
|
|
19352
19352
|
};
|
|
19353
|
-
SendStream.prototype.send = function send2(
|
|
19353
|
+
SendStream.prototype.send = function send2(path6, stat) {
|
|
19354
19354
|
var len = stat.size;
|
|
19355
19355
|
var options = this.options;
|
|
19356
19356
|
var opts = {};
|
|
@@ -19362,9 +19362,9 @@ var require_send = __commonJS({
|
|
|
19362
19362
|
this.headersAlreadySent();
|
|
19363
19363
|
return;
|
|
19364
19364
|
}
|
|
19365
|
-
debug('pipe "%s"',
|
|
19366
|
-
this.setHeader(
|
|
19367
|
-
this.type(
|
|
19365
|
+
debug('pipe "%s"', path6);
|
|
19366
|
+
this.setHeader(path6, stat);
|
|
19367
|
+
this.type(path6);
|
|
19368
19368
|
if (this.isConditionalGET()) {
|
|
19369
19369
|
if (this.isPreconditionFailure()) {
|
|
19370
19370
|
this.error(412);
|
|
@@ -19413,28 +19413,28 @@ var require_send = __commonJS({
|
|
|
19413
19413
|
res.end();
|
|
19414
19414
|
return;
|
|
19415
19415
|
}
|
|
19416
|
-
this.stream(
|
|
19416
|
+
this.stream(path6, opts);
|
|
19417
19417
|
};
|
|
19418
|
-
SendStream.prototype.sendFile = function sendFile(
|
|
19418
|
+
SendStream.prototype.sendFile = function sendFile(path6) {
|
|
19419
19419
|
var i = 0;
|
|
19420
19420
|
var self = this;
|
|
19421
|
-
debug('stat "%s"',
|
|
19422
|
-
|
|
19423
|
-
if (err && err.code === "ENOENT" && !extname(
|
|
19421
|
+
debug('stat "%s"', path6);
|
|
19422
|
+
fs3.stat(path6, function onstat(err, stat) {
|
|
19423
|
+
if (err && err.code === "ENOENT" && !extname(path6) && path6[path6.length - 1] !== sep) {
|
|
19424
19424
|
return next(err);
|
|
19425
19425
|
}
|
|
19426
19426
|
if (err) return self.onStatError(err);
|
|
19427
|
-
if (stat.isDirectory()) return self.redirect(
|
|
19428
|
-
self.emit("file",
|
|
19429
|
-
self.send(
|
|
19427
|
+
if (stat.isDirectory()) return self.redirect(path6);
|
|
19428
|
+
self.emit("file", path6, stat);
|
|
19429
|
+
self.send(path6, stat);
|
|
19430
19430
|
});
|
|
19431
19431
|
function next(err) {
|
|
19432
19432
|
if (self._extensions.length <= i) {
|
|
19433
19433
|
return err ? self.onStatError(err) : self.error(404);
|
|
19434
19434
|
}
|
|
19435
|
-
var p =
|
|
19435
|
+
var p = path6 + "." + self._extensions[i++];
|
|
19436
19436
|
debug('stat "%s"', p);
|
|
19437
|
-
|
|
19437
|
+
fs3.stat(p, function(err2, stat) {
|
|
19438
19438
|
if (err2) return next(err2);
|
|
19439
19439
|
if (stat.isDirectory()) return next();
|
|
19440
19440
|
self.emit("file", p, stat);
|
|
@@ -19442,7 +19442,7 @@ var require_send = __commonJS({
|
|
|
19442
19442
|
});
|
|
19443
19443
|
}
|
|
19444
19444
|
};
|
|
19445
|
-
SendStream.prototype.sendIndex = function sendIndex(
|
|
19445
|
+
SendStream.prototype.sendIndex = function sendIndex(path6) {
|
|
19446
19446
|
var i = -1;
|
|
19447
19447
|
var self = this;
|
|
19448
19448
|
function next(err) {
|
|
@@ -19450,9 +19450,9 @@ var require_send = __commonJS({
|
|
|
19450
19450
|
if (err) return self.onStatError(err);
|
|
19451
19451
|
return self.error(404);
|
|
19452
19452
|
}
|
|
19453
|
-
var p = join3(
|
|
19453
|
+
var p = join3(path6, self._index[i]);
|
|
19454
19454
|
debug('stat "%s"', p);
|
|
19455
|
-
|
|
19455
|
+
fs3.stat(p, function(err2, stat) {
|
|
19456
19456
|
if (err2) return next(err2);
|
|
19457
19457
|
if (stat.isDirectory()) return next();
|
|
19458
19458
|
self.emit("file", p, stat);
|
|
@@ -19461,10 +19461,10 @@ var require_send = __commonJS({
|
|
|
19461
19461
|
}
|
|
19462
19462
|
next();
|
|
19463
19463
|
};
|
|
19464
|
-
SendStream.prototype.stream = function stream(
|
|
19464
|
+
SendStream.prototype.stream = function stream(path6, options) {
|
|
19465
19465
|
var self = this;
|
|
19466
19466
|
var res = this.res;
|
|
19467
|
-
var stream2 =
|
|
19467
|
+
var stream2 = fs3.createReadStream(path6, options);
|
|
19468
19468
|
this.emit("stream", stream2);
|
|
19469
19469
|
stream2.pipe(res);
|
|
19470
19470
|
function cleanup2() {
|
|
@@ -19479,10 +19479,10 @@ var require_send = __commonJS({
|
|
|
19479
19479
|
self.emit("end");
|
|
19480
19480
|
});
|
|
19481
19481
|
};
|
|
19482
|
-
SendStream.prototype.type = function type(
|
|
19482
|
+
SendStream.prototype.type = function type(path6) {
|
|
19483
19483
|
var res = this.res;
|
|
19484
19484
|
if (res.getHeader("Content-Type")) return;
|
|
19485
|
-
var type2 = mime.lookup(
|
|
19485
|
+
var type2 = mime.lookup(path6);
|
|
19486
19486
|
if (!type2) {
|
|
19487
19487
|
debug("no content-type");
|
|
19488
19488
|
return;
|
|
@@ -19491,9 +19491,9 @@ var require_send = __commonJS({
|
|
|
19491
19491
|
debug("content-type %s", type2);
|
|
19492
19492
|
res.setHeader("Content-Type", type2 + (charset ? "; charset=" + charset : ""));
|
|
19493
19493
|
};
|
|
19494
|
-
SendStream.prototype.setHeader = function setHeader(
|
|
19494
|
+
SendStream.prototype.setHeader = function setHeader(path6, stat) {
|
|
19495
19495
|
var res = this.res;
|
|
19496
|
-
this.emit("headers", res,
|
|
19496
|
+
this.emit("headers", res, path6, stat);
|
|
19497
19497
|
if (this._acceptRanges && !res.getHeader("Accept-Ranges")) {
|
|
19498
19498
|
debug("accept ranges");
|
|
19499
19499
|
res.setHeader("Accept-Ranges", "bytes");
|
|
@@ -19552,9 +19552,9 @@ var require_send = __commonJS({
|
|
|
19552
19552
|
}
|
|
19553
19553
|
return err instanceof Error ? createError(status, err, { expose: false }) : createError(status, err);
|
|
19554
19554
|
}
|
|
19555
|
-
function decode3(
|
|
19555
|
+
function decode3(path6) {
|
|
19556
19556
|
try {
|
|
19557
|
-
return decodeURIComponent(
|
|
19557
|
+
return decodeURIComponent(path6);
|
|
19558
19558
|
} catch (err) {
|
|
19559
19559
|
return -1;
|
|
19560
19560
|
}
|
|
@@ -20463,10 +20463,10 @@ var require_utils2 = __commonJS({
|
|
|
20463
20463
|
var querystring = __require("querystring");
|
|
20464
20464
|
exports.etag = createETagGenerator({ weak: false });
|
|
20465
20465
|
exports.wetag = createETagGenerator({ weak: true });
|
|
20466
|
-
exports.isAbsolute = function(
|
|
20467
|
-
if ("/" ===
|
|
20468
|
-
if (":" ===
|
|
20469
|
-
if ("\\\\" ===
|
|
20466
|
+
exports.isAbsolute = function(path5) {
|
|
20467
|
+
if ("/" === path5[0]) return true;
|
|
20468
|
+
if (":" === path5[1] && ("\\" === path5[2] || "/" === path5[2])) return true;
|
|
20469
|
+
if ("\\\\" === path5.substring(0, 2)) return true;
|
|
20470
20470
|
};
|
|
20471
20471
|
exports.flatten = deprecate.function(
|
|
20472
20472
|
flatten,
|
|
@@ -20677,7 +20677,7 @@ var require_application = __commonJS({
|
|
|
20677
20677
|
};
|
|
20678
20678
|
app2.use = function use(fn) {
|
|
20679
20679
|
var offset = 0;
|
|
20680
|
-
var
|
|
20680
|
+
var path5 = "/";
|
|
20681
20681
|
if (typeof fn !== "function") {
|
|
20682
20682
|
var arg = fn;
|
|
20683
20683
|
while (Array.isArray(arg) && arg.length !== 0) {
|
|
@@ -20685,7 +20685,7 @@ var require_application = __commonJS({
|
|
|
20685
20685
|
}
|
|
20686
20686
|
if (typeof arg !== "function") {
|
|
20687
20687
|
offset = 1;
|
|
20688
|
-
|
|
20688
|
+
path5 = fn;
|
|
20689
20689
|
}
|
|
20690
20690
|
}
|
|
20691
20691
|
var fns = flatten(slice.call(arguments, offset));
|
|
@@ -20696,12 +20696,12 @@ var require_application = __commonJS({
|
|
|
20696
20696
|
var router = this._router;
|
|
20697
20697
|
fns.forEach(function(fn2) {
|
|
20698
20698
|
if (!fn2 || !fn2.handle || !fn2.set) {
|
|
20699
|
-
return router.use(
|
|
20699
|
+
return router.use(path5, fn2);
|
|
20700
20700
|
}
|
|
20701
|
-
debug(".use app under %s",
|
|
20702
|
-
fn2.mountpath =
|
|
20701
|
+
debug(".use app under %s", path5);
|
|
20702
|
+
fn2.mountpath = path5;
|
|
20703
20703
|
fn2.parent = this;
|
|
20704
|
-
router.use(
|
|
20704
|
+
router.use(path5, function mounted_app(req, res, next) {
|
|
20705
20705
|
var orig = req.app;
|
|
20706
20706
|
fn2.handle(req, res, function(err) {
|
|
20707
20707
|
setPrototypeOf(req, orig.request);
|
|
@@ -20713,9 +20713,9 @@ var require_application = __commonJS({
|
|
|
20713
20713
|
}, this);
|
|
20714
20714
|
return this;
|
|
20715
20715
|
};
|
|
20716
|
-
app2.route = function route(
|
|
20716
|
+
app2.route = function route(path5) {
|
|
20717
20717
|
this.lazyrouter();
|
|
20718
|
-
return this._router.route(
|
|
20718
|
+
return this._router.route(path5);
|
|
20719
20719
|
};
|
|
20720
20720
|
app2.engine = function engine(ext, fn) {
|
|
20721
20721
|
if (typeof fn !== "function") {
|
|
@@ -20766,7 +20766,7 @@ var require_application = __commonJS({
|
|
|
20766
20766
|
}
|
|
20767
20767
|
return this;
|
|
20768
20768
|
};
|
|
20769
|
-
app2.path = function
|
|
20769
|
+
app2.path = function path5() {
|
|
20770
20770
|
return this.parent ? this.parent.path() + this.mountpath : "";
|
|
20771
20771
|
};
|
|
20772
20772
|
app2.enabled = function enabled(setting) {
|
|
@@ -20782,19 +20782,19 @@ var require_application = __commonJS({
|
|
|
20782
20782
|
return this.set(setting, false);
|
|
20783
20783
|
};
|
|
20784
20784
|
methods.forEach(function(method) {
|
|
20785
|
-
app2[method] = function(
|
|
20785
|
+
app2[method] = function(path5) {
|
|
20786
20786
|
if (method === "get" && arguments.length === 1) {
|
|
20787
|
-
return this.set(
|
|
20787
|
+
return this.set(path5);
|
|
20788
20788
|
}
|
|
20789
20789
|
this.lazyrouter();
|
|
20790
|
-
var route = this._router.route(
|
|
20790
|
+
var route = this._router.route(path5);
|
|
20791
20791
|
route[method].apply(route, slice.call(arguments, 1));
|
|
20792
20792
|
return this;
|
|
20793
20793
|
};
|
|
20794
20794
|
});
|
|
20795
|
-
app2.all = function all(
|
|
20795
|
+
app2.all = function all(path5) {
|
|
20796
20796
|
this.lazyrouter();
|
|
20797
|
-
var route = this._router.route(
|
|
20797
|
+
var route = this._router.route(path5);
|
|
20798
20798
|
var args = slice.call(arguments, 1);
|
|
20799
20799
|
for (var i = 0; i < methods.length; i++) {
|
|
20800
20800
|
route[methods[i]].apply(route, args);
|
|
@@ -21553,7 +21553,7 @@ var require_request = __commonJS({
|
|
|
21553
21553
|
var subdomains2 = !isIP(hostname3) ? hostname3.split(".").reverse() : [hostname3];
|
|
21554
21554
|
return subdomains2.slice(offset);
|
|
21555
21555
|
});
|
|
21556
|
-
defineGetter(req, "path", function
|
|
21556
|
+
defineGetter(req, "path", function path5() {
|
|
21557
21557
|
return parse3(this).pathname;
|
|
21558
21558
|
});
|
|
21559
21559
|
defineGetter(req, "hostname", function hostname3() {
|
|
@@ -21875,7 +21875,7 @@ var require_response = __commonJS({
|
|
|
21875
21875
|
var http = __require("http");
|
|
21876
21876
|
var isAbsolute = require_utils2().isAbsolute;
|
|
21877
21877
|
var onFinished = require_on_finished();
|
|
21878
|
-
var
|
|
21878
|
+
var path5 = __require("path");
|
|
21879
21879
|
var statuses = require_statuses();
|
|
21880
21880
|
var merge2 = require_utils_merge();
|
|
21881
21881
|
var sign = require_cookie_signature().sign;
|
|
@@ -21884,9 +21884,9 @@ var require_response = __commonJS({
|
|
|
21884
21884
|
var setCharset = require_utils2().setCharset;
|
|
21885
21885
|
var cookie = require_cookie();
|
|
21886
21886
|
var send = require_send();
|
|
21887
|
-
var extname =
|
|
21887
|
+
var extname = path5.extname;
|
|
21888
21888
|
var mime = send.mime;
|
|
21889
|
-
var resolve2 =
|
|
21889
|
+
var resolve2 = path5.resolve;
|
|
21890
21890
|
var vary = require_vary();
|
|
21891
21891
|
var res = Object.create(http.ServerResponse.prototype);
|
|
21892
21892
|
module.exports = res;
|
|
@@ -22063,26 +22063,26 @@ var require_response = __commonJS({
|
|
|
22063
22063
|
this.type("txt");
|
|
22064
22064
|
return this.send(body);
|
|
22065
22065
|
};
|
|
22066
|
-
res.sendFile = function sendFile(
|
|
22066
|
+
res.sendFile = function sendFile(path6, options, callback) {
|
|
22067
22067
|
var done = callback;
|
|
22068
22068
|
var req = this.req;
|
|
22069
22069
|
var res2 = this;
|
|
22070
22070
|
var next = req.next;
|
|
22071
22071
|
var opts = options || {};
|
|
22072
|
-
if (!
|
|
22072
|
+
if (!path6) {
|
|
22073
22073
|
throw new TypeError("path argument is required to res.sendFile");
|
|
22074
22074
|
}
|
|
22075
|
-
if (typeof
|
|
22075
|
+
if (typeof path6 !== "string") {
|
|
22076
22076
|
throw new TypeError("path must be a string to res.sendFile");
|
|
22077
22077
|
}
|
|
22078
22078
|
if (typeof options === "function") {
|
|
22079
22079
|
done = options;
|
|
22080
22080
|
opts = {};
|
|
22081
22081
|
}
|
|
22082
|
-
if (!opts.root && !isAbsolute(
|
|
22082
|
+
if (!opts.root && !isAbsolute(path6)) {
|
|
22083
22083
|
throw new TypeError("path must be absolute or specify root to res.sendFile");
|
|
22084
22084
|
}
|
|
22085
|
-
var pathname = encodeURI(
|
|
22085
|
+
var pathname = encodeURI(path6);
|
|
22086
22086
|
var file2 = send(req, pathname, opts);
|
|
22087
22087
|
sendfile(res2, file2, opts, function(err) {
|
|
22088
22088
|
if (done) return done(err);
|
|
@@ -22092,7 +22092,7 @@ var require_response = __commonJS({
|
|
|
22092
22092
|
}
|
|
22093
22093
|
});
|
|
22094
22094
|
};
|
|
22095
|
-
res.sendfile = function(
|
|
22095
|
+
res.sendfile = function(path6, options, callback) {
|
|
22096
22096
|
var done = callback;
|
|
22097
22097
|
var req = this.req;
|
|
22098
22098
|
var res2 = this;
|
|
@@ -22102,7 +22102,7 @@ var require_response = __commonJS({
|
|
|
22102
22102
|
done = options;
|
|
22103
22103
|
opts = {};
|
|
22104
22104
|
}
|
|
22105
|
-
var file2 = send(req,
|
|
22105
|
+
var file2 = send(req, path6, opts);
|
|
22106
22106
|
sendfile(res2, file2, opts, function(err) {
|
|
22107
22107
|
if (done) return done(err);
|
|
22108
22108
|
if (err && err.code === "EISDIR") return next();
|
|
@@ -22115,7 +22115,7 @@ var require_response = __commonJS({
|
|
|
22115
22115
|
res.sendfile,
|
|
22116
22116
|
"res.sendfile: Use res.sendFile instead"
|
|
22117
22117
|
);
|
|
22118
|
-
res.download = function download(
|
|
22118
|
+
res.download = function download(path6, filename, options, callback) {
|
|
22119
22119
|
var done = callback;
|
|
22120
22120
|
var name = filename;
|
|
22121
22121
|
var opts = options || null;
|
|
@@ -22132,7 +22132,7 @@ var require_response = __commonJS({
|
|
|
22132
22132
|
opts = filename;
|
|
22133
22133
|
}
|
|
22134
22134
|
var headers = {
|
|
22135
|
-
"Content-Disposition": contentDisposition(name ||
|
|
22135
|
+
"Content-Disposition": contentDisposition(name || path6)
|
|
22136
22136
|
};
|
|
22137
22137
|
if (opts && opts.headers) {
|
|
22138
22138
|
var keys = Object.keys(opts.headers);
|
|
@@ -22145,7 +22145,7 @@ var require_response = __commonJS({
|
|
|
22145
22145
|
}
|
|
22146
22146
|
opts = Object.create(opts);
|
|
22147
22147
|
opts.headers = headers;
|
|
22148
|
-
var fullPath = !opts.root ? resolve2(
|
|
22148
|
+
var fullPath = !opts.root ? resolve2(path6) : path6;
|
|
22149
22149
|
return this.sendFile(fullPath, opts, done);
|
|
22150
22150
|
};
|
|
22151
22151
|
res.contentType = res.type = function contentType(type) {
|
|
@@ -22446,11 +22446,11 @@ var require_serve_static = __commonJS({
|
|
|
22446
22446
|
}
|
|
22447
22447
|
var forwardError = !fallthrough;
|
|
22448
22448
|
var originalUrl = parseUrl.original(req);
|
|
22449
|
-
var
|
|
22450
|
-
if (
|
|
22451
|
-
|
|
22449
|
+
var path5 = parseUrl(req).pathname;
|
|
22450
|
+
if (path5 === "/" && originalUrl.pathname.substr(-1) !== "/") {
|
|
22451
|
+
path5 = "";
|
|
22452
22452
|
}
|
|
22453
|
-
var stream = send(req,
|
|
22453
|
+
var stream = send(req, path5, opts);
|
|
22454
22454
|
stream.on("directory", onDirectory);
|
|
22455
22455
|
if (setHeaders) {
|
|
22456
22456
|
stream.on("headers", setHeaders);
|
|
@@ -26057,8 +26057,8 @@ var require_utils3 = __commonJS({
|
|
|
26057
26057
|
}
|
|
26058
26058
|
return ind;
|
|
26059
26059
|
}
|
|
26060
|
-
function removeDotSegments(
|
|
26061
|
-
let input =
|
|
26060
|
+
function removeDotSegments(path5) {
|
|
26061
|
+
let input = path5;
|
|
26062
26062
|
const output = [];
|
|
26063
26063
|
let nextSlash = -1;
|
|
26064
26064
|
let len = 0;
|
|
@@ -26257,8 +26257,8 @@ var require_schemes = __commonJS({
|
|
|
26257
26257
|
wsComponent.secure = void 0;
|
|
26258
26258
|
}
|
|
26259
26259
|
if (wsComponent.resourceName) {
|
|
26260
|
-
const [
|
|
26261
|
-
wsComponent.path =
|
|
26260
|
+
const [path5, query] = wsComponent.resourceName.split("?");
|
|
26261
|
+
wsComponent.path = path5 && path5 !== "/" ? path5 : void 0;
|
|
26262
26262
|
wsComponent.query = query;
|
|
26263
26263
|
wsComponent.resourceName = void 0;
|
|
26264
26264
|
}
|
|
@@ -29319,12 +29319,12 @@ var require_ajv = __commonJS({
|
|
|
29319
29319
|
// editor/server/index.ts
|
|
29320
29320
|
var import_express = __toESM(require_express2(), 1);
|
|
29321
29321
|
var import_cors = __toESM(require_lib3(), 1);
|
|
29322
|
-
import
|
|
29322
|
+
import path4 from "path";
|
|
29323
29323
|
import { fileURLToPath } from "url";
|
|
29324
29324
|
import { Firestore } from "@google-cloud/firestore";
|
|
29325
29325
|
|
|
29326
29326
|
// src/client.ts
|
|
29327
|
-
import { FieldValue as
|
|
29327
|
+
import { FieldValue as FieldValue5 } from "@google-cloud/firestore";
|
|
29328
29328
|
|
|
29329
29329
|
// src/docid.ts
|
|
29330
29330
|
import { createHash } from "node:crypto";
|
|
@@ -29434,6 +29434,12 @@ var RegistryScopeError = class extends FiregraphError {
|
|
|
29434
29434
|
this.name = "RegistryScopeError";
|
|
29435
29435
|
}
|
|
29436
29436
|
};
|
|
29437
|
+
var MigrationError = class extends FiregraphError {
|
|
29438
|
+
constructor(message) {
|
|
29439
|
+
super(message, "MIGRATION_ERROR");
|
|
29440
|
+
this.name = "MigrationError";
|
|
29441
|
+
}
|
|
29442
|
+
};
|
|
29437
29443
|
|
|
29438
29444
|
// src/query.ts
|
|
29439
29445
|
function buildEdgeQueryPlan(params) {
|
|
@@ -29624,7 +29630,7 @@ function createPipelineQueryAdapter(db2, collectionPath) {
|
|
|
29624
29630
|
}
|
|
29625
29631
|
|
|
29626
29632
|
// src/transaction.ts
|
|
29627
|
-
import { FieldValue as
|
|
29633
|
+
import { FieldValue as FieldValue3 } from "@google-cloud/firestore";
|
|
29628
29634
|
|
|
29629
29635
|
// src/query-safety.ts
|
|
29630
29636
|
var SAFE_INDEX_PATTERNS = [
|
|
@@ -29674,24 +29680,248 @@ function analyzeQuerySafety(filters) {
|
|
|
29674
29680
|
};
|
|
29675
29681
|
}
|
|
29676
29682
|
|
|
29683
|
+
// src/serialization.ts
|
|
29684
|
+
import { Timestamp, GeoPoint, FieldValue as FieldValue2 } from "@google-cloud/firestore";
|
|
29685
|
+
var SERIALIZATION_TAG = "__firegraph_ser__";
|
|
29686
|
+
var KNOWN_TYPES = /* @__PURE__ */ new Set(["Timestamp", "GeoPoint", "VectorValue", "DocumentReference"]);
|
|
29687
|
+
var _docRefWarned = false;
|
|
29688
|
+
function isTaggedValue(value) {
|
|
29689
|
+
if (value === null || typeof value !== "object") return false;
|
|
29690
|
+
const tag = value[SERIALIZATION_TAG];
|
|
29691
|
+
return typeof tag === "string" && KNOWN_TYPES.has(tag);
|
|
29692
|
+
}
|
|
29693
|
+
function isTimestamp(value) {
|
|
29694
|
+
return value instanceof Timestamp;
|
|
29695
|
+
}
|
|
29696
|
+
function isGeoPoint(value) {
|
|
29697
|
+
return value instanceof GeoPoint;
|
|
29698
|
+
}
|
|
29699
|
+
function isDocumentReference(value) {
|
|
29700
|
+
if (value === null || typeof value !== "object") return false;
|
|
29701
|
+
const v = value;
|
|
29702
|
+
return typeof v.path === "string" && v.firestore !== void 0 && typeof v.id === "string" && v.constructor?.name === "DocumentReference";
|
|
29703
|
+
}
|
|
29704
|
+
function isVectorValue(value) {
|
|
29705
|
+
if (value === null || typeof value !== "object") return false;
|
|
29706
|
+
const v = value;
|
|
29707
|
+
return v.constructor?.name === "VectorValue" && Array.isArray(v._values);
|
|
29708
|
+
}
|
|
29709
|
+
function serializeFirestoreTypes(data) {
|
|
29710
|
+
return serializeValue(data);
|
|
29711
|
+
}
|
|
29712
|
+
function serializeValue(value) {
|
|
29713
|
+
if (value === null || value === void 0) return value;
|
|
29714
|
+
if (typeof value !== "object") return value;
|
|
29715
|
+
if (isTimestamp(value)) {
|
|
29716
|
+
return { [SERIALIZATION_TAG]: "Timestamp", seconds: value.seconds, nanoseconds: value.nanoseconds };
|
|
29717
|
+
}
|
|
29718
|
+
if (isGeoPoint(value)) {
|
|
29719
|
+
return { [SERIALIZATION_TAG]: "GeoPoint", latitude: value.latitude, longitude: value.longitude };
|
|
29720
|
+
}
|
|
29721
|
+
if (isDocumentReference(value)) {
|
|
29722
|
+
return { [SERIALIZATION_TAG]: "DocumentReference", path: value.path };
|
|
29723
|
+
}
|
|
29724
|
+
if (isVectorValue(value)) {
|
|
29725
|
+
const v = value;
|
|
29726
|
+
const values = typeof v.toArray === "function" ? v.toArray() : v._values;
|
|
29727
|
+
return { [SERIALIZATION_TAG]: "VectorValue", values: [...values] };
|
|
29728
|
+
}
|
|
29729
|
+
if (Array.isArray(value)) {
|
|
29730
|
+
return value.map(serializeValue);
|
|
29731
|
+
}
|
|
29732
|
+
const result = {};
|
|
29733
|
+
for (const key of Object.keys(value)) {
|
|
29734
|
+
result[key] = serializeValue(value[key]);
|
|
29735
|
+
}
|
|
29736
|
+
return result;
|
|
29737
|
+
}
|
|
29738
|
+
function deserializeFirestoreTypes(data, db2) {
|
|
29739
|
+
return deserializeValue(data, db2);
|
|
29740
|
+
}
|
|
29741
|
+
function deserializeValue(value, db2) {
|
|
29742
|
+
if (value === null || value === void 0) return value;
|
|
29743
|
+
if (typeof value !== "object") return value;
|
|
29744
|
+
if (isTimestamp(value) || isGeoPoint(value) || isDocumentReference(value) || isVectorValue(value)) {
|
|
29745
|
+
return value;
|
|
29746
|
+
}
|
|
29747
|
+
if (Array.isArray(value)) {
|
|
29748
|
+
return value.map((v) => deserializeValue(v, db2));
|
|
29749
|
+
}
|
|
29750
|
+
const obj = value;
|
|
29751
|
+
if (isTaggedValue(obj)) {
|
|
29752
|
+
const tag = obj[SERIALIZATION_TAG];
|
|
29753
|
+
switch (tag) {
|
|
29754
|
+
case "Timestamp":
|
|
29755
|
+
if (typeof obj.seconds !== "number" || typeof obj.nanoseconds !== "number") return obj;
|
|
29756
|
+
return new Timestamp(obj.seconds, obj.nanoseconds);
|
|
29757
|
+
case "GeoPoint":
|
|
29758
|
+
if (typeof obj.latitude !== "number" || typeof obj.longitude !== "number") return obj;
|
|
29759
|
+
return new GeoPoint(obj.latitude, obj.longitude);
|
|
29760
|
+
case "VectorValue":
|
|
29761
|
+
if (!Array.isArray(obj.values)) return obj;
|
|
29762
|
+
return FieldValue2.vector(obj.values);
|
|
29763
|
+
case "DocumentReference":
|
|
29764
|
+
if (typeof obj.path !== "string") return obj;
|
|
29765
|
+
if (db2) {
|
|
29766
|
+
return db2.doc(obj.path);
|
|
29767
|
+
}
|
|
29768
|
+
if (!_docRefWarned) {
|
|
29769
|
+
_docRefWarned = true;
|
|
29770
|
+
console.warn(
|
|
29771
|
+
"[firegraph] DocumentReference encountered during migration deserialization but no Firestore instance available. The reference will remain as a tagged object with its path. Enable write-back for full reconstruction."
|
|
29772
|
+
);
|
|
29773
|
+
}
|
|
29774
|
+
return obj;
|
|
29775
|
+
default:
|
|
29776
|
+
return obj;
|
|
29777
|
+
}
|
|
29778
|
+
}
|
|
29779
|
+
const result = {};
|
|
29780
|
+
for (const key of Object.keys(obj)) {
|
|
29781
|
+
result[key] = deserializeValue(obj[key], db2);
|
|
29782
|
+
}
|
|
29783
|
+
return result;
|
|
29784
|
+
}
|
|
29785
|
+
|
|
29786
|
+
// src/migration.ts
|
|
29787
|
+
async function applyMigrationChain(data, currentVersion, targetVersion, migrations) {
|
|
29788
|
+
const sorted = [...migrations].sort((a, b) => a.fromVersion - b.fromVersion);
|
|
29789
|
+
let result = { ...data };
|
|
29790
|
+
let version2 = currentVersion;
|
|
29791
|
+
for (const step of sorted) {
|
|
29792
|
+
if (step.fromVersion === version2) {
|
|
29793
|
+
try {
|
|
29794
|
+
result = await step.up(result);
|
|
29795
|
+
} catch (err) {
|
|
29796
|
+
if (err instanceof MigrationError) throw err;
|
|
29797
|
+
throw new MigrationError(
|
|
29798
|
+
`Migration from v${step.fromVersion} to v${step.toVersion} failed: ${err.message}`
|
|
29799
|
+
);
|
|
29800
|
+
}
|
|
29801
|
+
if (!result || typeof result !== "object") {
|
|
29802
|
+
throw new MigrationError(
|
|
29803
|
+
`Migration from v${step.fromVersion} to v${step.toVersion} returned invalid data (expected object)`
|
|
29804
|
+
);
|
|
29805
|
+
}
|
|
29806
|
+
version2 = step.toVersion;
|
|
29807
|
+
}
|
|
29808
|
+
}
|
|
29809
|
+
if (version2 !== targetVersion) {
|
|
29810
|
+
throw new MigrationError(
|
|
29811
|
+
`Incomplete migration chain: reached v${version2} but target is v${targetVersion}`
|
|
29812
|
+
);
|
|
29813
|
+
}
|
|
29814
|
+
return result;
|
|
29815
|
+
}
|
|
29816
|
+
function validateMigrationChain(migrations, label) {
|
|
29817
|
+
if (migrations.length === 0) return;
|
|
29818
|
+
const seen = /* @__PURE__ */ new Set();
|
|
29819
|
+
for (const step of migrations) {
|
|
29820
|
+
if (step.toVersion <= step.fromVersion) {
|
|
29821
|
+
throw new MigrationError(
|
|
29822
|
+
`${label}: migration step has toVersion (${step.toVersion}) <= fromVersion (${step.fromVersion})`
|
|
29823
|
+
);
|
|
29824
|
+
}
|
|
29825
|
+
if (seen.has(step.fromVersion)) {
|
|
29826
|
+
throw new MigrationError(
|
|
29827
|
+
`${label}: duplicate migration step for fromVersion ${step.fromVersion}`
|
|
29828
|
+
);
|
|
29829
|
+
}
|
|
29830
|
+
seen.add(step.fromVersion);
|
|
29831
|
+
}
|
|
29832
|
+
const sorted = [...migrations].sort((a, b) => a.fromVersion - b.fromVersion);
|
|
29833
|
+
const targetVersion = Math.max(...migrations.map((m) => m.toVersion));
|
|
29834
|
+
let version2 = 0;
|
|
29835
|
+
for (const step of sorted) {
|
|
29836
|
+
if (step.fromVersion === version2) {
|
|
29837
|
+
version2 = step.toVersion;
|
|
29838
|
+
} else if (step.fromVersion > version2) {
|
|
29839
|
+
throw new MigrationError(
|
|
29840
|
+
`${label}: migration chain has a gap \u2014 no step covers v${version2} \u2192 v${step.fromVersion}`
|
|
29841
|
+
);
|
|
29842
|
+
}
|
|
29843
|
+
}
|
|
29844
|
+
if (version2 !== targetVersion) {
|
|
29845
|
+
throw new MigrationError(
|
|
29846
|
+
`${label}: migration chain does not reach v${targetVersion} (stuck at v${version2})`
|
|
29847
|
+
);
|
|
29848
|
+
}
|
|
29849
|
+
}
|
|
29850
|
+
async function migrateRecord(record2, registry2, globalWriteBack = "off") {
|
|
29851
|
+
const entry = registry2.lookup(record2.aType, record2.axbType, record2.bType);
|
|
29852
|
+
if (!entry?.migrations?.length || !entry.schemaVersion) {
|
|
29853
|
+
return { record: record2, migrated: false, writeBack: "off" };
|
|
29854
|
+
}
|
|
29855
|
+
const currentVersion = record2.v ?? 0;
|
|
29856
|
+
if (currentVersion >= entry.schemaVersion) {
|
|
29857
|
+
return { record: record2, migrated: false, writeBack: "off" };
|
|
29858
|
+
}
|
|
29859
|
+
const migratedData = await applyMigrationChain(
|
|
29860
|
+
record2.data,
|
|
29861
|
+
currentVersion,
|
|
29862
|
+
entry.schemaVersion,
|
|
29863
|
+
entry.migrations
|
|
29864
|
+
);
|
|
29865
|
+
const writeBack = entry.migrationWriteBack ?? globalWriteBack ?? "off";
|
|
29866
|
+
return {
|
|
29867
|
+
record: { ...record2, data: migratedData, v: entry.schemaVersion },
|
|
29868
|
+
migrated: true,
|
|
29869
|
+
writeBack
|
|
29870
|
+
};
|
|
29871
|
+
}
|
|
29872
|
+
async function migrateRecords(records, registry2, globalWriteBack = "off") {
|
|
29873
|
+
return Promise.all(
|
|
29874
|
+
records.map((r) => migrateRecord(r, registry2, globalWriteBack))
|
|
29875
|
+
);
|
|
29876
|
+
}
|
|
29877
|
+
|
|
29677
29878
|
// src/transaction.ts
|
|
29678
29879
|
var GraphTransactionImpl = class {
|
|
29679
|
-
constructor(adapter, registry2, scanProtection = "error", scopePath = "") {
|
|
29880
|
+
constructor(adapter, registry2, scanProtection = "error", scopePath = "", globalWriteBack = "off", db2) {
|
|
29680
29881
|
this.adapter = adapter;
|
|
29681
29882
|
this.registry = registry2;
|
|
29682
29883
|
this.scanProtection = scanProtection;
|
|
29683
29884
|
this.scopePath = scopePath;
|
|
29885
|
+
this.globalWriteBack = globalWriteBack;
|
|
29886
|
+
this.db = db2;
|
|
29684
29887
|
}
|
|
29685
29888
|
async getNode(uid) {
|
|
29686
29889
|
const docId = computeNodeDocId(uid);
|
|
29687
|
-
|
|
29890
|
+
const record2 = await this.adapter.getDoc(docId);
|
|
29891
|
+
if (!record2 || !this.registry) return record2;
|
|
29892
|
+
const result = await migrateRecord(record2, this.registry, this.globalWriteBack);
|
|
29893
|
+
if (result.migrated && result.writeBack !== "off") {
|
|
29894
|
+
const update = {
|
|
29895
|
+
data: deserializeFirestoreTypes(result.record.data, this.db),
|
|
29896
|
+
updatedAt: FieldValue3.serverTimestamp()
|
|
29897
|
+
};
|
|
29898
|
+
if (result.record.v !== void 0) {
|
|
29899
|
+
update.v = result.record.v;
|
|
29900
|
+
}
|
|
29901
|
+
this.adapter.updateDoc(docId, update);
|
|
29902
|
+
}
|
|
29903
|
+
return result.record;
|
|
29688
29904
|
}
|
|
29689
29905
|
async getEdge(aUid, axbType, bUid) {
|
|
29690
29906
|
const docId = computeEdgeDocId(aUid, axbType, bUid);
|
|
29691
|
-
|
|
29907
|
+
const record2 = await this.adapter.getDoc(docId);
|
|
29908
|
+
if (!record2 || !this.registry) return record2;
|
|
29909
|
+
const result = await migrateRecord(record2, this.registry, this.globalWriteBack);
|
|
29910
|
+
if (result.migrated && result.writeBack !== "off") {
|
|
29911
|
+
const update = {
|
|
29912
|
+
data: deserializeFirestoreTypes(result.record.data, this.db),
|
|
29913
|
+
updatedAt: FieldValue3.serverTimestamp()
|
|
29914
|
+
};
|
|
29915
|
+
if (result.record.v !== void 0) {
|
|
29916
|
+
update.v = result.record.v;
|
|
29917
|
+
}
|
|
29918
|
+
this.adapter.updateDoc(docId, update);
|
|
29919
|
+
}
|
|
29920
|
+
return result.record;
|
|
29692
29921
|
}
|
|
29693
29922
|
async edgeExists(aUid, axbType, bUid) {
|
|
29694
|
-
const
|
|
29923
|
+
const docId = computeEdgeDocId(aUid, axbType, bUid);
|
|
29924
|
+
const record2 = await this.adapter.getDoc(docId);
|
|
29695
29925
|
return record2 !== null;
|
|
29696
29926
|
}
|
|
29697
29927
|
checkQuerySafety(filters, allowCollectionScan) {
|
|
@@ -29705,21 +29935,45 @@ var GraphTransactionImpl = class {
|
|
|
29705
29935
|
}
|
|
29706
29936
|
async findEdges(params) {
|
|
29707
29937
|
const plan = buildEdgeQueryPlan(params);
|
|
29938
|
+
let records;
|
|
29708
29939
|
if (plan.strategy === "get") {
|
|
29709
29940
|
const record2 = await this.adapter.getDoc(plan.docId);
|
|
29710
|
-
|
|
29941
|
+
records = record2 ? [record2] : [];
|
|
29942
|
+
} else {
|
|
29943
|
+
this.checkQuerySafety(plan.filters, params.allowCollectionScan);
|
|
29944
|
+
records = await this.adapter.query(plan.filters, plan.options);
|
|
29711
29945
|
}
|
|
29712
|
-
this.
|
|
29713
|
-
return this.adapter.query(plan.filters, plan.options);
|
|
29946
|
+
return this.applyMigrations(records);
|
|
29714
29947
|
}
|
|
29715
29948
|
async findNodes(params) {
|
|
29716
29949
|
const plan = buildNodeQueryPlan(params);
|
|
29950
|
+
let records;
|
|
29717
29951
|
if (plan.strategy === "get") {
|
|
29718
29952
|
const record2 = await this.adapter.getDoc(plan.docId);
|
|
29719
|
-
|
|
29953
|
+
records = record2 ? [record2] : [];
|
|
29954
|
+
} else {
|
|
29955
|
+
this.checkQuerySafety(plan.filters, params.allowCollectionScan);
|
|
29956
|
+
records = await this.adapter.query(plan.filters, plan.options);
|
|
29957
|
+
}
|
|
29958
|
+
return this.applyMigrations(records);
|
|
29959
|
+
}
|
|
29960
|
+
async applyMigrations(records) {
|
|
29961
|
+
if (!this.registry || records.length === 0) return records;
|
|
29962
|
+
const results = await migrateRecords(records, this.registry, this.globalWriteBack);
|
|
29963
|
+
for (const result of results) {
|
|
29964
|
+
if (result.migrated && result.writeBack !== "off") {
|
|
29965
|
+
const docId = result.record.axbType === NODE_RELATION ? computeNodeDocId(result.record.aUid) : computeEdgeDocId(result.record.aUid, result.record.axbType, result.record.bUid);
|
|
29966
|
+
const update = {
|
|
29967
|
+
data: deserializeFirestoreTypes(result.record.data, this.db),
|
|
29968
|
+
updatedAt: FieldValue3.serverTimestamp()
|
|
29969
|
+
};
|
|
29970
|
+
if (result.record.v !== void 0) {
|
|
29971
|
+
update.v = result.record.v;
|
|
29972
|
+
}
|
|
29973
|
+
this.adapter.updateDoc(docId, update);
|
|
29974
|
+
}
|
|
29720
29975
|
}
|
|
29721
|
-
|
|
29722
|
-
return this.adapter.query(plan.filters, plan.options);
|
|
29976
|
+
return results.map((r) => r.record);
|
|
29723
29977
|
}
|
|
29724
29978
|
async putNode(aType, uid, data) {
|
|
29725
29979
|
if (this.registry) {
|
|
@@ -29727,6 +29981,12 @@ var GraphTransactionImpl = class {
|
|
|
29727
29981
|
}
|
|
29728
29982
|
const docId = computeNodeDocId(uid);
|
|
29729
29983
|
const record2 = buildNodeRecord(aType, uid, data);
|
|
29984
|
+
if (this.registry) {
|
|
29985
|
+
const entry = this.registry.lookup(aType, NODE_RELATION, aType);
|
|
29986
|
+
if (entry?.schemaVersion && entry.schemaVersion > 0) {
|
|
29987
|
+
record2.v = entry.schemaVersion;
|
|
29988
|
+
}
|
|
29989
|
+
}
|
|
29730
29990
|
this.adapter.setDoc(docId, record2);
|
|
29731
29991
|
}
|
|
29732
29992
|
async putEdge(aType, aUid, axbType, bType, bUid, data) {
|
|
@@ -29735,13 +29995,19 @@ var GraphTransactionImpl = class {
|
|
|
29735
29995
|
}
|
|
29736
29996
|
const docId = computeEdgeDocId(aUid, axbType, bUid);
|
|
29737
29997
|
const record2 = buildEdgeRecord(aType, aUid, axbType, bType, bUid, data);
|
|
29998
|
+
if (this.registry) {
|
|
29999
|
+
const entry = this.registry.lookup(aType, axbType, bType);
|
|
30000
|
+
if (entry?.schemaVersion && entry.schemaVersion > 0) {
|
|
30001
|
+
record2.v = entry.schemaVersion;
|
|
30002
|
+
}
|
|
30003
|
+
}
|
|
29738
30004
|
this.adapter.setDoc(docId, record2);
|
|
29739
30005
|
}
|
|
29740
30006
|
async updateNode(uid, data) {
|
|
29741
30007
|
const docId = computeNodeDocId(uid);
|
|
29742
30008
|
this.adapter.updateDoc(docId, {
|
|
29743
30009
|
...data,
|
|
29744
|
-
updatedAt:
|
|
30010
|
+
updatedAt: FieldValue3.serverTimestamp()
|
|
29745
30011
|
});
|
|
29746
30012
|
}
|
|
29747
30013
|
async removeNode(uid) {
|
|
@@ -29755,7 +30021,7 @@ var GraphTransactionImpl = class {
|
|
|
29755
30021
|
};
|
|
29756
30022
|
|
|
29757
30023
|
// src/batch.ts
|
|
29758
|
-
import { FieldValue as
|
|
30024
|
+
import { FieldValue as FieldValue4 } from "@google-cloud/firestore";
|
|
29759
30025
|
var GraphBatchImpl = class {
|
|
29760
30026
|
constructor(adapter, registry2, scopePath = "") {
|
|
29761
30027
|
this.adapter = adapter;
|
|
@@ -29768,6 +30034,12 @@ var GraphBatchImpl = class {
|
|
|
29768
30034
|
}
|
|
29769
30035
|
const docId = computeNodeDocId(uid);
|
|
29770
30036
|
const record2 = buildNodeRecord(aType, uid, data);
|
|
30037
|
+
if (this.registry) {
|
|
30038
|
+
const entry = this.registry.lookup(aType, NODE_RELATION, aType);
|
|
30039
|
+
if (entry?.schemaVersion && entry.schemaVersion > 0) {
|
|
30040
|
+
record2.v = entry.schemaVersion;
|
|
30041
|
+
}
|
|
30042
|
+
}
|
|
29771
30043
|
this.adapter.setDoc(docId, record2);
|
|
29772
30044
|
}
|
|
29773
30045
|
async putEdge(aType, aUid, axbType, bType, bUid, data) {
|
|
@@ -29776,13 +30048,19 @@ var GraphBatchImpl = class {
|
|
|
29776
30048
|
}
|
|
29777
30049
|
const docId = computeEdgeDocId(aUid, axbType, bUid);
|
|
29778
30050
|
const record2 = buildEdgeRecord(aType, aUid, axbType, bType, bUid, data);
|
|
30051
|
+
if (this.registry) {
|
|
30052
|
+
const entry = this.registry.lookup(aType, axbType, bType);
|
|
30053
|
+
if (entry?.schemaVersion && entry.schemaVersion > 0) {
|
|
30054
|
+
record2.v = entry.schemaVersion;
|
|
30055
|
+
}
|
|
30056
|
+
}
|
|
29779
30057
|
this.adapter.setDoc(docId, record2);
|
|
29780
30058
|
}
|
|
29781
30059
|
async updateNode(uid, data) {
|
|
29782
30060
|
const docId = computeNodeDocId(uid);
|
|
29783
30061
|
this.adapter.updateDoc(docId, {
|
|
29784
30062
|
...data,
|
|
29785
|
-
updatedAt:
|
|
30063
|
+
updatedAt: FieldValue4.serverTimestamp()
|
|
29786
30064
|
});
|
|
29787
30065
|
}
|
|
29788
30066
|
async removeNode(uid) {
|
|
@@ -29941,7 +30219,7 @@ async function removeNodeCascade(db2, collectionPath, reader, uid, options) {
|
|
|
29941
30219
|
}
|
|
29942
30220
|
|
|
29943
30221
|
// src/dynamic-registry.ts
|
|
29944
|
-
import { createHash as
|
|
30222
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
29945
30223
|
|
|
29946
30224
|
// src/json-schema.ts
|
|
29947
30225
|
var import_ajv = __toESM(require_ajv(), 1);
|
|
@@ -30047,23 +30325,23 @@ function matchScopeAny(scopePath, patterns) {
|
|
|
30047
30325
|
if (!patterns || patterns.length === 0) return true;
|
|
30048
30326
|
return patterns.some((p) => matchScope(scopePath, p));
|
|
30049
30327
|
}
|
|
30050
|
-
function matchSegments(
|
|
30051
|
-
if (pi ===
|
|
30328
|
+
function matchSegments(path5, pi, pattern, qi) {
|
|
30329
|
+
if (pi === path5.length && qi === pattern.length) return true;
|
|
30052
30330
|
if (qi === pattern.length) return false;
|
|
30053
30331
|
const seg = pattern[qi];
|
|
30054
30332
|
if (seg === "**") {
|
|
30055
30333
|
if (qi === pattern.length - 1) return true;
|
|
30056
|
-
for (let skip = 0; skip <=
|
|
30057
|
-
if (matchSegments(
|
|
30334
|
+
for (let skip = 0; skip <= path5.length - pi; skip++) {
|
|
30335
|
+
if (matchSegments(path5, pi + skip, pattern, qi + 1)) return true;
|
|
30058
30336
|
}
|
|
30059
30337
|
return false;
|
|
30060
30338
|
}
|
|
30061
|
-
if (pi ===
|
|
30339
|
+
if (pi === path5.length) return false;
|
|
30062
30340
|
if (seg === "*") {
|
|
30063
|
-
return matchSegments(
|
|
30341
|
+
return matchSegments(path5, pi + 1, pattern, qi + 1);
|
|
30064
30342
|
}
|
|
30065
|
-
if (
|
|
30066
|
-
return matchSegments(
|
|
30343
|
+
if (path5[pi] === seg) {
|
|
30344
|
+
return matchSegments(path5, pi + 1, pattern, qi + 1);
|
|
30067
30345
|
}
|
|
30068
30346
|
return false;
|
|
30069
30347
|
}
|
|
@@ -30090,6 +30368,13 @@ function createRegistry(input) {
|
|
|
30090
30368
|
`Entry (${entry.aType}) -[${entry.axbType}]-> (${entry.bType}) has invalid targetGraph "${entry.targetGraph}" \u2014 must be a single segment (no "/")`
|
|
30091
30369
|
);
|
|
30092
30370
|
}
|
|
30371
|
+
if (entry.migrations?.length) {
|
|
30372
|
+
const label = `Entry (${entry.aType}) -[${entry.axbType}]-> (${entry.bType})`;
|
|
30373
|
+
validateMigrationChain(entry.migrations, label);
|
|
30374
|
+
entry.schemaVersion = Math.max(...entry.migrations.map((m) => m.toVersion));
|
|
30375
|
+
} else {
|
|
30376
|
+
entry.schemaVersion = void 0;
|
|
30377
|
+
}
|
|
30093
30378
|
const key = tripleKey(entry.aType, entry.axbType, entry.bType);
|
|
30094
30379
|
const validator = entry.jsonSchema ? compileSchema(entry.jsonSchema, `(${entry.aType}) -[${entry.axbType}]-> (${entry.bType})`) : void 0;
|
|
30095
30380
|
map2.set(key, { entry, validate: validator });
|
|
@@ -30191,7 +30476,9 @@ function discoveryToEntries(discovery) {
|
|
|
30191
30476
|
description: entity.description,
|
|
30192
30477
|
titleField: entity.titleField,
|
|
30193
30478
|
subtitleField: entity.subtitleField,
|
|
30194
|
-
allowedIn: entity.allowedIn
|
|
30479
|
+
allowedIn: entity.allowedIn,
|
|
30480
|
+
migrations: entity.migrations,
|
|
30481
|
+
migrationWriteBack: entity.migrationWriteBack
|
|
30195
30482
|
});
|
|
30196
30483
|
}
|
|
30197
30484
|
for (const [axbType, entity] of discovery.edges) {
|
|
@@ -30217,7 +30504,9 @@ function discoveryToEntries(discovery) {
|
|
|
30217
30504
|
titleField: entity.titleField,
|
|
30218
30505
|
subtitleField: entity.subtitleField,
|
|
30219
30506
|
allowedIn: entity.allowedIn,
|
|
30220
|
-
targetGraph: resolvedTargetGraph
|
|
30507
|
+
targetGraph: resolvedTargetGraph,
|
|
30508
|
+
migrations: entity.migrations,
|
|
30509
|
+
migrationWriteBack: entity.migrationWriteBack
|
|
30221
30510
|
});
|
|
30222
30511
|
}
|
|
30223
30512
|
}
|
|
@@ -30225,9 +30514,248 @@ function discoveryToEntries(discovery) {
|
|
|
30225
30514
|
return entries;
|
|
30226
30515
|
}
|
|
30227
30516
|
|
|
30517
|
+
// src/sandbox.ts
|
|
30518
|
+
import { Worker } from "node:worker_threads";
|
|
30519
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
30520
|
+
var _worker = null;
|
|
30521
|
+
var _requestId = 0;
|
|
30522
|
+
var _pending = /* @__PURE__ */ new Map();
|
|
30523
|
+
var WORKER_SOURCE = [
|
|
30524
|
+
`'use strict';`,
|
|
30525
|
+
`var _wt = require('node:worker_threads');`,
|
|
30526
|
+
`var _mod = require('node:module');`,
|
|
30527
|
+
`var _crypto = require('node:crypto');`,
|
|
30528
|
+
`var parentPort = _wt.parentPort;`,
|
|
30529
|
+
`var workerData = _wt.workerData;`,
|
|
30530
|
+
``,
|
|
30531
|
+
`// Load SES using the parent module's resolution context`,
|
|
30532
|
+
`var esmRequire = _mod.createRequire(workerData.parentUrl);`,
|
|
30533
|
+
`esmRequire('ses');`,
|
|
30534
|
+
``,
|
|
30535
|
+
`lockdown({`,
|
|
30536
|
+
` errorTaming: 'unsafe',`,
|
|
30537
|
+
` consoleTaming: 'unsafe',`,
|
|
30538
|
+
` evalTaming: 'safe-eval',`,
|
|
30539
|
+
` overrideTaming: 'moderate',`,
|
|
30540
|
+
` stackFiltering: 'verbose'`,
|
|
30541
|
+
`});`,
|
|
30542
|
+
``,
|
|
30543
|
+
`// Defense-in-depth: verify lockdown() actually hardened JSON.`,
|
|
30544
|
+
`if (!Object.isFrozen(JSON)) {`,
|
|
30545
|
+
` throw new Error('SES lockdown failed: JSON is not frozen');`,
|
|
30546
|
+
`}`,
|
|
30547
|
+
``,
|
|
30548
|
+
`var cache = new Map();`,
|
|
30549
|
+
``,
|
|
30550
|
+
`function hashSource(s) {`,
|
|
30551
|
+
` return _crypto.createHash('sha256').update(s).digest('hex');`,
|
|
30552
|
+
`}`,
|
|
30553
|
+
``,
|
|
30554
|
+
`function buildWrapper(source) {`,
|
|
30555
|
+
` return '(function() {' +`,
|
|
30556
|
+
` ' var fn = (' + source + ');\\n' +`,
|
|
30557
|
+
` ' if (typeof fn !== "function") return null;\\n' +`,
|
|
30558
|
+
` ' return function(jsonIn) {\\n' +`,
|
|
30559
|
+
` ' var data = JSON.parse(jsonIn);\\n' +`,
|
|
30560
|
+
` ' var result = fn(data);\\n' +`,
|
|
30561
|
+
` ' if (result !== null && typeof result === "object" && typeof result.then === "function") {\\n' +`,
|
|
30562
|
+
` ' return result.then(function(r) { return JSON.stringify(r); });\\n' +`,
|
|
30563
|
+
` ' }\\n' +`,
|
|
30564
|
+
` ' return JSON.stringify(result);\\n' +`,
|
|
30565
|
+
` ' };\\n' +`,
|
|
30566
|
+
` '})()';`,
|
|
30567
|
+
`}`,
|
|
30568
|
+
``,
|
|
30569
|
+
`function compileSource(source) {`,
|
|
30570
|
+
` var key = hashSource(source);`,
|
|
30571
|
+
` var cached = cache.get(key);`,
|
|
30572
|
+
` if (cached) return cached;`,
|
|
30573
|
+
``,
|
|
30574
|
+
` var compartmentFn;`,
|
|
30575
|
+
` try {`,
|
|
30576
|
+
` var c = new Compartment({ JSON: JSON });`,
|
|
30577
|
+
` compartmentFn = c.evaluate(buildWrapper(source));`,
|
|
30578
|
+
` } catch (err) {`,
|
|
30579
|
+
` throw new Error('Failed to compile migration source: ' + (err.message || String(err)));`,
|
|
30580
|
+
` }`,
|
|
30581
|
+
``,
|
|
30582
|
+
` if (typeof compartmentFn !== 'function') {`,
|
|
30583
|
+
` throw new Error('Migration source did not produce a function: ' + source.slice(0, 80));`,
|
|
30584
|
+
` }`,
|
|
30585
|
+
``,
|
|
30586
|
+
` cache.set(key, compartmentFn);`,
|
|
30587
|
+
` return compartmentFn;`,
|
|
30588
|
+
`}`,
|
|
30589
|
+
``,
|
|
30590
|
+
`parentPort.on('message', function(msg) {`,
|
|
30591
|
+
` var id = msg.id;`,
|
|
30592
|
+
` try {`,
|
|
30593
|
+
` if (msg.type === 'compile') {`,
|
|
30594
|
+
` compileSource(msg.source);`,
|
|
30595
|
+
` parentPort.postMessage({ id: id, type: 'compiled' });`,
|
|
30596
|
+
` return;`,
|
|
30597
|
+
` }`,
|
|
30598
|
+
` if (msg.type === 'execute') {`,
|
|
30599
|
+
` var fn = compileSource(msg.source);`,
|
|
30600
|
+
` var raw;`,
|
|
30601
|
+
` try {`,
|
|
30602
|
+
` raw = fn(msg.jsonData);`,
|
|
30603
|
+
` } catch (err) {`,
|
|
30604
|
+
` parentPort.postMessage({ id: id, type: 'error', message: 'Migration function threw: ' + (err.message || String(err)) });`,
|
|
30605
|
+
` return;`,
|
|
30606
|
+
` }`,
|
|
30607
|
+
` if (raw !== null && typeof raw === 'object' && typeof raw.then === 'function') {`,
|
|
30608
|
+
` raw.then(`,
|
|
30609
|
+
` function(jsonResult) {`,
|
|
30610
|
+
` if (jsonResult === undefined || jsonResult === null) {`,
|
|
30611
|
+
` parentPort.postMessage({ id: id, type: 'error', message: 'Migration returned a non-JSON-serializable value' });`,
|
|
30612
|
+
` } else {`,
|
|
30613
|
+
` parentPort.postMessage({ id: id, type: 'result', jsonResult: jsonResult });`,
|
|
30614
|
+
` }`,
|
|
30615
|
+
` },`,
|
|
30616
|
+
` function(err) {`,
|
|
30617
|
+
` parentPort.postMessage({ id: id, type: 'error', message: 'Async migration function threw: ' + (err.message || String(err)) });`,
|
|
30618
|
+
` }`,
|
|
30619
|
+
` );`,
|
|
30620
|
+
` return;`,
|
|
30621
|
+
` }`,
|
|
30622
|
+
` if (raw === undefined || raw === null) {`,
|
|
30623
|
+
` parentPort.postMessage({ id: id, type: 'error', message: 'Migration returned a non-JSON-serializable value' });`,
|
|
30624
|
+
` } else {`,
|
|
30625
|
+
` parentPort.postMessage({ id: id, type: 'result', jsonResult: raw });`,
|
|
30626
|
+
` }`,
|
|
30627
|
+
` }`,
|
|
30628
|
+
` } catch (err) {`,
|
|
30629
|
+
` parentPort.postMessage({ id: id, type: 'error', message: err.message || String(err) });`,
|
|
30630
|
+
` }`,
|
|
30631
|
+
`});`
|
|
30632
|
+
].join("\n");
|
|
30633
|
+
function ensureWorker() {
|
|
30634
|
+
if (_worker) return _worker;
|
|
30635
|
+
_worker = new Worker(WORKER_SOURCE, {
|
|
30636
|
+
eval: true,
|
|
30637
|
+
workerData: { parentUrl: import.meta.url }
|
|
30638
|
+
});
|
|
30639
|
+
_worker.unref();
|
|
30640
|
+
_worker.on("message", (msg) => {
|
|
30641
|
+
if (msg.id === void 0) return;
|
|
30642
|
+
const pending = _pending.get(msg.id);
|
|
30643
|
+
if (!pending) return;
|
|
30644
|
+
_pending.delete(msg.id);
|
|
30645
|
+
if (msg.type === "error") {
|
|
30646
|
+
pending.reject(new MigrationError(msg.message ?? "Unknown sandbox error"));
|
|
30647
|
+
} else {
|
|
30648
|
+
pending.resolve(msg);
|
|
30649
|
+
}
|
|
30650
|
+
});
|
|
30651
|
+
_worker.on("error", (err) => {
|
|
30652
|
+
for (const [, p] of _pending) {
|
|
30653
|
+
p.reject(new MigrationError(`Sandbox worker error: ${err.message}`));
|
|
30654
|
+
}
|
|
30655
|
+
_pending.clear();
|
|
30656
|
+
_worker = null;
|
|
30657
|
+
});
|
|
30658
|
+
_worker.on("exit", (code) => {
|
|
30659
|
+
if (_pending.size > 0) {
|
|
30660
|
+
for (const [, p] of _pending) {
|
|
30661
|
+
p.reject(new MigrationError(`Sandbox worker exited with code ${code}`));
|
|
30662
|
+
}
|
|
30663
|
+
_pending.clear();
|
|
30664
|
+
}
|
|
30665
|
+
_worker = null;
|
|
30666
|
+
});
|
|
30667
|
+
return _worker;
|
|
30668
|
+
}
|
|
30669
|
+
function sendToWorker(msg) {
|
|
30670
|
+
const worker = ensureWorker();
|
|
30671
|
+
if (_requestId >= Number.MAX_SAFE_INTEGER) _requestId = 0;
|
|
30672
|
+
const id = ++_requestId;
|
|
30673
|
+
return new Promise((resolve2, reject) => {
|
|
30674
|
+
_pending.set(id, { resolve: resolve2, reject });
|
|
30675
|
+
worker.postMessage({ ...msg, id });
|
|
30676
|
+
});
|
|
30677
|
+
}
|
|
30678
|
+
var compiledCache = /* @__PURE__ */ new WeakMap();
|
|
30679
|
+
function getExecutorCache(executor) {
|
|
30680
|
+
let cache = compiledCache.get(executor);
|
|
30681
|
+
if (!cache) {
|
|
30682
|
+
cache = /* @__PURE__ */ new Map();
|
|
30683
|
+
compiledCache.set(executor, cache);
|
|
30684
|
+
}
|
|
30685
|
+
return cache;
|
|
30686
|
+
}
|
|
30687
|
+
function hashSource(source) {
|
|
30688
|
+
return createHash2("sha256").update(source).digest("hex");
|
|
30689
|
+
}
|
|
30690
|
+
function defaultExecutor(source) {
|
|
30691
|
+
ensureWorker();
|
|
30692
|
+
return (data) => {
|
|
30693
|
+
const jsonData = JSON.stringify(serializeFirestoreTypes(data));
|
|
30694
|
+
return sendToWorker({ type: "execute", source, jsonData }).then(
|
|
30695
|
+
(response) => {
|
|
30696
|
+
if (response.jsonResult === void 0 || response.jsonResult === null) {
|
|
30697
|
+
throw new MigrationError("Migration returned a non-JSON-serializable value");
|
|
30698
|
+
}
|
|
30699
|
+
try {
|
|
30700
|
+
return deserializeFirestoreTypes(JSON.parse(response.jsonResult));
|
|
30701
|
+
} catch {
|
|
30702
|
+
throw new MigrationError("Migration returned a non-JSON-serializable value");
|
|
30703
|
+
}
|
|
30704
|
+
}
|
|
30705
|
+
);
|
|
30706
|
+
};
|
|
30707
|
+
}
|
|
30708
|
+
async function precompileSource(source, executor) {
|
|
30709
|
+
if (executor && executor !== defaultExecutor) {
|
|
30710
|
+
try {
|
|
30711
|
+
executor(source);
|
|
30712
|
+
} catch (err) {
|
|
30713
|
+
if (err instanceof MigrationError) throw err;
|
|
30714
|
+
throw new MigrationError(
|
|
30715
|
+
`Failed to compile migration source: ${err.message}`
|
|
30716
|
+
);
|
|
30717
|
+
}
|
|
30718
|
+
return;
|
|
30719
|
+
}
|
|
30720
|
+
await sendToWorker({ type: "compile", source });
|
|
30721
|
+
}
|
|
30722
|
+
function compileMigrationFn(source, executor = defaultExecutor) {
|
|
30723
|
+
const cache = getExecutorCache(executor);
|
|
30724
|
+
const key = hashSource(source);
|
|
30725
|
+
const cached2 = cache.get(key);
|
|
30726
|
+
if (cached2) return cached2;
|
|
30727
|
+
try {
|
|
30728
|
+
const fn = executor(source);
|
|
30729
|
+
cache.set(key, fn);
|
|
30730
|
+
return fn;
|
|
30731
|
+
} catch (err) {
|
|
30732
|
+
if (err instanceof MigrationError) throw err;
|
|
30733
|
+
throw new MigrationError(
|
|
30734
|
+
`Failed to compile migration source: ${err.message}`
|
|
30735
|
+
);
|
|
30736
|
+
}
|
|
30737
|
+
}
|
|
30738
|
+
function compileMigrations(stored, executor) {
|
|
30739
|
+
return stored.map((step) => ({
|
|
30740
|
+
fromVersion: step.fromVersion,
|
|
30741
|
+
toVersion: step.toVersion,
|
|
30742
|
+
up: compileMigrationFn(step.up, executor)
|
|
30743
|
+
}));
|
|
30744
|
+
}
|
|
30745
|
+
|
|
30228
30746
|
// src/dynamic-registry.ts
|
|
30229
30747
|
var META_NODE_TYPE = "nodeType";
|
|
30230
30748
|
var META_EDGE_TYPE = "edgeType";
|
|
30749
|
+
var STORED_MIGRATION_STEP_SCHEMA = {
|
|
30750
|
+
type: "object",
|
|
30751
|
+
required: ["fromVersion", "toVersion", "up"],
|
|
30752
|
+
properties: {
|
|
30753
|
+
fromVersion: { type: "integer", minimum: 0 },
|
|
30754
|
+
toVersion: { type: "integer", minimum: 1 },
|
|
30755
|
+
up: { type: "string", minLength: 1 }
|
|
30756
|
+
},
|
|
30757
|
+
additionalProperties: false
|
|
30758
|
+
};
|
|
30231
30759
|
var NODE_TYPE_SCHEMA = {
|
|
30232
30760
|
type: "object",
|
|
30233
30761
|
required: ["name", "jsonSchema"],
|
|
@@ -30239,7 +30767,10 @@ var NODE_TYPE_SCHEMA = {
|
|
|
30239
30767
|
subtitleField: { type: "string" },
|
|
30240
30768
|
viewTemplate: { type: "string" },
|
|
30241
30769
|
viewCss: { type: "string" },
|
|
30242
|
-
allowedIn: { type: "array", items: { type: "string", minLength: 1 } }
|
|
30770
|
+
allowedIn: { type: "array", items: { type: "string", minLength: 1 } },
|
|
30771
|
+
schemaVersion: { type: "integer", minimum: 0 },
|
|
30772
|
+
migrations: { type: "array", items: STORED_MIGRATION_STEP_SCHEMA },
|
|
30773
|
+
migrationWriteBack: { type: "string", enum: ["off", "eager", "background"] }
|
|
30243
30774
|
},
|
|
30244
30775
|
additionalProperties: false
|
|
30245
30776
|
};
|
|
@@ -30268,7 +30799,10 @@ var EDGE_TYPE_SCHEMA = {
|
|
|
30268
30799
|
viewTemplate: { type: "string" },
|
|
30269
30800
|
viewCss: { type: "string" },
|
|
30270
30801
|
allowedIn: { type: "array", items: { type: "string", minLength: 1 } },
|
|
30271
|
-
targetGraph: { type: "string", minLength: 1, pattern: "^[^/]+$" }
|
|
30802
|
+
targetGraph: { type: "string", minLength: 1, pattern: "^[^/]+$" },
|
|
30803
|
+
schemaVersion: { type: "integer", minimum: 0 },
|
|
30804
|
+
migrations: { type: "array", items: STORED_MIGRATION_STEP_SCHEMA },
|
|
30805
|
+
migrationWriteBack: { type: "string", enum: ["off", "eager", "background"] }
|
|
30272
30806
|
},
|
|
30273
30807
|
additionalProperties: false
|
|
30274
30808
|
};
|
|
@@ -30292,15 +30826,33 @@ function createBootstrapRegistry() {
|
|
|
30292
30826
|
return createRegistry([...BOOTSTRAP_ENTRIES]);
|
|
30293
30827
|
}
|
|
30294
30828
|
function generateDeterministicUid(metaType, name) {
|
|
30295
|
-
const hash2 =
|
|
30829
|
+
const hash2 = createHash3("sha256").update(`${metaType}:${name}`).digest("base64url");
|
|
30296
30830
|
return hash2.slice(0, 21);
|
|
30297
30831
|
}
|
|
30298
|
-
async function createRegistryFromGraph(reader) {
|
|
30832
|
+
async function createRegistryFromGraph(reader, executor) {
|
|
30299
30833
|
const [nodeTypes, edgeTypes] = await Promise.all([
|
|
30300
30834
|
reader.findNodes({ aType: META_NODE_TYPE }),
|
|
30301
30835
|
reader.findNodes({ aType: META_EDGE_TYPE })
|
|
30302
30836
|
]);
|
|
30303
30837
|
const entries = [...BOOTSTRAP_ENTRIES];
|
|
30838
|
+
const prevalidations = [];
|
|
30839
|
+
for (const record2 of nodeTypes) {
|
|
30840
|
+
const data = record2.data;
|
|
30841
|
+
if (data.migrations) {
|
|
30842
|
+
for (const m of data.migrations) {
|
|
30843
|
+
prevalidations.push(precompileSource(m.up, executor));
|
|
30844
|
+
}
|
|
30845
|
+
}
|
|
30846
|
+
}
|
|
30847
|
+
for (const record2 of edgeTypes) {
|
|
30848
|
+
const data = record2.data;
|
|
30849
|
+
if (data.migrations) {
|
|
30850
|
+
for (const m of data.migrations) {
|
|
30851
|
+
prevalidations.push(precompileSource(m.up, executor));
|
|
30852
|
+
}
|
|
30853
|
+
}
|
|
30854
|
+
}
|
|
30855
|
+
await Promise.all(prevalidations);
|
|
30304
30856
|
for (const record2 of nodeTypes) {
|
|
30305
30857
|
const data = record2.data;
|
|
30306
30858
|
entries.push({
|
|
@@ -30311,13 +30863,16 @@ async function createRegistryFromGraph(reader) {
|
|
|
30311
30863
|
description: data.description,
|
|
30312
30864
|
titleField: data.titleField,
|
|
30313
30865
|
subtitleField: data.subtitleField,
|
|
30314
|
-
allowedIn: data.allowedIn
|
|
30866
|
+
allowedIn: data.allowedIn,
|
|
30867
|
+
migrations: data.migrations ? compileMigrations(data.migrations, executor) : void 0,
|
|
30868
|
+
migrationWriteBack: data.migrationWriteBack
|
|
30315
30869
|
});
|
|
30316
30870
|
}
|
|
30317
30871
|
for (const record2 of edgeTypes) {
|
|
30318
30872
|
const data = record2.data;
|
|
30319
30873
|
const fromTypes = Array.isArray(data.from) ? data.from : [data.from];
|
|
30320
30874
|
const toTypes = Array.isArray(data.to) ? data.to : [data.to];
|
|
30875
|
+
const compiledMigrations = data.migrations ? compileMigrations(data.migrations, executor) : void 0;
|
|
30321
30876
|
for (const aType of fromTypes) {
|
|
30322
30877
|
for (const bType of toTypes) {
|
|
30323
30878
|
entries.push({
|
|
@@ -30330,7 +30885,9 @@ async function createRegistryFromGraph(reader) {
|
|
|
30330
30885
|
titleField: data.titleField,
|
|
30331
30886
|
subtitleField: data.subtitleField,
|
|
30332
30887
|
allowedIn: data.allowedIn,
|
|
30333
|
-
targetGraph: data.targetGraph
|
|
30888
|
+
targetGraph: data.targetGraph,
|
|
30889
|
+
migrations: compiledMigrations,
|
|
30890
|
+
migrationWriteBack: data.migrationWriteBack
|
|
30334
30891
|
});
|
|
30335
30892
|
}
|
|
30336
30893
|
}
|
|
@@ -30346,6 +30903,8 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
30346
30903
|
this.db = db2;
|
|
30347
30904
|
this.scopePath = scopePath;
|
|
30348
30905
|
this.adapter = createFirestoreAdapter(db2, collectionPath);
|
|
30906
|
+
this.globalWriteBack = options?.migrationWriteBack ?? "off";
|
|
30907
|
+
this.migrationSandbox = options?.migrationSandbox;
|
|
30349
30908
|
if (options?.registryMode) {
|
|
30350
30909
|
this.dynamicConfig = options.registryMode;
|
|
30351
30910
|
this.bootstrapRegistry = createBootstrapRegistry();
|
|
@@ -30397,6 +30956,9 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
30397
30956
|
metaPipelineAdapter;
|
|
30398
30957
|
// Subgraph scope tracking
|
|
30399
30958
|
scopePath;
|
|
30959
|
+
// Migration settings
|
|
30960
|
+
globalWriteBack;
|
|
30961
|
+
migrationSandbox;
|
|
30400
30962
|
// ---------------------------------------------------------------------------
|
|
30401
30963
|
// Registry routing
|
|
30402
30964
|
// ---------------------------------------------------------------------------
|
|
@@ -30466,37 +31028,114 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
30466
31028
|
console.warn(`[firegraph] Query safety warning: ${result.reason}`);
|
|
30467
31029
|
}
|
|
30468
31030
|
// ---------------------------------------------------------------------------
|
|
31031
|
+
// Migration helpers
|
|
31032
|
+
// ---------------------------------------------------------------------------
|
|
31033
|
+
/**
|
|
31034
|
+
* Apply migration to a single record. Returns the (possibly migrated)
|
|
31035
|
+
* record and triggers write-back if applicable.
|
|
31036
|
+
*/
|
|
31037
|
+
async applyMigration(record2, docId) {
|
|
31038
|
+
const registry2 = this.getCombinedRegistry();
|
|
31039
|
+
if (!registry2) return record2;
|
|
31040
|
+
const result = await migrateRecord(record2, registry2, this.globalWriteBack);
|
|
31041
|
+
if (result.migrated) {
|
|
31042
|
+
this.handleWriteBack(result, docId);
|
|
31043
|
+
}
|
|
31044
|
+
return result.record;
|
|
31045
|
+
}
|
|
31046
|
+
/**
|
|
31047
|
+
* Apply migrations to an array of records. Returns all records
|
|
31048
|
+
* (migrated where applicable) and triggers write-backs.
|
|
31049
|
+
*/
|
|
31050
|
+
async applyMigrations(records) {
|
|
31051
|
+
const registry2 = this.getCombinedRegistry();
|
|
31052
|
+
if (!registry2 || records.length === 0) return records;
|
|
31053
|
+
const results = await migrateRecords(records, registry2, this.globalWriteBack);
|
|
31054
|
+
for (const result of results) {
|
|
31055
|
+
if (result.migrated) {
|
|
31056
|
+
const docId = result.record.axbType === NODE_RELATION ? computeNodeDocId(result.record.aUid) : computeEdgeDocId(result.record.aUid, result.record.axbType, result.record.bUid);
|
|
31057
|
+
this.handleWriteBack(result, docId);
|
|
31058
|
+
}
|
|
31059
|
+
}
|
|
31060
|
+
return results.map((r) => r.record);
|
|
31061
|
+
}
|
|
31062
|
+
/**
|
|
31063
|
+
* Handle write-back for a migrated record based on the resolved mode.
|
|
31064
|
+
*
|
|
31065
|
+
* Both `'eager'` and `'background'` are fire-and-forget (not awaited by
|
|
31066
|
+
* the caller). The difference is logging level on failure:
|
|
31067
|
+
* - `eager`: logs an error via `console.error`
|
|
31068
|
+
* - `background`: logs a warning via `console.warn`
|
|
31069
|
+
*
|
|
31070
|
+
* For truly synchronous write-back guarantees, use transactions — the
|
|
31071
|
+
* `GraphTransactionImpl` performs write-back inline within the transaction.
|
|
31072
|
+
*/
|
|
31073
|
+
handleWriteBack(result, docId) {
|
|
31074
|
+
if (result.writeBack === "off") return;
|
|
31075
|
+
const doWriteBack = async () => {
|
|
31076
|
+
try {
|
|
31077
|
+
const update = {
|
|
31078
|
+
data: deserializeFirestoreTypes(result.record.data, this.db),
|
|
31079
|
+
updatedAt: FieldValue5.serverTimestamp()
|
|
31080
|
+
};
|
|
31081
|
+
if (result.record.v !== void 0) {
|
|
31082
|
+
update.v = result.record.v;
|
|
31083
|
+
}
|
|
31084
|
+
await this.adapter.updateDoc(docId, update);
|
|
31085
|
+
} catch (err) {
|
|
31086
|
+
const msg = `[firegraph] Migration write-back failed for ${docId}: ${err.message}`;
|
|
31087
|
+
if (result.writeBack === "eager") {
|
|
31088
|
+
console.error(msg);
|
|
31089
|
+
} else {
|
|
31090
|
+
console.warn(msg);
|
|
31091
|
+
}
|
|
31092
|
+
}
|
|
31093
|
+
};
|
|
31094
|
+
void doWriteBack();
|
|
31095
|
+
}
|
|
31096
|
+
// ---------------------------------------------------------------------------
|
|
30469
31097
|
// GraphReader
|
|
30470
31098
|
// ---------------------------------------------------------------------------
|
|
30471
31099
|
async getNode(uid) {
|
|
30472
31100
|
const docId = computeNodeDocId(uid);
|
|
30473
|
-
|
|
31101
|
+
const record2 = await this.adapter.getDoc(docId);
|
|
31102
|
+
if (!record2) return null;
|
|
31103
|
+
return this.applyMigration(record2, docId);
|
|
30474
31104
|
}
|
|
30475
31105
|
async getEdge(aUid, axbType, bUid) {
|
|
30476
31106
|
const docId = computeEdgeDocId(aUid, axbType, bUid);
|
|
30477
|
-
|
|
31107
|
+
const record2 = await this.adapter.getDoc(docId);
|
|
31108
|
+
if (!record2) return null;
|
|
31109
|
+
return this.applyMigration(record2, docId);
|
|
30478
31110
|
}
|
|
30479
31111
|
async edgeExists(aUid, axbType, bUid) {
|
|
30480
|
-
const
|
|
31112
|
+
const docId = computeEdgeDocId(aUid, axbType, bUid);
|
|
31113
|
+
const record2 = await this.adapter.getDoc(docId);
|
|
30481
31114
|
return record2 !== null;
|
|
30482
31115
|
}
|
|
30483
31116
|
async findEdges(params) {
|
|
30484
31117
|
const plan = buildEdgeQueryPlan(params);
|
|
31118
|
+
let records;
|
|
30485
31119
|
if (plan.strategy === "get") {
|
|
30486
31120
|
const record2 = await this.adapter.getDoc(plan.docId);
|
|
30487
|
-
|
|
31121
|
+
records = record2 ? [record2] : [];
|
|
31122
|
+
} else {
|
|
31123
|
+
this.checkQuerySafety(plan.filters, params.allowCollectionScan);
|
|
31124
|
+
records = await this.executeQuery(plan.filters, plan.options);
|
|
30488
31125
|
}
|
|
30489
|
-
this.
|
|
30490
|
-
return this.executeQuery(plan.filters, plan.options);
|
|
31126
|
+
return this.applyMigrations(records);
|
|
30491
31127
|
}
|
|
30492
31128
|
async findNodes(params) {
|
|
30493
31129
|
const plan = buildNodeQueryPlan(params);
|
|
31130
|
+
let records;
|
|
30494
31131
|
if (plan.strategy === "get") {
|
|
30495
31132
|
const record2 = await this.adapter.getDoc(plan.docId);
|
|
30496
|
-
|
|
31133
|
+
records = record2 ? [record2] : [];
|
|
31134
|
+
} else {
|
|
31135
|
+
this.checkQuerySafety(plan.filters, params.allowCollectionScan);
|
|
31136
|
+
records = await this.executeQuery(plan.filters, plan.options);
|
|
30497
31137
|
}
|
|
30498
|
-
this.
|
|
30499
|
-
return this.executeQuery(plan.filters, plan.options);
|
|
31138
|
+
return this.applyMigrations(records);
|
|
30500
31139
|
}
|
|
30501
31140
|
// ---------------------------------------------------------------------------
|
|
30502
31141
|
// GraphWriter
|
|
@@ -30509,6 +31148,12 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
30509
31148
|
const adapter = this.getAdapterForType(aType);
|
|
30510
31149
|
const docId = computeNodeDocId(uid);
|
|
30511
31150
|
const record2 = buildNodeRecord(aType, uid, data);
|
|
31151
|
+
if (registry2) {
|
|
31152
|
+
const entry = registry2.lookup(aType, NODE_RELATION, aType);
|
|
31153
|
+
if (entry?.schemaVersion && entry.schemaVersion > 0) {
|
|
31154
|
+
record2.v = entry.schemaVersion;
|
|
31155
|
+
}
|
|
31156
|
+
}
|
|
30512
31157
|
await adapter.setDoc(docId, record2);
|
|
30513
31158
|
}
|
|
30514
31159
|
async putEdge(aType, aUid, axbType, bType, bUid, data) {
|
|
@@ -30519,13 +31164,19 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
30519
31164
|
const adapter = this.getAdapterForType(aType);
|
|
30520
31165
|
const docId = computeEdgeDocId(aUid, axbType, bUid);
|
|
30521
31166
|
const record2 = buildEdgeRecord(aType, aUid, axbType, bType, bUid, data);
|
|
31167
|
+
if (registry2) {
|
|
31168
|
+
const entry = registry2.lookup(aType, axbType, bType);
|
|
31169
|
+
if (entry?.schemaVersion && entry.schemaVersion > 0) {
|
|
31170
|
+
record2.v = entry.schemaVersion;
|
|
31171
|
+
}
|
|
31172
|
+
}
|
|
30522
31173
|
await adapter.setDoc(docId, record2);
|
|
30523
31174
|
}
|
|
30524
31175
|
async updateNode(uid, data) {
|
|
30525
31176
|
const docId = computeNodeDocId(uid);
|
|
30526
31177
|
await this.adapter.updateDoc(docId, {
|
|
30527
31178
|
...data,
|
|
30528
|
-
updatedAt:
|
|
31179
|
+
updatedAt: FieldValue5.serverTimestamp()
|
|
30529
31180
|
});
|
|
30530
31181
|
}
|
|
30531
31182
|
async removeNode(uid) {
|
|
@@ -30546,7 +31197,7 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
30546
31197
|
this.adapter.collectionPath,
|
|
30547
31198
|
firestoreTx
|
|
30548
31199
|
);
|
|
30549
|
-
const graphTx = new GraphTransactionImpl(adapter, this.getCombinedRegistry(), this.scanProtection, this.scopePath);
|
|
31200
|
+
const graphTx = new GraphTransactionImpl(adapter, this.getCombinedRegistry(), this.scanProtection, this.scopePath, this.globalWriteBack, this.db);
|
|
30550
31201
|
return fn(graphTx);
|
|
30551
31202
|
});
|
|
30552
31203
|
}
|
|
@@ -30578,7 +31229,9 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
30578
31229
|
{
|
|
30579
31230
|
registry: this.getCombinedRegistry(),
|
|
30580
31231
|
queryMode: this.queryMode === "pipeline" ? "pipeline" : "standard",
|
|
30581
|
-
scanProtection: this.scanProtection
|
|
31232
|
+
scanProtection: this.scanProtection,
|
|
31233
|
+
migrationWriteBack: this.globalWriteBack,
|
|
31234
|
+
migrationSandbox: this.migrationSandbox
|
|
30582
31235
|
},
|
|
30583
31236
|
newScopePath
|
|
30584
31237
|
);
|
|
@@ -30608,7 +31261,8 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
30608
31261
|
q = q.limit(plan.options.limit);
|
|
30609
31262
|
}
|
|
30610
31263
|
const snap = await q.get();
|
|
30611
|
-
|
|
31264
|
+
const records = snap.docs.map((doc) => doc.data());
|
|
31265
|
+
return this.applyMigrations(records);
|
|
30612
31266
|
}
|
|
30613
31267
|
// ---------------------------------------------------------------------------
|
|
30614
31268
|
// Bulk operations
|
|
@@ -30646,6 +31300,10 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
30646
31300
|
if (options?.viewTemplate !== void 0) data.viewTemplate = options.viewTemplate;
|
|
30647
31301
|
if (options?.viewCss !== void 0) data.viewCss = options.viewCss;
|
|
30648
31302
|
if (options?.allowedIn !== void 0) data.allowedIn = options.allowedIn;
|
|
31303
|
+
if (options?.migrationWriteBack !== void 0) data.migrationWriteBack = options.migrationWriteBack;
|
|
31304
|
+
if (options?.migrations !== void 0) {
|
|
31305
|
+
data.migrations = await this.serializeMigrations(options.migrations);
|
|
31306
|
+
}
|
|
30649
31307
|
await this.putNode(META_NODE_TYPE, uid, data);
|
|
30650
31308
|
}
|
|
30651
31309
|
async defineEdgeType(name, topology, jsonSchema, description, options) {
|
|
@@ -30687,6 +31345,10 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
30687
31345
|
if (options?.viewTemplate !== void 0) data.viewTemplate = options.viewTemplate;
|
|
30688
31346
|
if (options?.viewCss !== void 0) data.viewCss = options.viewCss;
|
|
30689
31347
|
if (options?.allowedIn !== void 0) data.allowedIn = options.allowedIn;
|
|
31348
|
+
if (options?.migrationWriteBack !== void 0) data.migrationWriteBack = options.migrationWriteBack;
|
|
31349
|
+
if (options?.migrations !== void 0) {
|
|
31350
|
+
data.migrations = await this.serializeMigrations(options.migrations);
|
|
31351
|
+
}
|
|
30690
31352
|
await this.putNode(META_EDGE_TYPE, uid, data);
|
|
30691
31353
|
}
|
|
30692
31354
|
async reloadRegistry() {
|
|
@@ -30696,13 +31358,28 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
30696
31358
|
);
|
|
30697
31359
|
}
|
|
30698
31360
|
const reader = this.createMetaReader();
|
|
30699
|
-
const dynamicOnly = await createRegistryFromGraph(reader);
|
|
31361
|
+
const dynamicOnly = await createRegistryFromGraph(reader, this.migrationSandbox);
|
|
30700
31362
|
if (this.staticRegistry) {
|
|
30701
31363
|
this.dynamicRegistry = createMergedRegistry(this.staticRegistry, dynamicOnly);
|
|
30702
31364
|
} else {
|
|
30703
31365
|
this.dynamicRegistry = dynamicOnly;
|
|
30704
31366
|
}
|
|
30705
31367
|
}
|
|
31368
|
+
/**
|
|
31369
|
+
* Serialize migration steps for storage in Firestore.
|
|
31370
|
+
* Function objects are converted via `.toString()`; strings are stored as-is.
|
|
31371
|
+
* Each migration is validated at define-time by pre-compiling in the sandbox.
|
|
31372
|
+
*/
|
|
31373
|
+
async serializeMigrations(migrations) {
|
|
31374
|
+
const result = migrations.map((m) => {
|
|
31375
|
+
const source = typeof m.up === "function" ? m.up.toString() : m.up;
|
|
31376
|
+
return { fromVersion: m.fromVersion, toVersion: m.toVersion, up: source };
|
|
31377
|
+
});
|
|
31378
|
+
await Promise.all(
|
|
31379
|
+
result.map((m) => precompileSource(m.up, this.migrationSandbox))
|
|
31380
|
+
);
|
|
31381
|
+
return result;
|
|
31382
|
+
}
|
|
30706
31383
|
/**
|
|
30707
31384
|
* Create a GraphReader for the meta-collection.
|
|
30708
31385
|
* If meta-collection is the same as main collection, returns `this`.
|
|
@@ -30860,11 +31537,39 @@ function findViewsFile(dir) {
|
|
|
30860
31537
|
}
|
|
30861
31538
|
return void 0;
|
|
30862
31539
|
}
|
|
31540
|
+
var MIGRATION_EXTENSIONS = [".ts", ".js", ".mts", ".mjs"];
|
|
31541
|
+
function findMigrationsFile(dir) {
|
|
31542
|
+
for (const ext of MIGRATION_EXTENSIONS) {
|
|
31543
|
+
const candidate = join(dir, `migrations${ext}`);
|
|
31544
|
+
if (existsSync(candidate)) return candidate;
|
|
31545
|
+
}
|
|
31546
|
+
return void 0;
|
|
31547
|
+
}
|
|
31548
|
+
function loadMigrations(filePath, entityLabel) {
|
|
31549
|
+
try {
|
|
31550
|
+
const jiti2 = getJiti();
|
|
31551
|
+
const mod = jiti2(filePath);
|
|
31552
|
+
const migrations = mod && typeof mod === "object" && "default" in mod ? mod.default : mod;
|
|
31553
|
+
if (!Array.isArray(migrations)) {
|
|
31554
|
+
throw new DiscoveryError(
|
|
31555
|
+
`Migrations file ${filePath} for ${entityLabel} must default-export an array of MigrationStep.`
|
|
31556
|
+
);
|
|
31557
|
+
}
|
|
31558
|
+
return migrations;
|
|
31559
|
+
} catch (err) {
|
|
31560
|
+
if (err instanceof DiscoveryError) throw err;
|
|
31561
|
+
throw new DiscoveryError(
|
|
31562
|
+
`Failed to load migrations ${filePath} for ${entityLabel}: ${err.message}`
|
|
31563
|
+
);
|
|
31564
|
+
}
|
|
31565
|
+
}
|
|
30863
31566
|
function loadNodeEntity(dir, name) {
|
|
30864
31567
|
const schema = loadSchema(dir, `node type "${name}"`);
|
|
30865
31568
|
const meta3 = readJsonIfExists(join(dir, "meta.json"));
|
|
30866
31569
|
const sampleData = readJsonIfExists(join(dir, "sample.json"));
|
|
30867
31570
|
const viewsPath = findViewsFile(dir);
|
|
31571
|
+
const migrationsPath = findMigrationsFile(dir);
|
|
31572
|
+
const migrations = migrationsPath ? loadMigrations(migrationsPath, `node type "${name}"`) : void 0;
|
|
30868
31573
|
return {
|
|
30869
31574
|
kind: "node",
|
|
30870
31575
|
name,
|
|
@@ -30875,7 +31580,9 @@ function loadNodeEntity(dir, name) {
|
|
|
30875
31580
|
viewDefaults: meta3?.viewDefaults,
|
|
30876
31581
|
viewsPath,
|
|
30877
31582
|
sampleData,
|
|
30878
|
-
allowedIn: meta3?.allowedIn
|
|
31583
|
+
allowedIn: meta3?.allowedIn,
|
|
31584
|
+
migrations,
|
|
31585
|
+
migrationWriteBack: meta3?.migrationWriteBack
|
|
30879
31586
|
};
|
|
30880
31587
|
}
|
|
30881
31588
|
function loadEdgeEntity(dir, name) {
|
|
@@ -30900,6 +31607,8 @@ function loadEdgeEntity(dir, name) {
|
|
|
30900
31607
|
const meta3 = readJsonIfExists(join(dir, "meta.json"));
|
|
30901
31608
|
const sampleData = readJsonIfExists(join(dir, "sample.json"));
|
|
30902
31609
|
const viewsPath = findViewsFile(dir);
|
|
31610
|
+
const migrationsPath = findMigrationsFile(dir);
|
|
31611
|
+
const migrations = migrationsPath ? loadMigrations(migrationsPath, `edge type "${name}"`) : void 0;
|
|
30903
31612
|
return {
|
|
30904
31613
|
kind: "edge",
|
|
30905
31614
|
name,
|
|
@@ -30912,7 +31621,9 @@ function loadEdgeEntity(dir, name) {
|
|
|
30912
31621
|
viewsPath,
|
|
30913
31622
|
sampleData,
|
|
30914
31623
|
allowedIn: meta3?.allowedIn,
|
|
30915
|
-
targetGraph: topology.targetGraph ?? meta3?.targetGraph
|
|
31624
|
+
targetGraph: topology.targetGraph ?? meta3?.targetGraph,
|
|
31625
|
+
migrations,
|
|
31626
|
+
migrationWriteBack: meta3?.migrationWriteBack
|
|
30916
31627
|
};
|
|
30917
31628
|
}
|
|
30918
31629
|
function getSubdirectories(dir) {
|
|
@@ -30975,7 +31686,9 @@ function introspectRegistry(registry2, dynamicNames) {
|
|
|
30975
31686
|
hasDataSchema: !!entry.jsonSchema,
|
|
30976
31687
|
fields,
|
|
30977
31688
|
isNodeEntry: isNode,
|
|
30978
|
-
isDynamic
|
|
31689
|
+
isDynamic,
|
|
31690
|
+
targetGraph: entry.targetGraph,
|
|
31691
|
+
allowedIn: entry.allowedIn
|
|
30979
31692
|
};
|
|
30980
31693
|
if (meta3.isNodeEntry) {
|
|
30981
31694
|
nodeTypes.push(meta3);
|
|
@@ -31056,6 +31769,7 @@ function resilientView(ViewClass, tagName) {
|
|
|
31056
31769
|
export function defineViews(input) {
|
|
31057
31770
|
const nodes = {};
|
|
31058
31771
|
const edges = {};
|
|
31772
|
+
const collections = {};
|
|
31059
31773
|
const registry = (typeof customElements !== 'undefined' && typeof customElements.define === 'function')
|
|
31060
31774
|
? customElements : null;
|
|
31061
31775
|
|
|
@@ -31079,7 +31793,17 @@ export function defineViews(input) {
|
|
|
31079
31793
|
edges[axbType] = { views: viewMetas, sampleData: config.sampleData };
|
|
31080
31794
|
}
|
|
31081
31795
|
|
|
31082
|
-
|
|
31796
|
+
for (const [colName, config] of Object.entries(input.collections ?? {})) {
|
|
31797
|
+
const viewMetas = [];
|
|
31798
|
+
for (const ViewClass of config.views) {
|
|
31799
|
+
const tagName = 'fg-col-' + sanitizeTagPart(colName) + '-' + sanitizeTagPart(ViewClass.viewName);
|
|
31800
|
+
viewMetas.push({ tagName, viewName: ViewClass.viewName, description: ViewClass.description });
|
|
31801
|
+
if (registry && !registry.get(tagName)) registry.define(tagName, resilientView(ViewClass, tagName));
|
|
31802
|
+
}
|
|
31803
|
+
collections[colName] = { views: viewMetas, sampleData: config.sampleData };
|
|
31804
|
+
}
|
|
31805
|
+
|
|
31806
|
+
return { nodes, edges, collections };
|
|
31083
31807
|
}
|
|
31084
31808
|
`;
|
|
31085
31809
|
var REACT_ADAPTER_SHIM = `
|
|
@@ -31171,9 +31895,10 @@ async function loadSveltePlugin() {
|
|
|
31171
31895
|
return null;
|
|
31172
31896
|
}
|
|
31173
31897
|
}
|
|
31174
|
-
async function bundleEntityViews(discovery) {
|
|
31898
|
+
async function bundleEntityViews(discovery, collectionViewPaths) {
|
|
31175
31899
|
const nodeViews = [];
|
|
31176
31900
|
const edgeViews = [];
|
|
31901
|
+
const colViews = collectionViewPaths ?? [];
|
|
31177
31902
|
for (const [name, entity] of discovery.nodes) {
|
|
31178
31903
|
if (entity.viewsPath) {
|
|
31179
31904
|
nodeViews.push({ name, absPath: path.resolve(entity.viewsPath) });
|
|
@@ -31184,10 +31909,11 @@ async function bundleEntityViews(discovery) {
|
|
|
31184
31909
|
edgeViews.push({ name, absPath: path.resolve(entity.viewsPath) });
|
|
31185
31910
|
}
|
|
31186
31911
|
}
|
|
31187
|
-
if (nodeViews.length === 0 && edgeViews.length === 0) return null;
|
|
31912
|
+
if (nodeViews.length === 0 && edgeViews.length === 0 && colViews.length === 0) return null;
|
|
31188
31913
|
const imports = [];
|
|
31189
31914
|
const nodeEntries = [];
|
|
31190
31915
|
const edgeEntries = [];
|
|
31916
|
+
const colEntries = [];
|
|
31191
31917
|
nodeViews.forEach(({ name, absPath }, i) => {
|
|
31192
31918
|
const varName = `nodeViews_${i}`;
|
|
31193
31919
|
imports.push(`import ${varName} from '${absPath.replace(/\\/g, "/")}';`);
|
|
@@ -31198,6 +31924,11 @@ async function bundleEntityViews(discovery) {
|
|
|
31198
31924
|
imports.push(`import ${varName} from '${absPath.replace(/\\/g, "/")}';`);
|
|
31199
31925
|
edgeEntries.push(` '${name}': { views: Array.isArray(${varName}) ? ${varName} : ${varName}.default || [] }`);
|
|
31200
31926
|
});
|
|
31927
|
+
colViews.forEach(({ name, absPath }, i) => {
|
|
31928
|
+
const varName = `colViews_${i}`;
|
|
31929
|
+
imports.push(`import ${varName} from '${absPath.replace(/\\/g, "/")}';`);
|
|
31930
|
+
colEntries.push(` '${name}': { views: Array.isArray(${varName}) ? ${varName} : ${varName}.default || [] }`);
|
|
31931
|
+
});
|
|
31201
31932
|
const syntheticEntry = `
|
|
31202
31933
|
${imports.join("\n")}
|
|
31203
31934
|
import { defineViews } from 'firegraph';
|
|
@@ -31208,6 +31939,9 @@ ${nodeEntries.join(",\n")}
|
|
|
31208
31939
|
},
|
|
31209
31940
|
edges: {
|
|
31210
31941
|
${edgeEntries.join(",\n")}
|
|
31942
|
+
},
|
|
31943
|
+
collections: {
|
|
31944
|
+
${colEntries.join(",\n")}
|
|
31211
31945
|
}
|
|
31212
31946
|
});
|
|
31213
31947
|
`;
|
|
@@ -31508,6 +32242,113 @@ function mergeViewDefaults(discovery, configDefaults) {
|
|
|
31508
32242
|
return { nodes, edges };
|
|
31509
32243
|
}
|
|
31510
32244
|
|
|
32245
|
+
// editor/server/collections-loader.ts
|
|
32246
|
+
import path3 from "path";
|
|
32247
|
+
import fs2 from "fs";
|
|
32248
|
+
function extractPathParams(pathTemplate) {
|
|
32249
|
+
const params = [];
|
|
32250
|
+
const re = /\{([^}]+)\}/g;
|
|
32251
|
+
let m;
|
|
32252
|
+
while ((m = re.exec(pathTemplate)) !== null) {
|
|
32253
|
+
params.push(m[1]);
|
|
32254
|
+
}
|
|
32255
|
+
return params;
|
|
32256
|
+
}
|
|
32257
|
+
function discoverCollections(entitiesDir) {
|
|
32258
|
+
const collectionsDir = path3.join(entitiesDir, "collections");
|
|
32259
|
+
if (!fs2.existsSync(collectionsDir)) return [];
|
|
32260
|
+
let entries;
|
|
32261
|
+
try {
|
|
32262
|
+
entries = fs2.readdirSync(collectionsDir, { withFileTypes: true });
|
|
32263
|
+
} catch {
|
|
32264
|
+
return [];
|
|
32265
|
+
}
|
|
32266
|
+
const results = [];
|
|
32267
|
+
for (const entry of entries) {
|
|
32268
|
+
if (!entry.isDirectory()) continue;
|
|
32269
|
+
const name = entry.name;
|
|
32270
|
+
const dir = path3.join(collectionsDir, name);
|
|
32271
|
+
const collectionJsonPath = path3.join(dir, "collection.json");
|
|
32272
|
+
if (!fs2.existsSync(collectionJsonPath)) continue;
|
|
32273
|
+
let collectionJson;
|
|
32274
|
+
try {
|
|
32275
|
+
const raw = fs2.readFileSync(collectionJsonPath, "utf-8");
|
|
32276
|
+
collectionJson = JSON.parse(raw);
|
|
32277
|
+
} catch (err) {
|
|
32278
|
+
console.warn(`[firegraph] Skipping collection "${name}": invalid collection.json \u2014 ${err.message}`);
|
|
32279
|
+
continue;
|
|
32280
|
+
}
|
|
32281
|
+
if (!collectionJson.path || typeof collectionJson.path !== "string") continue;
|
|
32282
|
+
let fields = [];
|
|
32283
|
+
let hasSchema = false;
|
|
32284
|
+
const schemaJsonPath = path3.join(dir, "schema.json");
|
|
32285
|
+
if (fs2.existsSync(schemaJsonPath)) {
|
|
32286
|
+
try {
|
|
32287
|
+
const raw = fs2.readFileSync(schemaJsonPath, "utf-8");
|
|
32288
|
+
const schema = JSON.parse(raw);
|
|
32289
|
+
fields = jsonSchemaToFieldMeta(schema);
|
|
32290
|
+
hasSchema = true;
|
|
32291
|
+
} catch {
|
|
32292
|
+
}
|
|
32293
|
+
}
|
|
32294
|
+
const pathParams = extractPathParams(collectionJson.path);
|
|
32295
|
+
const defaultOrderBy = collectionJson.orderBy ? {
|
|
32296
|
+
field: collectionJson.orderBy.field,
|
|
32297
|
+
direction: collectionJson.orderBy.direction ?? "asc"
|
|
32298
|
+
} : void 0;
|
|
32299
|
+
let viewsPath;
|
|
32300
|
+
for (const ext of ["ts", "js", "mts", "mjs"]) {
|
|
32301
|
+
const candidate = path3.join(dir, `views.${ext}`);
|
|
32302
|
+
if (fs2.existsSync(candidate)) {
|
|
32303
|
+
viewsPath = candidate;
|
|
32304
|
+
break;
|
|
32305
|
+
}
|
|
32306
|
+
}
|
|
32307
|
+
let sampleData;
|
|
32308
|
+
const sampleJsonPath = path3.join(dir, "sample.json");
|
|
32309
|
+
if (fs2.existsSync(sampleJsonPath)) {
|
|
32310
|
+
try {
|
|
32311
|
+
sampleData = JSON.parse(fs2.readFileSync(sampleJsonPath, "utf-8"));
|
|
32312
|
+
} catch {
|
|
32313
|
+
}
|
|
32314
|
+
}
|
|
32315
|
+
results.push({
|
|
32316
|
+
name,
|
|
32317
|
+
path: collectionJson.path,
|
|
32318
|
+
description: collectionJson.description,
|
|
32319
|
+
typeField: collectionJson.typeField,
|
|
32320
|
+
typeValue: collectionJson.typeValue,
|
|
32321
|
+
parentNodeType: collectionJson.parentNodeType,
|
|
32322
|
+
fields,
|
|
32323
|
+
hasSchema,
|
|
32324
|
+
pathParams,
|
|
32325
|
+
defaultOrderBy,
|
|
32326
|
+
viewsPath,
|
|
32327
|
+
sampleData
|
|
32328
|
+
});
|
|
32329
|
+
}
|
|
32330
|
+
return results;
|
|
32331
|
+
}
|
|
32332
|
+
async function buildCollectionViewRegistry(collections) {
|
|
32333
|
+
const result = {};
|
|
32334
|
+
for (const col of collections) {
|
|
32335
|
+
if (!col.viewsPath) continue;
|
|
32336
|
+
try {
|
|
32337
|
+
const viewClasses = await loadViewClasses(col.viewsPath);
|
|
32338
|
+
if (viewClasses.length === 0) continue;
|
|
32339
|
+
const views = viewClasses.map((vc) => ({
|
|
32340
|
+
tagName: `fg-col-${sanitizeTagPart(col.name)}-${sanitizeTagPart(vc.viewName)}`,
|
|
32341
|
+
viewName: vc.viewName,
|
|
32342
|
+
description: vc.description
|
|
32343
|
+
}));
|
|
32344
|
+
result[col.name] = { views, sampleData: col.sampleData };
|
|
32345
|
+
} catch (err) {
|
|
32346
|
+
console.warn(`[firegraph] Failed to load views for collection "${col.name}": ${err.message}`);
|
|
32347
|
+
}
|
|
32348
|
+
}
|
|
32349
|
+
return result;
|
|
32350
|
+
}
|
|
32351
|
+
|
|
31511
32352
|
// editor/node_modules/.pnpm/@trpc+server@11.10.0_typescript@5.9.3/node_modules/@trpc/server/dist/codes-DagpWZLc.mjs
|
|
31512
32353
|
function mergeWithoutOverrides(obj1, ...objs) {
|
|
31513
32354
|
const newObj = Object.assign(emptyObject(), obj1);
|
|
@@ -31628,27 +32469,27 @@ var noop = () => {
|
|
|
31628
32469
|
var freezeIfAvailable = (obj) => {
|
|
31629
32470
|
if (Object.freeze) Object.freeze(obj);
|
|
31630
32471
|
};
|
|
31631
|
-
function createInnerProxy(callback,
|
|
32472
|
+
function createInnerProxy(callback, path5, memo2) {
|
|
31632
32473
|
var _memo$cacheKey;
|
|
31633
|
-
const cacheKey =
|
|
32474
|
+
const cacheKey = path5.join(".");
|
|
31634
32475
|
(_memo$cacheKey = memo2[cacheKey]) !== null && _memo$cacheKey !== void 0 || (memo2[cacheKey] = new Proxy(noop, {
|
|
31635
32476
|
get(_obj, key) {
|
|
31636
32477
|
if (typeof key !== "string" || key === "then") return void 0;
|
|
31637
|
-
return createInnerProxy(callback, [...
|
|
32478
|
+
return createInnerProxy(callback, [...path5, key], memo2);
|
|
31638
32479
|
},
|
|
31639
32480
|
apply(_1, _2, args) {
|
|
31640
|
-
const lastOfPath =
|
|
32481
|
+
const lastOfPath = path5[path5.length - 1];
|
|
31641
32482
|
let opts = {
|
|
31642
32483
|
args,
|
|
31643
|
-
path:
|
|
32484
|
+
path: path5
|
|
31644
32485
|
};
|
|
31645
32486
|
if (lastOfPath === "call") opts = {
|
|
31646
32487
|
args: args.length >= 2 ? [args[1]] : [],
|
|
31647
|
-
path:
|
|
32488
|
+
path: path5.slice(0, -1)
|
|
31648
32489
|
};
|
|
31649
32490
|
else if (lastOfPath === "apply") opts = {
|
|
31650
32491
|
args: args.length >= 2 ? args[1] : [],
|
|
31651
|
-
path:
|
|
32492
|
+
path: path5.slice(0, -1)
|
|
31652
32493
|
};
|
|
31653
32494
|
freezeIfAvailable(opts.args);
|
|
31654
32495
|
freezeIfAvailable(opts.path);
|
|
@@ -31776,7 +32617,7 @@ var require_objectSpread2 = __commonJS2({ "../../node_modules/.pnpm/@oxc-project
|
|
|
31776
32617
|
} });
|
|
31777
32618
|
var import_objectSpread2 = __toESM2(require_objectSpread2(), 1);
|
|
31778
32619
|
function getErrorShape(opts) {
|
|
31779
|
-
const { path:
|
|
32620
|
+
const { path: path5, error: error48, config: config2 } = opts;
|
|
31780
32621
|
const { code } = opts.error;
|
|
31781
32622
|
const shape = {
|
|
31782
32623
|
message: error48.message,
|
|
@@ -31787,7 +32628,7 @@ function getErrorShape(opts) {
|
|
|
31787
32628
|
}
|
|
31788
32629
|
};
|
|
31789
32630
|
if (config2.isDev && typeof opts.error.stack === "string") shape.data.stack = opts.error.stack;
|
|
31790
|
-
if (typeof
|
|
32631
|
+
if (typeof path5 === "string") shape.data.path = path5;
|
|
31791
32632
|
return config2.errorFormatter((0, import_objectSpread2.default)((0, import_objectSpread2.default)({}, opts), {}, { shape }));
|
|
31792
32633
|
}
|
|
31793
32634
|
|
|
@@ -31913,12 +32754,12 @@ function createRouterFactory(config2) {
|
|
|
31913
32754
|
})
|
|
31914
32755
|
};
|
|
31915
32756
|
}
|
|
31916
|
-
function step(from,
|
|
32757
|
+
function step(from, path5 = []) {
|
|
31917
32758
|
const aggregate = emptyObject();
|
|
31918
32759
|
for (const [key, item] of Object.entries(from !== null && from !== void 0 ? from : {})) {
|
|
31919
32760
|
if (isLazy(item)) {
|
|
31920
|
-
lazy$1[[...
|
|
31921
|
-
path:
|
|
32761
|
+
lazy$1[[...path5, key].join(".")] = createLazyLoader({
|
|
32762
|
+
path: path5,
|
|
31922
32763
|
ref: item,
|
|
31923
32764
|
key,
|
|
31924
32765
|
aggregate
|
|
@@ -31926,14 +32767,14 @@ function createRouterFactory(config2) {
|
|
|
31926
32767
|
continue;
|
|
31927
32768
|
}
|
|
31928
32769
|
if (isRouter(item)) {
|
|
31929
|
-
aggregate[key] = step(item._def.record, [...
|
|
32770
|
+
aggregate[key] = step(item._def.record, [...path5, key]);
|
|
31930
32771
|
continue;
|
|
31931
32772
|
}
|
|
31932
32773
|
if (!isProcedure(item)) {
|
|
31933
|
-
aggregate[key] = step(item, [...
|
|
32774
|
+
aggregate[key] = step(item, [...path5, key]);
|
|
31934
32775
|
continue;
|
|
31935
32776
|
}
|
|
31936
|
-
const newPath = [...
|
|
32777
|
+
const newPath = [...path5, key].join(".");
|
|
31937
32778
|
if (procedures[newPath]) throw new Error(`Duplicate key: ${newPath}`);
|
|
31938
32779
|
procedures[newPath] = item;
|
|
31939
32780
|
aggregate[key] = item;
|
|
@@ -31958,15 +32799,15 @@ function createRouterFactory(config2) {
|
|
|
31958
32799
|
function isProcedure(procedureOrRouter) {
|
|
31959
32800
|
return typeof procedureOrRouter === "function";
|
|
31960
32801
|
}
|
|
31961
|
-
async function getProcedureAtPath(router,
|
|
32802
|
+
async function getProcedureAtPath(router, path5) {
|
|
31962
32803
|
const { _def } = router;
|
|
31963
|
-
let procedure = _def.procedures[
|
|
32804
|
+
let procedure = _def.procedures[path5];
|
|
31964
32805
|
while (!procedure) {
|
|
31965
|
-
const key = Object.keys(_def.lazy).find((key$1) =>
|
|
32806
|
+
const key = Object.keys(_def.lazy).find((key$1) => path5.startsWith(key$1));
|
|
31966
32807
|
if (!key) return null;
|
|
31967
32808
|
const lazyRouter = _def.lazy[key];
|
|
31968
32809
|
await lazyRouter.load();
|
|
31969
|
-
procedure = _def.procedures[
|
|
32810
|
+
procedure = _def.procedures[path5];
|
|
31970
32811
|
}
|
|
31971
32812
|
return procedure;
|
|
31972
32813
|
}
|
|
@@ -31975,15 +32816,15 @@ function createCallerFactory() {
|
|
|
31975
32816
|
const { _def } = router;
|
|
31976
32817
|
return function createCaller(ctxOrCallback, opts) {
|
|
31977
32818
|
return createRecursiveProxy(async (innerOpts) => {
|
|
31978
|
-
const { path:
|
|
31979
|
-
const fullPath =
|
|
31980
|
-
if (
|
|
32819
|
+
const { path: path5, args } = innerOpts;
|
|
32820
|
+
const fullPath = path5.join(".");
|
|
32821
|
+
if (path5.length === 1 && path5[0] === "_def") return _def;
|
|
31981
32822
|
const procedure = await getProcedureAtPath(router, fullPath);
|
|
31982
32823
|
let ctx = void 0;
|
|
31983
32824
|
try {
|
|
31984
32825
|
if (!procedure) throw new TRPCError({
|
|
31985
32826
|
code: "NOT_FOUND",
|
|
31986
|
-
message: `No procedure found on path "${
|
|
32827
|
+
message: `No procedure found on path "${path5}"`
|
|
31987
32828
|
});
|
|
31988
32829
|
ctx = isFunction(ctxOrCallback) ? await Promise.resolve(ctxOrCallback()) : ctxOrCallback;
|
|
31989
32830
|
return await procedure({
|
|
@@ -32199,11 +33040,11 @@ var jsonContentTypeHandler = {
|
|
|
32199
33040
|
}
|
|
32200
33041
|
return acc;
|
|
32201
33042
|
});
|
|
32202
|
-
const calls = await Promise.all(paths.map(async (
|
|
32203
|
-
const procedure = await getProcedureAtPath(opts.router,
|
|
33043
|
+
const calls = await Promise.all(paths.map(async (path5, index) => {
|
|
33044
|
+
const procedure = await getProcedureAtPath(opts.router, path5);
|
|
32204
33045
|
return {
|
|
32205
33046
|
batchIndex: index,
|
|
32206
|
-
path:
|
|
33047
|
+
path: path5,
|
|
32207
33048
|
procedure,
|
|
32208
33049
|
getRawInput: async () => {
|
|
32209
33050
|
const inputs = await getInputs.read();
|
|
@@ -33011,9 +33852,9 @@ function isPromise(value) {
|
|
|
33011
33852
|
return (isObject(value) || isFunction(value)) && typeof (value === null || value === void 0 ? void 0 : value["then"]) === "function" && typeof (value === null || value === void 0 ? void 0 : value["catch"]) === "function";
|
|
33012
33853
|
}
|
|
33013
33854
|
var MaxDepthError = class extends Error {
|
|
33014
|
-
constructor(
|
|
33015
|
-
super("Max depth reached at path: " +
|
|
33016
|
-
this.path =
|
|
33855
|
+
constructor(path5) {
|
|
33856
|
+
super("Max depth reached at path: " + path5.join("."));
|
|
33857
|
+
this.path = path5;
|
|
33017
33858
|
}
|
|
33018
33859
|
};
|
|
33019
33860
|
function createBatchStreamProducer(_x3) {
|
|
@@ -33031,16 +33872,16 @@ function _createBatchStreamProducer() {
|
|
|
33031
33872
|
mergedIterables.add(iterable$1);
|
|
33032
33873
|
return idx;
|
|
33033
33874
|
}
|
|
33034
|
-
function encodePromise(promise2,
|
|
33875
|
+
function encodePromise(promise2, path5) {
|
|
33035
33876
|
return registerAsync(/* @__PURE__ */ function() {
|
|
33036
33877
|
var _ref = (0, import_wrapAsyncGenerator$2.default)(function* (idx) {
|
|
33037
|
-
const error48 = checkMaxDepth(
|
|
33878
|
+
const error48 = checkMaxDepth(path5);
|
|
33038
33879
|
if (error48) {
|
|
33039
33880
|
promise2.catch((cause) => {
|
|
33040
33881
|
var _opts$onError;
|
|
33041
33882
|
(_opts$onError = opts.onError) === null || _opts$onError === void 0 || _opts$onError.call(opts, {
|
|
33042
33883
|
error: cause,
|
|
33043
|
-
path:
|
|
33884
|
+
path: path5
|
|
33044
33885
|
});
|
|
33045
33886
|
});
|
|
33046
33887
|
promise2 = Promise.reject(error48);
|
|
@@ -33050,20 +33891,20 @@ function _createBatchStreamProducer() {
|
|
|
33050
33891
|
yield [
|
|
33051
33892
|
idx,
|
|
33052
33893
|
PROMISE_STATUS_FULFILLED,
|
|
33053
|
-
encode3(next,
|
|
33894
|
+
encode3(next, path5)
|
|
33054
33895
|
];
|
|
33055
33896
|
} catch (cause) {
|
|
33056
33897
|
var _opts$onError2, _opts$formatError;
|
|
33057
33898
|
(_opts$onError2 = opts.onError) === null || _opts$onError2 === void 0 || _opts$onError2.call(opts, {
|
|
33058
33899
|
error: cause,
|
|
33059
|
-
path:
|
|
33900
|
+
path: path5
|
|
33060
33901
|
});
|
|
33061
33902
|
yield [
|
|
33062
33903
|
idx,
|
|
33063
33904
|
PROMISE_STATUS_REJECTED,
|
|
33064
33905
|
(_opts$formatError = opts.formatError) === null || _opts$formatError === void 0 ? void 0 : _opts$formatError.call(opts, {
|
|
33065
33906
|
error: cause,
|
|
33066
|
-
path:
|
|
33907
|
+
path: path5
|
|
33067
33908
|
})
|
|
33068
33909
|
];
|
|
33069
33910
|
}
|
|
@@ -33073,12 +33914,12 @@ function _createBatchStreamProducer() {
|
|
|
33073
33914
|
};
|
|
33074
33915
|
}());
|
|
33075
33916
|
}
|
|
33076
|
-
function encodeAsyncIterable(iterable$1,
|
|
33917
|
+
function encodeAsyncIterable(iterable$1, path5) {
|
|
33077
33918
|
return registerAsync(/* @__PURE__ */ function() {
|
|
33078
33919
|
var _ref2 = (0, import_wrapAsyncGenerator$2.default)(function* (idx) {
|
|
33079
33920
|
try {
|
|
33080
33921
|
var _usingCtx$1 = (0, import_usingCtx$1.default)();
|
|
33081
|
-
const error48 = checkMaxDepth(
|
|
33922
|
+
const error48 = checkMaxDepth(path5);
|
|
33082
33923
|
if (error48) throw error48;
|
|
33083
33924
|
const iterator = _usingCtx$1.a(iteratorResource(iterable$1));
|
|
33084
33925
|
try {
|
|
@@ -33088,28 +33929,28 @@ function _createBatchStreamProducer() {
|
|
|
33088
33929
|
yield [
|
|
33089
33930
|
idx,
|
|
33090
33931
|
ASYNC_ITERABLE_STATUS_RETURN,
|
|
33091
|
-
encode3(next.value,
|
|
33932
|
+
encode3(next.value, path5)
|
|
33092
33933
|
];
|
|
33093
33934
|
break;
|
|
33094
33935
|
}
|
|
33095
33936
|
yield [
|
|
33096
33937
|
idx,
|
|
33097
33938
|
ASYNC_ITERABLE_STATUS_YIELD,
|
|
33098
|
-
encode3(next.value,
|
|
33939
|
+
encode3(next.value, path5)
|
|
33099
33940
|
];
|
|
33100
33941
|
}
|
|
33101
33942
|
} catch (cause) {
|
|
33102
33943
|
var _opts$onError3, _opts$formatError2;
|
|
33103
33944
|
(_opts$onError3 = opts.onError) === null || _opts$onError3 === void 0 || _opts$onError3.call(opts, {
|
|
33104
33945
|
error: cause,
|
|
33105
|
-
path:
|
|
33946
|
+
path: path5
|
|
33106
33947
|
});
|
|
33107
33948
|
yield [
|
|
33108
33949
|
idx,
|
|
33109
33950
|
ASYNC_ITERABLE_STATUS_ERROR,
|
|
33110
33951
|
(_opts$formatError2 = opts.formatError) === null || _opts$formatError2 === void 0 ? void 0 : _opts$formatError2.call(opts, {
|
|
33111
33952
|
error: cause,
|
|
33112
|
-
path:
|
|
33953
|
+
path: path5
|
|
33113
33954
|
})
|
|
33114
33955
|
];
|
|
33115
33956
|
}
|
|
@@ -33124,27 +33965,27 @@ function _createBatchStreamProducer() {
|
|
|
33124
33965
|
};
|
|
33125
33966
|
}());
|
|
33126
33967
|
}
|
|
33127
|
-
function checkMaxDepth(
|
|
33128
|
-
if (opts.maxDepth &&
|
|
33968
|
+
function checkMaxDepth(path5) {
|
|
33969
|
+
if (opts.maxDepth && path5.length > opts.maxDepth) return new MaxDepthError(path5);
|
|
33129
33970
|
return null;
|
|
33130
33971
|
}
|
|
33131
|
-
function encodeAsync3(value,
|
|
33132
|
-
if (isPromise(value)) return [CHUNK_VALUE_TYPE_PROMISE, encodePromise(value,
|
|
33972
|
+
function encodeAsync3(value, path5) {
|
|
33973
|
+
if (isPromise(value)) return [CHUNK_VALUE_TYPE_PROMISE, encodePromise(value, path5)];
|
|
33133
33974
|
if (isAsyncIterable(value)) {
|
|
33134
|
-
if (opts.maxDepth &&
|
|
33135
|
-
return [CHUNK_VALUE_TYPE_ASYNC_ITERABLE, encodeAsyncIterable(value,
|
|
33975
|
+
if (opts.maxDepth && path5.length >= opts.maxDepth) throw new Error("Max depth reached");
|
|
33976
|
+
return [CHUNK_VALUE_TYPE_ASYNC_ITERABLE, encodeAsyncIterable(value, path5)];
|
|
33136
33977
|
}
|
|
33137
33978
|
return null;
|
|
33138
33979
|
}
|
|
33139
|
-
function encode3(value,
|
|
33980
|
+
function encode3(value, path5) {
|
|
33140
33981
|
if (value === void 0) return [[]];
|
|
33141
|
-
const reg = encodeAsync3(value,
|
|
33982
|
+
const reg = encodeAsync3(value, path5);
|
|
33142
33983
|
if (reg) return [[placeholder], [null, ...reg]];
|
|
33143
33984
|
if (!isPlainObject(value)) return [[value]];
|
|
33144
33985
|
const newObj = emptyObject();
|
|
33145
33986
|
const asyncValues = [];
|
|
33146
33987
|
for (const [key, item] of Object.entries(value)) {
|
|
33147
|
-
const transformed = encodeAsync3(item, [...
|
|
33988
|
+
const transformed = encodeAsync3(item, [...path5, key]);
|
|
33148
33989
|
if (!transformed) {
|
|
33149
33990
|
newObj[key] = item;
|
|
33150
33991
|
continue;
|
|
@@ -33584,11 +34425,11 @@ async function resolveResponse(opts) {
|
|
|
33584
34425
|
var _call$procedure$_def$2, _call$procedure3, _opts$onError2;
|
|
33585
34426
|
const error$1 = getTRPCErrorFromUnknown(errorOpts.error);
|
|
33586
34427
|
const input = call === null || call === void 0 ? void 0 : call.result();
|
|
33587
|
-
const
|
|
34428
|
+
const path5 = call === null || call === void 0 ? void 0 : call.path;
|
|
33588
34429
|
const type = (_call$procedure$_def$2 = call === null || call === void 0 || (_call$procedure3 = call.procedure) === null || _call$procedure3 === void 0 ? void 0 : _call$procedure3._def.type) !== null && _call$procedure$_def$2 !== void 0 ? _call$procedure$_def$2 : "unknown";
|
|
33589
34430
|
(_opts$onError2 = opts.onError) === null || _opts$onError2 === void 0 || _opts$onError2.call(opts, {
|
|
33590
34431
|
error: error$1,
|
|
33591
|
-
path:
|
|
34432
|
+
path: path5,
|
|
33592
34433
|
input,
|
|
33593
34434
|
ctx: ctxManager.valueOrUndefined(),
|
|
33594
34435
|
req: opts.req,
|
|
@@ -33599,7 +34440,7 @@ async function resolveResponse(opts) {
|
|
|
33599
34440
|
ctx: ctxManager.valueOrUndefined(),
|
|
33600
34441
|
error: error$1,
|
|
33601
34442
|
input,
|
|
33602
|
-
path:
|
|
34443
|
+
path: path5,
|
|
33603
34444
|
type
|
|
33604
34445
|
});
|
|
33605
34446
|
return shape;
|
|
@@ -33668,14 +34509,14 @@ async function resolveResponse(opts) {
|
|
|
33668
34509
|
const call = info === null || info === void 0 ? void 0 : info.calls[errorOpts.path[0]];
|
|
33669
34510
|
const error48 = getTRPCErrorFromUnknown(errorOpts.error);
|
|
33670
34511
|
const input = call === null || call === void 0 ? void 0 : call.result();
|
|
33671
|
-
const
|
|
34512
|
+
const path5 = call === null || call === void 0 ? void 0 : call.path;
|
|
33672
34513
|
const type = (_call$procedure$_def$3 = call === null || call === void 0 || (_call$procedure4 = call.procedure) === null || _call$procedure4 === void 0 ? void 0 : _call$procedure4._def.type) !== null && _call$procedure$_def$3 !== void 0 ? _call$procedure$_def$3 : "unknown";
|
|
33673
34514
|
const shape = getErrorShape({
|
|
33674
34515
|
config: config2,
|
|
33675
34516
|
ctx: ctxManager.valueOrUndefined(),
|
|
33676
34517
|
error: error48,
|
|
33677
34518
|
input,
|
|
33678
|
-
path:
|
|
34519
|
+
path: path5,
|
|
33679
34520
|
type
|
|
33680
34521
|
});
|
|
33681
34522
|
return shape;
|
|
@@ -34254,24 +35095,24 @@ async function nodeHTTPRequestHandler(opts) {
|
|
|
34254
35095
|
var import_objectSpread26 = __toESM2(require_objectSpread2(), 1);
|
|
34255
35096
|
function createExpressMiddleware(opts) {
|
|
34256
35097
|
return (req, res) => {
|
|
34257
|
-
let
|
|
35098
|
+
let path5 = "";
|
|
34258
35099
|
run(async () => {
|
|
34259
|
-
|
|
35100
|
+
path5 = req.path.slice(req.path.lastIndexOf("/") + 1);
|
|
34260
35101
|
await nodeHTTPRequestHandler((0, import_objectSpread26.default)((0, import_objectSpread26.default)({}, opts), {}, {
|
|
34261
35102
|
req,
|
|
34262
35103
|
res,
|
|
34263
|
-
path:
|
|
35104
|
+
path: path5
|
|
34264
35105
|
}));
|
|
34265
35106
|
}).catch(internal_exceptionHandler((0, import_objectSpread26.default)({
|
|
34266
35107
|
req,
|
|
34267
35108
|
res,
|
|
34268
|
-
path:
|
|
35109
|
+
path: path5
|
|
34269
35110
|
}, opts)));
|
|
34270
35111
|
};
|
|
34271
35112
|
}
|
|
34272
35113
|
|
|
34273
35114
|
// editor/server/trpc.ts
|
|
34274
|
-
import { Timestamp } from "@google-cloud/firestore";
|
|
35115
|
+
import { Timestamp as Timestamp2, FieldPath } from "@google-cloud/firestore";
|
|
34275
35116
|
|
|
34276
35117
|
// editor/node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/classic/external.js
|
|
34277
35118
|
var external_exports = {};
|
|
@@ -35040,10 +35881,10 @@ function mergeDefs(...defs) {
|
|
|
35040
35881
|
function cloneDef(schema) {
|
|
35041
35882
|
return mergeDefs(schema._zod.def);
|
|
35042
35883
|
}
|
|
35043
|
-
function getElementAtPath(obj,
|
|
35044
|
-
if (!
|
|
35884
|
+
function getElementAtPath(obj, path5) {
|
|
35885
|
+
if (!path5)
|
|
35045
35886
|
return obj;
|
|
35046
|
-
return
|
|
35887
|
+
return path5.reduce((acc, key) => acc?.[key], obj);
|
|
35047
35888
|
}
|
|
35048
35889
|
function promiseAllObject(promisesObj) {
|
|
35049
35890
|
const keys = Object.keys(promisesObj);
|
|
@@ -35426,11 +36267,11 @@ function aborted(x, startIndex = 0) {
|
|
|
35426
36267
|
}
|
|
35427
36268
|
return false;
|
|
35428
36269
|
}
|
|
35429
|
-
function prefixIssues(
|
|
36270
|
+
function prefixIssues(path5, issues) {
|
|
35430
36271
|
return issues.map((iss) => {
|
|
35431
36272
|
var _a2;
|
|
35432
36273
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
35433
|
-
iss.path.unshift(
|
|
36274
|
+
iss.path.unshift(path5);
|
|
35434
36275
|
return iss;
|
|
35435
36276
|
});
|
|
35436
36277
|
}
|
|
@@ -35613,7 +36454,7 @@ function formatError(error48, mapper = (issue2) => issue2.message) {
|
|
|
35613
36454
|
}
|
|
35614
36455
|
function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
35615
36456
|
const result = { errors: [] };
|
|
35616
|
-
const processError = (error49,
|
|
36457
|
+
const processError = (error49, path5 = []) => {
|
|
35617
36458
|
var _a2, _b;
|
|
35618
36459
|
for (const issue2 of error49.issues) {
|
|
35619
36460
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -35623,7 +36464,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
|
35623
36464
|
} else if (issue2.code === "invalid_element") {
|
|
35624
36465
|
processError({ issues: issue2.issues }, issue2.path);
|
|
35625
36466
|
} else {
|
|
35626
|
-
const fullpath = [...
|
|
36467
|
+
const fullpath = [...path5, ...issue2.path];
|
|
35627
36468
|
if (fullpath.length === 0) {
|
|
35628
36469
|
result.errors.push(mapper(issue2));
|
|
35629
36470
|
continue;
|
|
@@ -35655,8 +36496,8 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
|
35655
36496
|
}
|
|
35656
36497
|
function toDotPath(_path) {
|
|
35657
36498
|
const segs = [];
|
|
35658
|
-
const
|
|
35659
|
-
for (const seg of
|
|
36499
|
+
const path5 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
36500
|
+
for (const seg of path5) {
|
|
35660
36501
|
if (typeof seg === "number")
|
|
35661
36502
|
segs.push(`[${seg}]`);
|
|
35662
36503
|
else if (typeof seg === "symbol")
|
|
@@ -47633,13 +48474,13 @@ function resolveRef(ref, ctx) {
|
|
|
47633
48474
|
if (!ref.startsWith("#")) {
|
|
47634
48475
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
47635
48476
|
}
|
|
47636
|
-
const
|
|
47637
|
-
if (
|
|
48477
|
+
const path5 = ref.slice(1).split("/").filter(Boolean);
|
|
48478
|
+
if (path5.length === 0) {
|
|
47638
48479
|
return ctx.rootSchema;
|
|
47639
48480
|
}
|
|
47640
48481
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
47641
|
-
if (
|
|
47642
|
-
const key =
|
|
48482
|
+
if (path5[0] === defsKey) {
|
|
48483
|
+
const key = path5[1];
|
|
47643
48484
|
if (!key || !ctx.defs[key]) {
|
|
47644
48485
|
throw new Error(`Reference not found: ${ref}`);
|
|
47645
48486
|
}
|
|
@@ -48067,16 +48908,16 @@ var writeProcedure = t.procedure.use(async ({ ctx, next }) => {
|
|
|
48067
48908
|
return next();
|
|
48068
48909
|
});
|
|
48069
48910
|
var NODE_RELATION2 = "is";
|
|
48911
|
+
function serializeValue2(value) {
|
|
48912
|
+
if (value instanceof Timestamp2) return value.toDate().toISOString();
|
|
48913
|
+
if (Array.isArray(value)) return value.map(serializeValue2);
|
|
48914
|
+
if (value && typeof value === "object") return serializeRecord(value);
|
|
48915
|
+
return value;
|
|
48916
|
+
}
|
|
48070
48917
|
function serializeRecord(doc) {
|
|
48071
48918
|
const result = {};
|
|
48072
48919
|
for (const [key, value] of Object.entries(doc)) {
|
|
48073
|
-
|
|
48074
|
-
result[key] = value.toDate().toISOString();
|
|
48075
|
-
} else if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
48076
|
-
result[key] = serializeRecord(value);
|
|
48077
|
-
} else {
|
|
48078
|
-
result[key] = value;
|
|
48079
|
-
}
|
|
48920
|
+
result[key] = serializeValue2(value);
|
|
48080
48921
|
}
|
|
48081
48922
|
return result;
|
|
48082
48923
|
}
|
|
@@ -48089,6 +48930,55 @@ function stripTypePrefix(raw) {
|
|
|
48089
48930
|
}
|
|
48090
48931
|
return raw;
|
|
48091
48932
|
}
|
|
48933
|
+
function resolveCollectionPath(rootCollection, scope) {
|
|
48934
|
+
if (!scope) return rootCollection;
|
|
48935
|
+
const segments = scope.split("/");
|
|
48936
|
+
if (segments.length % 2 !== 0) {
|
|
48937
|
+
throw new TRPCError({
|
|
48938
|
+
code: "BAD_REQUEST",
|
|
48939
|
+
message: `Invalid scope path: "${scope}". Must be pairs of parentUid/subgraphName.`
|
|
48940
|
+
});
|
|
48941
|
+
}
|
|
48942
|
+
return `${rootCollection}/${scope}`;
|
|
48943
|
+
}
|
|
48944
|
+
function getScopedClient(rootClient, scope) {
|
|
48945
|
+
if (!scope) return rootClient;
|
|
48946
|
+
const segments = scope.split("/");
|
|
48947
|
+
if (segments.length % 2 !== 0) {
|
|
48948
|
+
throw new TRPCError({
|
|
48949
|
+
code: "BAD_REQUEST",
|
|
48950
|
+
message: `Invalid scope path: "${scope}". Must be pairs of parentUid/subgraphName.`
|
|
48951
|
+
});
|
|
48952
|
+
}
|
|
48953
|
+
let client = rootClient;
|
|
48954
|
+
for (let i = 0; i < segments.length; i += 2) {
|
|
48955
|
+
client = client.subgraph(segments[i], segments[i + 1]);
|
|
48956
|
+
}
|
|
48957
|
+
return client;
|
|
48958
|
+
}
|
|
48959
|
+
var scopeSchema = external_exports.string().optional();
|
|
48960
|
+
function substitutePathTemplate(template, params = {}) {
|
|
48961
|
+
return template.replace(/\{([^}]+)\}/g, (_, key) => {
|
|
48962
|
+
if (!(key in params)) {
|
|
48963
|
+
throw new TRPCError({ code: "BAD_REQUEST", message: `Missing required path parameter: "${key}"` });
|
|
48964
|
+
}
|
|
48965
|
+
const val = params[key];
|
|
48966
|
+
if (!val) {
|
|
48967
|
+
throw new TRPCError({ code: "BAD_REQUEST", message: `Path parameter "${key}" must not be empty` });
|
|
48968
|
+
}
|
|
48969
|
+
if (val.includes("/")) {
|
|
48970
|
+
throw new TRPCError({ code: "BAD_REQUEST", message: `Path parameter "${key}" must not contain "/"` });
|
|
48971
|
+
}
|
|
48972
|
+
return val;
|
|
48973
|
+
});
|
|
48974
|
+
}
|
|
48975
|
+
function getCollectionDef(ctx, name) {
|
|
48976
|
+
const def = ctx.collectionDefs.find((c) => c.name === name);
|
|
48977
|
+
if (!def) {
|
|
48978
|
+
throw new TRPCError({ code: "NOT_FOUND", message: `Collection "${name}" not found.` });
|
|
48979
|
+
}
|
|
48980
|
+
return def;
|
|
48981
|
+
}
|
|
48092
48982
|
var appRouter = t.router({
|
|
48093
48983
|
// --- Config ---
|
|
48094
48984
|
getConfig: publicProcedure.query(({ ctx }) => ({
|
|
@@ -48116,7 +49006,8 @@ var appRouter = t.router({
|
|
|
48116
49006
|
inverseLabel: e.inverseLabel,
|
|
48117
49007
|
titleField: e.titleField,
|
|
48118
49008
|
subtitleField: e.subtitleField,
|
|
48119
|
-
isDynamic: e.isDynamic
|
|
49009
|
+
isDynamic: e.isDynamic,
|
|
49010
|
+
targetGraph: e.targetGraph
|
|
48120
49011
|
}));
|
|
48121
49012
|
return {
|
|
48122
49013
|
nodeTypes,
|
|
@@ -48124,13 +49015,26 @@ var appRouter = t.router({
|
|
|
48124
49015
|
readonly: ctx.readonly,
|
|
48125
49016
|
nodeSchemas: ctx.schemaMetadata.nodeTypes,
|
|
48126
49017
|
edgeSchemas: ctx.schemaMetadata.edgeTypes,
|
|
48127
|
-
dynamicMode: ctx.reloadFn !== null
|
|
49018
|
+
dynamicMode: ctx.reloadFn !== null,
|
|
49019
|
+
collections: ctx.collectionDefs.map((c) => ({
|
|
49020
|
+
name: c.name,
|
|
49021
|
+
path: c.path,
|
|
49022
|
+
description: c.description,
|
|
49023
|
+
typeField: c.typeField,
|
|
49024
|
+
typeValue: c.typeValue,
|
|
49025
|
+
parentNodeType: c.parentNodeType,
|
|
49026
|
+
fields: c.fields,
|
|
49027
|
+
hasSchema: c.hasSchema,
|
|
49028
|
+
pathParams: c.pathParams,
|
|
49029
|
+
defaultOrderBy: c.defaultOrderBy
|
|
49030
|
+
}))
|
|
48128
49031
|
};
|
|
48129
49032
|
}),
|
|
48130
49033
|
// --- Views ---
|
|
48131
49034
|
getViews: publicProcedure.query(({ ctx }) => {
|
|
48132
49035
|
const nodes = ctx.viewRegistry?.nodes ? { ...ctx.viewRegistry.nodes } : {};
|
|
48133
49036
|
const edges = ctx.viewRegistry?.edges ? { ...ctx.viewRegistry.edges } : {};
|
|
49037
|
+
const collections = { ...ctx.collectionViewRegistry };
|
|
48134
49038
|
if (ctx.dynamicTypeMeta) {
|
|
48135
49039
|
for (const [name, meta3] of Object.entries(ctx.dynamicTypeMeta.nodes)) {
|
|
48136
49040
|
if (!meta3.viewTemplate) continue;
|
|
@@ -48155,8 +49059,8 @@ var appRouter = t.router({
|
|
|
48155
49059
|
}
|
|
48156
49060
|
}
|
|
48157
49061
|
}
|
|
48158
|
-
const hasViews = Object.keys(nodes).length > 0 || Object.keys(edges).length > 0;
|
|
48159
|
-
return { nodes, edges, hasViews };
|
|
49062
|
+
const hasViews = Object.keys(nodes).length > 0 || Object.keys(edges).length > 0 || Object.keys(collections).length > 0;
|
|
49063
|
+
return { nodes, edges, collections, hasViews };
|
|
48160
49064
|
}),
|
|
48161
49065
|
// --- Reload Schema (dynamic registry) ---
|
|
48162
49066
|
reloadSchema: writeProcedure.mutation(async ({ ctx }) => {
|
|
@@ -48175,6 +49079,7 @@ var appRouter = t.router({
|
|
|
48175
49079
|
})),
|
|
48176
49080
|
// --- Browse Nodes ---
|
|
48177
49081
|
getNodes: publicProcedure.input(external_exports.object({
|
|
49082
|
+
scope: scopeSchema,
|
|
48178
49083
|
type: external_exports.string().optional(),
|
|
48179
49084
|
limit: external_exports.number().min(1).max(200).default(25),
|
|
48180
49085
|
startAfter: external_exports.string().optional(),
|
|
@@ -48191,7 +49096,7 @@ var appRouter = t.router({
|
|
|
48191
49096
|
value: external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean()])
|
|
48192
49097
|
})).optional()
|
|
48193
49098
|
})).query(async ({ ctx, input }) => {
|
|
48194
|
-
const col = ctx.db.collection(ctx.collection);
|
|
49099
|
+
const col = ctx.db.collection(resolveCollectionPath(ctx.collection, input.scope));
|
|
48195
49100
|
const builtinSortFields = ["aUid", "createdAt", "updatedAt"];
|
|
48196
49101
|
let effectiveSortBy;
|
|
48197
49102
|
if (builtinSortFields.includes(input.sortBy)) {
|
|
@@ -48234,13 +49139,13 @@ var appRouter = t.router({
|
|
|
48234
49139
|
if (hasMore && docs.length > 0) {
|
|
48235
49140
|
const lastDoc = docs[docs.length - 1].data();
|
|
48236
49141
|
const cursorValue = lastDoc[effectiveSortBy];
|
|
48237
|
-
nextCursor = cursorValue instanceof
|
|
49142
|
+
nextCursor = cursorValue instanceof Timestamp2 ? cursorValue.toDate().toISOString() : String(cursorValue);
|
|
48238
49143
|
}
|
|
48239
49144
|
return { nodes, hasMore, nextCursor };
|
|
48240
49145
|
}),
|
|
48241
49146
|
// --- Get Single Node ---
|
|
48242
|
-
getNodeDetail: publicProcedure.input(external_exports.object({ uid: external_exports.string() })).query(async ({ ctx, input }) => {
|
|
48243
|
-
const col = ctx.db.collection(ctx.collection);
|
|
49147
|
+
getNodeDetail: publicProcedure.input(external_exports.object({ scope: scopeSchema, uid: external_exports.string() })).query(async ({ ctx, input }) => {
|
|
49148
|
+
const col = ctx.db.collection(resolveCollectionPath(ctx.collection, input.scope));
|
|
48244
49149
|
const edgeLimit = 50;
|
|
48245
49150
|
const uid = stripTypePrefix(input.uid);
|
|
48246
49151
|
const nodeDoc = await col.doc(uid).get();
|
|
@@ -48252,8 +49157,8 @@ var appRouter = t.router({
|
|
|
48252
49157
|
return { node, outEdges, inEdges };
|
|
48253
49158
|
}),
|
|
48254
49159
|
// --- Batch Get Nodes ---
|
|
48255
|
-
getNodesBatch: publicProcedure.input(external_exports.object({ uids: external_exports.array(external_exports.string()).min(1).max(100) })).query(async ({ ctx, input }) => {
|
|
48256
|
-
const col = ctx.db.collection(ctx.collection);
|
|
49160
|
+
getNodesBatch: publicProcedure.input(external_exports.object({ scope: scopeSchema, uids: external_exports.array(external_exports.string()).min(1).max(100) })).query(async ({ ctx, input }) => {
|
|
49161
|
+
const col = ctx.db.collection(resolveCollectionPath(ctx.collection, input.scope));
|
|
48257
49162
|
const cleanUids = input.uids.map(stripTypePrefix);
|
|
48258
49163
|
const refs = cleanUids.map((uid) => col.doc(uid));
|
|
48259
49164
|
const snapshots = await ctx.db.getAll(...refs);
|
|
@@ -48265,6 +49170,7 @@ var appRouter = t.router({
|
|
|
48265
49170
|
}),
|
|
48266
49171
|
// --- Query Edges ---
|
|
48267
49172
|
getEdges: publicProcedure.input(external_exports.object({
|
|
49173
|
+
scope: scopeSchema,
|
|
48268
49174
|
aType: external_exports.string().optional(),
|
|
48269
49175
|
aUid: external_exports.string().optional(),
|
|
48270
49176
|
axbType: external_exports.string().optional(),
|
|
@@ -48280,7 +49186,7 @@ var appRouter = t.router({
|
|
|
48280
49186
|
value: external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean()])
|
|
48281
49187
|
})).optional()
|
|
48282
49188
|
})).query(async ({ ctx, input }) => {
|
|
48283
|
-
const col = ctx.db.collection(ctx.collection);
|
|
49189
|
+
const col = ctx.db.collection(resolveCollectionPath(ctx.collection, input.scope));
|
|
48284
49190
|
let query = col;
|
|
48285
49191
|
if (input.aType) query = query.where("aType", "==", input.aType);
|
|
48286
49192
|
if (input.aUid) query = query.where("aUid", "==", input.aUid);
|
|
@@ -48320,12 +49226,13 @@ var appRouter = t.router({
|
|
|
48320
49226
|
if (hasMore && docs.length > 0) {
|
|
48321
49227
|
const lastDoc = docs[docs.length - 1].data();
|
|
48322
49228
|
const cursorValue = effectiveSortBy.startsWith("data.") ? effectiveSortBy.split(".").reduce((obj, key) => obj?.[key], lastDoc) : lastDoc[effectiveSortBy];
|
|
48323
|
-
nextCursor = cursorValue instanceof
|
|
49229
|
+
nextCursor = cursorValue instanceof Timestamp2 ? cursorValue.toDate().toISOString() : String(cursorValue);
|
|
48324
49230
|
}
|
|
48325
49231
|
return { edges, hasMore, nextCursor };
|
|
48326
49232
|
}),
|
|
48327
49233
|
// --- Traversal ---
|
|
48328
49234
|
traverse: publicProcedure.input(external_exports.object({
|
|
49235
|
+
scope: scopeSchema,
|
|
48329
49236
|
startUid: external_exports.string().min(1),
|
|
48330
49237
|
hops: external_exports.array(external_exports.object({
|
|
48331
49238
|
axbType: external_exports.string(),
|
|
@@ -48346,7 +49253,7 @@ var appRouter = t.router({
|
|
|
48346
49253
|
maxReads: external_exports.number().default(100),
|
|
48347
49254
|
concurrency: external_exports.number().default(5)
|
|
48348
49255
|
})).mutation(async ({ ctx, input }) => {
|
|
48349
|
-
const col = ctx.db.collection(ctx.collection);
|
|
49256
|
+
const col = ctx.db.collection(resolveCollectionPath(ctx.collection, input.scope));
|
|
48350
49257
|
let totalReads = 0;
|
|
48351
49258
|
let truncated = false;
|
|
48352
49259
|
let sourceUids = [input.startUid];
|
|
@@ -48433,12 +49340,13 @@ var appRouter = t.router({
|
|
|
48433
49340
|
}),
|
|
48434
49341
|
// --- Search ---
|
|
48435
49342
|
search: publicProcedure.input(external_exports.object({
|
|
49343
|
+
scope: scopeSchema,
|
|
48436
49344
|
q: external_exports.string(),
|
|
48437
49345
|
limit: external_exports.number().min(1).max(50).default(20)
|
|
48438
49346
|
})).query(async ({ ctx, input }) => {
|
|
48439
49347
|
const q = input.q.trim();
|
|
48440
49348
|
if (!q) return { results: [] };
|
|
48441
|
-
const col = ctx.db.collection(ctx.collection);
|
|
49349
|
+
const col = ctx.db.collection(resolveCollectionPath(ctx.collection, input.scope));
|
|
48442
49350
|
const strippedQ = stripTypePrefix(q);
|
|
48443
49351
|
const nodeDoc = await col.doc(strippedQ).get();
|
|
48444
49352
|
const results = [];
|
|
@@ -48462,8 +49370,8 @@ var appRouter = t.router({
|
|
|
48462
49370
|
return { results: results.slice(0, input.limit) };
|
|
48463
49371
|
}),
|
|
48464
49372
|
// --- Check Node Exists ---
|
|
48465
|
-
checkNode: publicProcedure.input(external_exports.object({ uid: external_exports.string().min(1) })).query(async ({ ctx, input }) => {
|
|
48466
|
-
const doc = await ctx.db.collection(ctx.collection).doc(stripTypePrefix(input.uid)).get();
|
|
49373
|
+
checkNode: publicProcedure.input(external_exports.object({ scope: scopeSchema, uid: external_exports.string().min(1) })).query(async ({ ctx, input }) => {
|
|
49374
|
+
const doc = await ctx.db.collection(resolveCollectionPath(ctx.collection, input.scope)).doc(stripTypePrefix(input.uid)).get();
|
|
48467
49375
|
if (!doc.exists) return { exists: false, node: null };
|
|
48468
49376
|
const data = serializeRecord(doc.data());
|
|
48469
49377
|
return {
|
|
@@ -48473,23 +49381,26 @@ var appRouter = t.router({
|
|
|
48473
49381
|
}),
|
|
48474
49382
|
// --- Check Edge Exists ---
|
|
48475
49383
|
checkEdge: publicProcedure.input(external_exports.object({
|
|
49384
|
+
scope: scopeSchema,
|
|
48476
49385
|
aUid: external_exports.string().min(1),
|
|
48477
49386
|
axbType: external_exports.string().min(1),
|
|
48478
49387
|
bUid: external_exports.string().min(1)
|
|
48479
49388
|
})).query(async ({ ctx, input }) => {
|
|
48480
49389
|
const docId = computeEdgeDocId(input.aUid, input.axbType, input.bUid);
|
|
48481
|
-
const doc = await ctx.db.collection(ctx.collection).doc(docId).get();
|
|
49390
|
+
const doc = await ctx.db.collection(resolveCollectionPath(ctx.collection, input.scope)).doc(docId).get();
|
|
48482
49391
|
return { exists: doc.exists };
|
|
48483
49392
|
}),
|
|
48484
49393
|
// --- Write: Create Node ---
|
|
48485
49394
|
createNode: writeProcedure.input(external_exports.object({
|
|
49395
|
+
scope: scopeSchema,
|
|
48486
49396
|
aType: external_exports.string(),
|
|
48487
49397
|
uid: external_exports.string().optional(),
|
|
48488
49398
|
data: external_exports.record(external_exports.string(), external_exports.unknown())
|
|
48489
49399
|
})).mutation(async ({ ctx, input }) => {
|
|
48490
49400
|
try {
|
|
49401
|
+
const client = getScopedClient(ctx.graphClient, input.scope);
|
|
48491
49402
|
const nodeUid = input.uid || generateId();
|
|
48492
|
-
await
|
|
49403
|
+
await client.putNode(input.aType, nodeUid, input.data);
|
|
48493
49404
|
return { success: true, uid: nodeUid };
|
|
48494
49405
|
} catch (err) {
|
|
48495
49406
|
if (err instanceof ValidationError || err instanceof RegistryViolationError) {
|
|
@@ -48500,15 +49411,17 @@ var appRouter = t.router({
|
|
|
48500
49411
|
}),
|
|
48501
49412
|
// --- Write: Update Node ---
|
|
48502
49413
|
updateNode: writeProcedure.input(external_exports.object({
|
|
49414
|
+
scope: scopeSchema,
|
|
48503
49415
|
uid: external_exports.string(),
|
|
48504
49416
|
data: external_exports.record(external_exports.string(), external_exports.unknown())
|
|
48505
49417
|
})).mutation(async ({ ctx, input }) => {
|
|
48506
49418
|
try {
|
|
48507
|
-
const
|
|
49419
|
+
const client = getScopedClient(ctx.graphClient, input.scope);
|
|
49420
|
+
const existing = await client.getNode(input.uid);
|
|
48508
49421
|
if (!existing) {
|
|
48509
49422
|
throw new TRPCError({ code: "NOT_FOUND", message: "Node not found" });
|
|
48510
49423
|
}
|
|
48511
|
-
await
|
|
49424
|
+
await client.putNode(existing.aType, input.uid, input.data);
|
|
48512
49425
|
return { success: true };
|
|
48513
49426
|
} catch (err) {
|
|
48514
49427
|
if (err instanceof TRPCError) throw err;
|
|
@@ -48519,13 +49432,15 @@ var appRouter = t.router({
|
|
|
48519
49432
|
}
|
|
48520
49433
|
}),
|
|
48521
49434
|
// --- Write: Delete Node ---
|
|
48522
|
-
deleteNode: writeProcedure.input(external_exports.object({ uid: external_exports.string() })).mutation(async ({ ctx, input }) => {
|
|
48523
|
-
|
|
49435
|
+
deleteNode: writeProcedure.input(external_exports.object({ scope: scopeSchema, uid: external_exports.string() })).mutation(async ({ ctx, input }) => {
|
|
49436
|
+
const client = getScopedClient(ctx.graphClient, input.scope);
|
|
49437
|
+
await client.removeNode(input.uid);
|
|
48524
49438
|
return { success: true };
|
|
48525
49439
|
}),
|
|
48526
49440
|
// --- Write: Delete Node + Cascade (all edges) ---
|
|
48527
|
-
deleteNodeCascade: writeProcedure.input(external_exports.object({ uid: external_exports.string() })).mutation(async ({ ctx, input }) => {
|
|
48528
|
-
const
|
|
49441
|
+
deleteNodeCascade: writeProcedure.input(external_exports.object({ scope: scopeSchema, uid: external_exports.string() })).mutation(async ({ ctx, input }) => {
|
|
49442
|
+
const client = getScopedClient(ctx.graphClient, input.scope);
|
|
49443
|
+
const result = await client.removeNodeCascade(input.uid);
|
|
48529
49444
|
return {
|
|
48530
49445
|
success: result.nodeDeleted,
|
|
48531
49446
|
edgesDeleted: result.edgesDeleted,
|
|
@@ -48539,6 +49454,7 @@ var appRouter = t.router({
|
|
|
48539
49454
|
}),
|
|
48540
49455
|
// --- Write: Create Edge ---
|
|
48541
49456
|
createEdge: writeProcedure.input(external_exports.object({
|
|
49457
|
+
scope: scopeSchema,
|
|
48542
49458
|
aType: external_exports.string(),
|
|
48543
49459
|
aUid: external_exports.string(),
|
|
48544
49460
|
axbType: external_exports.string(),
|
|
@@ -48547,7 +49463,8 @@ var appRouter = t.router({
|
|
|
48547
49463
|
data: external_exports.record(external_exports.string(), external_exports.unknown())
|
|
48548
49464
|
})).mutation(async ({ ctx, input }) => {
|
|
48549
49465
|
try {
|
|
48550
|
-
|
|
49466
|
+
const client = getScopedClient(ctx.graphClient, input.scope);
|
|
49467
|
+
await client.putEdge(
|
|
48551
49468
|
input.aType,
|
|
48552
49469
|
input.aUid,
|
|
48553
49470
|
input.axbType,
|
|
@@ -48565,6 +49482,7 @@ var appRouter = t.router({
|
|
|
48565
49482
|
}),
|
|
48566
49483
|
// --- Write: Create Edge + Target Node atomically ---
|
|
48567
49484
|
createEdgeWithNode: writeProcedure.input(external_exports.object({
|
|
49485
|
+
scope: scopeSchema,
|
|
48568
49486
|
aType: external_exports.string(),
|
|
48569
49487
|
axbType: external_exports.string(),
|
|
48570
49488
|
bType: external_exports.string(),
|
|
@@ -48578,13 +49496,14 @@ var appRouter = t.router({
|
|
|
48578
49496
|
nodeData: external_exports.record(external_exports.string(), external_exports.unknown())
|
|
48579
49497
|
})).mutation(async ({ ctx, input }) => {
|
|
48580
49498
|
try {
|
|
49499
|
+
const client = getScopedClient(ctx.graphClient, input.scope);
|
|
48581
49500
|
const newUid = input.newNodeUid || generateId();
|
|
48582
49501
|
const newNodeType = input.newNodeSide === "b" ? input.bType : input.aType;
|
|
48583
49502
|
const aUid = input.newNodeSide === "a" ? newUid : input.existingUid;
|
|
48584
49503
|
const bUid = input.newNodeSide === "b" ? newUid : input.existingUid;
|
|
48585
49504
|
const [existingNode, existingEdge] = await Promise.all([
|
|
48586
|
-
|
|
48587
|
-
|
|
49505
|
+
client.getNode(newUid),
|
|
49506
|
+
client.getEdge(aUid, input.axbType, bUid)
|
|
48588
49507
|
]);
|
|
48589
49508
|
if (existingNode && existingEdge) {
|
|
48590
49509
|
throw new TRPCError({
|
|
@@ -48592,7 +49511,7 @@ var appRouter = t.router({
|
|
|
48592
49511
|
message: `Both node "${newUid}" and edge ${aUid} \u2014[${input.axbType}]\u2192 ${bUid} already exist.`
|
|
48593
49512
|
});
|
|
48594
49513
|
}
|
|
48595
|
-
await
|
|
49514
|
+
await client.runTransaction(async (tx) => {
|
|
48596
49515
|
if (!existingNode) {
|
|
48597
49516
|
await tx.putNode(newNodeType, newUid, input.nodeData);
|
|
48598
49517
|
}
|
|
@@ -48616,15 +49535,18 @@ var appRouter = t.router({
|
|
|
48616
49535
|
}),
|
|
48617
49536
|
// --- Write: Delete Edge ---
|
|
48618
49537
|
deleteEdge: writeProcedure.input(external_exports.object({
|
|
49538
|
+
scope: scopeSchema,
|
|
48619
49539
|
aUid: external_exports.string(),
|
|
48620
49540
|
axbType: external_exports.string(),
|
|
48621
49541
|
bUid: external_exports.string()
|
|
48622
49542
|
})).mutation(async ({ ctx, input }) => {
|
|
48623
|
-
|
|
49543
|
+
const client = getScopedClient(ctx.graphClient, input.scope);
|
|
49544
|
+
await client.removeEdge(input.aUid, input.axbType, input.bUid);
|
|
48624
49545
|
return { success: true };
|
|
48625
49546
|
}),
|
|
48626
49547
|
// --- Write: Bulk Delete Edges (by query) ---
|
|
48627
49548
|
bulkDeleteEdges: writeProcedure.input(external_exports.object({
|
|
49549
|
+
scope: scopeSchema,
|
|
48628
49550
|
aUid: external_exports.string().optional(),
|
|
48629
49551
|
axbType: external_exports.string().optional(),
|
|
48630
49552
|
bUid: external_exports.string().optional(),
|
|
@@ -48636,12 +49558,13 @@ var appRouter = t.router({
|
|
|
48636
49558
|
value: external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean()])
|
|
48637
49559
|
})).optional()
|
|
48638
49560
|
})).mutation(async ({ ctx, input }) => {
|
|
48639
|
-
const
|
|
49561
|
+
const client = getScopedClient(ctx.graphClient, input.scope);
|
|
49562
|
+
const { where: whereClauses, scope: _scope, ...params } = input;
|
|
48640
49563
|
const findParams = { ...params };
|
|
48641
49564
|
if (whereClauses && whereClauses.length > 0) {
|
|
48642
49565
|
findParams.where = whereClauses;
|
|
48643
49566
|
}
|
|
48644
|
-
const result = await
|
|
49567
|
+
const result = await client.bulkRemoveEdges(findParams);
|
|
48645
49568
|
return {
|
|
48646
49569
|
success: true,
|
|
48647
49570
|
deleted: result.deleted,
|
|
@@ -48655,18 +49578,132 @@ var appRouter = t.router({
|
|
|
48655
49578
|
}),
|
|
48656
49579
|
// --- Write: Delete specific edges by ID ---
|
|
48657
49580
|
deleteEdgesBatch: writeProcedure.input(external_exports.object({
|
|
49581
|
+
scope: scopeSchema,
|
|
48658
49582
|
edges: external_exports.array(external_exports.object({
|
|
48659
49583
|
aUid: external_exports.string(),
|
|
48660
49584
|
axbType: external_exports.string(),
|
|
48661
49585
|
bUid: external_exports.string()
|
|
48662
49586
|
})).min(1).max(500)
|
|
48663
49587
|
})).mutation(async ({ ctx, input }) => {
|
|
48664
|
-
const
|
|
49588
|
+
const client = getScopedClient(ctx.graphClient, input.scope);
|
|
49589
|
+
const batch = client.batch();
|
|
48665
49590
|
for (const e of input.edges) {
|
|
48666
49591
|
await batch.removeEdge(e.aUid, e.axbType, e.bUid);
|
|
48667
49592
|
}
|
|
48668
49593
|
await batch.commit();
|
|
48669
49594
|
return { success: true, deleted: input.edges.length };
|
|
49595
|
+
}),
|
|
49596
|
+
// --- Plain Collection Procedures ---
|
|
49597
|
+
getCollectionDocs: publicProcedure.input(external_exports.object({
|
|
49598
|
+
collectionName: external_exports.string(),
|
|
49599
|
+
params: external_exports.record(external_exports.string(), external_exports.string()).optional(),
|
|
49600
|
+
cursor: external_exports.string().optional(),
|
|
49601
|
+
limit: external_exports.number().int().min(1).max(100).default(50)
|
|
49602
|
+
})).query(async ({ ctx, input }) => {
|
|
49603
|
+
const def = getCollectionDef(ctx, input.collectionName);
|
|
49604
|
+
const colPath = substitutePathTemplate(def.path, input.params ?? {});
|
|
49605
|
+
const col = ctx.db.collection(colPath);
|
|
49606
|
+
let query = col;
|
|
49607
|
+
if (def.typeField && def.typeValue !== void 0) {
|
|
49608
|
+
query = query.where(def.typeField, "==", def.typeValue);
|
|
49609
|
+
}
|
|
49610
|
+
if (def.defaultOrderBy) {
|
|
49611
|
+
query = query.orderBy(def.defaultOrderBy.field, def.defaultOrderBy.direction);
|
|
49612
|
+
} else {
|
|
49613
|
+
query = query.orderBy(FieldPath.documentId());
|
|
49614
|
+
}
|
|
49615
|
+
query = query.limit(input.limit + 1);
|
|
49616
|
+
if (input.cursor) {
|
|
49617
|
+
const cursorSnap = await col.doc(input.cursor).get();
|
|
49618
|
+
if (!cursorSnap.exists) {
|
|
49619
|
+
throw new TRPCError({
|
|
49620
|
+
code: "NOT_FOUND",
|
|
49621
|
+
message: `Cursor document "${input.cursor}" no longer exists. Refresh to start from the first page.`
|
|
49622
|
+
});
|
|
49623
|
+
}
|
|
49624
|
+
query = query.startAfter(cursorSnap);
|
|
49625
|
+
}
|
|
49626
|
+
const snapshot = await query.get();
|
|
49627
|
+
const docs = snapshot.docs.slice(0, input.limit);
|
|
49628
|
+
const hasMore = snapshot.docs.length > input.limit;
|
|
49629
|
+
const documents = docs.map((doc) => ({
|
|
49630
|
+
id: doc.id,
|
|
49631
|
+
data: serializeRecord(doc.data())
|
|
49632
|
+
}));
|
|
49633
|
+
const nextCursor = hasMore && docs.length > 0 ? docs[docs.length - 1].id : null;
|
|
49634
|
+
return {
|
|
49635
|
+
documents,
|
|
49636
|
+
hasMore,
|
|
49637
|
+
nextCursor
|
|
49638
|
+
};
|
|
49639
|
+
}),
|
|
49640
|
+
getCollectionDoc: publicProcedure.input(external_exports.object({
|
|
49641
|
+
collectionName: external_exports.string(),
|
|
49642
|
+
params: external_exports.record(external_exports.string(), external_exports.string()).optional(),
|
|
49643
|
+
docId: external_exports.string()
|
|
49644
|
+
})).query(async ({ ctx, input }) => {
|
|
49645
|
+
const def = getCollectionDef(ctx, input.collectionName);
|
|
49646
|
+
const colPath = substitutePathTemplate(def.path, input.params ?? {});
|
|
49647
|
+
const snap = await ctx.db.collection(colPath).doc(input.docId).get();
|
|
49648
|
+
if (!snap.exists) {
|
|
49649
|
+
throw new TRPCError({ code: "NOT_FOUND", message: `Document "${input.docId}" not found.` });
|
|
49650
|
+
}
|
|
49651
|
+
const docData = snap.data();
|
|
49652
|
+
if (def.typeField && def.typeValue !== void 0 && docData[def.typeField] !== def.typeValue) {
|
|
49653
|
+
throw new TRPCError({ code: "NOT_FOUND", message: `Document "${input.docId}" not found.` });
|
|
49654
|
+
}
|
|
49655
|
+
return { id: snap.id, data: serializeRecord(docData) };
|
|
49656
|
+
}),
|
|
49657
|
+
createCollectionDoc: writeProcedure.input(external_exports.object({
|
|
49658
|
+
collectionName: external_exports.string(),
|
|
49659
|
+
params: external_exports.record(external_exports.string(), external_exports.string()).optional(),
|
|
49660
|
+
data: external_exports.record(external_exports.string(), external_exports.unknown())
|
|
49661
|
+
})).mutation(async ({ ctx, input }) => {
|
|
49662
|
+
const def = getCollectionDef(ctx, input.collectionName);
|
|
49663
|
+
const colPath = substitutePathTemplate(def.path, input.params ?? {});
|
|
49664
|
+
const docData = { ...input.data };
|
|
49665
|
+
if (def.typeField && def.typeValue !== void 0) {
|
|
49666
|
+
docData[def.typeField] = def.typeValue;
|
|
49667
|
+
}
|
|
49668
|
+
const docRef = await ctx.db.collection(colPath).add(docData);
|
|
49669
|
+
return { success: true, id: docRef.id };
|
|
49670
|
+
}),
|
|
49671
|
+
updateCollectionDoc: writeProcedure.input(external_exports.object({
|
|
49672
|
+
collectionName: external_exports.string(),
|
|
49673
|
+
params: external_exports.record(external_exports.string(), external_exports.string()).optional(),
|
|
49674
|
+
docId: external_exports.string(),
|
|
49675
|
+
data: external_exports.record(external_exports.string(), external_exports.unknown())
|
|
49676
|
+
})).mutation(async ({ ctx, input }) => {
|
|
49677
|
+
const def = getCollectionDef(ctx, input.collectionName);
|
|
49678
|
+
const colPath = substitutePathTemplate(def.path, input.params ?? {});
|
|
49679
|
+
if (def.typeField && def.typeValue !== void 0) {
|
|
49680
|
+
const snap = await ctx.db.collection(colPath).doc(input.docId).get();
|
|
49681
|
+
if (!snap.exists || snap.data()[def.typeField] !== def.typeValue) {
|
|
49682
|
+
throw new TRPCError({ code: "NOT_FOUND", message: `Document "${input.docId}" not found.` });
|
|
49683
|
+
}
|
|
49684
|
+
}
|
|
49685
|
+
const docData = { ...input.data };
|
|
49686
|
+
if (def.typeField && def.typeValue !== void 0) {
|
|
49687
|
+
docData[def.typeField] = def.typeValue;
|
|
49688
|
+
}
|
|
49689
|
+
await ctx.db.collection(colPath).doc(input.docId).set(docData, { merge: true });
|
|
49690
|
+
return { success: true };
|
|
49691
|
+
}),
|
|
49692
|
+
deleteCollectionDoc: writeProcedure.input(external_exports.object({
|
|
49693
|
+
collectionName: external_exports.string(),
|
|
49694
|
+
params: external_exports.record(external_exports.string(), external_exports.string()).optional(),
|
|
49695
|
+
docId: external_exports.string()
|
|
49696
|
+
})).mutation(async ({ ctx, input }) => {
|
|
49697
|
+
const def = getCollectionDef(ctx, input.collectionName);
|
|
49698
|
+
const colPath = substitutePathTemplate(def.path, input.params ?? {});
|
|
49699
|
+
if (def.typeField && def.typeValue !== void 0) {
|
|
49700
|
+
const snap = await ctx.db.collection(colPath).doc(input.docId).get();
|
|
49701
|
+
if (!snap.exists || snap.data()[def.typeField] !== def.typeValue) {
|
|
49702
|
+
throw new TRPCError({ code: "NOT_FOUND", message: `Document "${input.docId}" not found.` });
|
|
49703
|
+
}
|
|
49704
|
+
}
|
|
49705
|
+
await ctx.db.collection(colPath).doc(input.docId).delete();
|
|
49706
|
+
return { success: true };
|
|
48670
49707
|
})
|
|
48671
49708
|
});
|
|
48672
49709
|
|
|
@@ -49158,7 +50195,7 @@ ${elements.join("\n")}`;
|
|
|
49158
50195
|
}
|
|
49159
50196
|
|
|
49160
50197
|
// editor/server/index.ts
|
|
49161
|
-
var __dirname =
|
|
50198
|
+
var __dirname = path4.dirname(fileURLToPath(import.meta.url));
|
|
49162
50199
|
function parseArgs() {
|
|
49163
50200
|
const args = process.argv.slice(2);
|
|
49164
50201
|
let configPath;
|
|
@@ -49218,6 +50255,8 @@ var resolvedChatEnabled = false;
|
|
|
49218
50255
|
var resolvedChatModel = "sonnet";
|
|
49219
50256
|
var resolvedChatMaxConcurrency = 2;
|
|
49220
50257
|
var viewDefaultsData = null;
|
|
50258
|
+
var resolvedCollectionDefs = [];
|
|
50259
|
+
var collectionViewRegistry = {};
|
|
49221
50260
|
var resolvedRegistryMode;
|
|
49222
50261
|
var db;
|
|
49223
50262
|
var state = {
|
|
@@ -49240,7 +50279,7 @@ async function init() {
|
|
|
49240
50279
|
const fileConfig = loaded?.config ?? {};
|
|
49241
50280
|
if (loaded) {
|
|
49242
50281
|
resolvedConfigPath = loaded.configPath;
|
|
49243
|
-
console.log(` Config loaded from ${
|
|
50282
|
+
console.log(` Config loaded from ${path4.relative(process.cwd(), loaded.configPath)}`);
|
|
49244
50283
|
}
|
|
49245
50284
|
resolvedProject = cliArgs.project ?? fileConfig.project;
|
|
49246
50285
|
resolvedCollection = cliArgs.collection ?? fileConfig.collection ?? "graph";
|
|
@@ -49363,6 +50402,11 @@ async function reloadDynamicSchema() {
|
|
|
49363
50402
|
async function initEntitiesMode(fileConfig) {
|
|
49364
50403
|
console.log(` Discovering entities from ${resolvedEntitiesPath}...`);
|
|
49365
50404
|
const { result: discovery, warnings } = discoverEntities(resolvedEntitiesPath);
|
|
50405
|
+
resolvedCollectionDefs = discoverCollections(resolvedEntitiesPath);
|
|
50406
|
+
if (resolvedCollectionDefs.length > 0) {
|
|
50407
|
+
console.log(` Collections loaded: ${resolvedCollectionDefs.length} collection(s)`);
|
|
50408
|
+
}
|
|
50409
|
+
collectionViewRegistry = await buildCollectionViewRegistry(resolvedCollectionDefs);
|
|
49366
50410
|
if (warnings.length > 0) {
|
|
49367
50411
|
for (const w of warnings) {
|
|
49368
50412
|
console.log(` [warn] ${w.message}`);
|
|
@@ -49386,8 +50430,11 @@ async function initEntitiesMode(fileConfig) {
|
|
|
49386
50430
|
const nodeViewCount = Object.values(state.viewRegistry.nodes).reduce((sum, m) => sum + m.views.length, 0);
|
|
49387
50431
|
const edgeViewCount = Object.values(state.viewRegistry.edges).reduce((sum, m) => sum + m.views.length, 0);
|
|
49388
50432
|
console.log(` Views loaded: ${nodeViewCount} node views, ${edgeViewCount} edge views`);
|
|
50433
|
+
}
|
|
50434
|
+
const colViewPaths = resolvedCollectionDefs.filter((c) => c.viewsPath).map((c) => ({ name: c.name, absPath: path4.resolve(c.viewsPath) }));
|
|
50435
|
+
if (state.viewRegistry || colViewPaths.length > 0) {
|
|
49389
50436
|
console.log(` Bundling views for browser...`);
|
|
49390
|
-
state.viewBundle = await bundleEntityViews(discovery);
|
|
50437
|
+
state.viewBundle = await bundleEntityViews(discovery, colViewPaths);
|
|
49391
50438
|
if (state.viewBundle) {
|
|
49392
50439
|
console.log(` Views bundled (${(state.viewBundle.code.length / 1024).toFixed(1)} KB)`);
|
|
49393
50440
|
}
|
|
@@ -49448,7 +50495,9 @@ async function start() {
|
|
|
49448
50495
|
projectId: resolvedProject,
|
|
49449
50496
|
viewDefaults: viewDefaultsData,
|
|
49450
50497
|
chatEnabled: resolvedChatEnabled,
|
|
49451
|
-
chatModel: resolvedChatModel
|
|
50498
|
+
chatModel: resolvedChatModel,
|
|
50499
|
+
collectionDefs: resolvedCollectionDefs,
|
|
50500
|
+
collectionViewRegistry
|
|
49452
50501
|
},
|
|
49453
50502
|
state,
|
|
49454
50503
|
resolvedRegistryMode ? reloadDynamicSchema : void 0
|
|
@@ -49464,17 +50513,17 @@ async function start() {
|
|
|
49464
50513
|
}
|
|
49465
50514
|
const isProduction = process.env.NODE_ENV === "production";
|
|
49466
50515
|
if (isProduction) {
|
|
49467
|
-
const clientDir =
|
|
50516
|
+
const clientDir = path4.join(__dirname, "..", "client");
|
|
49468
50517
|
app.use(import_express.default.static(clientDir));
|
|
49469
50518
|
app.get("*", (_req, res) => {
|
|
49470
|
-
res.sendFile(
|
|
50519
|
+
res.sendFile(path4.join(clientDir, "index.html"));
|
|
49471
50520
|
});
|
|
49472
50521
|
}
|
|
49473
50522
|
const server = app.listen(resolvedPort, () => {
|
|
49474
50523
|
console.log("");
|
|
49475
50524
|
console.log(" Firegraph Editor");
|
|
49476
50525
|
if (resolvedConfigPath) {
|
|
49477
|
-
console.log(` Config: ${
|
|
50526
|
+
console.log(` Config: ${path4.relative(process.cwd(), resolvedConfigPath)}`);
|
|
49478
50527
|
}
|
|
49479
50528
|
console.log(` Project: ${resolvedProject || "(auto-detected via ADC)"}`);
|
|
49480
50529
|
console.log(` Collection: ${resolvedCollection}`);
|