@malloy-publisher/server 0.0.197-dev → 0.0.197
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.docker.md +88 -20
- package/README.md +15 -0
- package/build.ts +16 -0
- package/dist/app/api-doc.yaml +20 -3
- package/dist/app/assets/EnvironmentPage-BVkQH_xQ.js +1 -0
- package/dist/app/assets/HomePage-BgH9UkjK.js +1 -0
- package/dist/app/assets/MainPage-DiBxABem.js +2 -0
- package/dist/app/assets/ModelPage-oS70fj83.js +1 -0
- package/dist/app/assets/PackagePage-F_qLDAdv.js +1 -0
- package/dist/app/assets/RouteError-WqpffppN.js +1 -0
- package/dist/app/assets/WorkbookPage-_YmC-ebR.js +1 -0
- package/dist/app/assets/{core-w79IMXAG.es-Bd0UlzOL.js → core-B8L9xCYT.es-BcRLJTnC.js} +14 -14
- package/dist/app/assets/index-BMViiwtJ.js +451 -0
- package/dist/app/assets/{index-C513UodQ.js → index-C3XPaTaS.js} +15 -15
- package/dist/app/assets/index-rg8Ok8nl.js +1803 -0
- package/dist/app/assets/{index.umd-BMeMPq_9.js → index.umd-CCAfKkxY.js} +1 -1
- package/dist/app/index.html +2 -3
- package/dist/default-publisher.config.json +23 -0
- package/dist/instrumentation.mjs +1 -3
- package/dist/server.mjs +958 -177
- package/package.json +11 -12
- package/publisher.config.example.bigquery.json +33 -0
- package/publisher.config.example.duckdb.json +23 -0
- package/publisher.config.json +1 -11
- package/src/config.spec.ts +225 -0
- package/src/config.ts +96 -2
- package/src/controller/connection.controller.ts +1 -1
- package/src/default-publisher.config.json +23 -0
- package/src/errors.spec.ts +42 -0
- package/src/errors.ts +8 -0
- package/src/health.ts +26 -0
- package/src/logger.ts +1 -3
- package/src/pg_helpers.spec.ts +226 -0
- package/src/pg_helpers.ts +129 -0
- package/src/server-old.ts +1119 -0
- package/src/server.ts +36 -0
- package/src/service/connection.spec.ts +6 -4
- package/src/service/connection.ts +8 -3
- package/src/service/connection_config.ts +2 -2
- package/src/service/environment.ts +53 -25
- package/src/service/environment_store.spec.ts +19 -0
- package/src/service/environment_store.ts +21 -2
- package/src/service/package.ts +4 -3
- package/src/storage/StorageManager.ts +71 -11
- package/src/storage/duckdb/schema.ts +41 -0
- package/src/utils.ts +11 -0
- package/tests/harness/rest_e2e.ts +2 -2
- package/tests/integration/legacy_routes/legacy_routes.integration.spec.ts +259 -0
- package/tests/unit/duckdb/attached_databases.test.ts +5 -5
- package/tests/unit/duckdb/legacy_schema_migration.test.ts +194 -0
- package/tests/unit/storage/StorageManager.test.ts +166 -0
- package/dist/app/assets/EnvironmentPage-1j6QDWAy.js +0 -1
- package/dist/app/assets/HomePage-DMop21VG.js +0 -1
- package/dist/app/assets/MainPage-BbE8ETz1.js +0 -2
- package/dist/app/assets/ModelPage-D2jvfe3t.js +0 -1
- package/dist/app/assets/PackagePage-BbnhGoD3.js +0 -1
- package/dist/app/assets/RouteError-D3LGEZ3i.js +0 -1
- package/dist/app/assets/WorkbookPage-DttVIj4u.js +0 -1
- package/dist/app/assets/index-5K9YjIxF.js +0 -456
- package/dist/app/assets/index-DIgzgp69.js +0 -1742
package/dist/server.mjs
CHANGED
|
@@ -199378,14 +199378,14 @@ var require_brace_expansion = __commonJS((exports, module) => {
|
|
|
199378
199378
|
var require_minimatch = __commonJS((exports, module) => {
|
|
199379
199379
|
module.exports = minimatch;
|
|
199380
199380
|
minimatch.Minimatch = Minimatch;
|
|
199381
|
-
var
|
|
199381
|
+
var path7 = function() {
|
|
199382
199382
|
try {
|
|
199383
199383
|
return __require("path");
|
|
199384
199384
|
} catch (e) {}
|
|
199385
199385
|
}() || {
|
|
199386
199386
|
sep: "/"
|
|
199387
199387
|
};
|
|
199388
|
-
minimatch.sep =
|
|
199388
|
+
minimatch.sep = path7.sep;
|
|
199389
199389
|
var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {};
|
|
199390
199390
|
var expand = require_brace_expansion();
|
|
199391
199391
|
var plTypes = {
|
|
@@ -199476,8 +199476,8 @@ var require_minimatch = __commonJS((exports, module) => {
|
|
|
199476
199476
|
if (!options)
|
|
199477
199477
|
options = {};
|
|
199478
199478
|
pattern = pattern.trim();
|
|
199479
|
-
if (!options.allowWindowsEscape &&
|
|
199480
|
-
pattern = pattern.split(
|
|
199479
|
+
if (!options.allowWindowsEscape && path7.sep !== "/") {
|
|
199480
|
+
pattern = pattern.split(path7.sep).join("/");
|
|
199481
199481
|
}
|
|
199482
199482
|
this.options = options;
|
|
199483
199483
|
this.set = [];
|
|
@@ -199854,8 +199854,8 @@ var require_minimatch = __commonJS((exports, module) => {
|
|
|
199854
199854
|
if (f === "/" && partial)
|
|
199855
199855
|
return true;
|
|
199856
199856
|
var options = this.options;
|
|
199857
|
-
if (
|
|
199858
|
-
f = f.split(
|
|
199857
|
+
if (path7.sep !== "/") {
|
|
199858
|
+
f = f.split(path7.sep).join("/");
|
|
199859
199859
|
}
|
|
199860
199860
|
f = f.split(slashSplit);
|
|
199861
199861
|
this.debug(this.pattern, "split", f);
|
|
@@ -199966,9 +199966,9 @@ var require_recursive_readdir = __commonJS((exports, module) => {
|
|
|
199966
199966
|
var p = __require("path");
|
|
199967
199967
|
var minimatch = require_minimatch();
|
|
199968
199968
|
function patternMatcher(pattern) {
|
|
199969
|
-
return function(
|
|
199969
|
+
return function(path7, stats) {
|
|
199970
199970
|
var minimatcher = new minimatch.Minimatch(pattern, { matchBase: true });
|
|
199971
|
-
return (!minimatcher.negate || stats.isFile()) && minimatcher.match(
|
|
199971
|
+
return (!minimatcher.negate || stats.isFile()) && minimatcher.match(path7);
|
|
199972
199972
|
};
|
|
199973
199973
|
}
|
|
199974
199974
|
function toMatcherFunction(ignoreEntry) {
|
|
@@ -199978,14 +199978,14 @@ var require_recursive_readdir = __commonJS((exports, module) => {
|
|
|
199978
199978
|
return patternMatcher(ignoreEntry);
|
|
199979
199979
|
}
|
|
199980
199980
|
}
|
|
199981
|
-
function readdir3(
|
|
199981
|
+
function readdir3(path7, ignores, callback) {
|
|
199982
199982
|
if (typeof ignores == "function") {
|
|
199983
199983
|
callback = ignores;
|
|
199984
199984
|
ignores = [];
|
|
199985
199985
|
}
|
|
199986
199986
|
if (!callback) {
|
|
199987
199987
|
return new Promise(function(resolve3, reject) {
|
|
199988
|
-
readdir3(
|
|
199988
|
+
readdir3(path7, ignores || [], function(err, data) {
|
|
199989
199989
|
if (err) {
|
|
199990
199990
|
reject(err);
|
|
199991
199991
|
} else {
|
|
@@ -199996,7 +199996,7 @@ var require_recursive_readdir = __commonJS((exports, module) => {
|
|
|
199996
199996
|
}
|
|
199997
199997
|
ignores = ignores.map(toMatcherFunction);
|
|
199998
199998
|
var list = [];
|
|
199999
|
-
fs4.readdir(
|
|
199999
|
+
fs4.readdir(path7, function(err, files) {
|
|
200000
200000
|
if (err) {
|
|
200001
200001
|
return callback(err);
|
|
200002
200002
|
}
|
|
@@ -200005,7 +200005,7 @@ var require_recursive_readdir = __commonJS((exports, module) => {
|
|
|
200005
200005
|
return callback(null, list);
|
|
200006
200006
|
}
|
|
200007
200007
|
files.forEach(function(file) {
|
|
200008
|
-
var filePath = p.join(
|
|
200008
|
+
var filePath = p.join(path7, file);
|
|
200009
200009
|
fs4.stat(filePath, function(_err, stats) {
|
|
200010
200010
|
if (_err) {
|
|
200011
200011
|
return callback(_err);
|
|
@@ -200851,8 +200851,8 @@ var require_uri_all = __commonJS((exports, module) => {
|
|
|
200851
200851
|
wsComponents.secure = undefined;
|
|
200852
200852
|
}
|
|
200853
200853
|
if (wsComponents.resourceName) {
|
|
200854
|
-
var _wsComponents$resourc = wsComponents.resourceName.split("?"), _wsComponents$resourc2 = slicedToArray(_wsComponents$resourc, 2),
|
|
200855
|
-
wsComponents.path =
|
|
200854
|
+
var _wsComponents$resourc = wsComponents.resourceName.split("?"), _wsComponents$resourc2 = slicedToArray(_wsComponents$resourc, 2), path12 = _wsComponents$resourc2[0], query = _wsComponents$resourc2[1];
|
|
200855
|
+
wsComponents.path = path12 && path12 !== "/" ? path12 : undefined;
|
|
200856
200856
|
wsComponents.query = query;
|
|
200857
200857
|
wsComponents.resourceName = undefined;
|
|
200858
200858
|
}
|
|
@@ -201245,12 +201245,12 @@ var require_util13 = __commonJS((exports, module) => {
|
|
|
201245
201245
|
return "'" + escapeQuotes(str) + "'";
|
|
201246
201246
|
}
|
|
201247
201247
|
function getPathExpr(currentPath, expr, jsonPointers, isNumber2) {
|
|
201248
|
-
var
|
|
201249
|
-
return joinPaths(currentPath,
|
|
201248
|
+
var path12 = jsonPointers ? "'/' + " + expr + (isNumber2 ? "" : ".replace(/~/g, '~0').replace(/\\//g, '~1')") : isNumber2 ? "'[' + " + expr + " + ']'" : "'[\\'' + " + expr + " + '\\']'";
|
|
201249
|
+
return joinPaths(currentPath, path12);
|
|
201250
201250
|
}
|
|
201251
201251
|
function getPath(currentPath, prop, jsonPointers) {
|
|
201252
|
-
var
|
|
201253
|
-
return joinPaths(currentPath,
|
|
201252
|
+
var path12 = jsonPointers ? toQuotedString("/" + escapeJsonPointer(prop)) : toQuotedString(getProperty(prop));
|
|
201253
|
+
return joinPaths(currentPath, path12);
|
|
201254
201254
|
}
|
|
201255
201255
|
var JSON_POINTER = /^\/(?:[^~]|~0|~1)*$/;
|
|
201256
201256
|
var RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/;
|
|
@@ -207304,11 +207304,11 @@ var require_ast = __commonJS((exports, module) => {
|
|
|
207304
207304
|
helperExpression: function helperExpression(node) {
|
|
207305
207305
|
return node.type === "SubExpression" || (node.type === "MustacheStatement" || node.type === "BlockStatement") && !!(node.params && node.params.length || node.hash);
|
|
207306
207306
|
},
|
|
207307
|
-
scopedId: function scopedId(
|
|
207308
|
-
return /^\.|this\b/.test(
|
|
207307
|
+
scopedId: function scopedId(path12) {
|
|
207308
|
+
return /^\.|this\b/.test(path12.original);
|
|
207309
207309
|
},
|
|
207310
|
-
simpleId: function simpleId(
|
|
207311
|
-
return
|
|
207310
|
+
simpleId: function simpleId(path12) {
|
|
207311
|
+
return path12.parts.length === 1 && !AST.helpers.scopedId(path12) && !path12.depth;
|
|
207312
207312
|
}
|
|
207313
207313
|
}
|
|
207314
207314
|
};
|
|
@@ -208368,12 +208368,12 @@ var require_helpers3 = __commonJS((exports) => {
|
|
|
208368
208368
|
loc
|
|
208369
208369
|
};
|
|
208370
208370
|
}
|
|
208371
|
-
function prepareMustache(
|
|
208371
|
+
function prepareMustache(path12, params, hash, open2, strip, locInfo) {
|
|
208372
208372
|
var escapeFlag = open2.charAt(3) || open2.charAt(2), escaped = escapeFlag !== "{" && escapeFlag !== "&";
|
|
208373
208373
|
var decorator = /\*/.test(open2);
|
|
208374
208374
|
return {
|
|
208375
208375
|
type: decorator ? "Decorator" : "MustacheStatement",
|
|
208376
|
-
path:
|
|
208376
|
+
path: path12,
|
|
208377
208377
|
params,
|
|
208378
208378
|
hash,
|
|
208379
208379
|
escaped,
|
|
@@ -208637,9 +208637,9 @@ var require_compiler = __commonJS((exports) => {
|
|
|
208637
208637
|
},
|
|
208638
208638
|
DecoratorBlock: function DecoratorBlock(decorator) {
|
|
208639
208639
|
var program = decorator.program && this.compileProgram(decorator.program);
|
|
208640
|
-
var params = this.setupFullMustacheParams(decorator, program, undefined),
|
|
208640
|
+
var params = this.setupFullMustacheParams(decorator, program, undefined), path12 = decorator.path;
|
|
208641
208641
|
this.useDecorators = true;
|
|
208642
|
-
this.opcode("registerDecorator", params.length,
|
|
208642
|
+
this.opcode("registerDecorator", params.length, path12.original);
|
|
208643
208643
|
},
|
|
208644
208644
|
PartialStatement: function PartialStatement(partial) {
|
|
208645
208645
|
this.usePartial = true;
|
|
@@ -208702,46 +208702,46 @@ var require_compiler = __commonJS((exports) => {
|
|
|
208702
208702
|
}
|
|
208703
208703
|
},
|
|
208704
208704
|
ambiguousSexpr: function ambiguousSexpr(sexpr, program, inverse) {
|
|
208705
|
-
var
|
|
208706
|
-
this.opcode("getContext",
|
|
208705
|
+
var path12 = sexpr.path, name = path12.parts[0], isBlock = program != null || inverse != null;
|
|
208706
|
+
this.opcode("getContext", path12.depth);
|
|
208707
208707
|
this.opcode("pushProgram", program);
|
|
208708
208708
|
this.opcode("pushProgram", inverse);
|
|
208709
|
-
|
|
208710
|
-
this.accept(
|
|
208709
|
+
path12.strict = true;
|
|
208710
|
+
this.accept(path12);
|
|
208711
208711
|
this.opcode("invokeAmbiguous", name, isBlock);
|
|
208712
208712
|
},
|
|
208713
208713
|
simpleSexpr: function simpleSexpr(sexpr) {
|
|
208714
|
-
var
|
|
208715
|
-
|
|
208716
|
-
this.accept(
|
|
208714
|
+
var path12 = sexpr.path;
|
|
208715
|
+
path12.strict = true;
|
|
208716
|
+
this.accept(path12);
|
|
208717
208717
|
this.opcode("resolvePossibleLambda");
|
|
208718
208718
|
},
|
|
208719
208719
|
helperSexpr: function helperSexpr(sexpr, program, inverse) {
|
|
208720
|
-
var params = this.setupFullMustacheParams(sexpr, program, inverse),
|
|
208720
|
+
var params = this.setupFullMustacheParams(sexpr, program, inverse), path12 = sexpr.path, name = path12.parts[0];
|
|
208721
208721
|
if (this.options.knownHelpers[name]) {
|
|
208722
208722
|
this.opcode("invokeKnownHelper", params.length, name);
|
|
208723
208723
|
} else if (this.options.knownHelpersOnly) {
|
|
208724
208724
|
throw new _exception2["default"]("You specified knownHelpersOnly, but used the unknown helper " + name, sexpr);
|
|
208725
208725
|
} else {
|
|
208726
|
-
|
|
208727
|
-
|
|
208728
|
-
this.accept(
|
|
208729
|
-
this.opcode("invokeHelper", params.length,
|
|
208726
|
+
path12.strict = true;
|
|
208727
|
+
path12.falsy = true;
|
|
208728
|
+
this.accept(path12);
|
|
208729
|
+
this.opcode("invokeHelper", params.length, path12.original, _ast2["default"].helpers.simpleId(path12));
|
|
208730
208730
|
}
|
|
208731
208731
|
},
|
|
208732
|
-
PathExpression: function PathExpression(
|
|
208733
|
-
this.addDepth(
|
|
208734
|
-
this.opcode("getContext",
|
|
208735
|
-
var name =
|
|
208732
|
+
PathExpression: function PathExpression(path12) {
|
|
208733
|
+
this.addDepth(path12.depth);
|
|
208734
|
+
this.opcode("getContext", path12.depth);
|
|
208735
|
+
var name = path12.parts[0], scoped = _ast2["default"].helpers.scopedId(path12), blockParamId = !path12.depth && !scoped && this.blockParamIndex(name);
|
|
208736
208736
|
if (blockParamId) {
|
|
208737
|
-
this.opcode("lookupBlockParam", blockParamId,
|
|
208737
|
+
this.opcode("lookupBlockParam", blockParamId, path12.parts);
|
|
208738
208738
|
} else if (!name) {
|
|
208739
208739
|
this.opcode("pushContext");
|
|
208740
|
-
} else if (
|
|
208740
|
+
} else if (path12.data) {
|
|
208741
208741
|
this.options.data = true;
|
|
208742
|
-
this.opcode("lookupData",
|
|
208742
|
+
this.opcode("lookupData", path12.depth, path12.parts, path12.strict);
|
|
208743
208743
|
} else {
|
|
208744
|
-
this.opcode("lookupOnContext",
|
|
208744
|
+
this.opcode("lookupOnContext", path12.parts, path12.falsy, path12.strict, scoped);
|
|
208745
208745
|
}
|
|
208746
208746
|
},
|
|
208747
208747
|
StringLiteral: function StringLiteral(string2) {
|
|
@@ -209085,16 +209085,16 @@ var require_util14 = __commonJS((exports) => {
|
|
|
209085
209085
|
}
|
|
209086
209086
|
exports.urlGenerate = urlGenerate;
|
|
209087
209087
|
function normalize2(aPath) {
|
|
209088
|
-
var
|
|
209088
|
+
var path12 = aPath;
|
|
209089
209089
|
var url2 = urlParse(aPath);
|
|
209090
209090
|
if (url2) {
|
|
209091
209091
|
if (!url2.path) {
|
|
209092
209092
|
return aPath;
|
|
209093
209093
|
}
|
|
209094
|
-
|
|
209094
|
+
path12 = url2.path;
|
|
209095
209095
|
}
|
|
209096
|
-
var isAbsolute3 = exports.isAbsolute(
|
|
209097
|
-
var parts =
|
|
209096
|
+
var isAbsolute3 = exports.isAbsolute(path12);
|
|
209097
|
+
var parts = path12.split(/\/+/);
|
|
209098
209098
|
for (var part, up = 0, i = parts.length - 1;i >= 0; i--) {
|
|
209099
209099
|
part = parts[i];
|
|
209100
209100
|
if (part === ".") {
|
|
@@ -209111,15 +209111,15 @@ var require_util14 = __commonJS((exports) => {
|
|
|
209111
209111
|
}
|
|
209112
209112
|
}
|
|
209113
209113
|
}
|
|
209114
|
-
|
|
209115
|
-
if (
|
|
209116
|
-
|
|
209114
|
+
path12 = parts.join("/");
|
|
209115
|
+
if (path12 === "") {
|
|
209116
|
+
path12 = isAbsolute3 ? "/" : ".";
|
|
209117
209117
|
}
|
|
209118
209118
|
if (url2) {
|
|
209119
|
-
url2.path =
|
|
209119
|
+
url2.path = path12;
|
|
209120
209120
|
return urlGenerate(url2);
|
|
209121
209121
|
}
|
|
209122
|
-
return
|
|
209122
|
+
return path12;
|
|
209123
209123
|
}
|
|
209124
209124
|
exports.normalize = normalize2;
|
|
209125
209125
|
function join9(aRoot, aPath) {
|
|
@@ -211676,8 +211676,8 @@ var require_printer = __commonJS((exports) => {
|
|
|
211676
211676
|
return this.accept(sexpr.path) + " " + params + hash;
|
|
211677
211677
|
};
|
|
211678
211678
|
PrintVisitor.prototype.PathExpression = function(id) {
|
|
211679
|
-
var
|
|
211680
|
-
return (id.data ? "@" : "") + "PATH:" +
|
|
211679
|
+
var path12 = id.parts.join("/");
|
|
211680
|
+
return (id.data ? "@" : "") + "PATH:" + path12;
|
|
211681
211681
|
};
|
|
211682
211682
|
PrintVisitor.prototype.StringLiteral = function(string2) {
|
|
211683
211683
|
return '"' + string2.value + '"';
|
|
@@ -211754,9 +211754,7 @@ var getLogLevel = () => {
|
|
|
211754
211754
|
};
|
|
211755
211755
|
var logger = import_winston.default.createLogger({
|
|
211756
211756
|
level: getLogLevel(),
|
|
211757
|
-
format: isTelemetryEnabled ? import_winston.default.format.combine(import_winston.default.format.uncolorize(), import_winston.default.format.timestamp(), import_winston.default.format.
|
|
211758
|
-
fillExcept: ["message", "level", "timestamp"]
|
|
211759
|
-
}), import_winston.default.format.json()) : import_winston.default.format.combine(import_winston.default.format.colorize(), import_winston.default.format.simple()),
|
|
211757
|
+
format: isTelemetryEnabled ? import_winston.default.format.combine(import_winston.default.format.uncolorize(), import_winston.default.format.timestamp(), import_winston.default.format.errors({ stack: true }), import_winston.default.format.json()) : import_winston.default.format.combine(import_winston.default.format.colorize(), import_winston.default.format.simple()),
|
|
211760
211758
|
transports: [new import_winston.default.transports.Console]
|
|
211761
211759
|
});
|
|
211762
211760
|
function extractTraceIdFromTraceparent(traceparent) {
|
|
@@ -216941,13 +216939,13 @@ class StreamableHTTPServerTransport {
|
|
|
216941
216939
|
}
|
|
216942
216940
|
|
|
216943
216941
|
// src/server.ts
|
|
216944
|
-
var
|
|
216942
|
+
var import_body_parser2 = __toESM(require_body_parser(), 1);
|
|
216945
216943
|
var import_cors = __toESM(require_lib7(), 1);
|
|
216946
216944
|
var import_express = __toESM(require_express(), 1);
|
|
216947
216945
|
var import_http_proxy_middleware = __toESM(require_dist4(), 1);
|
|
216948
216946
|
import * as http2 from "http";
|
|
216949
|
-
import * as
|
|
216950
|
-
import { fileURLToPath as
|
|
216947
|
+
import * as path12 from "path";
|
|
216948
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
216951
216949
|
|
|
216952
216950
|
// src/controller/compile.controller.ts
|
|
216953
216951
|
class CompileController {
|
|
@@ -216998,6 +216996,8 @@ function internalErrorToHttpError(error) {
|
|
|
216998
216996
|
return httpError(400, error.message);
|
|
216999
216997
|
} else if (error instanceof ConnectionNotFoundError) {
|
|
217000
216998
|
return httpError(404, error.message);
|
|
216999
|
+
} else if (error instanceof ConnectionAuthError) {
|
|
217000
|
+
return httpError(422, error.message);
|
|
217001
217001
|
} else if (error instanceof ModelCompilationError) {
|
|
217002
217002
|
return httpError(424, error.message);
|
|
217003
217003
|
} else if (error instanceof ConnectionError) {
|
|
@@ -217064,6 +217064,12 @@ class ConnectionError extends Error {
|
|
|
217064
217064
|
}
|
|
217065
217065
|
}
|
|
217066
217066
|
|
|
217067
|
+
class ConnectionAuthError extends Error {
|
|
217068
|
+
constructor(message) {
|
|
217069
|
+
super(message);
|
|
217070
|
+
}
|
|
217071
|
+
}
|
|
217072
|
+
|
|
217067
217073
|
class ModelCompilationError extends Error {
|
|
217068
217074
|
constructor(error) {
|
|
217069
217075
|
super(error.message);
|
|
@@ -220380,6 +220386,63 @@ var {
|
|
|
220380
220386
|
import fs from "fs/promises";
|
|
220381
220387
|
import path2 from "path";
|
|
220382
220388
|
|
|
220389
|
+
// src/pg_helpers.ts
|
|
220390
|
+
function pgConnectTimeoutSeconds() {
|
|
220391
|
+
const raw = process.env.PG_CONNECT_TIMEOUT_SECONDS;
|
|
220392
|
+
if (!raw)
|
|
220393
|
+
return 5;
|
|
220394
|
+
const parsed = Number.parseInt(raw, 10);
|
|
220395
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 5;
|
|
220396
|
+
}
|
|
220397
|
+
var URI_FORM_RE = /^[a-z][a-z0-9+.-]*:\/\//i;
|
|
220398
|
+
var HAS_CONNECT_TIMEOUT_RE = /[?&\s]connect_timeout=|^connect_timeout=/;
|
|
220399
|
+
function withPgConnectTimeout(connectionString, timeout) {
|
|
220400
|
+
if (HAS_CONNECT_TIMEOUT_RE.test(connectionString)) {
|
|
220401
|
+
return connectionString;
|
|
220402
|
+
}
|
|
220403
|
+
if (URI_FORM_RE.test(connectionString)) {
|
|
220404
|
+
if (!connectionString.includes("?")) {
|
|
220405
|
+
return `${connectionString}?connect_timeout=${timeout}`;
|
|
220406
|
+
}
|
|
220407
|
+
if (connectionString.endsWith("?")) {
|
|
220408
|
+
return `${connectionString}connect_timeout=${timeout}`;
|
|
220409
|
+
}
|
|
220410
|
+
return `${connectionString}&connect_timeout=${timeout}`;
|
|
220411
|
+
}
|
|
220412
|
+
return `${connectionString} connect_timeout=${timeout}`;
|
|
220413
|
+
}
|
|
220414
|
+
function redactPgSecrets(s) {
|
|
220415
|
+
return s.replace(/password=('[^']*'|"[^"]*"|\S+)/gi, "password=***");
|
|
220416
|
+
}
|
|
220417
|
+
function classifyPgError(error, context) {
|
|
220418
|
+
if (!(error instanceof Error))
|
|
220419
|
+
return;
|
|
220420
|
+
const msg = error.message;
|
|
220421
|
+
const patterns = [
|
|
220422
|
+
/password authentication failed/i,
|
|
220423
|
+
/pg_hba\.conf/i,
|
|
220424
|
+
/role ".*" does not exist/i,
|
|
220425
|
+
/database ".*" does not exist/i,
|
|
220426
|
+
/permission denied/i
|
|
220427
|
+
];
|
|
220428
|
+
if (!patterns.some((p) => p.test(msg)))
|
|
220429
|
+
return;
|
|
220430
|
+
return new ConnectionAuthError(`${context}: ${redactPgSecrets(msg)}`);
|
|
220431
|
+
}
|
|
220432
|
+
function handlePgAttachError(error, context) {
|
|
220433
|
+
if (error instanceof Error && (error.message.includes("already exists") || error.message.includes("already attached"))) {
|
|
220434
|
+
return { action: "swallow" };
|
|
220435
|
+
}
|
|
220436
|
+
const authErr = classifyPgError(error, context);
|
|
220437
|
+
if (authErr) {
|
|
220438
|
+
return { action: "throw", error: authErr };
|
|
220439
|
+
}
|
|
220440
|
+
if (error instanceof Error) {
|
|
220441
|
+
return { action: "throw", error };
|
|
220442
|
+
}
|
|
220443
|
+
return { action: "throw", error: new Error(String(error)) };
|
|
220444
|
+
}
|
|
220445
|
+
|
|
220383
220446
|
// src/service/connection_config.ts
|
|
220384
220447
|
import { createPrivateKey } from "crypto";
|
|
220385
220448
|
import path from "path";
|
|
@@ -220563,7 +220626,7 @@ function validateConnectionShape(connection) {
|
|
|
220563
220626
|
{
|
|
220564
220627
|
const attached = connection.duckdbConnection.attachedDatabases ?? [];
|
|
220565
220628
|
if (attached.length === 0) {
|
|
220566
|
-
throw new Error(
|
|
220629
|
+
throw new Error(`DuckDB connection "${connection.name}" has no attached databases. Add at least one foreign database (BigQuery, Snowflake, Postgres, GCS, S3, Azure) to attachedDatabases, or remove this connection entirely — each package already gets a per-package DuckDB sandbox named "duckdb" automatically.`);
|
|
220567
220630
|
}
|
|
220568
220631
|
}
|
|
220569
220632
|
break;
|
|
@@ -220636,7 +220699,7 @@ function assembleEnvironmentConnections(connections = [], environmentPath = "")
|
|
|
220636
220699
|
continue;
|
|
220637
220700
|
}
|
|
220638
220701
|
if (connection.name === "duckdb") {
|
|
220639
|
-
throw new Error("
|
|
220702
|
+
throw new Error("Connection name 'duckdb' is reserved for per-package sandboxes. Choose a different name for environment-level DuckDB connections (e.g. 'shared_duckdb').");
|
|
220640
220703
|
}
|
|
220641
220704
|
processedConnections.add(connection.name);
|
|
220642
220705
|
validateDuckdbApiSurface(connection);
|
|
@@ -221005,13 +221068,13 @@ async function attachDuckLake(connection, dbName, ducklakeConfig) {
|
|
|
221005
221068
|
}
|
|
221006
221069
|
const pg = ducklakeConfig.catalog.postgresConnection;
|
|
221007
221070
|
const pgConnString = buildPgConnectionString(pg);
|
|
221008
|
-
logger.info(`pgConnString: ${pgConnString}`);
|
|
221071
|
+
logger.info(`pgConnString: ${redactPgSecrets(pgConnString)}`);
|
|
221009
221072
|
const escapedPgConnString = escapeSQL(pgConnString);
|
|
221010
|
-
logger.info(`Final escaped connection string: ${escapedPgConnString}`);
|
|
221073
|
+
logger.info(`Final escaped connection string: ${redactPgSecrets(escapedPgConnString)}`);
|
|
221011
221074
|
const escapedBucketUrl = escapeSQL(ducklakeConfig.storage.bucketUrl);
|
|
221012
221075
|
logger.info(`escapedBucketUrl: ${escapedBucketUrl}`);
|
|
221013
221076
|
const attachCommand = `ATTACH OR REPLACE 'ducklake:postgres:${escapedPgConnString}' AS ${dbName} (DATA_PATH '${escapedBucketUrl}', OVERRIDE_DATA_PATH true, READ_ONLY true);`;
|
|
221014
|
-
logger.info(`Attaching DuckLake database using command: ${attachCommand}`);
|
|
221077
|
+
logger.info(`Attaching DuckLake database using command: ${redactPgSecrets(attachCommand)}`);
|
|
221015
221078
|
try {
|
|
221016
221079
|
await connection.runSQL(attachCommand);
|
|
221017
221080
|
logger.info(`Successfully attached DuckLake database in READ_ONLY mode: ${dbName}`);
|
|
@@ -222783,7 +222846,7 @@ function validateAzureAttachedDatabases(connectionConfig) {
|
|
|
222783
222846
|
}
|
|
222784
222847
|
function validateAdminAuthoredConnection(connectionName, connectionConfig) {
|
|
222785
222848
|
if (connectionName === "duckdb" || connectionConfig.name === "duckdb") {
|
|
222786
|
-
throw new BadRequestError("
|
|
222849
|
+
throw new BadRequestError("Connection name 'duckdb' is reserved for per-package sandboxes. Choose a different name for environment-level DuckDB connections (e.g. 'shared_duckdb').");
|
|
222787
222850
|
}
|
|
222788
222851
|
try {
|
|
222789
222852
|
validateDuckdbApiSurface(connectionConfig);
|
|
@@ -224801,7 +224864,7 @@ function watch(paths, options = {}) {
|
|
|
224801
224864
|
var esm_default = { watch, FSWatcher };
|
|
224802
224865
|
|
|
224803
224866
|
// src/controller/watch-mode.controller.ts
|
|
224804
|
-
import
|
|
224867
|
+
import path11 from "path";
|
|
224805
224868
|
|
|
224806
224869
|
// src/service/environment_store.ts
|
|
224807
224870
|
var import_client_s32 = __toESM(require_dist_cjs75(), 1);
|
|
@@ -225019,7 +225082,7 @@ class Mutex {
|
|
|
225019
225082
|
// src/service/environment_store.ts
|
|
225020
225083
|
import crypto4 from "crypto";
|
|
225021
225084
|
import * as fs7 from "fs";
|
|
225022
|
-
import * as
|
|
225085
|
+
import * as path10 from "path";
|
|
225023
225086
|
|
|
225024
225087
|
// ../../node_modules/simple-git/dist/esm/index.js
|
|
225025
225088
|
var import_file_exists = __toESM(require_dist11(), 1);
|
|
@@ -229007,6 +229070,25 @@ import { Writable } from "stream";
|
|
|
229007
229070
|
// src/config.ts
|
|
229008
229071
|
import fs2 from "fs";
|
|
229009
229072
|
import path4 from "path";
|
|
229073
|
+
import { fileURLToPath } from "url";
|
|
229074
|
+
var BUNDLED_DEFAULT_CONFIG_PATH = path4.join(path4.dirname(fileURLToPath(import.meta.url)), "default-publisher.config.json");
|
|
229075
|
+
function resolvePublisherConfigPath(serverRoot) {
|
|
229076
|
+
const explicitPath = process.env.PUBLISHER_CONFIG_PATH;
|
|
229077
|
+
if (explicitPath && explicitPath.length > 0) {
|
|
229078
|
+
if (!fs2.existsSync(explicitPath)) {
|
|
229079
|
+
return null;
|
|
229080
|
+
}
|
|
229081
|
+
return { path: explicitPath, isBundledDefault: false };
|
|
229082
|
+
}
|
|
229083
|
+
const serverRootPath = path4.join(serverRoot, PUBLISHER_CONFIG_NAME);
|
|
229084
|
+
if (fs2.existsSync(serverRootPath)) {
|
|
229085
|
+
return { path: serverRootPath, isBundledDefault: false };
|
|
229086
|
+
}
|
|
229087
|
+
if (process.env.PUBLISHER_USE_BUNDLED_DEFAULT === "true" && fs2.existsSync(BUNDLED_DEFAULT_CONFIG_PATH)) {
|
|
229088
|
+
return { path: BUNDLED_DEFAULT_CONFIG_PATH, isBundledDefault: true };
|
|
229089
|
+
}
|
|
229090
|
+
return null;
|
|
229091
|
+
}
|
|
229010
229092
|
function substituteEnvVars(value) {
|
|
229011
229093
|
const envVarPattern = /\$\{([A-Z_][A-Z0-9_]*)\}/g;
|
|
229012
229094
|
return value.replace(envVarPattern, (_match, varName) => {
|
|
@@ -229034,13 +229116,20 @@ function processConfigValue(value) {
|
|
|
229034
229116
|
return value;
|
|
229035
229117
|
}
|
|
229036
229118
|
var getPublisherConfig = (serverRoot) => {
|
|
229037
|
-
const
|
|
229038
|
-
if (!
|
|
229119
|
+
const resolved = resolvePublisherConfigPath(serverRoot);
|
|
229120
|
+
if (!resolved) {
|
|
229121
|
+
if (process.env.PUBLISHER_CONFIG_PATH && process.env.PUBLISHER_CONFIG_PATH.length > 0) {
|
|
229122
|
+
logger.error(`--config path not found: ${process.env.PUBLISHER_CONFIG_PATH}. Using default empty config.`);
|
|
229123
|
+
}
|
|
229039
229124
|
return {
|
|
229040
229125
|
frozenConfig: false,
|
|
229041
229126
|
environments: []
|
|
229042
229127
|
};
|
|
229043
229128
|
}
|
|
229129
|
+
const publisherConfigPath = resolved.path;
|
|
229130
|
+
if (resolved.isBundledDefault) {
|
|
229131
|
+
logger.info(`No publisher.config.json found at ${path4.join(serverRoot, PUBLISHER_CONFIG_NAME)}; falling back to bundled DuckDB-only default. Pass --config <path> or place a config in the server root to override.`);
|
|
229132
|
+
}
|
|
229044
229133
|
let rawConfig;
|
|
229045
229134
|
try {
|
|
229046
229135
|
const fileContent = fs2.readFileSync(publisherConfigPath, "utf8");
|
|
@@ -229058,6 +229147,10 @@ var getPublisherConfig = (serverRoot) => {
|
|
|
229058
229147
|
};
|
|
229059
229148
|
}
|
|
229060
229149
|
const processedConfig = processConfigValue(rawConfig);
|
|
229150
|
+
if (processedConfig && typeof processedConfig === "object" && !("environments" in processedConfig) && "projects" in processedConfig) {
|
|
229151
|
+
logger.warn(`${PUBLISHER_CONFIG_NAME} uses deprecated "projects" key; rename to "environments".`);
|
|
229152
|
+
processedConfig.environments = processedConfig.projects;
|
|
229153
|
+
}
|
|
229061
229154
|
if (processedConfig && typeof processedConfig === "object" && "environments" in processedConfig && processedConfig.environments && typeof processedConfig.environments === "object" && !Array.isArray(processedConfig.environments)) {
|
|
229062
229155
|
logger.error(`Invalid ${PUBLISHER_CONFIG_NAME}: the "environments" field must be a JSON array. Using default empty config.`);
|
|
229063
229156
|
return {
|
|
@@ -229181,6 +229274,15 @@ function markReady() {
|
|
|
229181
229274
|
logger.error("Service is already draining - cannot mark as ready");
|
|
229182
229275
|
}
|
|
229183
229276
|
}
|
|
229277
|
+
function markDegraded() {
|
|
229278
|
+
if (operationalState !== "draining") {
|
|
229279
|
+
operationalState = "degraded";
|
|
229280
|
+
ready = false;
|
|
229281
|
+
logger.warn("Service marked as degraded; one or more environments failed to initialize. Readiness probe will fail until the config is fixed and the process restarts.");
|
|
229282
|
+
} else {
|
|
229283
|
+
logger.error("Service is already draining - cannot mark as degraded");
|
|
229284
|
+
}
|
|
229285
|
+
}
|
|
229184
229286
|
function markNotReady() {
|
|
229185
229287
|
ready = false;
|
|
229186
229288
|
logger.info("Service marked as not ready - readiness probe will fail");
|
|
@@ -230075,6 +230177,7 @@ async function initializeSchema(db, force = false) {
|
|
|
230075
230177
|
logger.info("Reinitializing database schema dropping and recreating all tables");
|
|
230076
230178
|
await dropAllTables(db);
|
|
230077
230179
|
} else {
|
|
230180
|
+
await dropLegacyProjectSchema(db);
|
|
230078
230181
|
logger.info("Creating database schema for the first time...");
|
|
230079
230182
|
}
|
|
230080
230183
|
await db.run(`
|
|
@@ -230152,6 +230255,27 @@ async function initializeSchema(db, force = false) {
|
|
|
230152
230255
|
await db.run("CREATE UNIQUE INDEX IF NOT EXISTS idx_materializations_active_key ON materializations(active_key)");
|
|
230153
230256
|
await db.run("CREATE INDEX IF NOT EXISTS idx_build_manifests_environment_package ON build_manifests(environment_id, package_name)");
|
|
230154
230257
|
}
|
|
230258
|
+
var LEGACY_TABLES_DROP_ORDER = [
|
|
230259
|
+
"build_manifests",
|
|
230260
|
+
"materializations",
|
|
230261
|
+
"packages",
|
|
230262
|
+
"connections",
|
|
230263
|
+
"projects"
|
|
230264
|
+
];
|
|
230265
|
+
async function dropLegacyProjectSchema(db) {
|
|
230266
|
+
const legacy = await db.all("SELECT name FROM sqlite_master WHERE type='table' AND name='projects'");
|
|
230267
|
+
if (!legacy || legacy.length === 0) {
|
|
230268
|
+
return;
|
|
230269
|
+
}
|
|
230270
|
+
logger.warn("Detected legacy 'projects' schema. Dropping legacy tables; existing environments/packages/connections/materializations data will be lost. Re-create them via the API after upgrade.");
|
|
230271
|
+
for (const table of LEGACY_TABLES_DROP_ORDER) {
|
|
230272
|
+
try {
|
|
230273
|
+
await db.run(`DROP TABLE IF EXISTS ${table}`);
|
|
230274
|
+
} catch (err) {
|
|
230275
|
+
logger.warn(`Failed to drop legacy table ${table}:`, err);
|
|
230276
|
+
}
|
|
230277
|
+
}
|
|
230278
|
+
}
|
|
230155
230279
|
async function dropAllTables(db) {
|
|
230156
230280
|
const tables = [
|
|
230157
230281
|
"build_manifests",
|
|
@@ -230267,6 +230391,7 @@ class StorageManager {
|
|
|
230267
230391
|
defaultManifestStore = null;
|
|
230268
230392
|
environmentManifestStores = new Map;
|
|
230269
230393
|
attachedCatalogs = new Map;
|
|
230394
|
+
duckLakeAttachMutex = new Mutex;
|
|
230270
230395
|
config;
|
|
230271
230396
|
constructor(config) {
|
|
230272
230397
|
this.config = config;
|
|
@@ -230304,12 +230429,15 @@ class StorageManager {
|
|
|
230304
230429
|
throw new Error("Storage not initialized. Call initialize() first.");
|
|
230305
230430
|
}
|
|
230306
230431
|
const key = configKey(config);
|
|
230307
|
-
|
|
230308
|
-
|
|
230309
|
-
|
|
230310
|
-
|
|
230311
|
-
|
|
230312
|
-
|
|
230432
|
+
const catalogName = await this.duckLakeAttachMutex.runExclusive(async () => {
|
|
230433
|
+
const existing = this.attachedCatalogs.get(key);
|
|
230434
|
+
if (existing)
|
|
230435
|
+
return existing;
|
|
230436
|
+
const name = catalogNameForConfig(config);
|
|
230437
|
+
await this.attachDuckLakeCatalog(config, name);
|
|
230438
|
+
this.attachedCatalogs.set(key, name);
|
|
230439
|
+
return name;
|
|
230440
|
+
});
|
|
230313
230441
|
const store = new DuckLakeManifestStore(this.duckDbConnection, catalogName, environmentName);
|
|
230314
230442
|
await store.bootstrapSchema();
|
|
230315
230443
|
this.environmentManifestStores.set(environmentId, store);
|
|
@@ -230326,9 +230454,13 @@ class StorageManager {
|
|
|
230326
230454
|
if (isPostgres) {
|
|
230327
230455
|
await connection.run("INSTALL postgres; LOAD postgres;");
|
|
230328
230456
|
}
|
|
230329
|
-
const
|
|
230457
|
+
const catalogUrl = isPostgres ? withPgConnectTimeout(config.catalogUrl, pgConnectTimeoutSeconds()) : config.catalogUrl;
|
|
230458
|
+
const escapedCatalogUrl = escapeSQL2(catalogUrl);
|
|
230330
230459
|
const escapedDataPath = escapeSQL2(config.dataPath);
|
|
230331
230460
|
const isCloudStorage = config.dataPath.startsWith("gs://") || config.dataPath.startsWith("s3://");
|
|
230461
|
+
if (isCloudStorage) {
|
|
230462
|
+
await connection.run("INSTALL httpfs; LOAD httpfs;");
|
|
230463
|
+
}
|
|
230332
230464
|
let attachCmd = `ATTACH 'ducklake:${escapedCatalogUrl}' AS ${catalogName}`;
|
|
230333
230465
|
const attachOpts = [
|
|
230334
230466
|
`DATA_PATH '${escapedDataPath}'`,
|
|
@@ -230338,8 +230470,22 @@ class StorageManager {
|
|
|
230338
230470
|
attachOpts.push("OVERRIDE_DATA_PATH true");
|
|
230339
230471
|
}
|
|
230340
230472
|
attachCmd += ` (${attachOpts.join(", ")});`;
|
|
230341
|
-
logger.info(`Attaching DuckLake manifest catalog: ${attachCmd}`);
|
|
230342
|
-
|
|
230473
|
+
logger.info(`Attaching DuckLake manifest catalog: ${redactPgSecrets(attachCmd)}`);
|
|
230474
|
+
try {
|
|
230475
|
+
await connection.run(attachCmd);
|
|
230476
|
+
} catch (error) {
|
|
230477
|
+
const outcome = handlePgAttachError(error, `DuckLake catalog credentials rejected for ${catalogName}`);
|
|
230478
|
+
if (outcome.action === "swallow") {
|
|
230479
|
+
logger.info(`DuckLake catalog ${catalogName} is already attached, skipping`);
|
|
230480
|
+
return;
|
|
230481
|
+
}
|
|
230482
|
+
if (outcome.error instanceof ConnectionAuthError) {
|
|
230483
|
+
logger.warn("DuckLake catalog credentials rejected", {
|
|
230484
|
+
catalogName
|
|
230485
|
+
});
|
|
230486
|
+
}
|
|
230487
|
+
throw outcome.error;
|
|
230488
|
+
}
|
|
230343
230489
|
}
|
|
230344
230490
|
getRepository() {
|
|
230345
230491
|
if (!this.repository) {
|
|
@@ -230378,26 +230524,30 @@ class StorageManager {
|
|
|
230378
230524
|
// src/service/environment.ts
|
|
230379
230525
|
import { MalloyError as MalloyError3, Runtime as Runtime2 } from "@malloydata/malloy";
|
|
230380
230526
|
import * as fs6 from "fs";
|
|
230381
|
-
import * as
|
|
230527
|
+
import * as path9 from "path";
|
|
230382
230528
|
|
|
230383
230529
|
// src/utils.ts
|
|
230384
230530
|
import * as fs3 from "fs";
|
|
230385
|
-
import
|
|
230531
|
+
import * as path6 from "path";
|
|
230532
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
230386
230533
|
var URL_READER = {
|
|
230387
230534
|
readURL: (url2) => {
|
|
230388
|
-
let
|
|
230535
|
+
let path7 = url2.toString();
|
|
230389
230536
|
if (url2.protocol == "file:") {
|
|
230390
|
-
|
|
230537
|
+
path7 = fileURLToPath2(url2);
|
|
230391
230538
|
}
|
|
230392
|
-
return fs3.promises.readFile(
|
|
230539
|
+
return fs3.promises.readFile(path7, "utf8");
|
|
230393
230540
|
}
|
|
230394
230541
|
};
|
|
230542
|
+
function ignoreDotfiles(file) {
|
|
230543
|
+
return path6.basename(file).startsWith(".");
|
|
230544
|
+
}
|
|
230395
230545
|
|
|
230396
230546
|
// src/service/package.ts
|
|
230397
230547
|
var import_api3 = __toESM(require_src(), 1);
|
|
230398
230548
|
var import_recursive_readdir = __toESM(require_recursive_readdir(), 1);
|
|
230399
230549
|
import * as fs5 from "fs/promises";
|
|
230400
|
-
import * as
|
|
230550
|
+
import * as path8 from "path";
|
|
230401
230551
|
import { DuckDBConnection as DuckDBConnection3 } from "@malloydata/db-duckdb";
|
|
230402
230552
|
import"@malloydata/db-duckdb/native";
|
|
230403
230553
|
import {
|
|
@@ -230425,7 +230575,7 @@ import {
|
|
|
230425
230575
|
} from "@malloydata/malloy-sql";
|
|
230426
230576
|
import * as fs4 from "fs/promises";
|
|
230427
230577
|
import { createRequire as createRequire2 } from "module";
|
|
230428
|
-
import * as
|
|
230578
|
+
import * as path7 from "path";
|
|
230429
230579
|
|
|
230430
230580
|
// src/data_styles.ts
|
|
230431
230581
|
function compileDataStyles(styles) {
|
|
@@ -231036,7 +231186,7 @@ run: ${sourceName ? sourceName + "->" : ""}${queryName}`;
|
|
|
231036
231186
|
};
|
|
231037
231187
|
}
|
|
231038
231188
|
static async getModelRuntime(packagePath, modelPath, malloyConfig, options) {
|
|
231039
|
-
const fullModelPath =
|
|
231189
|
+
const fullModelPath = path7.join(packagePath, modelPath);
|
|
231040
231190
|
try {
|
|
231041
231191
|
if (!(await fs4.stat(fullModelPath)).isFile()) {
|
|
231042
231192
|
throw new ModelNotFoundError(`${modelPath} is not a file.`);
|
|
@@ -231249,7 +231399,7 @@ run: ${sourceName ? sourceName + "->" : ""}${queryName}`;
|
|
|
231249
231399
|
return this.modelType;
|
|
231250
231400
|
}
|
|
231251
231401
|
async getFileText(packagePath) {
|
|
231252
|
-
const fullPath =
|
|
231402
|
+
const fullPath = path7.join(packagePath, this.modelPath);
|
|
231253
231403
|
try {
|
|
231254
231404
|
return await fs4.readFile(fullPath, "utf8");
|
|
231255
231405
|
} catch {
|
|
@@ -231484,17 +231634,17 @@ class Package {
|
|
|
231484
231634
|
static async getModelPaths(packagePath) {
|
|
231485
231635
|
let files = undefined;
|
|
231486
231636
|
try {
|
|
231487
|
-
files = await import_recursive_readdir.default(packagePath);
|
|
231637
|
+
files = await import_recursive_readdir.default(packagePath, [ignoreDotfiles]);
|
|
231488
231638
|
} catch (error) {
|
|
231489
231639
|
logger.error(error);
|
|
231490
231640
|
throw new PackageNotFoundError(`Package config for ${packagePath} does not exist.`);
|
|
231491
231641
|
}
|
|
231492
231642
|
return files.map((fullPath) => {
|
|
231493
|
-
return
|
|
231643
|
+
return path8.relative(packagePath, fullPath).replace(/\\/g, "/");
|
|
231494
231644
|
}).filter((modelPath) => modelPath.endsWith(MODEL_FILE_SUFFIX) || modelPath.endsWith(NOTEBOOK_FILE_SUFFIX));
|
|
231495
231645
|
}
|
|
231496
231646
|
static async validatePackageManifestExistsOrThrowError(packagePath) {
|
|
231497
|
-
const packageConfigPath =
|
|
231647
|
+
const packageConfigPath = path8.join(packagePath, PACKAGE_MANIFEST_NAME);
|
|
231498
231648
|
try {
|
|
231499
231649
|
await fs5.stat(packageConfigPath);
|
|
231500
231650
|
} catch {
|
|
@@ -231503,7 +231653,7 @@ class Package {
|
|
|
231503
231653
|
}
|
|
231504
231654
|
}
|
|
231505
231655
|
static async readPackageConfig(packagePath) {
|
|
231506
|
-
const packageConfigPath =
|
|
231656
|
+
const packageConfigPath = path8.join(packagePath, PACKAGE_MANIFEST_NAME);
|
|
231507
231657
|
const packageConfigContents = await fs5.readFile(packageConfigPath);
|
|
231508
231658
|
const packageManifest = JSON.parse(packageConfigContents.toString());
|
|
231509
231659
|
return {
|
|
@@ -231522,14 +231672,13 @@ class Package {
|
|
|
231522
231672
|
}));
|
|
231523
231673
|
}
|
|
231524
231674
|
static async getDatabasePaths(packagePath) {
|
|
231525
|
-
|
|
231526
|
-
files = await import_recursive_readdir.default(packagePath);
|
|
231675
|
+
const files = await import_recursive_readdir.default(packagePath, [ignoreDotfiles]);
|
|
231527
231676
|
return files.map((fullPath) => {
|
|
231528
|
-
return
|
|
231677
|
+
return path8.relative(packagePath, fullPath).replace(/\\/g, "/");
|
|
231529
231678
|
}).filter((modelPath) => modelPath.endsWith(".parquet") || modelPath.endsWith(".csv"));
|
|
231530
231679
|
}
|
|
231531
231680
|
static async getDatabaseInfo(packagePath, databasePath) {
|
|
231532
|
-
const fullPath =
|
|
231681
|
+
const fullPath = path8.join(packagePath, databasePath);
|
|
231533
231682
|
const runtime = new ConnectionRuntime({
|
|
231534
231683
|
urlReader: new EmptyURLReader,
|
|
231535
231684
|
connections: [new DuckDBConnection3("duckdb")]
|
|
@@ -231586,7 +231735,7 @@ class Environment {
|
|
|
231586
231735
|
async writeEnvironmentReadme(readme) {
|
|
231587
231736
|
if (readme === undefined)
|
|
231588
231737
|
return;
|
|
231589
|
-
const readmePath =
|
|
231738
|
+
const readmePath = path9.join(this.environmentPath, "README.md");
|
|
231590
231739
|
try {
|
|
231591
231740
|
await fs6.promises.writeFile(readmePath, readme, "utf-8");
|
|
231592
231741
|
logger.info(`Updated README.md for environment ${this.environmentName}`);
|
|
@@ -231633,7 +231782,7 @@ class Environment {
|
|
|
231633
231782
|
async reloadEnvironmentMetadata() {
|
|
231634
231783
|
let readme = "";
|
|
231635
231784
|
try {
|
|
231636
|
-
readme = (await fs6.promises.readFile(
|
|
231785
|
+
readme = (await fs6.promises.readFile(path9.join(this.environmentPath, README_NAME))).toString();
|
|
231637
231786
|
} catch {}
|
|
231638
231787
|
this.metadata = {
|
|
231639
231788
|
...this.metadata,
|
|
@@ -231644,10 +231793,10 @@ class Environment {
|
|
|
231644
231793
|
return this.metadata;
|
|
231645
231794
|
}
|
|
231646
231795
|
async compileSource(packageName, modelName, source, includeSql = false) {
|
|
231647
|
-
const modelDir =
|
|
231648
|
-
const virtualUri = `file://${
|
|
231796
|
+
const modelDir = path9.dirname(path9.join(this.environmentPath, packageName, modelName));
|
|
231797
|
+
const virtualUri = `file://${path9.join(modelDir, "__compile_check.malloy")}`;
|
|
231649
231798
|
const virtualUrl = new URL(virtualUri);
|
|
231650
|
-
const modelPath =
|
|
231799
|
+
const modelPath = path9.join(this.environmentPath, packageName, modelName);
|
|
231651
231800
|
let modelContent = "";
|
|
231652
231801
|
try {
|
|
231653
231802
|
modelContent = await fs6.promises.readFile(modelPath, "utf8");
|
|
@@ -231759,24 +231908,30 @@ ${source}` : source;
|
|
|
231759
231908
|
throw error;
|
|
231760
231909
|
}
|
|
231761
231910
|
}
|
|
231911
|
+
getOrCreatePackageMutex(packageName) {
|
|
231912
|
+
let packageMutex = this.packageMutexes.get(packageName);
|
|
231913
|
+
if (packageMutex === undefined) {
|
|
231914
|
+
packageMutex = new Mutex;
|
|
231915
|
+
this.packageMutexes.set(packageName, packageMutex);
|
|
231916
|
+
}
|
|
231917
|
+
return packageMutex;
|
|
231918
|
+
}
|
|
231762
231919
|
async getPackage(packageName, reload = false) {
|
|
231763
231920
|
const _package = this.packages.get(packageName);
|
|
231764
231921
|
if (_package !== undefined && !reload) {
|
|
231765
231922
|
return _package;
|
|
231766
231923
|
}
|
|
231767
|
-
|
|
231768
|
-
if (packageMutex
|
|
231924
|
+
const packageMutex = this.getOrCreatePackageMutex(packageName);
|
|
231925
|
+
if (packageMutex.isLocked()) {
|
|
231769
231926
|
logger.debug(`Package ${packageName} is being loaded, waiting for unlock...`);
|
|
231770
231927
|
await packageMutex.waitForUnlock();
|
|
231771
231928
|
logger.debug(`Package ${packageName} unlocked`);
|
|
231772
231929
|
const existingPackage = this.packages.get(packageName);
|
|
231773
|
-
if (existingPackage) {
|
|
231930
|
+
if (existingPackage !== undefined && !reload) {
|
|
231774
231931
|
logger.debug(`Package ${packageName} loaded by another request`);
|
|
231775
231932
|
return existingPackage;
|
|
231776
231933
|
}
|
|
231777
231934
|
}
|
|
231778
|
-
packageMutex = new Mutex;
|
|
231779
|
-
this.packageMutexes.set(packageName, packageMutex);
|
|
231780
231935
|
return packageMutex.runExclusive(async () => {
|
|
231781
231936
|
const existingPackage = this.packages.get(packageName);
|
|
231782
231937
|
if (existingPackage !== undefined && !reload) {
|
|
@@ -231785,7 +231940,7 @@ ${source}` : source;
|
|
|
231785
231940
|
this.setPackageStatus(packageName, "loading" /* LOADING */);
|
|
231786
231941
|
try {
|
|
231787
231942
|
logger.debug(`Loading package ${packageName}...`);
|
|
231788
|
-
const packagePath =
|
|
231943
|
+
const packagePath = path9.join(this.environmentPath, packageName);
|
|
231789
231944
|
const _package2 = await Package.create(this.environmentName, packageName, packagePath, () => this.malloyConfig.malloyConfig);
|
|
231790
231945
|
if (existingPackage !== undefined && reload) {
|
|
231791
231946
|
this.retireConnectionGeneration(`package ${packageName}`, () => existingPackage.getMalloyConfig().releaseConnections());
|
|
@@ -231803,7 +231958,7 @@ ${source}` : source;
|
|
|
231803
231958
|
});
|
|
231804
231959
|
}
|
|
231805
231960
|
async addPackage(packageName) {
|
|
231806
|
-
const packagePath =
|
|
231961
|
+
const packagePath = path9.join(this.environmentPath, packageName);
|
|
231807
231962
|
if (!await fs6.promises.access(packagePath).then(() => true).catch(() => false) || !(await fs6.promises.stat(packagePath))?.isDirectory()) {
|
|
231808
231963
|
throw new PackageNotFoundError(`Package ${packageName} not found`);
|
|
231809
231964
|
}
|
|
@@ -231811,20 +231966,35 @@ ${source}` : source;
|
|
|
231811
231966
|
packagePath,
|
|
231812
231967
|
malloyConfig: this.malloyConfig.malloyConfig
|
|
231813
231968
|
});
|
|
231814
|
-
this.
|
|
231815
|
-
|
|
231816
|
-
|
|
231817
|
-
|
|
231818
|
-
|
|
231819
|
-
|
|
231820
|
-
|
|
231969
|
+
const packageMutex = this.getOrCreatePackageMutex(packageName);
|
|
231970
|
+
if (packageMutex.isLocked()) {
|
|
231971
|
+
logger.debug(`Package ${packageName} is being loaded, waiting before addPackage...`);
|
|
231972
|
+
await packageMutex.waitForUnlock();
|
|
231973
|
+
const alreadyLoaded = this.packages.get(packageName);
|
|
231974
|
+
if (alreadyLoaded !== undefined) {
|
|
231975
|
+
return alreadyLoaded;
|
|
231976
|
+
}
|
|
231821
231977
|
}
|
|
231822
|
-
|
|
231823
|
-
|
|
231978
|
+
return packageMutex.runExclusive(async () => {
|
|
231979
|
+
const existingPackage = this.packages.get(packageName);
|
|
231980
|
+
if (existingPackage !== undefined) {
|
|
231981
|
+
return existingPackage;
|
|
231982
|
+
}
|
|
231983
|
+
this.setPackageStatus(packageName, "loading" /* LOADING */);
|
|
231984
|
+
try {
|
|
231985
|
+
this.packages.set(packageName, await Package.create(this.environmentName, packageName, packagePath, () => this.malloyConfig.malloyConfig));
|
|
231986
|
+
} catch (error) {
|
|
231987
|
+
logger.error("Error adding package", { error });
|
|
231988
|
+
this.deletePackageStatus(packageName);
|
|
231989
|
+
throw error;
|
|
231990
|
+
}
|
|
231991
|
+
this.setPackageStatus(packageName, "serving" /* SERVING */);
|
|
231992
|
+
return this.packages.get(packageName);
|
|
231993
|
+
});
|
|
231824
231994
|
}
|
|
231825
231995
|
async writePackageManifest(packageName, metadata) {
|
|
231826
|
-
const packagePath =
|
|
231827
|
-
const manifestPath =
|
|
231996
|
+
const packagePath = path9.join(this.environmentPath, packageName);
|
|
231997
|
+
const manifestPath = path9.join(packagePath, "publisher.json");
|
|
231828
231998
|
try {
|
|
231829
231999
|
let existingManifest = {};
|
|
231830
232000
|
try {
|
|
@@ -231896,7 +232066,7 @@ ${source}` : source;
|
|
|
231896
232066
|
}
|
|
231897
232067
|
await _package.getMalloyConfig().releaseConnections();
|
|
231898
232068
|
try {
|
|
231899
|
-
await fs6.promises.rm(
|
|
232069
|
+
await fs6.promises.rm(path9.join(this.environmentPath, packageName), {
|
|
231900
232070
|
recursive: true,
|
|
231901
232071
|
force: true
|
|
231902
232072
|
});
|
|
@@ -231960,7 +232130,7 @@ ${source}` : source;
|
|
|
231960
232130
|
};
|
|
231961
232131
|
}
|
|
231962
232132
|
async deleteDuckDBConnection(connectionName) {
|
|
231963
|
-
const duckdbPath =
|
|
232133
|
+
const duckdbPath = path9.join(this.environmentPath, `${connectionName}.duckdb`);
|
|
231964
232134
|
try {
|
|
231965
232135
|
await fs6.promises.rm(duckdbPath, { force: true });
|
|
231966
232136
|
logger.info(`Removed DuckDB connection file ${connectionName} from environment ${this.environmentName}`);
|
|
@@ -232029,6 +232199,7 @@ class EnvironmentStore {
|
|
|
232029
232199
|
publisherConfigIsFrozen;
|
|
232030
232200
|
finishedInitialization;
|
|
232031
232201
|
isInitialized = false;
|
|
232202
|
+
failedEnvironments = [];
|
|
232032
232203
|
storageManager;
|
|
232033
232204
|
s3Client = new import_client_s32.S3({
|
|
232034
232205
|
followRegionRedirects: true
|
|
@@ -232040,7 +232211,7 @@ class EnvironmentStore {
|
|
|
232040
232211
|
const storageConfig = {
|
|
232041
232212
|
type: "duckdb",
|
|
232042
232213
|
duckdb: {
|
|
232043
|
-
path:
|
|
232214
|
+
path: path10.join(serverRootPath, "publisher.db")
|
|
232044
232215
|
}
|
|
232045
232216
|
};
|
|
232046
232217
|
this.storageManager = new StorageManager(storageConfig);
|
|
@@ -232061,6 +232232,10 @@ class EnvironmentStore {
|
|
|
232061
232232
|
logEnvironmentInitializationError(environmentName, error) {
|
|
232062
232233
|
const label = environmentName ? ` "${environmentName}"` : "";
|
|
232063
232234
|
logger.error(`Error initializing environment${label}; skipping environment`, this.extractErrorDataFromError(error));
|
|
232235
|
+
this.failedEnvironments.push({
|
|
232236
|
+
name: environmentName ?? "<unknown>",
|
|
232237
|
+
error: error instanceof Error ? error.message : String(error)
|
|
232238
|
+
});
|
|
232064
232239
|
}
|
|
232065
232240
|
async initialize() {
|
|
232066
232241
|
const reInit = process.env.INITIALIZE_STORAGE === "true";
|
|
@@ -232123,7 +232298,11 @@ class EnvironmentStore {
|
|
|
232123
232298
|
}
|
|
232124
232299
|
}
|
|
232125
232300
|
this.isInitialized = true;
|
|
232126
|
-
|
|
232301
|
+
if (this.failedEnvironments.length > 0) {
|
|
232302
|
+
markDegraded();
|
|
232303
|
+
} else {
|
|
232304
|
+
markReady();
|
|
232305
|
+
}
|
|
232127
232306
|
const initializationDuration = performance.now() - initialTime;
|
|
232128
232307
|
logger.info(`Environment store successfully initialized in ${formatDuration(initializationDuration)}`);
|
|
232129
232308
|
} catch (error) {
|
|
@@ -232327,7 +232506,7 @@ class EnvironmentStore {
|
|
|
232327
232506
|
const reInit = process.env.INITIALIZE_STORAGE === "true";
|
|
232328
232507
|
await fs7.promises.mkdir(this.serverRootPath, { recursive: true });
|
|
232329
232508
|
if (reInit) {
|
|
232330
|
-
const uploadDocsPath2 =
|
|
232509
|
+
const uploadDocsPath2 = path10.join(this.serverRootPath, PUBLISHER_DATA_DIR);
|
|
232331
232510
|
logger.info(`Reinitialization mode: Cleaning up upload documents path ${uploadDocsPath2}`);
|
|
232332
232511
|
try {
|
|
232333
232512
|
await fs7.promises.rm(uploadDocsPath2, {
|
|
@@ -232344,7 +232523,7 @@ class EnvironmentStore {
|
|
|
232344
232523
|
} else {
|
|
232345
232524
|
logger.info(`Using existing publisher path`);
|
|
232346
232525
|
}
|
|
232347
|
-
const uploadDocsPath =
|
|
232526
|
+
const uploadDocsPath = path10.join(this.serverRootPath, PUBLISHER_DATA_DIR);
|
|
232348
232527
|
await fs7.promises.mkdir(uploadDocsPath, { recursive: true });
|
|
232349
232528
|
}
|
|
232350
232529
|
async listEnvironments(skipInitializationCheck = false) {
|
|
@@ -232359,7 +232538,12 @@ class EnvironmentStore {
|
|
|
232359
232538
|
environments: [],
|
|
232360
232539
|
initialized: this.isInitialized,
|
|
232361
232540
|
frozenConfig: isPublisherConfigFrozen(this.serverRootPath),
|
|
232362
|
-
operationalState: getOperationalState()
|
|
232541
|
+
operationalState: getOperationalState(),
|
|
232542
|
+
...this.failedEnvironments.length > 0 && {
|
|
232543
|
+
failedEnvironments: [
|
|
232544
|
+
...this.failedEnvironments
|
|
232545
|
+
]
|
|
232546
|
+
}
|
|
232363
232547
|
};
|
|
232364
232548
|
const environments = await this.listEnvironments(true);
|
|
232365
232549
|
await Promise.all(environments.map(async (environment) => {
|
|
@@ -232576,12 +232760,12 @@ class EnvironmentStore {
|
|
|
232576
232760
|
const absoluteEnvironmentPath = `${this.serverRootPath}/${PUBLISHER_DATA_DIR}/${environmentName}`;
|
|
232577
232761
|
await fs7.promises.mkdir(absoluteEnvironmentPath, { recursive: true });
|
|
232578
232762
|
if (environment.readme) {
|
|
232579
|
-
await fs7.promises.writeFile(
|
|
232763
|
+
await fs7.promises.writeFile(path10.join(absoluteEnvironmentPath, "README.md"), environment.readme);
|
|
232580
232764
|
}
|
|
232581
232765
|
return absoluteEnvironmentPath;
|
|
232582
232766
|
}
|
|
232583
232767
|
isLocalPath(location) {
|
|
232584
|
-
return location.startsWith("./") || location.startsWith("../") || location.startsWith("~/") || location.startsWith("/") ||
|
|
232768
|
+
return location.startsWith("./") || location.startsWith("../") || location.startsWith("~/") || location.startsWith("/") || path10.isAbsolute(location);
|
|
232585
232769
|
}
|
|
232586
232770
|
isGitHubURL(location) {
|
|
232587
232771
|
return location.startsWith("https://github.com/") || location.startsWith("git@github.com:");
|
|
@@ -232637,7 +232821,7 @@ class EnvironmentStore {
|
|
|
232637
232821
|
if (githubInfo && githubInfo.packagePath) {
|
|
232638
232822
|
const subPathMatch = _package.location.match(/\/tree\/[^/]+\/(.+)$/);
|
|
232639
232823
|
if (subPathMatch) {
|
|
232640
|
-
sourcePath =
|
|
232824
|
+
sourcePath = path10.join(tempDownloadPath, subPathMatch[1]);
|
|
232641
232825
|
} else {
|
|
232642
232826
|
sourcePath = tempDownloadPath;
|
|
232643
232827
|
}
|
|
@@ -232648,7 +232832,7 @@ class EnvironmentStore {
|
|
|
232648
232832
|
if (this.isLocalPath(_package.location)) {
|
|
232649
232833
|
sourcePath = _package.location;
|
|
232650
232834
|
} else {
|
|
232651
|
-
sourcePath =
|
|
232835
|
+
sourcePath = path10.join(tempDownloadPath, groupedLocation);
|
|
232652
232836
|
}
|
|
232653
232837
|
}
|
|
232654
232838
|
const sourceExists = await fs7.promises.access(sourcePath).then(() => true).catch(() => false);
|
|
@@ -232724,7 +232908,7 @@ class EnvironmentStore {
|
|
|
232724
232908
|
}
|
|
232725
232909
|
}
|
|
232726
232910
|
if (this.isLocalPath(location)) {
|
|
232727
|
-
const packagePath =
|
|
232911
|
+
const packagePath = path10.isAbsolute(location) ? location : path10.join(this.serverRootPath, location);
|
|
232728
232912
|
try {
|
|
232729
232913
|
logger.info(`Mounting local directory at "${packagePath}" to "${targetPath}"`);
|
|
232730
232914
|
await this.mountLocalDirectory(packagePath, targetPath, environmentName, packageName);
|
|
@@ -232778,11 +232962,11 @@ class EnvironmentStore {
|
|
|
232778
232962
|
}
|
|
232779
232963
|
await Promise.all(files.map(async (file) => {
|
|
232780
232964
|
const relativeFilePath = file.name.replace(prefix, "");
|
|
232781
|
-
const absoluteFilePath = isCompressedFile ? absoluteDirPath :
|
|
232965
|
+
const absoluteFilePath = isCompressedFile ? absoluteDirPath : path10.join(absoluteDirPath, relativeFilePath);
|
|
232782
232966
|
if (file.name.endsWith("/")) {
|
|
232783
232967
|
return;
|
|
232784
232968
|
}
|
|
232785
|
-
await fs7.promises.mkdir(
|
|
232969
|
+
await fs7.promises.mkdir(path10.dirname(absoluteFilePath), {
|
|
232786
232970
|
recursive: true
|
|
232787
232971
|
});
|
|
232788
232972
|
return fs7.promises.writeFile(absoluteFilePath, await file.download());
|
|
@@ -232798,7 +232982,7 @@ class EnvironmentStore {
|
|
|
232798
232982
|
const prefix = prefixParts.join("/");
|
|
232799
232983
|
if (isCompressedFile) {
|
|
232800
232984
|
const zipFilePath = `${absoluteDirPath}.zip`;
|
|
232801
|
-
await fs7.promises.mkdir(
|
|
232985
|
+
await fs7.promises.mkdir(path10.dirname(zipFilePath), {
|
|
232802
232986
|
recursive: true
|
|
232803
232987
|
});
|
|
232804
232988
|
const command = new import_client_s32.GetObjectCommand({
|
|
@@ -232837,8 +233021,8 @@ class EnvironmentStore {
|
|
|
232837
233021
|
if (!relativeFilePath || relativeFilePath.endsWith("/")) {
|
|
232838
233022
|
return;
|
|
232839
233023
|
}
|
|
232840
|
-
const absoluteFilePath =
|
|
232841
|
-
await fs7.promises.mkdir(
|
|
233024
|
+
const absoluteFilePath = path10.join(absoluteDirPath, relativeFilePath);
|
|
233025
|
+
await fs7.promises.mkdir(path10.dirname(absoluteFilePath), {
|
|
232842
233026
|
recursive: true
|
|
232843
233027
|
});
|
|
232844
233028
|
const command = new import_client_s32.GetObjectCommand({
|
|
@@ -232900,7 +233084,7 @@ class EnvironmentStore {
|
|
|
232900
233084
|
logger.info(`Successfully cloned entire repository to: ${absoluteDirPath}`);
|
|
232901
233085
|
return;
|
|
232902
233086
|
}
|
|
232903
|
-
const packageFullPath =
|
|
233087
|
+
const packageFullPath = path10.join(absoluteDirPath, cleanPackagePath);
|
|
232904
233088
|
const packageExists = await fs7.promises.access(packageFullPath).then(() => true).catch(() => false);
|
|
232905
233089
|
if (!packageExists) {
|
|
232906
233090
|
throw new Error(`Package path "${cleanPackagePath}" does not exist in the cloned repository.`);
|
|
@@ -232908,7 +233092,7 @@ class EnvironmentStore {
|
|
|
232908
233092
|
const dirContents = await fs7.promises.readdir(absoluteDirPath);
|
|
232909
233093
|
for (const entry of dirContents) {
|
|
232910
233094
|
if (entry !== cleanPackagePath.replace(/^\/+/, "").split("/")[0]) {
|
|
232911
|
-
await fs7.promises.rm(
|
|
233095
|
+
await fs7.promises.rm(path10.join(absoluteDirPath, entry), {
|
|
232912
233096
|
recursive: true,
|
|
232913
233097
|
force: true
|
|
232914
233098
|
});
|
|
@@ -232916,7 +233100,7 @@ class EnvironmentStore {
|
|
|
232916
233100
|
}
|
|
232917
233101
|
const packageContents = await fs7.promises.readdir(packageFullPath);
|
|
232918
233102
|
for (const entry of packageContents) {
|
|
232919
|
-
await fs7.promises.rename(
|
|
233103
|
+
await fs7.promises.rename(path10.join(packageFullPath, entry), path10.join(absoluteDirPath, entry));
|
|
232920
233104
|
}
|
|
232921
233105
|
await fs7.promises.rm(packageFullPath, { recursive: true, force: true });
|
|
232922
233106
|
}
|
|
@@ -232964,9 +233148,9 @@ class WatchModeController {
|
|
|
232964
233148
|
});
|
|
232965
233149
|
return;
|
|
232966
233150
|
}
|
|
232967
|
-
this.watchingPath =
|
|
233151
|
+
this.watchingPath = path11.join(this.environmentStore.serverRootPath, watchName);
|
|
232968
233152
|
this.watcher = esm_default.watch(this.watchingPath, {
|
|
232969
|
-
ignored: (
|
|
233153
|
+
ignored: (path12, stats) => !!stats?.isFile() && !path12.endsWith(".malloy") && !path12.endsWith(".md"),
|
|
232970
233154
|
ignoreInitial: true
|
|
232971
233155
|
});
|
|
232972
233156
|
const reloadEnvironment = async () => {
|
|
@@ -232974,16 +233158,16 @@ class WatchModeController {
|
|
|
232974
233158
|
await this.environmentStore.addEnvironment(environment2.metadata);
|
|
232975
233159
|
logger.info(`Reloaded environment ${watchName}`);
|
|
232976
233160
|
};
|
|
232977
|
-
this.watcher.on("add", async (
|
|
232978
|
-
logger.info(`Detected new file ${
|
|
233161
|
+
this.watcher.on("add", async (path12) => {
|
|
233162
|
+
logger.info(`Detected new file ${path12}, reloading environment ${watchName}`);
|
|
232979
233163
|
await reloadEnvironment();
|
|
232980
233164
|
});
|
|
232981
|
-
this.watcher.on("unlink", async (
|
|
232982
|
-
logger.info(`Detected deletion of ${
|
|
233165
|
+
this.watcher.on("unlink", async (path12) => {
|
|
233166
|
+
logger.info(`Detected deletion of ${path12}, reloading environment ${watchName}`);
|
|
232983
233167
|
await reloadEnvironment();
|
|
232984
233168
|
});
|
|
232985
|
-
this.watcher.on("change", async (
|
|
232986
|
-
logger.info(`Detected change on ${
|
|
233169
|
+
this.watcher.on("change", async (path12) => {
|
|
233170
|
+
logger.info(`Detected change on ${path12}, reloading environment ${watchName}`);
|
|
232987
233171
|
await reloadEnvironment();
|
|
232988
233172
|
});
|
|
232989
233173
|
res.json();
|
|
@@ -236074,25 +236258,25 @@ async function getModelForQuery(environmentStore, environmentName, packageName,
|
|
|
236074
236258
|
}
|
|
236075
236259
|
}
|
|
236076
236260
|
function buildMalloyUri(components, fragment) {
|
|
236077
|
-
let
|
|
236261
|
+
let path12 = "/environment/";
|
|
236078
236262
|
if (components.environment) {
|
|
236079
|
-
|
|
236263
|
+
path12 += encodeURIComponent(components.environment);
|
|
236080
236264
|
} else {
|
|
236081
|
-
|
|
236265
|
+
path12 += "home";
|
|
236082
236266
|
}
|
|
236083
236267
|
if (components.package) {
|
|
236084
|
-
|
|
236268
|
+
path12 += "/package/" + encodeURIComponent(components.package);
|
|
236085
236269
|
}
|
|
236086
236270
|
if (components.resourceType) {
|
|
236087
|
-
|
|
236271
|
+
path12 += "/" + components.resourceType;
|
|
236088
236272
|
if (components.resourceName) {
|
|
236089
|
-
|
|
236273
|
+
path12 += "/" + encodeURIComponent(components.resourceName);
|
|
236090
236274
|
if (components.subResourceType && components.subResourceName) {
|
|
236091
|
-
|
|
236275
|
+
path12 += "/" + components.subResourceType + "/" + encodeURIComponent(components.subResourceName);
|
|
236092
236276
|
}
|
|
236093
236277
|
}
|
|
236094
236278
|
}
|
|
236095
|
-
let uriString = "malloy:/" +
|
|
236279
|
+
let uriString = "malloy:/" + path12;
|
|
236096
236280
|
if (fragment) {
|
|
236097
236281
|
uriString += "#" + fragment;
|
|
236098
236282
|
}
|
|
@@ -236986,6 +237170,581 @@ function initializeMcpServer(environmentStore) {
|
|
|
236986
237170
|
return mcpServer;
|
|
236987
237171
|
}
|
|
236988
237172
|
|
|
237173
|
+
// src/server-old.ts
|
|
237174
|
+
var import_body_parser = __toESM(require_body_parser(), 1);
|
|
237175
|
+
var LEGACY_API_PREFIX = "/api/v0";
|
|
237176
|
+
function remapMaterializationResponse(mat) {
|
|
237177
|
+
if (!mat || typeof mat !== "object")
|
|
237178
|
+
return mat;
|
|
237179
|
+
if (Array.isArray(mat)) {
|
|
237180
|
+
return mat.map(remapMaterializationResponse);
|
|
237181
|
+
}
|
|
237182
|
+
const out = { ...mat };
|
|
237183
|
+
if ("environmentId" in out) {
|
|
237184
|
+
out.projectId = out.environmentId;
|
|
237185
|
+
delete out.environmentId;
|
|
237186
|
+
}
|
|
237187
|
+
return out;
|
|
237188
|
+
}
|
|
237189
|
+
var setVersionIdError = (res) => {
|
|
237190
|
+
const { json, status } = internalErrorToHttpError(new NotImplementedError("Version IDs not implemented."));
|
|
237191
|
+
res.status(status).json(json);
|
|
237192
|
+
};
|
|
237193
|
+
function registerLegacyRoutes(app, controllers) {
|
|
237194
|
+
const {
|
|
237195
|
+
environmentStore,
|
|
237196
|
+
connectionController,
|
|
237197
|
+
modelController,
|
|
237198
|
+
packageController,
|
|
237199
|
+
databaseController,
|
|
237200
|
+
queryController,
|
|
237201
|
+
compileController,
|
|
237202
|
+
materializationController,
|
|
237203
|
+
manifestController
|
|
237204
|
+
} = controllers;
|
|
237205
|
+
app.get(`${LEGACY_API_PREFIX}/projects`, async (_req, res) => {
|
|
237206
|
+
try {
|
|
237207
|
+
res.status(200).json(await environmentStore.listEnvironments());
|
|
237208
|
+
} catch (error) {
|
|
237209
|
+
logger.error(error);
|
|
237210
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237211
|
+
res.status(status).json(json);
|
|
237212
|
+
}
|
|
237213
|
+
});
|
|
237214
|
+
app.post(`${LEGACY_API_PREFIX}/projects`, async (req, res) => {
|
|
237215
|
+
try {
|
|
237216
|
+
logger.info("Adding project", { body: req.body });
|
|
237217
|
+
const environment = await environmentStore.addEnvironment(req.body);
|
|
237218
|
+
res.status(200).json(await environment.serialize());
|
|
237219
|
+
} catch (error) {
|
|
237220
|
+
logger.error(error);
|
|
237221
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237222
|
+
res.status(status).json(json);
|
|
237223
|
+
}
|
|
237224
|
+
});
|
|
237225
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName`, async (req, res) => {
|
|
237226
|
+
try {
|
|
237227
|
+
const environment = await environmentStore.getEnvironment(req.params.projectName, req.query.reload === "true");
|
|
237228
|
+
res.status(200).json(await environment.serialize());
|
|
237229
|
+
} catch (error) {
|
|
237230
|
+
logger.error(error);
|
|
237231
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237232
|
+
res.status(status).json(json);
|
|
237233
|
+
}
|
|
237234
|
+
});
|
|
237235
|
+
app.patch(`${LEGACY_API_PREFIX}/projects/:projectName`, async (req, res) => {
|
|
237236
|
+
try {
|
|
237237
|
+
const environment = await environmentStore.updateEnvironment(req.body);
|
|
237238
|
+
res.status(200).json(await environment.serialize());
|
|
237239
|
+
} catch (error) {
|
|
237240
|
+
logger.error(error);
|
|
237241
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237242
|
+
res.status(status).json(json);
|
|
237243
|
+
}
|
|
237244
|
+
});
|
|
237245
|
+
app.delete(`${LEGACY_API_PREFIX}/projects/:projectName`, async (req, res) => {
|
|
237246
|
+
try {
|
|
237247
|
+
const environment = await environmentStore.deleteEnvironment(req.params.projectName);
|
|
237248
|
+
res.status(200).json(await environment?.serialize());
|
|
237249
|
+
} catch (error) {
|
|
237250
|
+
logger.error(error);
|
|
237251
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237252
|
+
res.status(status).json(json);
|
|
237253
|
+
}
|
|
237254
|
+
});
|
|
237255
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/connections`, async (req, res) => {
|
|
237256
|
+
try {
|
|
237257
|
+
res.status(200).json(await connectionController.listConnections(req.params.projectName));
|
|
237258
|
+
} catch (error) {
|
|
237259
|
+
logger.error(error);
|
|
237260
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237261
|
+
res.status(status).json(json);
|
|
237262
|
+
}
|
|
237263
|
+
});
|
|
237264
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/connections/:connectionName`, async (req, res) => {
|
|
237265
|
+
try {
|
|
237266
|
+
res.status(200).json(await connectionController.getConnection(req.params.projectName, req.params.connectionName));
|
|
237267
|
+
} catch (error) {
|
|
237268
|
+
logger.error(error);
|
|
237269
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237270
|
+
res.status(status).json(json);
|
|
237271
|
+
}
|
|
237272
|
+
});
|
|
237273
|
+
app.post(`${LEGACY_API_PREFIX}/projects/:projectName/connections/:connectionName`, async (req, res) => {
|
|
237274
|
+
try {
|
|
237275
|
+
const result = await connectionController.addConnection(req.params.projectName, req.params.connectionName, req.body);
|
|
237276
|
+
res.status(201).json(result);
|
|
237277
|
+
} catch (error) {
|
|
237278
|
+
logger.error("Error creating connection", { error });
|
|
237279
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237280
|
+
res.status(status).json(json);
|
|
237281
|
+
}
|
|
237282
|
+
});
|
|
237283
|
+
app.patch(`${LEGACY_API_PREFIX}/projects/:projectName/connections/:connectionName`, async (req, res) => {
|
|
237284
|
+
try {
|
|
237285
|
+
const result = await connectionController.updateConnection(req.params.projectName, req.params.connectionName, req.body);
|
|
237286
|
+
res.status(200).json(result);
|
|
237287
|
+
} catch (error) {
|
|
237288
|
+
logger.error("Error updating connection", { error });
|
|
237289
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237290
|
+
res.status(status).json(json);
|
|
237291
|
+
}
|
|
237292
|
+
});
|
|
237293
|
+
app.delete(`${LEGACY_API_PREFIX}/projects/:projectName/connections/:connectionName`, async (req, res) => {
|
|
237294
|
+
try {
|
|
237295
|
+
const result = await connectionController.deleteConnection(req.params.projectName, req.params.connectionName);
|
|
237296
|
+
res.status(200).json(result);
|
|
237297
|
+
} catch (error) {
|
|
237298
|
+
logger.error("Error deleting connection", { error });
|
|
237299
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237300
|
+
res.status(status).json(json);
|
|
237301
|
+
}
|
|
237302
|
+
});
|
|
237303
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/connections/:connectionName/schemas`, async (req, res) => {
|
|
237304
|
+
try {
|
|
237305
|
+
res.status(200).json(await connectionController.listSchemas(req.params.projectName, req.params.connectionName));
|
|
237306
|
+
} catch (error) {
|
|
237307
|
+
logger.error(error);
|
|
237308
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237309
|
+
res.status(status).json(json);
|
|
237310
|
+
}
|
|
237311
|
+
});
|
|
237312
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/connections/:connectionName/schemas/:schemaName/tables`, async (req, res) => {
|
|
237313
|
+
try {
|
|
237314
|
+
const results = await connectionController.listTables(req.params.projectName, req.params.connectionName, req.params.schemaName, normalizeQueryArray(req.query.tableNames));
|
|
237315
|
+
res.status(200).json(results);
|
|
237316
|
+
} catch (error) {
|
|
237317
|
+
logger.error(error);
|
|
237318
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237319
|
+
res.status(status).json(json);
|
|
237320
|
+
}
|
|
237321
|
+
});
|
|
237322
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/connections/:connectionName/schemas/:schemaName/tables/:tablePath`, async (req, res) => {
|
|
237323
|
+
try {
|
|
237324
|
+
const results = await connectionController.getTable(req.params.projectName, req.params.connectionName, req.params.schemaName, req.params.tablePath);
|
|
237325
|
+
res.status(200).json(results);
|
|
237326
|
+
} catch (error) {
|
|
237327
|
+
logger.error(error);
|
|
237328
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237329
|
+
res.status(status).json(json);
|
|
237330
|
+
}
|
|
237331
|
+
});
|
|
237332
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/connections/:connectionName/schemas`, async (req, res) => {
|
|
237333
|
+
try {
|
|
237334
|
+
res.status(200).json(await connectionController.listSchemas(req.params.projectName, req.params.connectionName, req.params.packageName));
|
|
237335
|
+
} catch (error) {
|
|
237336
|
+
logger.error(error);
|
|
237337
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237338
|
+
res.status(status).json(json);
|
|
237339
|
+
}
|
|
237340
|
+
});
|
|
237341
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/connections/:connectionName/schemas/:schemaName/tables`, async (req, res) => {
|
|
237342
|
+
try {
|
|
237343
|
+
res.status(200).json(await connectionController.listTables(req.params.projectName, req.params.connectionName, req.params.schemaName, normalizeQueryArray(req.query.tableNames), req.params.packageName));
|
|
237344
|
+
} catch (error) {
|
|
237345
|
+
logger.error(error);
|
|
237346
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237347
|
+
res.status(status).json(json);
|
|
237348
|
+
}
|
|
237349
|
+
});
|
|
237350
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/connections/:connectionName/schemas/:schemaName/tables/:tablePath`, async (req, res) => {
|
|
237351
|
+
try {
|
|
237352
|
+
res.status(200).json(await connectionController.getTable(req.params.projectName, req.params.connectionName, req.params.schemaName, req.params.tablePath, req.params.packageName));
|
|
237353
|
+
} catch (error) {
|
|
237354
|
+
logger.error(error);
|
|
237355
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237356
|
+
res.status(status).json(json);
|
|
237357
|
+
}
|
|
237358
|
+
});
|
|
237359
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/connections/:connectionName/sqlSource`, async (req, res) => {
|
|
237360
|
+
try {
|
|
237361
|
+
res.status(200).json(await connectionController.getConnectionSqlSource(req.params.projectName, req.params.connectionName, req.query.sqlStatement));
|
|
237362
|
+
} catch (error) {
|
|
237363
|
+
logger.error(error);
|
|
237364
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237365
|
+
res.status(status).json(json);
|
|
237366
|
+
}
|
|
237367
|
+
});
|
|
237368
|
+
app.post(`${LEGACY_API_PREFIX}/projects/:projectName/connections/:connectionName/sqlSource`, async (req, res) => {
|
|
237369
|
+
try {
|
|
237370
|
+
res.status(200).json(await connectionController.getConnectionSqlSource(req.params.projectName, req.params.connectionName, req.body.sqlStatement));
|
|
237371
|
+
} catch (error) {
|
|
237372
|
+
logger.error(error);
|
|
237373
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237374
|
+
res.status(status).json(json);
|
|
237375
|
+
}
|
|
237376
|
+
});
|
|
237377
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/connections/:connectionName/sqlSource`, async (req, res) => {
|
|
237378
|
+
try {
|
|
237379
|
+
res.status(200).json(await connectionController.getConnectionSqlSource(req.params.projectName, req.params.connectionName, req.query.sqlStatement, req.params.packageName));
|
|
237380
|
+
} catch (error) {
|
|
237381
|
+
logger.error(error);
|
|
237382
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237383
|
+
res.status(status).json(json);
|
|
237384
|
+
}
|
|
237385
|
+
});
|
|
237386
|
+
app.post(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/connections/:connectionName/sqlSource`, async (req, res) => {
|
|
237387
|
+
try {
|
|
237388
|
+
res.status(200).json(await connectionController.getConnectionSqlSource(req.params.projectName, req.params.connectionName, req.body.sqlStatement, req.params.packageName));
|
|
237389
|
+
} catch (error) {
|
|
237390
|
+
logger.error(error);
|
|
237391
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237392
|
+
res.status(status).json(json);
|
|
237393
|
+
}
|
|
237394
|
+
});
|
|
237395
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/connections/:connectionName/queryData`, async (req, res) => {
|
|
237396
|
+
try {
|
|
237397
|
+
res.status(200).json(await connectionController.getConnectionQueryData(req.params.projectName, req.params.connectionName, req.query.sqlStatement, req.query.options));
|
|
237398
|
+
} catch (error) {
|
|
237399
|
+
logger.error(error);
|
|
237400
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237401
|
+
res.status(status).json(json);
|
|
237402
|
+
}
|
|
237403
|
+
});
|
|
237404
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/connections/:connectionName/queryData`, async (req, res) => {
|
|
237405
|
+
try {
|
|
237406
|
+
res.status(200).json(await connectionController.getConnectionQueryData(req.params.projectName, req.params.connectionName, req.query.sqlStatement, req.query.options, req.params.packageName));
|
|
237407
|
+
} catch (error) {
|
|
237408
|
+
logger.error(error);
|
|
237409
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237410
|
+
res.status(status).json(json);
|
|
237411
|
+
}
|
|
237412
|
+
});
|
|
237413
|
+
app.post(`${LEGACY_API_PREFIX}/projects/:projectName/connections/:connectionName/sqlQuery`, async (req, res) => {
|
|
237414
|
+
try {
|
|
237415
|
+
let options;
|
|
237416
|
+
if (req.body?.options) {
|
|
237417
|
+
options = req.body.options;
|
|
237418
|
+
} else {
|
|
237419
|
+
options = req.query.options;
|
|
237420
|
+
}
|
|
237421
|
+
res.status(200).json(await connectionController.getConnectionQueryData(req.params.projectName, req.params.connectionName, req.body.sqlStatement, options));
|
|
237422
|
+
} catch (error) {
|
|
237423
|
+
logger.error(error);
|
|
237424
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237425
|
+
res.status(status).json(json);
|
|
237426
|
+
}
|
|
237427
|
+
});
|
|
237428
|
+
app.post(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/connections/:connectionName/sqlQuery`, async (req, res) => {
|
|
237429
|
+
try {
|
|
237430
|
+
let options;
|
|
237431
|
+
if (req.body?.options) {
|
|
237432
|
+
options = req.body.options;
|
|
237433
|
+
} else {
|
|
237434
|
+
options = req.query.options;
|
|
237435
|
+
}
|
|
237436
|
+
res.status(200).json(await connectionController.getConnectionQueryData(req.params.projectName, req.params.connectionName, req.body.sqlStatement, options, req.params.packageName));
|
|
237437
|
+
} catch (error) {
|
|
237438
|
+
logger.error(error);
|
|
237439
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237440
|
+
res.status(status).json(json);
|
|
237441
|
+
}
|
|
237442
|
+
});
|
|
237443
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/connections/:connectionName/temporaryTable`, async (req, res) => {
|
|
237444
|
+
try {
|
|
237445
|
+
res.status(200).json(await connectionController.getConnectionTemporaryTable(req.params.projectName, req.params.connectionName, req.query.sqlStatement));
|
|
237446
|
+
} catch (error) {
|
|
237447
|
+
logger.error(error);
|
|
237448
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237449
|
+
res.status(status).json(json);
|
|
237450
|
+
}
|
|
237451
|
+
});
|
|
237452
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/connections/:connectionName/temporaryTable`, async (req, res) => {
|
|
237453
|
+
try {
|
|
237454
|
+
res.status(200).json(await connectionController.getConnectionTemporaryTable(req.params.projectName, req.params.connectionName, req.query.sqlStatement, req.params.packageName));
|
|
237455
|
+
} catch (error) {
|
|
237456
|
+
logger.error(error);
|
|
237457
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237458
|
+
res.status(status).json(json);
|
|
237459
|
+
}
|
|
237460
|
+
});
|
|
237461
|
+
app.post(`${LEGACY_API_PREFIX}/projects/:projectName/connections/:connectionName/sqlTemporaryTable`, async (req, res) => {
|
|
237462
|
+
try {
|
|
237463
|
+
res.status(200).json(await connectionController.getConnectionTemporaryTable(req.params.projectName, req.params.connectionName, req.body.sqlStatement));
|
|
237464
|
+
} catch (error) {
|
|
237465
|
+
logger.error(error);
|
|
237466
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237467
|
+
res.status(status).json(json);
|
|
237468
|
+
}
|
|
237469
|
+
});
|
|
237470
|
+
app.post(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/connections/:connectionName/sqlTemporaryTable`, async (req, res) => {
|
|
237471
|
+
try {
|
|
237472
|
+
res.status(200).json(await connectionController.getConnectionTemporaryTable(req.params.projectName, req.params.connectionName, req.body.sqlStatement, req.params.packageName));
|
|
237473
|
+
} catch (error) {
|
|
237474
|
+
logger.error(error);
|
|
237475
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237476
|
+
res.status(status).json(json);
|
|
237477
|
+
}
|
|
237478
|
+
});
|
|
237479
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/packages`, async (req, res) => {
|
|
237480
|
+
if (req.query.versionId) {
|
|
237481
|
+
setVersionIdError(res);
|
|
237482
|
+
return;
|
|
237483
|
+
}
|
|
237484
|
+
try {
|
|
237485
|
+
res.status(200).json(await packageController.listPackages(req.params.projectName));
|
|
237486
|
+
} catch (error) {
|
|
237487
|
+
logger.error(error);
|
|
237488
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237489
|
+
res.status(status).json(json);
|
|
237490
|
+
}
|
|
237491
|
+
});
|
|
237492
|
+
app.post(`${LEGACY_API_PREFIX}/projects/:projectName/packages`, async (req, res) => {
|
|
237493
|
+
try {
|
|
237494
|
+
const autoLoadManifest = req.query.autoLoadManifest === "true";
|
|
237495
|
+
const _package = await packageController.addPackage(req.params.projectName, req.body, { autoLoadManifest });
|
|
237496
|
+
res.status(200).json(_package?.getPackageMetadata());
|
|
237497
|
+
} catch (error) {
|
|
237498
|
+
logger.error(error);
|
|
237499
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237500
|
+
res.status(status).json(json);
|
|
237501
|
+
}
|
|
237502
|
+
});
|
|
237503
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName`, async (req, res) => {
|
|
237504
|
+
if (req.query.versionId) {
|
|
237505
|
+
setVersionIdError(res);
|
|
237506
|
+
return;
|
|
237507
|
+
}
|
|
237508
|
+
try {
|
|
237509
|
+
res.status(200).json(await packageController.getPackage(req.params.projectName, req.params.packageName, req.query.reload === "true"));
|
|
237510
|
+
} catch (error) {
|
|
237511
|
+
logger.error(error);
|
|
237512
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237513
|
+
res.status(status).json(json);
|
|
237514
|
+
}
|
|
237515
|
+
});
|
|
237516
|
+
app.patch(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName`, async (req, res) => {
|
|
237517
|
+
try {
|
|
237518
|
+
res.status(200).json(await packageController.updatePackage(req.params.projectName, req.params.packageName, req.body));
|
|
237519
|
+
} catch (error) {
|
|
237520
|
+
logger.error(error);
|
|
237521
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237522
|
+
res.status(status).json(json);
|
|
237523
|
+
}
|
|
237524
|
+
});
|
|
237525
|
+
app.delete(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName`, async (req, res) => {
|
|
237526
|
+
try {
|
|
237527
|
+
res.status(200).json(await packageController.deletePackage(req.params.projectName, req.params.packageName));
|
|
237528
|
+
} catch (error) {
|
|
237529
|
+
logger.error(error);
|
|
237530
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237531
|
+
res.status(status).json(json);
|
|
237532
|
+
}
|
|
237533
|
+
});
|
|
237534
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/models`, async (req, res) => {
|
|
237535
|
+
if (req.query.versionId) {
|
|
237536
|
+
setVersionIdError(res);
|
|
237537
|
+
return;
|
|
237538
|
+
}
|
|
237539
|
+
try {
|
|
237540
|
+
res.status(200).json(await modelController.listModels(req.params.projectName, req.params.packageName));
|
|
237541
|
+
} catch (error) {
|
|
237542
|
+
logger.error(error);
|
|
237543
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237544
|
+
res.status(status).json(json);
|
|
237545
|
+
}
|
|
237546
|
+
});
|
|
237547
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/models/*?`, async (req, res) => {
|
|
237548
|
+
if (req.query.versionId) {
|
|
237549
|
+
setVersionIdError(res);
|
|
237550
|
+
return;
|
|
237551
|
+
}
|
|
237552
|
+
try {
|
|
237553
|
+
const modelPath = req.params["0"];
|
|
237554
|
+
res.status(200).json(await modelController.getModel(req.params.projectName, req.params.packageName, modelPath));
|
|
237555
|
+
} catch (error) {
|
|
237556
|
+
logger.error(error);
|
|
237557
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237558
|
+
res.status(status).json(json);
|
|
237559
|
+
}
|
|
237560
|
+
});
|
|
237561
|
+
app.post(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/models/*?/query`, async (req, res) => {
|
|
237562
|
+
if (req.body.versionId) {
|
|
237563
|
+
setVersionIdError(res);
|
|
237564
|
+
return;
|
|
237565
|
+
}
|
|
237566
|
+
try {
|
|
237567
|
+
const modelPath = req.params["0"];
|
|
237568
|
+
res.status(200).json(await queryController.getQuery(req.params.projectName, req.params.packageName, modelPath, req.body.sourceName, req.body.queryName, req.body.query, req.body.compactJson === true, req.body.filterParams ?? req.body.sourceFilters, req.body.bypassFilters === true ? true : undefined));
|
|
237569
|
+
} catch (error) {
|
|
237570
|
+
logger.error(error);
|
|
237571
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237572
|
+
res.status(status).json(json);
|
|
237573
|
+
}
|
|
237574
|
+
});
|
|
237575
|
+
app.post(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/models/:modelName/compile`, async (req, res) => {
|
|
237576
|
+
try {
|
|
237577
|
+
const result = await compileController.compile(req.params.projectName, req.params.packageName, req.params.modelName, req.body.source, req.body.includeSql === true);
|
|
237578
|
+
res.status(200).json(result);
|
|
237579
|
+
} catch (error) {
|
|
237580
|
+
logger.error("Compilation error", { error });
|
|
237581
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237582
|
+
res.status(status).json(json);
|
|
237583
|
+
}
|
|
237584
|
+
});
|
|
237585
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/notebooks`, async (req, res) => {
|
|
237586
|
+
if (req.query.versionId) {
|
|
237587
|
+
setVersionIdError(res);
|
|
237588
|
+
return;
|
|
237589
|
+
}
|
|
237590
|
+
try {
|
|
237591
|
+
res.status(200).json(await modelController.listNotebooks(req.params.projectName, req.params.packageName));
|
|
237592
|
+
} catch (error) {
|
|
237593
|
+
logger.error(error);
|
|
237594
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237595
|
+
res.status(status).json(json);
|
|
237596
|
+
}
|
|
237597
|
+
});
|
|
237598
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/notebooks/*/cells/:cellIndex`, async (req, res) => {
|
|
237599
|
+
if (req.query.versionId) {
|
|
237600
|
+
setVersionIdError(res);
|
|
237601
|
+
return;
|
|
237602
|
+
}
|
|
237603
|
+
try {
|
|
237604
|
+
const cellIndex = parseInt(req.params.cellIndex, 10);
|
|
237605
|
+
if (isNaN(cellIndex)) {
|
|
237606
|
+
res.status(400).json({ error: "Invalid cell index" });
|
|
237607
|
+
return;
|
|
237608
|
+
}
|
|
237609
|
+
const notebookPath = req.params["0"];
|
|
237610
|
+
let filterParams;
|
|
237611
|
+
if (typeof req.query.filter_params === "string") {
|
|
237612
|
+
try {
|
|
237613
|
+
filterParams = JSON.parse(req.query.filter_params);
|
|
237614
|
+
} catch {
|
|
237615
|
+
res.status(400).json({
|
|
237616
|
+
error: "Invalid filter_params: must be valid JSON"
|
|
237617
|
+
});
|
|
237618
|
+
return;
|
|
237619
|
+
}
|
|
237620
|
+
}
|
|
237621
|
+
const bypassFilters = req.query.bypass_filters === "true" ? true : undefined;
|
|
237622
|
+
res.status(200).json(await modelController.executeNotebookCell(req.params.projectName, req.params.packageName, notebookPath, cellIndex, filterParams, bypassFilters));
|
|
237623
|
+
} catch (error) {
|
|
237624
|
+
logger.error(error);
|
|
237625
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237626
|
+
res.status(status).json(json);
|
|
237627
|
+
}
|
|
237628
|
+
});
|
|
237629
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/notebooks/*?`, async (req, res) => {
|
|
237630
|
+
if (req.query.versionId) {
|
|
237631
|
+
setVersionIdError(res);
|
|
237632
|
+
return;
|
|
237633
|
+
}
|
|
237634
|
+
try {
|
|
237635
|
+
const notebookPath = req.params["0"];
|
|
237636
|
+
res.status(200).json(await modelController.getNotebook(req.params.projectName, req.params.packageName, notebookPath));
|
|
237637
|
+
} catch (error) {
|
|
237638
|
+
logger.error(error);
|
|
237639
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237640
|
+
res.status(status).json(json);
|
|
237641
|
+
}
|
|
237642
|
+
});
|
|
237643
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/databases`, async (req, res) => {
|
|
237644
|
+
if (req.query.versionId) {
|
|
237645
|
+
setVersionIdError(res);
|
|
237646
|
+
return;
|
|
237647
|
+
}
|
|
237648
|
+
try {
|
|
237649
|
+
res.status(200).json(await databaseController.listDatabases(req.params.projectName, req.params.packageName));
|
|
237650
|
+
} catch (error) {
|
|
237651
|
+
logger.error(error);
|
|
237652
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237653
|
+
res.status(status).json(json);
|
|
237654
|
+
}
|
|
237655
|
+
});
|
|
237656
|
+
app.post(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/materializations`, async (req, res) => {
|
|
237657
|
+
try {
|
|
237658
|
+
const build = await materializationController.createMaterialization(req.params.projectName, req.params.packageName, req.body || {});
|
|
237659
|
+
res.status(201).json(remapMaterializationResponse(build));
|
|
237660
|
+
} catch (error) {
|
|
237661
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237662
|
+
res.status(status).json(json);
|
|
237663
|
+
}
|
|
237664
|
+
});
|
|
237665
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/materializations`, async (req, res) => {
|
|
237666
|
+
try {
|
|
237667
|
+
const limit = req.query.limit ? parseInt(req.query.limit, 10) : undefined;
|
|
237668
|
+
const offset = req.query.offset ? parseInt(req.query.offset, 10) : undefined;
|
|
237669
|
+
const builds = await materializationController.listMaterializations(req.params.projectName, req.params.packageName, { limit, offset });
|
|
237670
|
+
res.status(200).json(remapMaterializationResponse(builds));
|
|
237671
|
+
} catch (error) {
|
|
237672
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237673
|
+
res.status(status).json(json);
|
|
237674
|
+
}
|
|
237675
|
+
});
|
|
237676
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/materializations/:materializationId`, async (req, res) => {
|
|
237677
|
+
try {
|
|
237678
|
+
const build = await materializationController.getMaterialization(req.params.projectName, req.params.packageName, req.params.materializationId);
|
|
237679
|
+
res.status(200).json(remapMaterializationResponse(build));
|
|
237680
|
+
} catch (error) {
|
|
237681
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237682
|
+
res.status(status).json(json);
|
|
237683
|
+
}
|
|
237684
|
+
});
|
|
237685
|
+
app.post(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/materializations/teardown`, async (req, res) => {
|
|
237686
|
+
try {
|
|
237687
|
+
const result = await materializationController.teardownPackage(req.params.projectName, req.params.packageName, req.body || {});
|
|
237688
|
+
res.status(200).json(result);
|
|
237689
|
+
} catch (error) {
|
|
237690
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237691
|
+
res.status(status).json(json);
|
|
237692
|
+
}
|
|
237693
|
+
});
|
|
237694
|
+
app.post(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/materializations/:materializationId`, async (req, res) => {
|
|
237695
|
+
try {
|
|
237696
|
+
const action = req.query.action;
|
|
237697
|
+
if (action === "start") {
|
|
237698
|
+
const build = await materializationController.startMaterialization(req.params.projectName, req.params.packageName, req.params.materializationId);
|
|
237699
|
+
res.status(202).json(remapMaterializationResponse(build));
|
|
237700
|
+
} else if (action === "stop") {
|
|
237701
|
+
const build = await materializationController.stopMaterialization(req.params.projectName, req.params.packageName, req.params.materializationId);
|
|
237702
|
+
res.status(200).json(remapMaterializationResponse(build));
|
|
237703
|
+
} else {
|
|
237704
|
+
throw new BadRequestError(`Unsupported action '${String(action ?? "")}'. Expected 'start' or 'stop'.`);
|
|
237705
|
+
}
|
|
237706
|
+
} catch (error) {
|
|
237707
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237708
|
+
res.status(status).json(json);
|
|
237709
|
+
}
|
|
237710
|
+
});
|
|
237711
|
+
app.delete(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/materializations/:materializationId`, async (req, res) => {
|
|
237712
|
+
try {
|
|
237713
|
+
await materializationController.deleteMaterialization(req.params.projectName, req.params.packageName, req.params.materializationId);
|
|
237714
|
+
res.status(204).send();
|
|
237715
|
+
} catch (error) {
|
|
237716
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237717
|
+
res.status(status).json(json);
|
|
237718
|
+
}
|
|
237719
|
+
});
|
|
237720
|
+
app.get(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/manifest`, async (req, res) => {
|
|
237721
|
+
try {
|
|
237722
|
+
const manifest = await manifestController.getManifest(req.params.projectName, req.params.packageName);
|
|
237723
|
+
res.status(200).json(manifest);
|
|
237724
|
+
} catch (error) {
|
|
237725
|
+
logger.error("Get manifest error", { error });
|
|
237726
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237727
|
+
res.status(status).json(json);
|
|
237728
|
+
}
|
|
237729
|
+
});
|
|
237730
|
+
app.post(`${LEGACY_API_PREFIX}/projects/:projectName/packages/:packageName/manifest`, async (req, res) => {
|
|
237731
|
+
try {
|
|
237732
|
+
const action = req.query.action;
|
|
237733
|
+
if (action === "reload") {
|
|
237734
|
+
const manifest = await manifestController.reloadManifest(req.params.projectName, req.params.packageName);
|
|
237735
|
+
res.status(200).json(manifest);
|
|
237736
|
+
} else {
|
|
237737
|
+
throw new BadRequestError(`Unsupported action '${String(action ?? "")}'. Expected 'reload'.`);
|
|
237738
|
+
}
|
|
237739
|
+
} catch (error) {
|
|
237740
|
+
logger.error("Manifest action error", { error });
|
|
237741
|
+
const { json, status } = internalErrorToHttpError(error);
|
|
237742
|
+
res.status(status).json(json);
|
|
237743
|
+
}
|
|
237744
|
+
});
|
|
237745
|
+
logger.info("Legacy /projects/* routes registered for backwards compatibility");
|
|
237746
|
+
}
|
|
237747
|
+
|
|
236989
237748
|
// src/service/manifest_service.ts
|
|
236990
237749
|
class ManifestService {
|
|
236991
237750
|
environmentStore;
|
|
@@ -237036,8 +237795,8 @@ import {
|
|
|
237036
237795
|
} from "@malloydata/malloy";
|
|
237037
237796
|
|
|
237038
237797
|
// src/service/quoting.ts
|
|
237039
|
-
function quoteTablePath(
|
|
237040
|
-
return
|
|
237798
|
+
function quoteTablePath(path12, dialect) {
|
|
237799
|
+
return path12.split(".").map((seg) => dialect.quoteTablePath(seg)).join(".");
|
|
237041
237800
|
}
|
|
237042
237801
|
function splitTablePath(tableName) {
|
|
237043
237802
|
const lastDot = tableName.lastIndexOf(".");
|
|
@@ -237635,6 +238394,8 @@ function normalizeQueryArray(value) {
|
|
|
237635
238394
|
}
|
|
237636
238395
|
function parseArgs() {
|
|
237637
238396
|
const args = process.argv.slice(2);
|
|
238397
|
+
let sawServerRoot = false;
|
|
238398
|
+
let sawConfig = false;
|
|
237638
238399
|
for (let i = 0;i < args.length; i++) {
|
|
237639
238400
|
const arg = args[i];
|
|
237640
238401
|
if (arg === "--port" && args[i + 1]) {
|
|
@@ -237644,8 +238405,13 @@ function parseArgs() {
|
|
|
237644
238405
|
process.env.PUBLISHER_HOST = args[i + 1];
|
|
237645
238406
|
i++;
|
|
237646
238407
|
} else if (arg === "--server_root" && args[i + 1]) {
|
|
238408
|
+
sawServerRoot = true;
|
|
237647
238409
|
process.env.SERVER_ROOT = args[i + 1];
|
|
237648
238410
|
i++;
|
|
238411
|
+
} else if (arg === "--config" && args[i + 1]) {
|
|
238412
|
+
sawConfig = true;
|
|
238413
|
+
process.env.PUBLISHER_CONFIG_PATH = args[i + 1];
|
|
238414
|
+
i++;
|
|
237649
238415
|
} else if (arg === "--mcp_port" && args[i + 1]) {
|
|
237650
238416
|
process.env.MCP_PORT = args[i + 1];
|
|
237651
238417
|
i++;
|
|
@@ -237666,6 +238432,7 @@ function parseArgs() {
|
|
|
237666
238432
|
console.log(" --port <number> Port to run the server on (default: 4000)");
|
|
237667
238433
|
console.log(" --host <string> Host to bind the server to (default: localhost)");
|
|
237668
238434
|
console.log(" --server_root <path> Root directory to serve files from (default: .)");
|
|
238435
|
+
console.log(" --config <path> Path to publisher.config.json (default: <server_root>/publisher.config.json; falls back to bundled DuckDB-only sample config if missing)");
|
|
237669
238436
|
console.log(" --mcp_port <number> Port for MCP server (default: 4040)");
|
|
237670
238437
|
console.log(" --shutdown_drain_duration_seconds <number> Time in seconds to keep service in draining state before closing servers (default: 0)");
|
|
237671
238438
|
console.log(" --shutdown_graceful_close_timeout_seconds <number> Time in seconds to wait after closing servers before exit (default: 0)");
|
|
@@ -237674,6 +238441,9 @@ function parseArgs() {
|
|
|
237674
238441
|
process.exit(0);
|
|
237675
238442
|
}
|
|
237676
238443
|
}
|
|
238444
|
+
if (!sawServerRoot && !sawConfig && true) {
|
|
238445
|
+
process.env.PUBLISHER_USE_BUNDLED_DEFAULT = "true";
|
|
238446
|
+
}
|
|
237677
238447
|
}
|
|
237678
238448
|
parseArgs();
|
|
237679
238449
|
var PUBLISHER_PORT = Number(process.env.PUBLISHER_PORT || 4000);
|
|
@@ -237682,9 +238452,9 @@ var MCP_PORT = Number(process.env.MCP_PORT || 4040);
|
|
|
237682
238452
|
var MCP_ENDPOINT = "/mcp";
|
|
237683
238453
|
var SHUTDOWN_DRAIN_DURATION_SECONDS = Number(process.env.SHUTDOWN_DRAIN_DURATION_SECONDS || 0);
|
|
237684
238454
|
var SHUTDOWN_GRACEFUL_CLOSE_TIMEOUT_SECONDS = Number(process.env.SHUTDOWN_GRACEFUL_CLOSE_TIMEOUT_SECONDS || 0);
|
|
237685
|
-
var __filename_esm =
|
|
237686
|
-
var ROOT =
|
|
237687
|
-
var SERVER_ROOT =
|
|
238455
|
+
var __filename_esm = fileURLToPath3(import.meta.url);
|
|
238456
|
+
var ROOT = path12.join(path12.dirname(__filename_esm), "app");
|
|
238457
|
+
var SERVER_ROOT = path12.resolve(process.cwd(), process.env.SERVER_ROOT || ".");
|
|
237688
238458
|
var API_PREFIX2 = "/api/v0";
|
|
237689
238459
|
var isDevelopment = process.env["NODE_ENV"] === "development";
|
|
237690
238460
|
var app = import_express.default();
|
|
@@ -237765,17 +238535,17 @@ mcpApp.all(MCP_ENDPOINT, async (req, res) => {
|
|
|
237765
238535
|
});
|
|
237766
238536
|
if (!isDevelopment) {
|
|
237767
238537
|
app.use("/", import_express.default.static(ROOT));
|
|
237768
|
-
app.use("/api-doc.html", import_express.default.static(
|
|
238538
|
+
app.use("/api-doc.html", import_express.default.static(path12.join(ROOT, "api-doc.html")));
|
|
237769
238539
|
} else {
|
|
237770
238540
|
app.use(`${API_PREFIX2}`, loggerMiddleware);
|
|
237771
238541
|
app.use(import_http_proxy_middleware.createProxyMiddleware({
|
|
237772
238542
|
target: "http://localhost:5173",
|
|
237773
238543
|
changeOrigin: true,
|
|
237774
238544
|
ws: true,
|
|
237775
|
-
pathFilter: (
|
|
238545
|
+
pathFilter: (path13) => !path13.startsWith("/api/") && !path13.startsWith("/metrics") && !path13.startsWith("/health")
|
|
237776
238546
|
}));
|
|
237777
238547
|
}
|
|
237778
|
-
var
|
|
238548
|
+
var setVersionIdError2 = (res) => {
|
|
237779
238549
|
const { json, status } = internalErrorToHttpError(new NotImplementedError("Version IDs not implemented."));
|
|
237780
238550
|
res.status(status).json(json);
|
|
237781
238551
|
};
|
|
@@ -237783,7 +238553,7 @@ app.use(import_cors.default({
|
|
|
237783
238553
|
origin: "http://localhost:5173",
|
|
237784
238554
|
credentials: true
|
|
237785
238555
|
}));
|
|
237786
|
-
app.use(
|
|
238556
|
+
app.use(import_body_parser2.default.json({ limit: "1mb" }));
|
|
237787
238557
|
registerHealthEndpoints(app);
|
|
237788
238558
|
try {
|
|
237789
238559
|
const metricsHandler = getPrometheusMetricsHandler();
|
|
@@ -238094,7 +238864,7 @@ app.post(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/con
|
|
|
238094
238864
|
});
|
|
238095
238865
|
app.get(`${API_PREFIX2}/environments/:environmentName/packages`, async (req, res) => {
|
|
238096
238866
|
if (req.query.versionId) {
|
|
238097
|
-
|
|
238867
|
+
setVersionIdError2(res);
|
|
238098
238868
|
return;
|
|
238099
238869
|
}
|
|
238100
238870
|
try {
|
|
@@ -238118,7 +238888,7 @@ app.post(`${API_PREFIX2}/environments/:environmentName/packages`, async (req, re
|
|
|
238118
238888
|
});
|
|
238119
238889
|
app.get(`${API_PREFIX2}/environments/:environmentName/packages/:packageName`, async (req, res) => {
|
|
238120
238890
|
if (req.query.versionId) {
|
|
238121
|
-
|
|
238891
|
+
setVersionIdError2(res);
|
|
238122
238892
|
return;
|
|
238123
238893
|
}
|
|
238124
238894
|
try {
|
|
@@ -238149,7 +238919,7 @@ app.delete(`${API_PREFIX2}/environments/:environmentName/packages/:packageName`,
|
|
|
238149
238919
|
});
|
|
238150
238920
|
app.get(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/models`, async (req, res) => {
|
|
238151
238921
|
if (req.query.versionId) {
|
|
238152
|
-
|
|
238922
|
+
setVersionIdError2(res);
|
|
238153
238923
|
return;
|
|
238154
238924
|
}
|
|
238155
238925
|
try {
|
|
@@ -238162,7 +238932,7 @@ app.get(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/mode
|
|
|
238162
238932
|
});
|
|
238163
238933
|
app.get(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/models/*?`, async (req, res) => {
|
|
238164
238934
|
if (req.query.versionId) {
|
|
238165
|
-
|
|
238935
|
+
setVersionIdError2(res);
|
|
238166
238936
|
return;
|
|
238167
238937
|
}
|
|
238168
238938
|
try {
|
|
@@ -238176,7 +238946,7 @@ app.get(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/mode
|
|
|
238176
238946
|
});
|
|
238177
238947
|
app.get(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/notebooks`, async (req, res) => {
|
|
238178
238948
|
if (req.query.versionId) {
|
|
238179
|
-
|
|
238949
|
+
setVersionIdError2(res);
|
|
238180
238950
|
return;
|
|
238181
238951
|
}
|
|
238182
238952
|
try {
|
|
@@ -238189,7 +238959,7 @@ app.get(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/note
|
|
|
238189
238959
|
});
|
|
238190
238960
|
app.get(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/notebooks/*/cells/:cellIndex`, async (req, res) => {
|
|
238191
238961
|
if (req.query.versionId) {
|
|
238192
|
-
|
|
238962
|
+
setVersionIdError2(res);
|
|
238193
238963
|
return;
|
|
238194
238964
|
}
|
|
238195
238965
|
try {
|
|
@@ -238222,7 +238992,7 @@ app.get(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/note
|
|
|
238222
238992
|
});
|
|
238223
238993
|
app.get(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/notebooks/*?`, async (req, res) => {
|
|
238224
238994
|
if (req.query.versionId) {
|
|
238225
|
-
|
|
238995
|
+
setVersionIdError2(res);
|
|
238226
238996
|
return;
|
|
238227
238997
|
}
|
|
238228
238998
|
try {
|
|
@@ -238236,7 +239006,7 @@ app.get(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/note
|
|
|
238236
239006
|
});
|
|
238237
239007
|
app.post(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/models/*?/query`, async (req, res) => {
|
|
238238
239008
|
if (req.body.versionId) {
|
|
238239
|
-
|
|
239009
|
+
setVersionIdError2(res);
|
|
238240
239010
|
return;
|
|
238241
239011
|
}
|
|
238242
239012
|
try {
|
|
@@ -238250,7 +239020,7 @@ app.post(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/mod
|
|
|
238250
239020
|
});
|
|
238251
239021
|
app.get(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/databases`, async (req, res) => {
|
|
238252
239022
|
if (req.query.versionId) {
|
|
238253
|
-
|
|
239023
|
+
setVersionIdError2(res);
|
|
238254
239024
|
return;
|
|
238255
239025
|
}
|
|
238256
239026
|
try {
|
|
@@ -238360,8 +239130,19 @@ app.post(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/man
|
|
|
238360
239130
|
res.status(status).json(json);
|
|
238361
239131
|
}
|
|
238362
239132
|
});
|
|
239133
|
+
registerLegacyRoutes(app, {
|
|
239134
|
+
environmentStore,
|
|
239135
|
+
connectionController,
|
|
239136
|
+
modelController,
|
|
239137
|
+
packageController,
|
|
239138
|
+
databaseController,
|
|
239139
|
+
queryController,
|
|
239140
|
+
compileController,
|
|
239141
|
+
materializationController,
|
|
239142
|
+
manifestController
|
|
239143
|
+
});
|
|
238363
239144
|
if (!isDevelopment) {
|
|
238364
|
-
app.get("*", (_req, res) => res.sendFile(
|
|
239145
|
+
app.get("*", (_req, res) => res.sendFile(path12.resolve(ROOT, "index.html")));
|
|
238365
239146
|
}
|
|
238366
239147
|
app.use((err, _req, res, _next) => {
|
|
238367
239148
|
logger.error("Unhandled error:", err);
|