@malloy-publisher/server 0.0.197 → 0.0.198

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.
Files changed (36) hide show
  1. package/README.docker.md +47 -0
  2. package/dist/app/api-doc.yaml +3 -20
  3. package/dist/app/assets/{EnvironmentPage-BVkQH_xQ.js → EnvironmentPage-C7rtH4mC.js} +1 -1
  4. package/dist/app/assets/{HomePage-BgH9UkjK.js → HomePage-DwkH7OrS.js} +1 -1
  5. package/dist/app/assets/{MainPage-DiBxABem.js → MainPage-D38LtZDV.js} +1 -1
  6. package/dist/app/assets/{ModelPage-oS70fj83.js → ModelPage-DOol8Mz7.js} +1 -1
  7. package/dist/app/assets/{PackagePage-F_qLDAdv.js → PackagePage-0tgzA_kO.js} +1 -1
  8. package/dist/app/assets/{RouteError-WqpffppN.js → RouteError-BaMsOSly.js} +1 -1
  9. package/dist/app/assets/{WorkbookPage-_YmC-ebR.js → WorkbookPage-Cx4SePkx.js} +1 -1
  10. package/dist/app/assets/{core-B8L9xCYT.es-BcRLJTnC.js → core-CbsC6R_Y.es-Cwf6asf3.js} +1 -1
  11. package/dist/app/assets/{index-rg8Ok8nl.js → index-DL6BZTuw.js} +1 -1
  12. package/dist/app/assets/{index-C3XPaTaS.js → index-DNofXMxi.js} +1 -1
  13. package/dist/app/assets/{index-BMViiwtJ.js → index-U38AyjJL.js} +3 -3
  14. package/dist/app/assets/{index.umd-CCAfKkxY.js → index.umd-B68wGGkM.js} +1 -1
  15. package/dist/app/index.html +1 -1
  16. package/dist/server.mjs +812 -450
  17. package/package.json +1 -1
  18. package/src/config.spec.ts +81 -0
  19. package/src/config.ts +126 -0
  20. package/src/controller/package.controller.ts +70 -29
  21. package/src/errors.ts +13 -0
  22. package/src/health.ts +0 -26
  23. package/src/mcp/tools/discovery_tools.ts +6 -2
  24. package/src/path_safety.spec.ts +158 -0
  25. package/src/path_safety.ts +140 -0
  26. package/src/server.ts +13 -0
  27. package/src/service/environment.ts +614 -198
  28. package/src/service/environment_admission.spec.ts +180 -0
  29. package/src/service/environment_store.spec.ts +0 -19
  30. package/src/service/environment_store.ts +24 -21
  31. package/src/service/manifest_service.spec.ts +7 -2
  32. package/src/service/manifest_service.ts +8 -2
  33. package/src/service/materialization_service.ts +14 -3
  34. package/src/service/package_memory_governor.spec.ts +173 -0
  35. package/src/service/package_memory_governor.ts +233 -0
  36. package/src/service/package_race.spec.ts +208 -0
package/dist/server.mjs CHANGED
@@ -196989,26 +196989,26 @@ var require_utils74 = __commonJS((exports, module) => {
196989
196989
  }
196990
196990
  mkdirSync(folder);
196991
196991
  };
196992
- Utils.prototype.writeFileTo = function(path4, content, overwrite, attr) {
196992
+ Utils.prototype.writeFileTo = function(path3, content, overwrite, attr) {
196993
196993
  const self2 = this;
196994
- if (self2.fs.existsSync(path4)) {
196994
+ if (self2.fs.existsSync(path3)) {
196995
196995
  if (!overwrite)
196996
196996
  return false;
196997
- var stat4 = self2.fs.statSync(path4);
196997
+ var stat4 = self2.fs.statSync(path3);
196998
196998
  if (stat4.isDirectory()) {
196999
196999
  return false;
197000
197000
  }
197001
197001
  }
197002
- var folder = pth.dirname(path4);
197002
+ var folder = pth.dirname(path3);
197003
197003
  if (!self2.fs.existsSync(folder)) {
197004
197004
  self2.makeDir(folder);
197005
197005
  }
197006
197006
  var fd;
197007
197007
  try {
197008
- fd = self2.fs.openSync(path4, "w", 438);
197008
+ fd = self2.fs.openSync(path3, "w", 438);
197009
197009
  } catch (e) {
197010
- self2.fs.chmodSync(path4, 438);
197011
- fd = self2.fs.openSync(path4, "w", 438);
197010
+ self2.fs.chmodSync(path3, 438);
197011
+ fd = self2.fs.openSync(path3, "w", 438);
197012
197012
  }
197013
197013
  if (fd) {
197014
197014
  try {
@@ -197017,33 +197017,33 @@ var require_utils74 = __commonJS((exports, module) => {
197017
197017
  self2.fs.closeSync(fd);
197018
197018
  }
197019
197019
  }
197020
- self2.fs.chmodSync(path4, attr || 438);
197020
+ self2.fs.chmodSync(path3, attr || 438);
197021
197021
  return true;
197022
197022
  };
197023
- Utils.prototype.writeFileToAsync = function(path4, content, overwrite, attr, callback) {
197023
+ Utils.prototype.writeFileToAsync = function(path3, content, overwrite, attr, callback) {
197024
197024
  if (typeof attr === "function") {
197025
197025
  callback = attr;
197026
197026
  attr = undefined;
197027
197027
  }
197028
197028
  const self2 = this;
197029
- self2.fs.exists(path4, function(exist) {
197029
+ self2.fs.exists(path3, function(exist) {
197030
197030
  if (exist && !overwrite)
197031
197031
  return callback(false);
197032
- self2.fs.stat(path4, function(err, stat4) {
197032
+ self2.fs.stat(path3, function(err, stat4) {
197033
197033
  if (exist && stat4.isDirectory()) {
197034
197034
  return callback(false);
197035
197035
  }
197036
- var folder = pth.dirname(path4);
197036
+ var folder = pth.dirname(path3);
197037
197037
  self2.fs.exists(folder, function(exists) {
197038
197038
  if (!exists)
197039
197039
  self2.makeDir(folder);
197040
- self2.fs.open(path4, "w", 438, function(err2, fd) {
197040
+ self2.fs.open(path3, "w", 438, function(err2, fd) {
197041
197041
  if (err2) {
197042
- self2.fs.chmod(path4, 438, function() {
197043
- self2.fs.open(path4, "w", 438, function(err3, fd2) {
197042
+ self2.fs.chmod(path3, 438, function() {
197043
+ self2.fs.open(path3, "w", 438, function(err3, fd2) {
197044
197044
  self2.fs.write(fd2, content, 0, content.length, 0, function() {
197045
197045
  self2.fs.close(fd2, function() {
197046
- self2.fs.chmod(path4, attr || 438, function() {
197046
+ self2.fs.chmod(path3, attr || 438, function() {
197047
197047
  callback(true);
197048
197048
  });
197049
197049
  });
@@ -197053,13 +197053,13 @@ var require_utils74 = __commonJS((exports, module) => {
197053
197053
  } else if (fd) {
197054
197054
  self2.fs.write(fd, content, 0, content.length, 0, function() {
197055
197055
  self2.fs.close(fd, function() {
197056
- self2.fs.chmod(path4, attr || 438, function() {
197056
+ self2.fs.chmod(path3, attr || 438, function() {
197057
197057
  callback(true);
197058
197058
  });
197059
197059
  });
197060
197060
  });
197061
197061
  } else {
197062
- self2.fs.chmod(path4, attr || 438, function() {
197062
+ self2.fs.chmod(path3, attr || 438, function() {
197063
197063
  callback(true);
197064
197064
  });
197065
197065
  }
@@ -197068,7 +197068,7 @@ var require_utils74 = __commonJS((exports, module) => {
197068
197068
  });
197069
197069
  });
197070
197070
  };
197071
- Utils.prototype.findFiles = function(path4) {
197071
+ Utils.prototype.findFiles = function(path3) {
197072
197072
  const self2 = this;
197073
197073
  function findSync(dir, pattern, recursive) {
197074
197074
  if (typeof pattern === "boolean") {
@@ -197077,17 +197077,17 @@ var require_utils74 = __commonJS((exports, module) => {
197077
197077
  }
197078
197078
  let files = [];
197079
197079
  self2.fs.readdirSync(dir).forEach(function(file) {
197080
- const path5 = pth.join(dir, file);
197081
- const stat4 = self2.fs.statSync(path5);
197082
- if (!pattern || pattern.test(path5)) {
197083
- files.push(pth.normalize(path5) + (stat4.isDirectory() ? self2.sep : ""));
197080
+ const path4 = pth.join(dir, file);
197081
+ const stat4 = self2.fs.statSync(path4);
197082
+ if (!pattern || pattern.test(path4)) {
197083
+ files.push(pth.normalize(path4) + (stat4.isDirectory() ? self2.sep : ""));
197084
197084
  }
197085
197085
  if (stat4.isDirectory() && recursive)
197086
- files = files.concat(findSync(path5, pattern, recursive));
197086
+ files = files.concat(findSync(path4, pattern, recursive));
197087
197087
  });
197088
197088
  return files;
197089
197089
  }
197090
- return findSync(path4, undefined, true);
197090
+ return findSync(path3, undefined, true);
197091
197091
  };
197092
197092
  Utils.prototype.findFilesAsync = function(dir, cb) {
197093
197093
  const self2 = this;
@@ -197147,16 +197147,16 @@ var require_utils74 = __commonJS((exports, module) => {
197147
197147
  return "UNSUPPORTED (" + method + ")";
197148
197148
  }
197149
197149
  };
197150
- Utils.canonical = function(path4) {
197151
- if (!path4)
197150
+ Utils.canonical = function(path3) {
197151
+ if (!path3)
197152
197152
  return "";
197153
- const safeSuffix = pth.posix.normalize("/" + path4.split("\\").join("/"));
197153
+ const safeSuffix = pth.posix.normalize("/" + path3.split("\\").join("/"));
197154
197154
  return pth.join(".", safeSuffix);
197155
197155
  };
197156
- Utils.zipnamefix = function(path4) {
197157
- if (!path4)
197156
+ Utils.zipnamefix = function(path3) {
197157
+ if (!path3)
197158
197158
  return "";
197159
- const safeSuffix = pth.posix.normalize("/" + path4.split("\\").join("/"));
197159
+ const safeSuffix = pth.posix.normalize("/" + path3.split("\\").join("/"));
197160
197160
  return pth.posix.join(".", safeSuffix);
197161
197161
  };
197162
197162
  Utils.findLast = function(arr, callback) {
@@ -197174,9 +197174,9 @@ var require_utils74 = __commonJS((exports, module) => {
197174
197174
  prefix = pth.resolve(pth.normalize(prefix));
197175
197175
  var parts = name.split("/");
197176
197176
  for (var i = 0, l = parts.length;i < l; i++) {
197177
- var path4 = pth.normalize(pth.join(prefix, parts.slice(i, l).join(pth.sep)));
197178
- if (path4.indexOf(prefix) === 0) {
197179
- return path4;
197177
+ var path3 = pth.normalize(pth.join(prefix, parts.slice(i, l).join(pth.sep)));
197178
+ if (path3.indexOf(prefix) === 0) {
197179
+ return path3;
197180
197180
  }
197181
197181
  }
197182
197182
  return pth.normalize(pth.join(prefix, pth.basename(name)));
@@ -197214,8 +197214,8 @@ var require_utils74 = __commonJS((exports, module) => {
197214
197214
  // ../../node_modules/adm-zip/util/fattr.js
197215
197215
  var require_fattr = __commonJS((exports, module) => {
197216
197216
  var pth = __require("path");
197217
- module.exports = function(path4, { fs: fs2 }) {
197218
- var _path = path4 || "", _obj = newAttr(), _stat = null;
197217
+ module.exports = function(path3, { fs: fs2 }) {
197218
+ var _path = path3 || "", _obj = newAttr(), _stat = null;
197219
197219
  function newAttr() {
197220
197220
  return {
197221
197221
  directory: false,
@@ -198545,8 +198545,8 @@ var require_adm_zip = __commonJS((exports, module) => {
198545
198545
  return null;
198546
198546
  }
198547
198547
  function fixPath(zipPath) {
198548
- const { join: join4, normalize: normalize2, sep } = pth.posix;
198549
- return join4(".", normalize2(sep + zipPath.split("\\").join(sep) + sep));
198548
+ const { join: join3, normalize: normalize2, sep } = pth.posix;
198549
+ return join3(".", normalize2(sep + zipPath.split("\\").join(sep) + sep));
198550
198550
  }
198551
198551
  function filenameFilter(filterfn) {
198552
198552
  if (filterfn instanceof RegExp) {
@@ -199074,10 +199074,10 @@ var require_src122 = __commonJS((exports) => {
199074
199074
  var fs_1 = __require("fs");
199075
199075
  var debug_1 = __importDefault(require_src5());
199076
199076
  var log = debug_1.default("@kwsites/file-exists");
199077
- function check(path4, isFile2, isDirectory) {
199078
- log(`checking %s`, path4);
199077
+ function check(path3, isFile2, isDirectory) {
199078
+ log(`checking %s`, path3);
199079
199079
  try {
199080
- const stat4 = fs_1.statSync(path4);
199080
+ const stat4 = fs_1.statSync(path3);
199081
199081
  if (stat4.isFile() && isFile2) {
199082
199082
  log(`[OK] path represents a file`);
199083
199083
  return true;
@@ -199097,8 +199097,8 @@ var require_src122 = __commonJS((exports) => {
199097
199097
  throw e;
199098
199098
  }
199099
199099
  }
199100
- function exists(path4, type = exports.READABLE) {
199101
- return check(path4, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
199100
+ function exists(path3, type = exports.READABLE) {
199101
+ return check(path3, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
199102
199102
  }
199103
199103
  exports.exists = exists;
199104
199104
  exports.FILE = 1;
@@ -199984,12 +199984,12 @@ var require_recursive_readdir = __commonJS((exports, module) => {
199984
199984
  ignores = [];
199985
199985
  }
199986
199986
  if (!callback) {
199987
- return new Promise(function(resolve3, reject) {
199987
+ return new Promise(function(resolve4, reject) {
199988
199988
  readdir3(path7, ignores || [], function(err, data) {
199989
199989
  if (err) {
199990
199990
  reject(err);
199991
199991
  } else {
199992
- resolve3(data);
199992
+ resolve4(data);
199993
199993
  }
199994
199994
  });
199995
199995
  });
@@ -200771,7 +200771,7 @@ var require_uri_all = __commonJS((exports, module) => {
200771
200771
  target.fragment = relative4.fragment;
200772
200772
  return target;
200773
200773
  }
200774
- function resolve3(baseURI, relativeURI, options) {
200774
+ function resolve4(baseURI, relativeURI, options) {
200775
200775
  var schemelessOptions = assign({ scheme: "null" }, options);
200776
200776
  return serialize(resolveComponents(parse(baseURI, schemelessOptions), parse(relativeURI, schemelessOptions), schemelessOptions, true), schemelessOptions);
200777
200777
  }
@@ -201039,7 +201039,7 @@ var require_uri_all = __commonJS((exports, module) => {
201039
201039
  exports2.removeDotSegments = removeDotSegments;
201040
201040
  exports2.serialize = serialize;
201041
201041
  exports2.resolveComponents = resolveComponents;
201042
- exports2.resolve = resolve3;
201042
+ exports2.resolve = resolve4;
201043
201043
  exports2.normalize = normalize2;
201044
201044
  exports2.equal = equal;
201045
201045
  exports2.escapeComponent = escapeComponent;
@@ -201405,20 +201405,20 @@ var require_resolve2 = __commonJS((exports, module) => {
201405
201405
  var util5 = require_util13();
201406
201406
  var SchemaObject = require_schema_obj();
201407
201407
  var traverse = require_json_schema_traverse();
201408
- module.exports = resolve3;
201409
- resolve3.normalizeId = normalizeId;
201410
- resolve3.fullPath = getFullPath;
201411
- resolve3.url = resolveUrl;
201412
- resolve3.ids = resolveIds;
201413
- resolve3.inlineRef = inlineRef;
201414
- resolve3.schema = resolveSchema;
201415
- function resolve3(compile, root, ref) {
201408
+ module.exports = resolve4;
201409
+ resolve4.normalizeId = normalizeId;
201410
+ resolve4.fullPath = getFullPath;
201411
+ resolve4.url = resolveUrl;
201412
+ resolve4.ids = resolveIds;
201413
+ resolve4.inlineRef = inlineRef;
201414
+ resolve4.schema = resolveSchema;
201415
+ function resolve4(compile, root, ref) {
201416
201416
  var refVal = this._refs[ref];
201417
201417
  if (typeof refVal == "string") {
201418
201418
  if (this._refs[refVal])
201419
201419
  refVal = this._refs[refVal];
201420
201420
  else
201421
- return resolve3.call(this, compile, root, refVal);
201421
+ return resolve4.call(this, compile, root, refVal);
201422
201422
  }
201423
201423
  refVal = refVal || this._schemas[ref];
201424
201424
  if (refVal instanceof SchemaObject) {
@@ -201641,7 +201641,7 @@ var require_resolve2 = __commonJS((exports, module) => {
201641
201641
 
201642
201642
  // ../../node_modules/@modelcontextprotocol/sdk/node_modules/ajv/lib/compile/error_classes.js
201643
201643
  var require_error_classes = __commonJS((exports, module) => {
201644
- var resolve3 = require_resolve2();
201644
+ var resolve4 = require_resolve2();
201645
201645
  module.exports = {
201646
201646
  Validation: errorSubclass(ValidationError),
201647
201647
  MissingRef: errorSubclass(MissingRefError)
@@ -201656,8 +201656,8 @@ var require_error_classes = __commonJS((exports, module) => {
201656
201656
  };
201657
201657
  function MissingRefError(baseId, ref, message) {
201658
201658
  this.message = message || MissingRefError.message(baseId, ref);
201659
- this.missingRef = resolve3.url(baseId, ref);
201660
- this.missingSchema = resolve3.normalizeId(resolve3.fullPath(this.missingRef));
201659
+ this.missingRef = resolve4.url(baseId, ref);
201660
+ this.missingSchema = resolve4.normalizeId(resolve4.fullPath(this.missingRef));
201661
201661
  }
201662
201662
  function errorSubclass(Subclass) {
201663
201663
  Subclass.prototype = Object.create(Error.prototype);
@@ -202199,7 +202199,7 @@ var require_validate4 = __commonJS((exports, module) => {
202199
202199
 
202200
202200
  // ../../node_modules/@modelcontextprotocol/sdk/node_modules/ajv/lib/compile/index.js
202201
202201
  var require_compile2 = __commonJS((exports, module) => {
202202
- var resolve3 = require_resolve2();
202202
+ var resolve4 = require_resolve2();
202203
202203
  var util5 = require_util13();
202204
202204
  var errorClasses = require_error_classes();
202205
202205
  var stableStringify = require_fast_json_stable_stringify();
@@ -202259,7 +202259,7 @@ var require_compile2 = __commonJS((exports, module) => {
202259
202259
  RULES,
202260
202260
  validate: validateGenerator,
202261
202261
  util: util5,
202262
- resolve: resolve3,
202262
+ resolve: resolve4,
202263
202263
  resolveRef,
202264
202264
  usePattern,
202265
202265
  useDefault,
@@ -202298,7 +202298,7 @@ var require_compile2 = __commonJS((exports, module) => {
202298
202298
  return validate;
202299
202299
  }
202300
202300
  function resolveRef(baseId2, ref, isRoot) {
202301
- ref = resolve3.url(baseId2, ref);
202301
+ ref = resolve4.url(baseId2, ref);
202302
202302
  var refIndex = refs[ref];
202303
202303
  var _refVal, refCode;
202304
202304
  if (refIndex !== undefined) {
@@ -202315,11 +202315,11 @@ var require_compile2 = __commonJS((exports, module) => {
202315
202315
  }
202316
202316
  }
202317
202317
  refCode = addLocalRef(ref);
202318
- var v2 = resolve3.call(self2, localCompile, root, ref);
202318
+ var v2 = resolve4.call(self2, localCompile, root, ref);
202319
202319
  if (v2 === undefined) {
202320
202320
  var localSchema = localRefs && localRefs[ref];
202321
202321
  if (localSchema) {
202322
- v2 = resolve3.inlineRef(localSchema, opts.inlineRefs) ? localSchema : compile.call(self2, localSchema, root, localRefs, baseId2);
202322
+ v2 = resolve4.inlineRef(localSchema, opts.inlineRefs) ? localSchema : compile.call(self2, localSchema, root, localRefs, baseId2);
202323
202323
  }
202324
202324
  }
202325
202325
  if (v2 === undefined) {
@@ -205836,7 +205836,7 @@ var require_data2 = __commonJS((exports, module) => {
205836
205836
  // ../../node_modules/@modelcontextprotocol/sdk/node_modules/ajv/lib/ajv.js
205837
205837
  var require_ajv = __commonJS((exports, module) => {
205838
205838
  var compileSchema = require_compile2();
205839
- var resolve3 = require_resolve2();
205839
+ var resolve4 = require_resolve2();
205840
205840
  var Cache = require_cache();
205841
205841
  var SchemaObject = require_schema_obj();
205842
205842
  var stableStringify = require_fast_json_stable_stringify();
@@ -205928,7 +205928,7 @@ var require_ajv = __commonJS((exports, module) => {
205928
205928
  var id = this._getId(schema);
205929
205929
  if (id !== undefined && typeof id != "string")
205930
205930
  throw new Error("schema id must be string");
205931
- key = resolve3.normalizeId(key || id);
205931
+ key = resolve4.normalizeId(key || id);
205932
205932
  checkUnique(this, key);
205933
205933
  this._schemas[key] = this._addSchema(schema, _skipValidation, _meta, true);
205934
205934
  return this;
@@ -205974,7 +205974,7 @@ var require_ajv = __commonJS((exports, module) => {
205974
205974
  }
205975
205975
  }
205976
205976
  function _getSchemaFragment(self2, ref) {
205977
- var res = resolve3.schema.call(self2, { schema: {} }, ref);
205977
+ var res = resolve4.schema.call(self2, { schema: {} }, ref);
205978
205978
  if (res) {
205979
205979
  var { schema, root, baseId } = res;
205980
205980
  var v = compileSchema.call(self2, schema, root, undefined, baseId);
@@ -205990,7 +205990,7 @@ var require_ajv = __commonJS((exports, module) => {
205990
205990
  }
205991
205991
  }
205992
205992
  function _getSchemaObj(self2, keyRef) {
205993
- keyRef = resolve3.normalizeId(keyRef);
205993
+ keyRef = resolve4.normalizeId(keyRef);
205994
205994
  return self2._schemas[keyRef] || self2._refs[keyRef] || self2._fragments[keyRef];
205995
205995
  }
205996
205996
  function removeSchema(schemaKeyRef) {
@@ -206018,7 +206018,7 @@ var require_ajv = __commonJS((exports, module) => {
206018
206018
  this._cache.del(cacheKey);
206019
206019
  var id = this._getId(schemaKeyRef);
206020
206020
  if (id) {
206021
- id = resolve3.normalizeId(id);
206021
+ id = resolve4.normalizeId(id);
206022
206022
  delete this._schemas[id];
206023
206023
  delete this._refs[id];
206024
206024
  }
@@ -206043,14 +206043,14 @@ var require_ajv = __commonJS((exports, module) => {
206043
206043
  if (cached)
206044
206044
  return cached;
206045
206045
  shouldAddSchema = shouldAddSchema || this._opts.addUsedSchema !== false;
206046
- var id = resolve3.normalizeId(this._getId(schema));
206046
+ var id = resolve4.normalizeId(this._getId(schema));
206047
206047
  if (id && shouldAddSchema)
206048
206048
  checkUnique(this, id);
206049
206049
  var willValidate = this._opts.validateSchema !== false && !skipValidation;
206050
206050
  var recursiveMeta;
206051
- if (willValidate && !(recursiveMeta = id && id == resolve3.normalizeId(schema.$schema)))
206051
+ if (willValidate && !(recursiveMeta = id && id == resolve4.normalizeId(schema.$schema)))
206052
206052
  this.validateSchema(schema, true);
206053
- var localRefs = resolve3.ids.call(this, schema);
206053
+ var localRefs = resolve4.ids.call(this, schema);
206054
206054
  var schemaObj = new SchemaObject({
206055
206055
  id,
206056
206056
  schema,
@@ -209093,7 +209093,7 @@ var require_util14 = __commonJS((exports) => {
209093
209093
  }
209094
209094
  path12 = url2.path;
209095
209095
  }
209096
- var isAbsolute3 = exports.isAbsolute(path12);
209096
+ var isAbsolute4 = exports.isAbsolute(path12);
209097
209097
  var parts = path12.split(/\/+/);
209098
209098
  for (var part, up = 0, i = parts.length - 1;i >= 0; i--) {
209099
209099
  part = parts[i];
@@ -209113,7 +209113,7 @@ var require_util14 = __commonJS((exports) => {
209113
209113
  }
209114
209114
  path12 = parts.join("/");
209115
209115
  if (path12 === "") {
209116
- path12 = isAbsolute3 ? "/" : ".";
209116
+ path12 = isAbsolute4 ? "/" : ".";
209117
209117
  }
209118
209118
  if (url2) {
209119
209119
  url2.path = path12;
@@ -209122,7 +209122,7 @@ var require_util14 = __commonJS((exports) => {
209122
209122
  return path12;
209123
209123
  }
209124
209124
  exports.normalize = normalize2;
209125
- function join9(aRoot, aPath) {
209125
+ function join8(aRoot, aPath) {
209126
209126
  if (aRoot === "") {
209127
209127
  aRoot = ".";
209128
209128
  }
@@ -209154,7 +209154,7 @@ var require_util14 = __commonJS((exports) => {
209154
209154
  }
209155
209155
  return joined;
209156
209156
  }
209157
- exports.join = join9;
209157
+ exports.join = join8;
209158
209158
  exports.isAbsolute = function(aPath) {
209159
209159
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
209160
209160
  };
@@ -209327,7 +209327,7 @@ var require_util14 = __commonJS((exports) => {
209327
209327
  parsed.path = parsed.path.substring(0, index + 1);
209328
209328
  }
209329
209329
  }
209330
- sourceURL = join9(urlGenerate(parsed), sourceURL);
209330
+ sourceURL = join8(urlGenerate(parsed), sourceURL);
209331
209331
  }
209332
209332
  return normalize2(sourceURL);
209333
209333
  }
@@ -217008,6 +217008,8 @@ function internalErrorToHttpError(error) {
217008
217008
  return httpError(409, error.message);
217009
217009
  } else if (error instanceof InvalidStateTransitionError) {
217010
217010
  return httpError(409, error.message);
217011
+ } else if (error instanceof ServiceUnavailableError) {
217012
+ return httpError(503, error.message);
217011
217013
  } else {
217012
217014
  return httpError(500, error.message);
217013
217015
  }
@@ -217100,6 +217102,12 @@ class InvalidStateTransitionError extends Error {
217100
217102
  }
217101
217103
  }
217102
217104
 
217105
+ class ServiceUnavailableError extends Error {
217106
+ constructor(message) {
217107
+ super(message);
217108
+ }
217109
+ }
217110
+
217103
217111
  // src/service/connection.ts
217104
217112
  import"@malloydata/db-bigquery";
217105
217113
  import"@malloydata/db-databricks";
@@ -223161,7 +223169,6 @@ class ModelController {
223161
223169
  }
223162
223170
 
223163
223171
  // src/controller/package.controller.ts
223164
- import * as path3 from "path";
223165
223172
  class PackageController {
223166
223173
  environmentStore;
223167
223174
  manifestService;
@@ -223175,11 +223182,20 @@ class PackageController {
223175
223182
  }
223176
223183
  async getPackage(environmentName, packageName, reload) {
223177
223184
  const environment = await this.environmentStore.getEnvironment(environmentName, false);
223178
- const _package = await environment.getPackage(packageName, reload);
223179
- const packageLocation = _package.getPackageMetadata().location;
223180
- if (reload && packageLocation) {
223181
- await this.downloadPackage(environmentName, packageName, packageLocation);
223185
+ if (reload) {
223186
+ let location;
223187
+ try {
223188
+ const cached = await environment.getPackage(packageName, false);
223189
+ location = cached.getPackageMetadata().location;
223190
+ } catch {}
223191
+ if (location) {
223192
+ const reinstalled = await environment.installPackage(packageName, (stagingPath) => this.downloadInto(environmentName, packageName, location, stagingPath));
223193
+ return reinstalled.getPackageMetadata();
223194
+ }
223195
+ const _package2 = await environment.getPackage(packageName, true);
223196
+ return _package2.getPackageMetadata();
223182
223197
  }
223198
+ const _package = await environment.getPackage(packageName, false);
223183
223199
  return _package.getPackageMetadata();
223184
223200
  }
223185
223201
  async addPackage(environmentName, body, options) {
@@ -223189,14 +223205,18 @@ class PackageController {
223189
223205
  if (!body.name) {
223190
223206
  throw new BadRequestError("Package name is required");
223191
223207
  }
223208
+ const packageName = body.name;
223192
223209
  const environment = await this.environmentStore.getEnvironment(environmentName, false);
223210
+ let result;
223193
223211
  if (body.location) {
223194
- await this.downloadPackage(environmentName, body.name, body.location);
223212
+ const bodyLocation = body.location;
223213
+ result = await environment.installPackage(packageName, (stagingPath) => this.downloadInto(environmentName, packageName, bodyLocation, stagingPath));
223214
+ } else {
223215
+ result = await environment.addPackage(packageName);
223195
223216
  }
223196
- const result = await environment.addPackage(body.name);
223197
- await this.environmentStore.addPackageToDatabase(environmentName, body.name);
223217
+ await this.environmentStore.addPackageToDatabase(environmentName, packageName);
223198
223218
  if (options?.autoLoadManifest === true) {
223199
- await this.tryLoadExistingManifest(environmentName, body.name);
223219
+ await this.tryLoadExistingManifest(environmentName, packageName);
223200
223220
  }
223201
223221
  return result;
223202
223222
  }
@@ -223238,24 +223258,24 @@ class PackageController {
223238
223258
  }
223239
223259
  const environment = await this.environmentStore.getEnvironment(environmentName, false);
223240
223260
  if (body.location) {
223241
- await this.downloadPackage(environmentName, packageName, body.location);
223261
+ const bodyLocation = body.location;
223262
+ await environment.installPackage(packageName, (stagingPath) => this.downloadInto(environmentName, packageName, bodyLocation, stagingPath));
223242
223263
  }
223243
223264
  const result = await environment.updatePackage(packageName, body);
223244
223265
  await this.environmentStore.addPackageToDatabase(environmentName, packageName);
223245
223266
  return result;
223246
223267
  }
223247
- async downloadPackage(environmentName, packageName, packageLocation) {
223248
- const absoluteTargetPath = path3.join(this.environmentStore.serverRootPath, PUBLISHER_DATA_DIR, environmentName, packageName);
223268
+ async downloadInto(environmentName, packageName, packageLocation, targetPath) {
223249
223269
  const isCompressedFile = packageLocation.endsWith(".zip");
223250
223270
  if (packageLocation.startsWith("https://") || packageLocation.startsWith("git@")) {
223251
- await this.environmentStore.downloadGitHubDirectory(packageLocation, absoluteTargetPath);
223271
+ await this.environmentStore.downloadGitHubDirectory(packageLocation, targetPath);
223252
223272
  } else if (packageLocation.startsWith("gs://")) {
223253
- await this.environmentStore.downloadGcsDirectory(packageLocation, environmentName, absoluteTargetPath, isCompressedFile);
223273
+ await this.environmentStore.downloadGcsDirectory(packageLocation, environmentName, targetPath, isCompressedFile);
223254
223274
  } else if (packageLocation.startsWith("s3://")) {
223255
- await this.environmentStore.downloadS3Directory(packageLocation, environmentName, absoluteTargetPath, isCompressedFile);
223275
+ await this.environmentStore.downloadS3Directory(packageLocation, environmentName, targetPath, isCompressedFile);
223256
223276
  }
223257
223277
  if (packageLocation.startsWith("/")) {
223258
- await this.environmentStore.mountLocalDirectory(packageLocation, absoluteTargetPath, environmentName, packageName);
223278
+ await this.environmentStore.mountLocalDirectory(packageLocation, targetPath, environmentName, packageName);
223259
223279
  }
223260
223280
  }
223261
223281
  }
@@ -223369,7 +223389,7 @@ class ReaddirpStream extends Readable2 {
223369
223389
  this._directoryFilter = normalizeFilter(opts.directoryFilter);
223370
223390
  const statMethod = opts.lstat ? lstat : stat;
223371
223391
  if (wantBigintFsStats) {
223372
- this._stat = (path4) => statMethod(path4, { bigint: true });
223392
+ this._stat = (path3) => statMethod(path3, { bigint: true });
223373
223393
  } else {
223374
223394
  this._stat = statMethod;
223375
223395
  }
@@ -223394,8 +223414,8 @@ class ReaddirpStream extends Readable2 {
223394
223414
  const par = this.parent;
223395
223415
  const fil = par && par.files;
223396
223416
  if (fil && fil.length > 0) {
223397
- const { path: path4, depth } = par;
223398
- const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path4));
223417
+ const { path: path3, depth } = par;
223418
+ const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path3));
223399
223419
  const awaited = await Promise.all(slice);
223400
223420
  for (const entry of awaited) {
223401
223421
  if (!entry)
@@ -223435,20 +223455,20 @@ class ReaddirpStream extends Readable2 {
223435
223455
  this.reading = false;
223436
223456
  }
223437
223457
  }
223438
- async _exploreDir(path4, depth) {
223458
+ async _exploreDir(path3, depth) {
223439
223459
  let files;
223440
223460
  try {
223441
- files = await readdir(path4, this._rdOptions);
223461
+ files = await readdir(path3, this._rdOptions);
223442
223462
  } catch (error) {
223443
223463
  this._onError(error);
223444
223464
  }
223445
- return { files, depth, path: path4 };
223465
+ return { files, depth, path: path3 };
223446
223466
  }
223447
- async _formatEntry(dirent, path4) {
223467
+ async _formatEntry(dirent, path3) {
223448
223468
  let entry;
223449
223469
  const basename = this._isDirent ? dirent.name : dirent;
223450
223470
  try {
223451
- const fullPath = presolve(pjoin(path4, basename));
223471
+ const fullPath = presolve(pjoin(path3, basename));
223452
223472
  entry = { path: prelative(this._root, fullPath), fullPath, basename };
223453
223473
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
223454
223474
  } catch (err) {
@@ -223847,16 +223867,16 @@ var delFromSet = (main, prop, item) => {
223847
223867
  };
223848
223868
  var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
223849
223869
  var FsWatchInstances = new Map;
223850
- function createFsWatchInstance(path4, options, listener, errHandler, emitRaw) {
223870
+ function createFsWatchInstance(path3, options, listener, errHandler, emitRaw) {
223851
223871
  const handleEvent = (rawEvent, evPath) => {
223852
- listener(path4);
223853
- emitRaw(rawEvent, evPath, { watchedPath: path4 });
223854
- if (evPath && path4 !== evPath) {
223855
- fsWatchBroadcast(sysPath.resolve(path4, evPath), KEY_LISTENERS, sysPath.join(path4, evPath));
223872
+ listener(path3);
223873
+ emitRaw(rawEvent, evPath, { watchedPath: path3 });
223874
+ if (evPath && path3 !== evPath) {
223875
+ fsWatchBroadcast(sysPath.resolve(path3, evPath), KEY_LISTENERS, sysPath.join(path3, evPath));
223856
223876
  }
223857
223877
  };
223858
223878
  try {
223859
- return fs_watch(path4, {
223879
+ return fs_watch(path3, {
223860
223880
  persistent: options.persistent
223861
223881
  }, handleEvent);
223862
223882
  } catch (error) {
@@ -223872,12 +223892,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
223872
223892
  listener(val1, val2, val3);
223873
223893
  });
223874
223894
  };
223875
- var setFsWatchListener = (path4, fullPath, options, handlers) => {
223895
+ var setFsWatchListener = (path3, fullPath, options, handlers) => {
223876
223896
  const { listener, errHandler, rawEmitter } = handlers;
223877
223897
  let cont = FsWatchInstances.get(fullPath);
223878
223898
  let watcher;
223879
223899
  if (!options.persistent) {
223880
- watcher = createFsWatchInstance(path4, options, listener, errHandler, rawEmitter);
223900
+ watcher = createFsWatchInstance(path3, options, listener, errHandler, rawEmitter);
223881
223901
  if (!watcher)
223882
223902
  return;
223883
223903
  return watcher.close.bind(watcher);
@@ -223887,7 +223907,7 @@ var setFsWatchListener = (path4, fullPath, options, handlers) => {
223887
223907
  addAndConvert(cont, KEY_ERR, errHandler);
223888
223908
  addAndConvert(cont, KEY_RAW, rawEmitter);
223889
223909
  } else {
223890
- watcher = createFsWatchInstance(path4, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, fsWatchBroadcast.bind(null, fullPath, KEY_RAW));
223910
+ watcher = createFsWatchInstance(path3, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, fsWatchBroadcast.bind(null, fullPath, KEY_RAW));
223891
223911
  if (!watcher)
223892
223912
  return;
223893
223913
  watcher.on(EV.ERROR, async (error) => {
@@ -223896,7 +223916,7 @@ var setFsWatchListener = (path4, fullPath, options, handlers) => {
223896
223916
  cont.watcherUnusable = true;
223897
223917
  if (isWindows && error.code === "EPERM") {
223898
223918
  try {
223899
- const fd = await open(path4, "r");
223919
+ const fd = await open(path3, "r");
223900
223920
  await fd.close();
223901
223921
  broadcastErr(error);
223902
223922
  } catch (err) {}
@@ -223926,7 +223946,7 @@ var setFsWatchListener = (path4, fullPath, options, handlers) => {
223926
223946
  };
223927
223947
  };
223928
223948
  var FsWatchFileInstances = new Map;
223929
- var setFsWatchFileListener = (path4, fullPath, options, handlers) => {
223949
+ var setFsWatchFileListener = (path3, fullPath, options, handlers) => {
223930
223950
  const { listener, rawEmitter } = handlers;
223931
223951
  let cont = FsWatchFileInstances.get(fullPath);
223932
223952
  const copts = cont && cont.options;
@@ -223948,7 +223968,7 @@ var setFsWatchFileListener = (path4, fullPath, options, handlers) => {
223948
223968
  });
223949
223969
  const currmtime = curr.mtimeMs;
223950
223970
  if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
223951
- foreach(cont.listeners, (listener2) => listener2(path4, curr));
223971
+ foreach(cont.listeners, (listener2) => listener2(path3, curr));
223952
223972
  }
223953
223973
  })
223954
223974
  };
@@ -223971,13 +223991,13 @@ class NodeFsHandler {
223971
223991
  this.fsw = fsW;
223972
223992
  this._boundHandleError = (error) => fsW._handleError(error);
223973
223993
  }
223974
- _watchWithNodeFs(path4, listener) {
223994
+ _watchWithNodeFs(path3, listener) {
223975
223995
  const opts = this.fsw.options;
223976
- const directory = sysPath.dirname(path4);
223977
- const basename2 = sysPath.basename(path4);
223996
+ const directory = sysPath.dirname(path3);
223997
+ const basename2 = sysPath.basename(path3);
223978
223998
  const parent = this.fsw._getWatchedDir(directory);
223979
223999
  parent.add(basename2);
223980
- const absolutePath = sysPath.resolve(path4);
224000
+ const absolutePath = sysPath.resolve(path3);
223981
224001
  const options = {
223982
224002
  persistent: opts.persistent
223983
224003
  };
@@ -223987,12 +224007,12 @@ class NodeFsHandler {
223987
224007
  if (opts.usePolling) {
223988
224008
  const enableBin = opts.interval !== opts.binaryInterval;
223989
224009
  options.interval = enableBin && isBinaryPath(basename2) ? opts.binaryInterval : opts.interval;
223990
- closer = setFsWatchFileListener(path4, absolutePath, options, {
224010
+ closer = setFsWatchFileListener(path3, absolutePath, options, {
223991
224011
  listener,
223992
224012
  rawEmitter: this.fsw._emitRaw
223993
224013
  });
223994
224014
  } else {
223995
- closer = setFsWatchListener(path4, absolutePath, options, {
224015
+ closer = setFsWatchListener(path3, absolutePath, options, {
223996
224016
  listener,
223997
224017
  errHandler: this._boundHandleError,
223998
224018
  rawEmitter: this.fsw._emitRaw
@@ -224010,7 +224030,7 @@ class NodeFsHandler {
224010
224030
  let prevStats = stats;
224011
224031
  if (parent.has(basename2))
224012
224032
  return;
224013
- const listener = async (path4, newStats) => {
224033
+ const listener = async (path3, newStats) => {
224014
224034
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
224015
224035
  return;
224016
224036
  if (!newStats || newStats.mtimeMs === 0) {
@@ -224024,11 +224044,11 @@ class NodeFsHandler {
224024
224044
  this.fsw._emit(EV.CHANGE, file, newStats2);
224025
224045
  }
224026
224046
  if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
224027
- this.fsw._closeFile(path4);
224047
+ this.fsw._closeFile(path3);
224028
224048
  prevStats = newStats2;
224029
224049
  const closer2 = this._watchWithNodeFs(file, listener);
224030
224050
  if (closer2)
224031
- this.fsw._addPathCloser(path4, closer2);
224051
+ this.fsw._addPathCloser(path3, closer2);
224032
224052
  } else {
224033
224053
  prevStats = newStats2;
224034
224054
  }
@@ -224052,7 +224072,7 @@ class NodeFsHandler {
224052
224072
  }
224053
224073
  return closer;
224054
224074
  }
224055
- async _handleSymlink(entry, directory, path4, item) {
224075
+ async _handleSymlink(entry, directory, path3, item) {
224056
224076
  if (this.fsw.closed) {
224057
224077
  return;
224058
224078
  }
@@ -224062,7 +224082,7 @@ class NodeFsHandler {
224062
224082
  this.fsw._incrReadyCount();
224063
224083
  let linkPath;
224064
224084
  try {
224065
- linkPath = await fsrealpath(path4);
224085
+ linkPath = await fsrealpath(path3);
224066
224086
  } catch (e) {
224067
224087
  this.fsw._emitReady();
224068
224088
  return true;
@@ -224072,12 +224092,12 @@ class NodeFsHandler {
224072
224092
  if (dir.has(item)) {
224073
224093
  if (this.fsw._symlinkPaths.get(full) !== linkPath) {
224074
224094
  this.fsw._symlinkPaths.set(full, linkPath);
224075
- this.fsw._emit(EV.CHANGE, path4, entry.stats);
224095
+ this.fsw._emit(EV.CHANGE, path3, entry.stats);
224076
224096
  }
224077
224097
  } else {
224078
224098
  dir.add(item);
224079
224099
  this.fsw._symlinkPaths.set(full, linkPath);
224080
- this.fsw._emit(EV.ADD, path4, entry.stats);
224100
+ this.fsw._emit(EV.ADD, path3, entry.stats);
224081
224101
  }
224082
224102
  this.fsw._emitReady();
224083
224103
  return true;
@@ -224106,9 +224126,9 @@ class NodeFsHandler {
224106
224126
  return;
224107
224127
  }
224108
224128
  const item = entry.path;
224109
- let path4 = sysPath.join(directory, item);
224129
+ let path3 = sysPath.join(directory, item);
224110
224130
  current.add(item);
224111
- if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path4, item)) {
224131
+ if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path3, item)) {
224112
224132
  return;
224113
224133
  }
224114
224134
  if (this.fsw.closed) {
@@ -224117,8 +224137,8 @@ class NodeFsHandler {
224117
224137
  }
224118
224138
  if (item === target || !target && !previous.has(item)) {
224119
224139
  this.fsw._incrReadyCount();
224120
- path4 = sysPath.join(dir, sysPath.relative(dir, path4));
224121
- this._addToNodeFs(path4, initialAdd, wh, depth + 1);
224140
+ path3 = sysPath.join(dir, sysPath.relative(dir, path3));
224141
+ this._addToNodeFs(path3, initialAdd, wh, depth + 1);
224122
224142
  }
224123
224143
  }).on(EV.ERROR, this._boundHandleError);
224124
224144
  return new Promise((resolve2, reject) => {
@@ -224167,13 +224187,13 @@ class NodeFsHandler {
224167
224187
  }
224168
224188
  return closer;
224169
224189
  }
224170
- async _addToNodeFs(path4, initialAdd, priorWh, depth, target) {
224190
+ async _addToNodeFs(path3, initialAdd, priorWh, depth, target) {
224171
224191
  const ready = this.fsw._emitReady;
224172
- if (this.fsw._isIgnored(path4) || this.fsw.closed) {
224192
+ if (this.fsw._isIgnored(path3) || this.fsw.closed) {
224173
224193
  ready();
224174
224194
  return false;
224175
224195
  }
224176
- const wh = this.fsw._getWatchHelpers(path4);
224196
+ const wh = this.fsw._getWatchHelpers(path3);
224177
224197
  if (priorWh) {
224178
224198
  wh.filterPath = (entry) => priorWh.filterPath(entry);
224179
224199
  wh.filterDir = (entry) => priorWh.filterDir(entry);
@@ -224189,8 +224209,8 @@ class NodeFsHandler {
224189
224209
  const follow = this.fsw.options.followSymlinks;
224190
224210
  let closer;
224191
224211
  if (stats.isDirectory()) {
224192
- const absPath = sysPath.resolve(path4);
224193
- const targetPath = follow ? await fsrealpath(path4) : path4;
224212
+ const absPath = sysPath.resolve(path3);
224213
+ const targetPath = follow ? await fsrealpath(path3) : path3;
224194
224214
  if (this.fsw.closed)
224195
224215
  return;
224196
224216
  closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
@@ -224200,29 +224220,29 @@ class NodeFsHandler {
224200
224220
  this.fsw._symlinkPaths.set(absPath, targetPath);
224201
224221
  }
224202
224222
  } else if (stats.isSymbolicLink()) {
224203
- const targetPath = follow ? await fsrealpath(path4) : path4;
224223
+ const targetPath = follow ? await fsrealpath(path3) : path3;
224204
224224
  if (this.fsw.closed)
224205
224225
  return;
224206
224226
  const parent = sysPath.dirname(wh.watchPath);
224207
224227
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
224208
224228
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
224209
- closer = await this._handleDir(parent, stats, initialAdd, depth, path4, wh, targetPath);
224229
+ closer = await this._handleDir(parent, stats, initialAdd, depth, path3, wh, targetPath);
224210
224230
  if (this.fsw.closed)
224211
224231
  return;
224212
224232
  if (targetPath !== undefined) {
224213
- this.fsw._symlinkPaths.set(sysPath.resolve(path4), targetPath);
224233
+ this.fsw._symlinkPaths.set(sysPath.resolve(path3), targetPath);
224214
224234
  }
224215
224235
  } else {
224216
224236
  closer = this._handleFile(wh.watchPath, stats, initialAdd);
224217
224237
  }
224218
224238
  ready();
224219
224239
  if (closer)
224220
- this.fsw._addPathCloser(path4, closer);
224240
+ this.fsw._addPathCloser(path3, closer);
224221
224241
  return false;
224222
224242
  } catch (error) {
224223
224243
  if (this.fsw._handleError(error)) {
224224
224244
  ready();
224225
- return path4;
224245
+ return path3;
224226
224246
  }
224227
224247
  }
224228
224248
  }
@@ -224266,26 +224286,26 @@ function createPattern(matcher) {
224266
224286
  }
224267
224287
  return () => false;
224268
224288
  }
224269
- function normalizePath(path4) {
224270
- if (typeof path4 !== "string")
224289
+ function normalizePath(path3) {
224290
+ if (typeof path3 !== "string")
224271
224291
  throw new Error("string expected");
224272
- path4 = sysPath2.normalize(path4);
224273
- path4 = path4.replace(/\\/g, "/");
224292
+ path3 = sysPath2.normalize(path3);
224293
+ path3 = path3.replace(/\\/g, "/");
224274
224294
  let prepend = false;
224275
- if (path4.startsWith("//"))
224295
+ if (path3.startsWith("//"))
224276
224296
  prepend = true;
224277
224297
  const DOUBLE_SLASH_RE2 = /\/\//;
224278
- while (path4.match(DOUBLE_SLASH_RE2))
224279
- path4 = path4.replace(DOUBLE_SLASH_RE2, "/");
224298
+ while (path3.match(DOUBLE_SLASH_RE2))
224299
+ path3 = path3.replace(DOUBLE_SLASH_RE2, "/");
224280
224300
  if (prepend)
224281
- path4 = "/" + path4;
224282
- return path4;
224301
+ path3 = "/" + path3;
224302
+ return path3;
224283
224303
  }
224284
224304
  function matchPatterns(patterns, testString, stats) {
224285
- const path4 = normalizePath(testString);
224305
+ const path3 = normalizePath(testString);
224286
224306
  for (let index = 0;index < patterns.length; index++) {
224287
224307
  const pattern = patterns[index];
224288
- if (pattern(path4, stats)) {
224308
+ if (pattern(path3, stats)) {
224289
224309
  return true;
224290
224310
  }
224291
224311
  }
@@ -224325,19 +224345,19 @@ var toUnix = (string) => {
224325
224345
  }
224326
224346
  return str;
224327
224347
  };
224328
- var normalizePathToUnix = (path4) => toUnix(sysPath2.normalize(toUnix(path4)));
224329
- var normalizeIgnored = (cwd = "") => (path4) => {
224330
- if (typeof path4 === "string") {
224331
- return normalizePathToUnix(sysPath2.isAbsolute(path4) ? path4 : sysPath2.join(cwd, path4));
224348
+ var normalizePathToUnix = (path3) => toUnix(sysPath2.normalize(toUnix(path3)));
224349
+ var normalizeIgnored = (cwd = "") => (path3) => {
224350
+ if (typeof path3 === "string") {
224351
+ return normalizePathToUnix(sysPath2.isAbsolute(path3) ? path3 : sysPath2.join(cwd, path3));
224332
224352
  } else {
224333
- return path4;
224353
+ return path3;
224334
224354
  }
224335
224355
  };
224336
- var getAbsolutePath = (path4, cwd) => {
224337
- if (sysPath2.isAbsolute(path4)) {
224338
- return path4;
224356
+ var getAbsolutePath = (path3, cwd) => {
224357
+ if (sysPath2.isAbsolute(path3)) {
224358
+ return path3;
224339
224359
  }
224340
- return sysPath2.join(cwd, path4);
224360
+ return sysPath2.join(cwd, path3);
224341
224361
  };
224342
224362
  var EMPTY_SET = Object.freeze(new Set);
224343
224363
 
@@ -224394,10 +224414,10 @@ var STAT_METHOD_F = "stat";
224394
224414
  var STAT_METHOD_L = "lstat";
224395
224415
 
224396
224416
  class WatchHelper {
224397
- constructor(path4, follow, fsw) {
224417
+ constructor(path3, follow, fsw) {
224398
224418
  this.fsw = fsw;
224399
- const watchPath = path4;
224400
- this.path = path4 = path4.replace(REPLACER_RE, "");
224419
+ const watchPath = path3;
224420
+ this.path = path3 = path3.replace(REPLACER_RE, "");
224401
224421
  this.watchPath = watchPath;
224402
224422
  this.fullWatchPath = sysPath2.resolve(watchPath);
224403
224423
  this.dirParts = [];
@@ -224510,20 +224530,20 @@ class FSWatcher extends EventEmitter2 {
224510
224530
  this._closePromise = undefined;
224511
224531
  let paths = unifyPaths(paths_);
224512
224532
  if (cwd) {
224513
- paths = paths.map((path4) => {
224514
- const absPath = getAbsolutePath(path4, cwd);
224533
+ paths = paths.map((path3) => {
224534
+ const absPath = getAbsolutePath(path3, cwd);
224515
224535
  return absPath;
224516
224536
  });
224517
224537
  }
224518
- paths.forEach((path4) => {
224519
- this._removeIgnoredPath(path4);
224538
+ paths.forEach((path3) => {
224539
+ this._removeIgnoredPath(path3);
224520
224540
  });
224521
224541
  this._userIgnored = undefined;
224522
224542
  if (!this._readyCount)
224523
224543
  this._readyCount = 0;
224524
224544
  this._readyCount += paths.length;
224525
- Promise.all(paths.map(async (path4) => {
224526
- const res = await this._nodeFsHandler._addToNodeFs(path4, !_internal, undefined, 0, _origAdd);
224545
+ Promise.all(paths.map(async (path3) => {
224546
+ const res = await this._nodeFsHandler._addToNodeFs(path3, !_internal, undefined, 0, _origAdd);
224527
224547
  if (res)
224528
224548
  this._emitReady();
224529
224549
  return res;
@@ -224542,17 +224562,17 @@ class FSWatcher extends EventEmitter2 {
224542
224562
  return this;
224543
224563
  const paths = unifyPaths(paths_);
224544
224564
  const { cwd } = this.options;
224545
- paths.forEach((path4) => {
224546
- if (!sysPath2.isAbsolute(path4) && !this._closers.has(path4)) {
224565
+ paths.forEach((path3) => {
224566
+ if (!sysPath2.isAbsolute(path3) && !this._closers.has(path3)) {
224547
224567
  if (cwd)
224548
- path4 = sysPath2.join(cwd, path4);
224549
- path4 = sysPath2.resolve(path4);
224568
+ path3 = sysPath2.join(cwd, path3);
224569
+ path3 = sysPath2.resolve(path3);
224550
224570
  }
224551
- this._closePath(path4);
224552
- this._addIgnoredPath(path4);
224553
- if (this._watched.has(path4)) {
224571
+ this._closePath(path3);
224572
+ this._addIgnoredPath(path3);
224573
+ if (this._watched.has(path3)) {
224554
224574
  this._addIgnoredPath({
224555
- path: path4,
224575
+ path: path3,
224556
224576
  recursive: true
224557
224577
  });
224558
224578
  }
@@ -224601,38 +224621,38 @@ class FSWatcher extends EventEmitter2 {
224601
224621
  if (event !== EVENTS.ERROR)
224602
224622
  this.emit(EVENTS.ALL, event, ...args);
224603
224623
  }
224604
- async _emit(event, path4, stats) {
224624
+ async _emit(event, path3, stats) {
224605
224625
  if (this.closed)
224606
224626
  return;
224607
224627
  const opts = this.options;
224608
224628
  if (isWindows)
224609
- path4 = sysPath2.normalize(path4);
224629
+ path3 = sysPath2.normalize(path3);
224610
224630
  if (opts.cwd)
224611
- path4 = sysPath2.relative(opts.cwd, path4);
224612
- const args = [path4];
224631
+ path3 = sysPath2.relative(opts.cwd, path3);
224632
+ const args = [path3];
224613
224633
  if (stats != null)
224614
224634
  args.push(stats);
224615
224635
  const awf = opts.awaitWriteFinish;
224616
224636
  let pw;
224617
- if (awf && (pw = this._pendingWrites.get(path4))) {
224637
+ if (awf && (pw = this._pendingWrites.get(path3))) {
224618
224638
  pw.lastChange = new Date;
224619
224639
  return this;
224620
224640
  }
224621
224641
  if (opts.atomic) {
224622
224642
  if (event === EVENTS.UNLINK) {
224623
- this._pendingUnlinks.set(path4, [event, ...args]);
224643
+ this._pendingUnlinks.set(path3, [event, ...args]);
224624
224644
  setTimeout(() => {
224625
- this._pendingUnlinks.forEach((entry, path5) => {
224645
+ this._pendingUnlinks.forEach((entry, path4) => {
224626
224646
  this.emit(...entry);
224627
224647
  this.emit(EVENTS.ALL, ...entry);
224628
- this._pendingUnlinks.delete(path5);
224648
+ this._pendingUnlinks.delete(path4);
224629
224649
  });
224630
224650
  }, typeof opts.atomic === "number" ? opts.atomic : 100);
224631
224651
  return this;
224632
224652
  }
224633
- if (event === EVENTS.ADD && this._pendingUnlinks.has(path4)) {
224653
+ if (event === EVENTS.ADD && this._pendingUnlinks.has(path3)) {
224634
224654
  event = EVENTS.CHANGE;
224635
- this._pendingUnlinks.delete(path4);
224655
+ this._pendingUnlinks.delete(path3);
224636
224656
  }
224637
224657
  }
224638
224658
  if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
@@ -224650,16 +224670,16 @@ class FSWatcher extends EventEmitter2 {
224650
224670
  this.emitWithAll(event, args);
224651
224671
  }
224652
224672
  };
224653
- this._awaitWriteFinish(path4, awf.stabilityThreshold, event, awfEmit);
224673
+ this._awaitWriteFinish(path3, awf.stabilityThreshold, event, awfEmit);
224654
224674
  return this;
224655
224675
  }
224656
224676
  if (event === EVENTS.CHANGE) {
224657
- const isThrottled = !this._throttle(EVENTS.CHANGE, path4, 50);
224677
+ const isThrottled = !this._throttle(EVENTS.CHANGE, path3, 50);
224658
224678
  if (isThrottled)
224659
224679
  return this;
224660
224680
  }
224661
224681
  if (opts.alwaysStat && stats === undefined && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
224662
- const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path4) : path4;
224682
+ const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path3) : path3;
224663
224683
  let stats2;
224664
224684
  try {
224665
224685
  stats2 = await stat3(fullPath);
@@ -224678,23 +224698,23 @@ class FSWatcher extends EventEmitter2 {
224678
224698
  }
224679
224699
  return error || this.closed;
224680
224700
  }
224681
- _throttle(actionType, path4, timeout) {
224701
+ _throttle(actionType, path3, timeout) {
224682
224702
  if (!this._throttled.has(actionType)) {
224683
224703
  this._throttled.set(actionType, new Map);
224684
224704
  }
224685
224705
  const action = this._throttled.get(actionType);
224686
224706
  if (!action)
224687
224707
  throw new Error("invalid throttle");
224688
- const actionPath = action.get(path4);
224708
+ const actionPath = action.get(path3);
224689
224709
  if (actionPath) {
224690
224710
  actionPath.count++;
224691
224711
  return false;
224692
224712
  }
224693
224713
  let timeoutObject;
224694
224714
  const clear = () => {
224695
- const item = action.get(path4);
224715
+ const item = action.get(path3);
224696
224716
  const count = item ? item.count : 0;
224697
- action.delete(path4);
224717
+ action.delete(path3);
224698
224718
  clearTimeout(timeoutObject);
224699
224719
  if (item)
224700
224720
  clearTimeout(item.timeoutObject);
@@ -224702,50 +224722,50 @@ class FSWatcher extends EventEmitter2 {
224702
224722
  };
224703
224723
  timeoutObject = setTimeout(clear, timeout);
224704
224724
  const thr = { timeoutObject, clear, count: 0 };
224705
- action.set(path4, thr);
224725
+ action.set(path3, thr);
224706
224726
  return thr;
224707
224727
  }
224708
224728
  _incrReadyCount() {
224709
224729
  return this._readyCount++;
224710
224730
  }
224711
- _awaitWriteFinish(path4, threshold, event, awfEmit) {
224731
+ _awaitWriteFinish(path3, threshold, event, awfEmit) {
224712
224732
  const awf = this.options.awaitWriteFinish;
224713
224733
  if (typeof awf !== "object")
224714
224734
  return;
224715
224735
  const pollInterval = awf.pollInterval;
224716
224736
  let timeoutHandler;
224717
- let fullPath = path4;
224718
- if (this.options.cwd && !sysPath2.isAbsolute(path4)) {
224719
- fullPath = sysPath2.join(this.options.cwd, path4);
224737
+ let fullPath = path3;
224738
+ if (this.options.cwd && !sysPath2.isAbsolute(path3)) {
224739
+ fullPath = sysPath2.join(this.options.cwd, path3);
224720
224740
  }
224721
224741
  const now = new Date;
224722
224742
  const writes = this._pendingWrites;
224723
224743
  function awaitWriteFinishFn(prevStat) {
224724
224744
  statcb(fullPath, (err, curStat) => {
224725
- if (err || !writes.has(path4)) {
224745
+ if (err || !writes.has(path3)) {
224726
224746
  if (err && err.code !== "ENOENT")
224727
224747
  awfEmit(err);
224728
224748
  return;
224729
224749
  }
224730
224750
  const now2 = Number(new Date);
224731
224751
  if (prevStat && curStat.size !== prevStat.size) {
224732
- writes.get(path4).lastChange = now2;
224752
+ writes.get(path3).lastChange = now2;
224733
224753
  }
224734
- const pw = writes.get(path4);
224754
+ const pw = writes.get(path3);
224735
224755
  const df = now2 - pw.lastChange;
224736
224756
  if (df >= threshold) {
224737
- writes.delete(path4);
224757
+ writes.delete(path3);
224738
224758
  awfEmit(undefined, curStat);
224739
224759
  } else {
224740
224760
  timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
224741
224761
  }
224742
224762
  });
224743
224763
  }
224744
- if (!writes.has(path4)) {
224745
- writes.set(path4, {
224764
+ if (!writes.has(path3)) {
224765
+ writes.set(path3, {
224746
224766
  lastChange: now,
224747
224767
  cancelWait: () => {
224748
- writes.delete(path4);
224768
+ writes.delete(path3);
224749
224769
  clearTimeout(timeoutHandler);
224750
224770
  return event;
224751
224771
  }
@@ -224753,8 +224773,8 @@ class FSWatcher extends EventEmitter2 {
224753
224773
  timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval);
224754
224774
  }
224755
224775
  }
224756
- _isIgnored(path4, stats) {
224757
- if (this.options.atomic && DOT_RE.test(path4))
224776
+ _isIgnored(path3, stats) {
224777
+ if (this.options.atomic && DOT_RE.test(path3))
224758
224778
  return true;
224759
224779
  if (!this._userIgnored) {
224760
224780
  const { cwd } = this.options;
@@ -224764,13 +224784,13 @@ class FSWatcher extends EventEmitter2 {
224764
224784
  const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
224765
224785
  this._userIgnored = anymatch(list, undefined);
224766
224786
  }
224767
- return this._userIgnored(path4, stats);
224787
+ return this._userIgnored(path3, stats);
224768
224788
  }
224769
- _isntIgnored(path4, stat4) {
224770
- return !this._isIgnored(path4, stat4);
224789
+ _isntIgnored(path3, stat4) {
224790
+ return !this._isIgnored(path3, stat4);
224771
224791
  }
224772
- _getWatchHelpers(path4) {
224773
- return new WatchHelper(path4, this.options.followSymlinks, this);
224792
+ _getWatchHelpers(path3) {
224793
+ return new WatchHelper(path3, this.options.followSymlinks, this);
224774
224794
  }
224775
224795
  _getWatchedDir(directory) {
224776
224796
  const dir = sysPath2.resolve(directory);
@@ -224784,57 +224804,57 @@ class FSWatcher extends EventEmitter2 {
224784
224804
  return Boolean(Number(stats.mode) & 256);
224785
224805
  }
224786
224806
  _remove(directory, item, isDirectory) {
224787
- const path4 = sysPath2.join(directory, item);
224788
- const fullPath = sysPath2.resolve(path4);
224789
- isDirectory = isDirectory != null ? isDirectory : this._watched.has(path4) || this._watched.has(fullPath);
224790
- if (!this._throttle("remove", path4, 100))
224807
+ const path3 = sysPath2.join(directory, item);
224808
+ const fullPath = sysPath2.resolve(path3);
224809
+ isDirectory = isDirectory != null ? isDirectory : this._watched.has(path3) || this._watched.has(fullPath);
224810
+ if (!this._throttle("remove", path3, 100))
224791
224811
  return;
224792
224812
  if (!isDirectory && this._watched.size === 1) {
224793
224813
  this.add(directory, item, true);
224794
224814
  }
224795
- const wp = this._getWatchedDir(path4);
224815
+ const wp = this._getWatchedDir(path3);
224796
224816
  const nestedDirectoryChildren = wp.getChildren();
224797
- nestedDirectoryChildren.forEach((nested) => this._remove(path4, nested));
224817
+ nestedDirectoryChildren.forEach((nested) => this._remove(path3, nested));
224798
224818
  const parent = this._getWatchedDir(directory);
224799
224819
  const wasTracked = parent.has(item);
224800
224820
  parent.remove(item);
224801
224821
  if (this._symlinkPaths.has(fullPath)) {
224802
224822
  this._symlinkPaths.delete(fullPath);
224803
224823
  }
224804
- let relPath = path4;
224824
+ let relPath = path3;
224805
224825
  if (this.options.cwd)
224806
- relPath = sysPath2.relative(this.options.cwd, path4);
224826
+ relPath = sysPath2.relative(this.options.cwd, path3);
224807
224827
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
224808
224828
  const event = this._pendingWrites.get(relPath).cancelWait();
224809
224829
  if (event === EVENTS.ADD)
224810
224830
  return;
224811
224831
  }
224812
- this._watched.delete(path4);
224832
+ this._watched.delete(path3);
224813
224833
  this._watched.delete(fullPath);
224814
224834
  const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
224815
- if (wasTracked && !this._isIgnored(path4))
224816
- this._emit(eventName, path4);
224817
- this._closePath(path4);
224835
+ if (wasTracked && !this._isIgnored(path3))
224836
+ this._emit(eventName, path3);
224837
+ this._closePath(path3);
224818
224838
  }
224819
- _closePath(path4) {
224820
- this._closeFile(path4);
224821
- const dir = sysPath2.dirname(path4);
224822
- this._getWatchedDir(dir).remove(sysPath2.basename(path4));
224839
+ _closePath(path3) {
224840
+ this._closeFile(path3);
224841
+ const dir = sysPath2.dirname(path3);
224842
+ this._getWatchedDir(dir).remove(sysPath2.basename(path3));
224823
224843
  }
224824
- _closeFile(path4) {
224825
- const closers = this._closers.get(path4);
224844
+ _closeFile(path3) {
224845
+ const closers = this._closers.get(path3);
224826
224846
  if (!closers)
224827
224847
  return;
224828
224848
  closers.forEach((closer) => closer());
224829
- this._closers.delete(path4);
224849
+ this._closers.delete(path3);
224830
224850
  }
224831
- _addPathCloser(path4, closer) {
224851
+ _addPathCloser(path3, closer) {
224832
224852
  if (!closer)
224833
224853
  return;
224834
- let list = this._closers.get(path4);
224854
+ let list = this._closers.get(path3);
224835
224855
  if (!list) {
224836
224856
  list = [];
224837
- this._closers.set(path4, list);
224857
+ this._closers.set(path3, list);
224838
224858
  }
224839
224859
  list.push(closer);
224840
224860
  }
@@ -225080,7 +225100,7 @@ class Mutex {
225080
225100
  }
225081
225101
 
225082
225102
  // src/service/environment_store.ts
225083
- import crypto4 from "crypto";
225103
+ import crypto5 from "crypto";
225084
225104
  import * as fs7 from "fs";
225085
225105
  import * as path10 from "path";
225086
225106
 
@@ -225120,8 +225140,8 @@ function pathspec(...paths) {
225120
225140
  cache.set(key, paths);
225121
225141
  return key;
225122
225142
  }
225123
- function isPathSpec(path4) {
225124
- return path4 instanceof String && cache.has(path4);
225143
+ function isPathSpec(path3) {
225144
+ return path3 instanceof String && cache.has(path3);
225125
225145
  }
225126
225146
  function toPaths(pathSpec) {
225127
225147
  return cache.get(pathSpec) || [];
@@ -225207,8 +225227,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = `
225207
225227
  function forEachLineWithContent(input, callback) {
225208
225228
  return toLinesWithContent(input, true).map((line) => callback(line));
225209
225229
  }
225210
- function folderExists(path4) {
225211
- return import_file_exists.exists(path4, import_file_exists.FOLDER);
225230
+ function folderExists(path3) {
225231
+ return import_file_exists.exists(path3, import_file_exists.FOLDER);
225212
225232
  }
225213
225233
  function append2(target, item) {
225214
225234
  if (Array.isArray(target)) {
@@ -225589,8 +225609,8 @@ function checkIsRepoRootTask() {
225589
225609
  commands,
225590
225610
  format: "utf-8",
225591
225611
  onError,
225592
- parser(path4) {
225593
- return /^\.(git)?$/.test(path4.trim());
225612
+ parser(path3) {
225613
+ return /^\.(git)?$/.test(path3.trim());
225594
225614
  }
225595
225615
  };
225596
225616
  }
@@ -226001,11 +226021,11 @@ function parseGrep(grep) {
226001
226021
  const paths = /* @__PURE__ */ new Set;
226002
226022
  const results = {};
226003
226023
  forEachLineWithContent(grep, (input) => {
226004
- const [path4, line, preview] = input.split(NULL);
226005
- paths.add(path4);
226006
- (results[path4] = results[path4] || []).push({
226024
+ const [path3, line, preview] = input.split(NULL);
226025
+ paths.add(path3);
226026
+ (results[path3] = results[path3] || []).push({
226007
226027
  line: asNumber(line),
226008
- path: path4,
226028
+ path: path3,
226009
226029
  preview
226010
226030
  });
226011
226031
  });
@@ -226667,14 +226687,14 @@ var init_hash_object = __esm({
226667
226687
  init_task();
226668
226688
  }
226669
226689
  });
226670
- function parseInit(bare, path4, text) {
226690
+ function parseInit(bare, path3, text) {
226671
226691
  const response = String(text).trim();
226672
226692
  let result;
226673
226693
  if (result = initResponseRegex.exec(response)) {
226674
- return new InitSummary(bare, path4, false, result[1]);
226694
+ return new InitSummary(bare, path3, false, result[1]);
226675
226695
  }
226676
226696
  if (result = reInitResponseRegex.exec(response)) {
226677
- return new InitSummary(bare, path4, true, result[1]);
226697
+ return new InitSummary(bare, path3, true, result[1]);
226678
226698
  }
226679
226699
  let gitDir = "";
226680
226700
  const tokens = response.split(" ");
@@ -226685,7 +226705,7 @@ function parseInit(bare, path4, text) {
226685
226705
  break;
226686
226706
  }
226687
226707
  }
226688
- return new InitSummary(bare, path4, /^re/i.test(response), gitDir);
226708
+ return new InitSummary(bare, path3, /^re/i.test(response), gitDir);
226689
226709
  }
226690
226710
  var InitSummary;
226691
226711
  var initResponseRegex;
@@ -226693,9 +226713,9 @@ var reInitResponseRegex;
226693
226713
  var init_InitSummary = __esm({
226694
226714
  "src/lib/responses/InitSummary.ts"() {
226695
226715
  InitSummary = class {
226696
- constructor(bare, path4, existing, gitDir) {
226716
+ constructor(bare, path3, existing, gitDir) {
226697
226717
  this.bare = bare;
226698
- this.path = path4;
226718
+ this.path = path3;
226699
226719
  this.existing = existing;
226700
226720
  this.gitDir = gitDir;
226701
226721
  }
@@ -226707,7 +226727,7 @@ var init_InitSummary = __esm({
226707
226727
  function hasBareCommand(command) {
226708
226728
  return command.includes(bareCommand);
226709
226729
  }
226710
- function initTask(bare = false, path4, customArgs) {
226730
+ function initTask(bare = false, path3, customArgs) {
226711
226731
  const commands = ["init", ...customArgs];
226712
226732
  if (bare && !hasBareCommand(commands)) {
226713
226733
  commands.splice(1, 0, bareCommand);
@@ -226716,7 +226736,7 @@ function initTask(bare = false, path4, customArgs) {
226716
226736
  commands,
226717
226737
  format: "utf-8",
226718
226738
  parser(text) {
226719
- return parseInit(commands.includes("--bare"), path4, text);
226739
+ return parseInit(commands.includes("--bare"), path3, text);
226720
226740
  }
226721
226741
  };
226722
226742
  }
@@ -227431,12 +227451,12 @@ var init_FileStatusSummary = __esm({
227431
227451
  "src/lib/responses/FileStatusSummary.ts"() {
227432
227452
  fromPathRegex = /^(.+)\0(.+)$/;
227433
227453
  FileStatusSummary = class {
227434
- constructor(path4, index, working_dir) {
227435
- this.path = path4;
227454
+ constructor(path3, index, working_dir) {
227455
+ this.path = path3;
227436
227456
  this.index = index;
227437
227457
  this.working_dir = working_dir;
227438
227458
  if (index === "R" || working_dir === "R") {
227439
- const detail = fromPathRegex.exec(path4) || [null, path4, path4];
227459
+ const detail = fromPathRegex.exec(path3) || [null, path3, path3];
227440
227460
  this.from = detail[2] || "";
227441
227461
  this.path = detail[1] || "";
227442
227462
  }
@@ -227467,14 +227487,14 @@ function splitLine(result, lineStr) {
227467
227487
  default:
227468
227488
  return;
227469
227489
  }
227470
- function data(index, workingDir, path4) {
227490
+ function data(index, workingDir, path3) {
227471
227491
  const raw = `${index}${workingDir}`;
227472
227492
  const handler = parsers6.get(raw);
227473
227493
  if (handler) {
227474
- handler(result, path4);
227494
+ handler(result, path3);
227475
227495
  }
227476
227496
  if (raw !== "##" && raw !== "!!") {
227477
- result.files.push(new FileStatusSummary(path4, index, workingDir));
227497
+ result.files.push(new FileStatusSummary(path3, index, workingDir));
227478
227498
  }
227479
227499
  }
227480
227500
  }
@@ -227705,8 +227725,8 @@ var init_simple_git_api = __esm({
227705
227725
  }
227706
227726
  return this._runTask(configurationErrorTask("Git.cwd: workingDirectory must be supplied as a string"), next);
227707
227727
  }
227708
- hashObject(path4, write) {
227709
- return this._runTask(hashObjectTask(path4, write === true), trailingFunctionArgument(arguments));
227728
+ hashObject(path3, write) {
227729
+ return this._runTask(hashObjectTask(path3, write === true), trailingFunctionArgument(arguments));
227710
227730
  }
227711
227731
  init(bare) {
227712
227732
  return this._runTask(initTask(bare === true, this._executor.cwd, getTrailingOptions(arguments)), trailingFunctionArgument(arguments));
@@ -228283,8 +228303,8 @@ __export2(sub_module_exports, {
228283
228303
  subModuleTask: () => subModuleTask,
228284
228304
  updateSubModuleTask: () => updateSubModuleTask
228285
228305
  });
228286
- function addSubModuleTask(repo, path4) {
228287
- return subModuleTask(["add", repo, path4]);
228306
+ function addSubModuleTask(repo, path3) {
228307
+ return subModuleTask(["add", repo, path3]);
228288
228308
  }
228289
228309
  function initSubModuleTask(customArgs) {
228290
228310
  return subModuleTask(["init", ...customArgs]);
@@ -228552,8 +228572,8 @@ var require_git = __commonJS2({
228552
228572
  }
228553
228573
  return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
228554
228574
  };
228555
- Git2.prototype.submoduleAdd = function(repo, path4, then) {
228556
- return this._runTask(addSubModuleTask2(repo, path4), trailingFunctionArgument2(arguments));
228575
+ Git2.prototype.submoduleAdd = function(repo, path3, then) {
228576
+ return this._runTask(addSubModuleTask2(repo, path3), trailingFunctionArgument2(arguments));
228557
228577
  };
228558
228578
  Git2.prototype.submoduleUpdate = function(args, then) {
228559
228579
  return this._runTask(updateSubModuleTask2(getTrailingOptions2(arguments, true)), trailingFunctionArgument2(arguments));
@@ -229069,9 +229089,9 @@ import { Writable } from "stream";
229069
229089
 
229070
229090
  // src/config.ts
229071
229091
  import fs2 from "fs";
229072
- import path4 from "path";
229092
+ import path3 from "path";
229073
229093
  import { fileURLToPath } from "url";
229074
- var BUNDLED_DEFAULT_CONFIG_PATH = path4.join(path4.dirname(fileURLToPath(import.meta.url)), "default-publisher.config.json");
229094
+ var BUNDLED_DEFAULT_CONFIG_PATH = path3.join(path3.dirname(fileURLToPath(import.meta.url)), "default-publisher.config.json");
229075
229095
  function resolvePublisherConfigPath(serverRoot) {
229076
229096
  const explicitPath = process.env.PUBLISHER_CONFIG_PATH;
229077
229097
  if (explicitPath && explicitPath.length > 0) {
@@ -229080,7 +229100,7 @@ function resolvePublisherConfigPath(serverRoot) {
229080
229100
  }
229081
229101
  return { path: explicitPath, isBundledDefault: false };
229082
229102
  }
229083
- const serverRootPath = path4.join(serverRoot, PUBLISHER_CONFIG_NAME);
229103
+ const serverRootPath = path3.join(serverRoot, PUBLISHER_CONFIG_NAME);
229084
229104
  if (fs2.existsSync(serverRootPath)) {
229085
229105
  return { path: serverRootPath, isBundledDefault: false };
229086
229106
  }
@@ -229089,6 +229109,73 @@ function resolvePublisherConfigPath(serverRoot) {
229089
229109
  }
229090
229110
  return null;
229091
229111
  }
229112
+ var DEFAULT_HIGH_WATER_FRACTION = 0.8;
229113
+ var DEFAULT_LOW_WATER_FRACTION = 0.7;
229114
+ var DEFAULT_CHECK_INTERVAL_MS = 5000;
229115
+ var MIN_CHECK_INTERVAL_MS = 100;
229116
+ function parseIntEnv(name) {
229117
+ const raw = process.env[name];
229118
+ if (raw === undefined || raw.trim() === "")
229119
+ return;
229120
+ const value = Number.parseInt(raw, 10);
229121
+ if (!Number.isFinite(value) || String(value) !== raw.trim()) {
229122
+ throw new Error(`Invalid value for ${name}: expected a base-10 integer, got "${raw}"`);
229123
+ }
229124
+ return value;
229125
+ }
229126
+ function parseFloatEnv(name) {
229127
+ const raw = process.env[name];
229128
+ if (raw === undefined || raw.trim() === "")
229129
+ return;
229130
+ const value = Number.parseFloat(raw);
229131
+ if (!Number.isFinite(value)) {
229132
+ throw new Error(`Invalid value for ${name}: expected a finite number, got "${raw}"`);
229133
+ }
229134
+ return value;
229135
+ }
229136
+ function parseBoolEnv(name) {
229137
+ const raw = process.env[name];
229138
+ if (raw === undefined || raw.trim() === "")
229139
+ return;
229140
+ const normalised = raw.trim().toLowerCase();
229141
+ if (["1", "true", "yes", "on"].includes(normalised))
229142
+ return true;
229143
+ if (["0", "false", "no", "off"].includes(normalised))
229144
+ return false;
229145
+ throw new Error(`Invalid value for ${name}: expected a boolean (true/false), got "${raw}"`);
229146
+ }
229147
+ var getMemoryGovernorConfig = () => {
229148
+ const maxMemoryBytes = parseIntEnv("PUBLISHER_MAX_MEMORY_BYTES");
229149
+ if (maxMemoryBytes === undefined || maxMemoryBytes === 0) {
229150
+ return null;
229151
+ }
229152
+ if (maxMemoryBytes < 0) {
229153
+ throw new Error(`PUBLISHER_MAX_MEMORY_BYTES must be a positive integer (got ${maxMemoryBytes})`);
229154
+ }
229155
+ const highWaterFraction = parseFloatEnv("PUBLISHER_MEMORY_HIGH_WATER_FRACTION") ?? DEFAULT_HIGH_WATER_FRACTION;
229156
+ const lowWaterFraction = parseFloatEnv("PUBLISHER_MEMORY_LOW_WATER_FRACTION") ?? DEFAULT_LOW_WATER_FRACTION;
229157
+ const checkIntervalMs = parseIntEnv("PUBLISHER_MEMORY_CHECK_INTERVAL_MS") ?? DEFAULT_CHECK_INTERVAL_MS;
229158
+ const backpressureEnabled = parseBoolEnv("PUBLISHER_MEMORY_BACKPRESSURE") ?? true;
229159
+ if (highWaterFraction <= 0 || highWaterFraction >= 1) {
229160
+ throw new Error(`PUBLISHER_MEMORY_HIGH_WATER_FRACTION must be in (0, 1) (got ${highWaterFraction})`);
229161
+ }
229162
+ if (lowWaterFraction <= 0 || lowWaterFraction >= 1) {
229163
+ throw new Error(`PUBLISHER_MEMORY_LOW_WATER_FRACTION must be in (0, 1) (got ${lowWaterFraction})`);
229164
+ }
229165
+ if (lowWaterFraction >= highWaterFraction) {
229166
+ throw new Error(`PUBLISHER_MEMORY_LOW_WATER_FRACTION (${lowWaterFraction}) must be strictly less than PUBLISHER_MEMORY_HIGH_WATER_FRACTION (${highWaterFraction})`);
229167
+ }
229168
+ if (checkIntervalMs < MIN_CHECK_INTERVAL_MS) {
229169
+ throw new Error(`PUBLISHER_MEMORY_CHECK_INTERVAL_MS must be >= ${MIN_CHECK_INTERVAL_MS} (got ${checkIntervalMs})`);
229170
+ }
229171
+ return {
229172
+ maxMemoryBytes,
229173
+ highWaterFraction,
229174
+ lowWaterFraction,
229175
+ checkIntervalMs,
229176
+ backpressureEnabled
229177
+ };
229178
+ };
229092
229179
  function substituteEnvVars(value) {
229093
229180
  const envVarPattern = /\$\{([A-Z_][A-Z0-9_]*)\}/g;
229094
229181
  return value.replace(envVarPattern, (_match, varName) => {
@@ -229128,7 +229215,7 @@ var getPublisherConfig = (serverRoot) => {
229128
229215
  }
229129
229216
  const publisherConfigPath = resolved.path;
229130
229217
  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.`);
229218
+ logger.info(`No publisher.config.json found at ${path3.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
229219
  }
229133
229220
  let rawConfig;
229134
229221
  try {
@@ -229274,15 +229361,6 @@ function markReady() {
229274
229361
  logger.error("Service is already draining - cannot mark as ready");
229275
229362
  }
229276
229363
  }
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
- }
229286
229364
  function markNotReady() {
229287
229365
  ready = false;
229288
229366
  logger.info("Service marked as not ready - readiness probe will fail");
@@ -229366,7 +229444,7 @@ import * as crypto3 from "crypto";
229366
229444
 
229367
229445
  // src/storage/duckdb/DuckDBConnection.ts
229368
229446
  import duckdb from "duckdb";
229369
- import * as path5 from "path";
229447
+ import * as path4 from "path";
229370
229448
 
229371
229449
  class DuckDBConnection2 {
229372
229450
  db = null;
@@ -229374,7 +229452,7 @@ class DuckDBConnection2 {
229374
229452
  dbPath;
229375
229453
  mutex = new Mutex;
229376
229454
  constructor(dbPath) {
229377
- this.dbPath = dbPath || path5.join(process.cwd(), "publisher.db");
229455
+ this.dbPath = dbPath || path4.join(process.cwd(), "publisher.db");
229378
229456
  }
229379
229457
  async initialize() {
229380
229458
  return new Promise((resolve3, reject) => {
@@ -230523,9 +230601,62 @@ class StorageManager {
230523
230601
 
230524
230602
  // src/service/environment.ts
230525
230603
  import { MalloyError as MalloyError3, Runtime as Runtime2 } from "@malloydata/malloy";
230604
+ import crypto4 from "crypto";
230526
230605
  import * as fs6 from "fs";
230527
230606
  import * as path9 from "path";
230528
230607
 
230608
+ // src/path_safety.ts
230609
+ import * as path5 from "path";
230610
+ var SAFE_NAME_RE = /^(?!\.\.?$)(?!\.)[A-Za-z0-9._-]{1,255}$/;
230611
+ var MAX_MODEL_PATH_LEN = 1024;
230612
+ var SAFE_ENVIRONMENT_PATH_RE = /^(?:\/|[A-Za-z]:[\\/])[\x20-\x7E]*$/;
230613
+ var MAX_ENVIRONMENT_PATH_LEN = 4096;
230614
+ function assertSafePackageName(packageName) {
230615
+ if (typeof packageName !== "string" || !SAFE_NAME_RE.test(packageName)) {
230616
+ throw new BadRequestError(`Invalid package name: must be 1-255 characters of letters, digits, "-", "_", or "." and must not start with "."`);
230617
+ }
230618
+ }
230619
+ function assertSafeRelativeModelPath(modelPath) {
230620
+ if (typeof modelPath !== "string" || modelPath.length === 0 || modelPath.length > MAX_MODEL_PATH_LEN || modelPath.includes("\x00") || modelPath.includes("\\") || path5.isAbsolute(modelPath) || modelPath.startsWith("/")) {
230621
+ throw new BadRequestError(`Invalid model path`);
230622
+ }
230623
+ const segments = modelPath.split("/");
230624
+ for (const segment of segments) {
230625
+ if (segment === "" || segment === "." || segment === "..") {
230626
+ throw new BadRequestError(`Invalid model path`);
230627
+ }
230628
+ if (segment.startsWith(".")) {
230629
+ throw new BadRequestError(`Invalid model path`);
230630
+ }
230631
+ }
230632
+ }
230633
+ function assertSafeEnvironmentPath(environmentPath) {
230634
+ if (typeof environmentPath !== "string") {
230635
+ throw new BadRequestError(`Invalid environment path: must be a string`);
230636
+ }
230637
+ if (environmentPath.length === 0 || environmentPath.length > MAX_ENVIRONMENT_PATH_LEN) {
230638
+ throw new BadRequestError(`Invalid environment path: bad length`);
230639
+ }
230640
+ if (environmentPath.indexOf("\x00") !== -1) {
230641
+ throw new BadRequestError(`Invalid environment path: contains NUL byte`);
230642
+ }
230643
+ if (environmentPath.indexOf("..") !== -1) {
230644
+ throw new BadRequestError(`Invalid environment path: contains ".." traversal segment`);
230645
+ }
230646
+ if (!SAFE_ENVIRONMENT_PATH_RE.test(environmentPath)) {
230647
+ throw new BadRequestError(`Invalid environment path: must be an absolute path of printable ASCII characters`);
230648
+ }
230649
+ }
230650
+ function safeJoinUnderRoot(root, ...segments) {
230651
+ const resolvedRoot = path5.resolve(root);
230652
+ const joined = path5.resolve(resolvedRoot, ...segments);
230653
+ const rootWithSep = resolvedRoot.endsWith(path5.sep) ? resolvedRoot : resolvedRoot + path5.sep;
230654
+ if (joined !== resolvedRoot && !joined.startsWith(rootWithSep)) {
230655
+ throw new BadRequestError(`Resolved path is outside of root`);
230656
+ }
230657
+ return joined;
230658
+ }
230659
+
230529
230660
  // src/utils.ts
230530
230661
  import * as fs3 from "fs";
230531
230662
  import * as path6 from "path";
@@ -231707,6 +231838,8 @@ class Package {
231707
231838
  }
231708
231839
 
231709
231840
  // src/service/environment.ts
231841
+ var STAGING_DIR_NAME = ".staging";
231842
+ var RETIRED_DIR_NAME = ".retired";
231710
231843
  var RETIRED_CONNECTION_DRAIN_MS = 30000;
231711
231844
 
231712
231845
  class Environment {
@@ -231720,7 +231853,9 @@ class Environment {
231720
231853
  environmentPath;
231721
231854
  environmentName;
231722
231855
  metadata;
231856
+ memoryGovernor = null;
231723
231857
  constructor(environmentName, environmentPath, malloyConfig, apiConnections) {
231858
+ assertSafeEnvironmentPath(environmentPath);
231724
231859
  this.environmentName = environmentName;
231725
231860
  this.environmentPath = environmentPath;
231726
231861
  this.malloyConfig = malloyConfig;
@@ -231777,6 +231912,7 @@ class Environment {
231777
231912
  apiConnections: malloyConfig.apiConnections
231778
231913
  });
231779
231914
  const environment = new Environment(environmentName, environmentPath, malloyConfig, malloyConfig.apiConnections);
231915
+ await Environment.sweepStaleInstallDirs(environmentPath);
231780
231916
  return environment;
231781
231917
  }
231782
231918
  async reloadEnvironmentMetadata() {
@@ -231793,46 +231929,50 @@ class Environment {
231793
231929
  return this.metadata;
231794
231930
  }
231795
231931
  async compileSource(packageName, modelName, source, includeSql = false) {
231796
- const modelDir = path9.dirname(path9.join(this.environmentPath, packageName, modelName));
231797
- const virtualUri = `file://${path9.join(modelDir, "__compile_check.malloy")}`;
231798
- const virtualUrl = new URL(virtualUri);
231799
- const modelPath = path9.join(this.environmentPath, packageName, modelName);
231800
- let modelContent = "";
231801
- try {
231802
- modelContent = await fs6.promises.readFile(modelPath, "utf8");
231803
- } catch {}
231804
- const fullSource = modelContent ? `${modelContent}
231932
+ assertSafePackageName(packageName);
231933
+ assertSafeRelativeModelPath(modelName);
231934
+ return this.withPackageLock(packageName, async () => {
231935
+ const modelPath = safeJoinUnderRoot(this.environmentPath, packageName, modelName);
231936
+ const modelDir = path9.dirname(modelPath);
231937
+ const virtualUri = `file://${path9.join(modelDir, "__compile_check.malloy")}`;
231938
+ const virtualUrl = new URL(virtualUri);
231939
+ let modelContent = "";
231940
+ try {
231941
+ modelContent = await fs6.promises.readFile(modelPath, "utf8");
231942
+ } catch {}
231943
+ const fullSource = modelContent ? `${modelContent}
231805
231944
  ${source}` : source;
231806
- const interceptingReader = {
231807
- readURL: async (url2) => {
231808
- if (url2.toString() === virtualUri) {
231809
- return fullSource;
231945
+ const interceptingReader = {
231946
+ readURL: async (url2) => {
231947
+ if (url2.toString() === virtualUri) {
231948
+ return fullSource;
231949
+ }
231950
+ return URL_READER.readURL(url2);
231951
+ }
231952
+ };
231953
+ const pkg = await this._loadOrGetPackageLocked(packageName);
231954
+ const runtime = new Runtime2({
231955
+ urlReader: interceptingReader,
231956
+ config: pkg.getMalloyConfig()
231957
+ });
231958
+ try {
231959
+ const modelMaterializer = runtime.loadModel(virtualUrl);
231960
+ const model = await modelMaterializer.getModel();
231961
+ let sql;
231962
+ if (includeSql) {
231963
+ try {
231964
+ const queryMaterializer = modelMaterializer.loadFinalQuery();
231965
+ sql = await queryMaterializer.getSQL();
231966
+ } catch {}
231810
231967
  }
231811
- return URL_READER.readURL(url2);
231968
+ return { problems: model.problems, sql };
231969
+ } catch (error) {
231970
+ if (error instanceof MalloyError3) {
231971
+ return { problems: error.problems };
231972
+ }
231973
+ throw error;
231812
231974
  }
231813
- };
231814
- const pkg = await this.getPackage(packageName);
231815
- const runtime = new Runtime2({
231816
- urlReader: interceptingReader,
231817
- config: pkg.getMalloyConfig()
231818
231975
  });
231819
- try {
231820
- const modelMaterializer = runtime.loadModel(virtualUrl);
231821
- const model = await modelMaterializer.getModel();
231822
- let sql;
231823
- if (includeSql) {
231824
- try {
231825
- const queryMaterializer = modelMaterializer.loadFinalQuery();
231826
- sql = await queryMaterializer.getSQL();
231827
- } catch {}
231828
- }
231829
- return { problems: model.problems, sql };
231830
- } catch (error) {
231831
- if (error instanceof MalloyError3) {
231832
- return { problems: error.problems };
231833
- }
231834
- throw error;
231835
- }
231836
231976
  }
231837
231977
  listApiConnections() {
231838
231978
  return this.apiConnections;
@@ -231916,85 +232056,190 @@ ${source}` : source;
231916
232056
  }
231917
232057
  return packageMutex;
231918
232058
  }
231919
- async getPackage(packageName, reload = false) {
232059
+ async withPackageLock(packageName, fn) {
232060
+ assertSafePackageName(packageName);
232061
+ return this.getOrCreatePackageMutex(packageName).runExclusive(fn);
232062
+ }
232063
+ allocateStagingPath(packageName) {
232064
+ return safeJoinUnderRoot(this.environmentPath, STAGING_DIR_NAME, `${packageName}-${crypto4.randomUUID()}`);
232065
+ }
232066
+ allocateRetiredPath(packageName) {
232067
+ return safeJoinUnderRoot(this.environmentPath, RETIRED_DIR_NAME, `${packageName}-${crypto4.randomUUID()}`);
232068
+ }
232069
+ static async sweepStaleInstallDirs(environmentPath) {
232070
+ assertSafeEnvironmentPath(environmentPath);
232071
+ for (const dirName of [STAGING_DIR_NAME, RETIRED_DIR_NAME]) {
232072
+ const dir = safeJoinUnderRoot(environmentPath, dirName);
232073
+ if (dir.indexOf("..") !== -1)
232074
+ continue;
232075
+ if (path9.basename(dir) !== dirName)
232076
+ continue;
232077
+ try {
232078
+ await fs6.promises.rm(dir, { recursive: true, force: true });
232079
+ } catch (err) {
232080
+ logger.warn(`Failed to sweep stale ${dirName} dir at ${dir}`, {
232081
+ error: err
232082
+ });
232083
+ }
232084
+ }
232085
+ }
232086
+ setMemoryGovernor(governor) {
232087
+ this.memoryGovernor = governor;
232088
+ }
232089
+ assertCanAdmitNewPackage(packageName, reason, allowAdmission) {
232090
+ if (allowAdmission)
232091
+ return;
232092
+ if (!this.memoryGovernor?.isBackpressured())
232093
+ return;
232094
+ throw new ServiceUnavailableError(`Publisher is under memory pressure and cannot ${reason} (package "${packageName}", environment "${this.environmentName}"). Retry after the server's memory usage drops below the configured low-water mark.`);
232095
+ }
232096
+ async getPackage(packageName, reload = false, options = {}) {
232097
+ assertSafePackageName(packageName);
231920
232098
  const _package = this.packages.get(packageName);
231921
232099
  if (_package !== undefined && !reload) {
231922
232100
  return _package;
231923
232101
  }
231924
- const packageMutex = this.getOrCreatePackageMutex(packageName);
231925
- if (packageMutex.isLocked()) {
231926
- logger.debug(`Package ${packageName} is being loaded, waiting for unlock...`);
231927
- await packageMutex.waitForUnlock();
231928
- logger.debug(`Package ${packageName} unlocked`);
231929
- const existingPackage = this.packages.get(packageName);
231930
- if (existingPackage !== undefined && !reload) {
231931
- logger.debug(`Package ${packageName} loaded by another request`);
231932
- return existingPackage;
231933
- }
232102
+ this.assertCanAdmitNewPackage(packageName, reload ? "reload a package" : "load a package", options.allowAdmission === true);
232103
+ return this.withPackageLock(packageName, () => this._loadOrGetPackageLocked(packageName, reload));
232104
+ }
232105
+ async _loadOrGetPackageLocked(packageName, reload = false) {
232106
+ const existingPackage = this.packages.get(packageName);
232107
+ if (existingPackage !== undefined && !reload) {
232108
+ return existingPackage;
231934
232109
  }
231935
- return packageMutex.runExclusive(async () => {
231936
- const existingPackage = this.packages.get(packageName);
231937
- if (existingPackage !== undefined && !reload) {
231938
- return existingPackage;
231939
- }
231940
- this.setPackageStatus(packageName, "loading" /* LOADING */);
231941
- try {
231942
- logger.debug(`Loading package ${packageName}...`);
231943
- const packagePath = path9.join(this.environmentPath, packageName);
231944
- const _package2 = await Package.create(this.environmentName, packageName, packagePath, () => this.malloyConfig.malloyConfig);
231945
- if (existingPackage !== undefined && reload) {
231946
- this.retireConnectionGeneration(`package ${packageName}`, () => existingPackage.getMalloyConfig().releaseConnections());
231947
- }
231948
- this.packages.set(packageName, _package2);
231949
- this.setPackageStatus(packageName, "serving" /* SERVING */);
231950
- logger.debug(`Successfully loaded package ${packageName}`);
231951
- return _package2;
231952
- } catch (error) {
231953
- logger.error(`Failed to load package ${packageName}`, { error });
231954
- this.packages.delete(packageName);
231955
- this.packageStatuses.delete(packageName);
231956
- throw error;
232110
+ this.setPackageStatus(packageName, "loading" /* LOADING */);
232111
+ try {
232112
+ logger.debug(`Loading package ${packageName}...`);
232113
+ const packagePath = safeJoinUnderRoot(this.environmentPath, packageName);
232114
+ const _package = await Package.create(this.environmentName, packageName, packagePath, () => this.malloyConfig.malloyConfig);
232115
+ if (existingPackage !== undefined && reload) {
232116
+ this.retireConnectionGeneration(`package ${packageName}`, () => existingPackage.getMalloyConfig().releaseConnections());
231957
232117
  }
231958
- });
232118
+ this.packages.set(packageName, _package);
232119
+ this.setPackageStatus(packageName, "serving" /* SERVING */);
232120
+ logger.debug(`Successfully loaded package ${packageName}`);
232121
+ return _package;
232122
+ } catch (error) {
232123
+ logger.error(`Failed to load package ${packageName}`, { error });
232124
+ this.packages.delete(packageName);
232125
+ this.packageStatuses.delete(packageName);
232126
+ throw error;
232127
+ }
231959
232128
  }
231960
- async addPackage(packageName) {
231961
- const packagePath = path9.join(this.environmentPath, packageName);
232129
+ async addPackage(packageName, options = {}) {
232130
+ assertSafePackageName(packageName);
232131
+ const packagePath = safeJoinUnderRoot(this.environmentPath, packageName);
231962
232132
  if (!await fs6.promises.access(packagePath).then(() => true).catch(() => false) || !(await fs6.promises.stat(packagePath))?.isDirectory()) {
231963
232133
  throw new PackageNotFoundError(`Package ${packageName} not found`);
231964
232134
  }
232135
+ this.assertCanAdmitNewPackage(packageName, "add a new package", options.allowAdmission === true);
231965
232136
  logger.info(`Adding package ${packageName} to environment ${this.environmentName}`, {
231966
232137
  packagePath,
231967
232138
  malloyConfig: this.malloyConfig.malloyConfig
231968
232139
  });
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
- }
232140
+ return this.withPackageLock(packageName, () => this._addPackageLocked(packageName));
232141
+ }
232142
+ async _addPackageLocked(packageName) {
232143
+ const packagePath = safeJoinUnderRoot(this.environmentPath, packageName);
232144
+ const existingPackage = this.packages.get(packageName);
232145
+ if (existingPackage !== undefined) {
232146
+ return existingPackage;
232147
+ }
232148
+ this.setPackageStatus(packageName, "loading" /* LOADING */);
232149
+ try {
232150
+ this.packages.set(packageName, await Package.create(this.environmentName, packageName, packagePath, () => this.malloyConfig.malloyConfig));
232151
+ } catch (error) {
232152
+ logger.error("Error adding package", { error });
232153
+ this.deletePackageStatus(packageName);
232154
+ throw error;
231977
232155
  }
231978
- return packageMutex.runExclusive(async () => {
231979
- const existingPackage = this.packages.get(packageName);
231980
- if (existingPackage !== undefined) {
231981
- return existingPackage;
232156
+ this.setPackageStatus(packageName, "serving" /* SERVING */);
232157
+ return this.packages.get(packageName);
232158
+ }
232159
+ async installPackage(packageName, downloader) {
232160
+ assertSafePackageName(packageName);
232161
+ const stagingPath = this.allocateStagingPath(packageName);
232162
+ await fs6.promises.mkdir(path9.dirname(stagingPath), { recursive: true });
232163
+ try {
232164
+ await downloader(stagingPath);
232165
+ } catch (err) {
232166
+ await fs6.promises.rm(stagingPath, { recursive: true, force: true }).catch(() => {});
232167
+ throw err;
232168
+ }
232169
+ return this.withPackageLock(packageName, async () => {
232170
+ const canonicalPath = safeJoinUnderRoot(this.environmentPath, packageName);
232171
+ let retiredPath;
232172
+ const oldPackage = this.packages.get(packageName);
232173
+ const oldExistsOnDisk = await fs6.promises.access(canonicalPath).then(() => true).catch(() => false);
232174
+ if (oldExistsOnDisk) {
232175
+ retiredPath = this.allocateRetiredPath(packageName);
232176
+ await fs6.promises.mkdir(path9.dirname(retiredPath), {
232177
+ recursive: true
232178
+ });
232179
+ await fs6.promises.rename(canonicalPath, retiredPath);
231982
232180
  }
231983
- this.setPackageStatus(packageName, "loading" /* LOADING */);
232181
+ let newPackage;
231984
232182
  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 });
232183
+ await fs6.promises.rename(stagingPath, canonicalPath);
232184
+ this.setPackageStatus(packageName, "loading" /* LOADING */);
232185
+ newPackage = await Package.create(this.environmentName, packageName, canonicalPath, () => this.malloyConfig.malloyConfig);
232186
+ } catch (err) {
232187
+ await fs6.promises.rm(canonicalPath, { recursive: true, force: true }).catch(() => {});
232188
+ if (retiredPath) {
232189
+ try {
232190
+ await fs6.promises.rename(retiredPath, canonicalPath);
232191
+ } catch (restoreErr) {
232192
+ logger.error("Failed to restore retired package after install rollback", {
232193
+ error: restoreErr,
232194
+ retiredPath,
232195
+ canonicalPath
232196
+ });
232197
+ }
232198
+ }
232199
+ await fs6.promises.rm(stagingPath, { recursive: true, force: true }).catch(() => {});
231988
232200
  this.deletePackageStatus(packageName);
231989
- throw error;
232201
+ throw err;
231990
232202
  }
232203
+ this.packages.set(packageName, newPackage);
231991
232204
  this.setPackageStatus(packageName, "serving" /* SERVING */);
231992
- return this.packages.get(packageName);
232205
+ if (oldPackage) {
232206
+ this.retireConnectionGeneration(`package ${packageName}`, () => oldPackage.getMalloyConfig().releaseConnections());
232207
+ }
232208
+ if (retiredPath) {
232209
+ const pathToClean = retiredPath;
232210
+ setImmediate(() => {
232211
+ fs6.promises.rm(pathToClean, { recursive: true, force: true }).catch((err) => {
232212
+ logger.warn(`Failed to clean up retired package directory ${pathToClean}`, { error: err });
232213
+ });
232214
+ });
232215
+ }
232216
+ return newPackage;
232217
+ });
232218
+ }
232219
+ async reloadAllModelsForPackage(packageName, manifest) {
232220
+ assertSafePackageName(packageName);
232221
+ return this.withPackageLock(packageName, async () => {
232222
+ const pkg = this.packages.get(packageName);
232223
+ if (!pkg) {
232224
+ throw new PackageNotFoundError(`Package ${packageName} is not loaded`);
232225
+ }
232226
+ await pkg.reloadAllModels(manifest);
232227
+ });
232228
+ }
232229
+ async getModelFileText(packageName, modelPath) {
232230
+ assertSafePackageName(packageName);
232231
+ assertSafeRelativeModelPath(modelPath);
232232
+ return this.withPackageLock(packageName, async () => {
232233
+ const pkg = this.packages.get(packageName);
232234
+ if (!pkg) {
232235
+ throw new PackageNotFoundError(`Package ${packageName} is not loaded`);
232236
+ }
232237
+ return pkg.getModelFileText(modelPath);
231993
232238
  });
231994
232239
  }
231995
232240
  async writePackageManifest(packageName, metadata) {
231996
- const packagePath = path9.join(this.environmentPath, packageName);
231997
- const manifestPath = path9.join(packagePath, "publisher.json");
232241
+ const packagePath = safeJoinUnderRoot(this.environmentPath, packageName);
232242
+ const manifestPath = safeJoinUnderRoot(packagePath, "publisher.json");
231998
232243
  try {
231999
232244
  let existingManifest = {};
232000
232245
  try {
@@ -232016,24 +232261,27 @@ ${source}` : source;
232016
232261
  }
232017
232262
  }
232018
232263
  async updatePackage(packageName, body) {
232019
- const _package = this.packages.get(packageName);
232020
- if (!_package) {
232021
- throw new PackageNotFoundError(`Package ${packageName} not found`);
232022
- }
232023
- if (body.name) {
232024
- _package.setName(body.name);
232025
- }
232026
- _package.setPackageMetadata({
232027
- name: body.name,
232028
- description: body.description,
232029
- resource: body.resource,
232030
- location: body.location
232031
- });
232032
- await this.writePackageManifest(packageName, {
232033
- name: packageName,
232034
- description: body.description
232264
+ assertSafePackageName(packageName);
232265
+ return this.withPackageLock(packageName, async () => {
232266
+ const _package = this.packages.get(packageName);
232267
+ if (!_package) {
232268
+ throw new PackageNotFoundError(`Package ${packageName} not found`);
232269
+ }
232270
+ if (body.name) {
232271
+ _package.setName(body.name);
232272
+ }
232273
+ _package.setPackageMetadata({
232274
+ name: body.name,
232275
+ description: body.description,
232276
+ resource: body.resource,
232277
+ location: body.location
232278
+ });
232279
+ await this.writePackageManifest(packageName, {
232280
+ name: packageName,
232281
+ description: body.description
232282
+ });
232283
+ return _package.getPackageMetadata();
232035
232284
  });
232036
- return _package.getPackageMetadata();
232037
232285
  }
232038
232286
  getPackageStatus(packageName) {
232039
232287
  return this.packageStatuses.get(packageName);
@@ -232050,35 +232298,49 @@ ${source}` : source;
232050
232298
  this.packageStatuses.delete(packageName);
232051
232299
  }
232052
232300
  async deletePackage(packageName) {
232053
- const _package = this.packages.get(packageName);
232054
- if (!_package) {
232055
- return;
232056
- }
232057
- const packageStatus = this.packageStatuses.get(packageName);
232058
- if (packageStatus?.status === "loading" /* LOADING */) {
232059
- logger.error("Package loading. Can't unload.", {
232060
- environmentName: this.environmentName,
232061
- packageName
232062
- });
232063
- throw new Error("Package loading. Can't unload. " + this.environmentName + " " + packageName);
232064
- } else if (packageStatus?.status === "serving" /* SERVING */) {
232065
- this.setPackageStatus(packageName, "unloading" /* UNLOADING */);
232066
- }
232067
- await _package.getMalloyConfig().releaseConnections();
232068
- try {
232069
- await fs6.promises.rm(path9.join(this.environmentPath, packageName), {
232070
- recursive: true,
232071
- force: true
232072
- });
232073
- } catch (err) {
232074
- logger.error("Error removing package directory while unloading package", {
232075
- error: err,
232076
- environmentName: this.environmentName,
232077
- packageName
232078
- });
232079
- }
232080
- this.packages.delete(packageName);
232081
- this.packageStatuses.delete(packageName);
232301
+ assertSafePackageName(packageName);
232302
+ return this.withPackageLock(packageName, async () => {
232303
+ const _package = this.packages.get(packageName);
232304
+ if (!_package) {
232305
+ return;
232306
+ }
232307
+ const packageStatus = this.packageStatuses.get(packageName);
232308
+ if (packageStatus?.status === "loading" /* LOADING */) {
232309
+ logger.error("Package loading. Can't unload.", {
232310
+ environmentName: this.environmentName,
232311
+ packageName
232312
+ });
232313
+ throw new Error("Package loading. Can't unload. " + this.environmentName + " " + packageName);
232314
+ } else if (packageStatus?.status === "serving" /* SERVING */) {
232315
+ this.setPackageStatus(packageName, "unloading" /* UNLOADING */);
232316
+ }
232317
+ this.retireConnectionGeneration(`package ${packageName}`, () => _package.getMalloyConfig().releaseConnections());
232318
+ const canonicalPath = safeJoinUnderRoot(this.environmentPath, packageName);
232319
+ const retiredPath = this.allocateRetiredPath(packageName);
232320
+ let renamed = false;
232321
+ try {
232322
+ await fs6.promises.mkdir(path9.dirname(retiredPath), {
232323
+ recursive: true
232324
+ });
232325
+ await fs6.promises.rename(canonicalPath, retiredPath);
232326
+ renamed = true;
232327
+ } catch (err) {
232328
+ logger.error("Error renaming package directory to retired during unload", {
232329
+ error: err,
232330
+ environmentName: this.environmentName,
232331
+ packageName
232332
+ });
232333
+ }
232334
+ this.packages.delete(packageName);
232335
+ this.packageStatuses.delete(packageName);
232336
+ if (renamed) {
232337
+ setImmediate(() => {
232338
+ fs6.promises.rm(retiredPath, { recursive: true, force: true }).catch((err) => {
232339
+ logger.warn(`Failed to clean up retired package directory ${retiredPath}`, { error: err });
232340
+ });
232341
+ });
232342
+ }
232343
+ });
232082
232344
  }
232083
232345
  updateConnections(malloyConfig, _apiConnections, afterPreviousRelease) {
232084
232346
  const previousMalloyConfig = this.malloyConfig;
@@ -232199,12 +232461,12 @@ class EnvironmentStore {
232199
232461
  publisherConfigIsFrozen;
232200
232462
  finishedInitialization;
232201
232463
  isInitialized = false;
232202
- failedEnvironments = [];
232203
232464
  storageManager;
232204
232465
  s3Client = new import_client_s32.S3({
232205
232466
  followRegionRedirects: true
232206
232467
  });
232207
232468
  gcsClient;
232469
+ memoryGovernor = null;
232208
232470
  constructor(serverRootPath) {
232209
232471
  this.serverRootPath = serverRootPath;
232210
232472
  this.gcsClient = new Storage;
@@ -232217,6 +232479,12 @@ class EnvironmentStore {
232217
232479
  this.storageManager = new StorageManager(storageConfig);
232218
232480
  this.finishedInitialization = this.initialize();
232219
232481
  }
232482
+ setMemoryGovernor(governor) {
232483
+ this.memoryGovernor = governor;
232484
+ for (const env of this.environments.values()) {
232485
+ env.setMemoryGovernor(governor);
232486
+ }
232487
+ }
232220
232488
  async addConfiguredEnvironment(environment) {
232221
232489
  try {
232222
232490
  await this.addEnvironment({
@@ -232232,10 +232500,6 @@ class EnvironmentStore {
232232
232500
  logEnvironmentInitializationError(environmentName, error) {
232233
232501
  const label = environmentName ? ` "${environmentName}"` : "";
232234
232502
  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
- });
232239
232503
  }
232240
232504
  async initialize() {
232241
232505
  const reInit = process.env.INITIALIZE_STORAGE === "true";
@@ -232281,6 +232545,7 @@ class EnvironmentStore {
232281
232545
  resource: `${API_PREFIX}/connections/${conn.name}`,
232282
232546
  ...conn.config
232283
232547
  })));
232548
+ environmentInstance.setMemoryGovernor(this.memoryGovernor);
232284
232549
  const packages = await repository.listPackages(dbEnvironment.id);
232285
232550
  packages.forEach((pkg) => {
232286
232551
  environmentInstance.setPackageStatus(pkg.name, "serving" /* SERVING */);
@@ -232298,11 +232563,7 @@ class EnvironmentStore {
232298
232563
  }
232299
232564
  }
232300
232565
  this.isInitialized = true;
232301
- if (this.failedEnvironments.length > 0) {
232302
- markDegraded();
232303
- } else {
232304
- markReady();
232305
- }
232566
+ markReady();
232306
232567
  const initializationDuration = performance.now() - initialTime;
232307
232568
  logger.info(`Environment store successfully initialized in ${formatDuration(initializationDuration)}`);
232308
232569
  } catch (error) {
@@ -232538,12 +232799,7 @@ class EnvironmentStore {
232538
232799
  environments: [],
232539
232800
  initialized: this.isInitialized,
232540
232801
  frozenConfig: isPublisherConfigFrozen(this.serverRootPath),
232541
- operationalState: getOperationalState(),
232542
- ...this.failedEnvironments.length > 0 && {
232543
- failedEnvironments: [
232544
- ...this.failedEnvironments
232545
- ]
232546
- }
232802
+ operationalState: getOperationalState()
232547
232803
  };
232548
232804
  const environments = await this.listEnvironments(true);
232549
232805
  await Promise.all(environments.map(async (environment) => {
@@ -232641,6 +232897,7 @@ class EnvironmentStore {
232641
232897
  absoluteEnvironmentPath = await this.scaffoldEnvironment(environment);
232642
232898
  }
232643
232899
  const newEnvironment = await Environment.create(environmentName, absoluteEnvironmentPath, environment.connections || []);
232900
+ newEnvironment.setMemoryGovernor(this.memoryGovernor);
232644
232901
  if (!newEnvironment.metadata)
232645
232902
  newEnvironment.metadata = {};
232646
232903
  newEnvironment.metadata.location = absoluteEnvironmentPath;
@@ -232806,7 +233063,7 @@ class EnvironmentStore {
232806
233063
  });
232807
233064
  }
232808
233065
  for (const [groupedLocation, packagesForLocation] of locationGroups) {
232809
- const locationHash = crypto4.createHash("sha256").update(groupedLocation).digest("hex").substring(0, 16);
233066
+ const locationHash = crypto5.createHash("sha256").update(groupedLocation).digest("hex").substring(0, 16);
232810
233067
  const tempDownloadPath = `${absoluteTargetPath}/.temp_${locationHash}`;
232811
233068
  await fs7.promises.mkdir(tempDownloadPath, { recursive: true });
232812
233069
  logger.info(`Created temporary directory: ${tempDownloadPath}`);
@@ -232995,9 +233252,9 @@ class EnvironmentStore {
232995
233252
  }
232996
233253
  const file = fs7.createWriteStream(zipFilePath);
232997
233254
  item.Body.transformToWebStream().pipeTo(Writable.toWeb(file));
232998
- await new Promise((resolve3, reject) => {
233255
+ await new Promise((resolve4, reject) => {
232999
233256
  file.on("error", reject);
233000
- file.on("finish", resolve3);
233257
+ file.on("finish", resolve4);
233001
233258
  });
233002
233259
  await this.unzipEnvironment(zipFilePath);
233003
233260
  logger.info(`Downloaded S3 zip file ${s3Path} to ${absoluteDirPath}`);
@@ -233035,9 +233292,9 @@ class EnvironmentStore {
233035
233292
  }
233036
233293
  const file = fs7.createWriteStream(absoluteFilePath);
233037
233294
  item.Body.transformToWebStream().pipeTo(Writable.toWeb(file));
233038
- await new Promise((resolve3, reject) => {
233295
+ await new Promise((resolve4, reject) => {
233039
233296
  file.on("error", reject);
233040
- file.on("finish", resolve3);
233297
+ file.on("finish", resolve4);
233041
233298
  });
233042
233299
  }));
233043
233300
  logger.info(`Downloaded S3 directory ${s3Path} to ${absoluteDirPath}`);
@@ -233070,14 +233327,14 @@ class EnvironmentStore {
233070
233327
  });
233071
233328
  await fs7.promises.mkdir(absoluteDirPath, { recursive: true });
233072
233329
  const repoUrl = `https://github.com/${owner}/${repoName}`;
233073
- await new Promise((resolve3, reject) => {
233330
+ await new Promise((resolve4, reject) => {
233074
233331
  esm_default2().clone(repoUrl, absoluteDirPath, {}, (err) => {
233075
233332
  if (err) {
233076
233333
  const errorData = this.extractErrorDataFromError(err);
233077
233334
  logger.error(`Failed to clone GitHub repository "${repoUrl}"`, errorData);
233078
233335
  reject(err);
233079
233336
  }
233080
- resolve3();
233337
+ resolve4();
233081
233338
  });
233082
233339
  });
233083
233340
  if (!cleanPackagePath) {
@@ -233473,7 +233730,7 @@ class Protocol {
233473
233730
  }
233474
233731
  request(request, resultSchema, options) {
233475
233732
  const { relatedRequestId, resumptionToken, onresumptiontoken } = options !== null && options !== undefined ? options : {};
233476
- return new Promise((resolve3, reject) => {
233733
+ return new Promise((resolve4, reject) => {
233477
233734
  var _a2, _b, _c, _d, _e, _f;
233478
233735
  if (!this._transport) {
233479
233736
  reject(new Error("Not connected"));
@@ -233524,7 +233781,7 @@ class Protocol {
233524
233781
  }
233525
233782
  try {
233526
233783
  const result = resultSchema.parse(response.result);
233527
- resolve3(result);
233784
+ resolve4(result);
233528
233785
  } catch (error) {
233529
233786
  reject(error);
233530
233787
  }
@@ -236926,7 +237183,7 @@ function registerTools(mcpServer, environmentStore) {
236926
237183
  console.log("model not found", modelPath, "in ", pkg.listModels());
236927
237184
  throw new Error(`Model not found: ${modelPath}`);
236928
237185
  }
236929
- const fileText = await pkg.getModelFileText(modelPath);
237186
+ const fileText = await environment.getModelFileText(packageName, modelPath);
236930
237187
  console.log(`[MCP LOG] Successfully retrieved model text for ${modelPath}`);
236931
237188
  return {
236932
237189
  content: [
@@ -237766,8 +238023,8 @@ class ManifestService {
237766
238023
  async reloadManifest(environmentId, packageName, environmentName) {
237767
238024
  const manifest = await this.getManifest(environmentId, packageName);
237768
238025
  const environment = await this.environmentStore.getEnvironment(environmentName, false);
237769
- const pkg = await environment.getPackage(packageName, false);
237770
- await pkg.reloadAllModels(manifest.entries);
238026
+ await environment.getPackage(packageName, false);
238027
+ await environment.reloadAllModelsForPackage(packageName, manifest.entries);
237771
238028
  logger.info("Reloaded manifest and recompiled models", {
237772
238029
  environmentId,
237773
238030
  packageName,
@@ -238088,8 +238345,8 @@ class MaterializationService {
238088
238345
  if (metadata.autoLoadManifest) {
238089
238346
  const updatedManifest = await this.manifestService.getManifest(environmentId, packageName);
238090
238347
  const environment = await this.environmentStore.getEnvironment(environmentName, false);
238091
- const pkg = await environment.getPackage(packageName, false);
238092
- await pkg.reloadAllModels(updatedManifest.entries);
238348
+ await environment.getPackage(packageName, false);
238349
+ await environment.reloadAllModelsForPackage(packageName, updatedManifest.entries);
238093
238350
  }
238094
238351
  await this.transitionExecution(executionId, "SUCCESS", {
238095
238352
  completedAt: new Date,
@@ -238179,7 +238436,7 @@ class MaterializationService {
238179
238436
  manifest.loadText(JSON.stringify(existingManifest));
238180
238437
  const existingEntries = await this.manifestService.listEntries(environmentId, packageName);
238181
238438
  const knownMaterializedTables = new Set(existingEntries.map((e) => manifestTableKey(e.connectionName, e.tableName)));
238182
- const { graphs, sources, connectionDigests, connections } = await this.compilePackageBuildPlan(pkg, signal);
238439
+ const { graphs, sources, connectionDigests, connections } = await environment.withPackageLock(packageName, () => this.compilePackageBuildPlan(pkg, signal));
238183
238440
  if (graphs.length === 0) {
238184
238441
  logger.info("No persist sources to build");
238185
238442
  return { sourcesBuilt: 0, sourcesSkipped: 0 };
@@ -238384,6 +238641,107 @@ class MaterializationService {
238384
238641
  }
238385
238642
  }
238386
238643
 
238644
+ // src/service/package_memory_governor.ts
238645
+ var import_api4 = __toESM(require_src(), 1);
238646
+ var DEFAULT_RSS_SAMPLER = () => process.memoryUsage().rss;
238647
+
238648
+ class PackageMemoryGovernor {
238649
+ config;
238650
+ rssSampler;
238651
+ highWaterBytes;
238652
+ lowWaterBytes;
238653
+ timer = null;
238654
+ backpressured = false;
238655
+ lastSampledRss = 0;
238656
+ lastSampledAt = null;
238657
+ backpressureActivationsCounter;
238658
+ constructor(config, rssSampler) {
238659
+ this.config = config;
238660
+ this.rssSampler = rssSampler ?? DEFAULT_RSS_SAMPLER;
238661
+ this.highWaterBytes = Math.floor(config.maxMemoryBytes * config.highWaterFraction);
238662
+ this.lowWaterBytes = Math.floor(config.maxMemoryBytes * config.lowWaterFraction);
238663
+ const meter2 = import_api4.metrics.getMeter("publisher");
238664
+ meter2.createObservableGauge("publisher_process_rss_bytes", {
238665
+ description: "Current resident set size of the publisher process in bytes",
238666
+ unit: "By"
238667
+ }).addCallback((observation) => {
238668
+ observation.observe(this.rssSampler());
238669
+ });
238670
+ meter2.createObservableGauge("publisher_memory_backpressure_active", {
238671
+ description: "1 when the publisher is rejecting new package loads to stay under PUBLISHER_MAX_MEMORY_BYTES; 0 otherwise"
238672
+ }).addCallback((observation) => {
238673
+ observation.observe(this.backpressured ? 1 : 0);
238674
+ });
238675
+ this.backpressureActivationsCounter = meter2.createCounter("publisher_memory_backpressure_activations_total", {
238676
+ description: "Number of times the memory governor has activated back-pressure"
238677
+ });
238678
+ meter2.createObservableGauge("publisher_memory_max_bytes", {
238679
+ description: "Configured PUBLISHER_MAX_MEMORY_BYTES",
238680
+ unit: "By"
238681
+ }).addCallback((observation) => observation.observe(this.config.maxMemoryBytes));
238682
+ meter2.createObservableGauge("publisher_memory_high_water_bytes", {
238683
+ description: "RSS threshold at which back-pressure activates",
238684
+ unit: "By"
238685
+ }).addCallback((observation) => observation.observe(this.highWaterBytes));
238686
+ meter2.createObservableGauge("publisher_memory_low_water_bytes", {
238687
+ description: "RSS threshold at which back-pressure clears",
238688
+ unit: "By"
238689
+ }).addCallback((observation) => observation.observe(this.lowWaterBytes));
238690
+ }
238691
+ start() {
238692
+ if (this.timer !== null)
238693
+ return;
238694
+ this.tick();
238695
+ this.timer = setInterval(() => this.tick(), this.config.checkIntervalMs);
238696
+ this.timer.unref?.();
238697
+ logger.info(`PackageMemoryGovernor started (max=${this.config.maxMemoryBytes}B, high=${this.highWaterBytes}B, low=${this.lowWaterBytes}B, interval=${this.config.checkIntervalMs}ms, backpressure=${this.config.backpressureEnabled})`);
238698
+ }
238699
+ stop() {
238700
+ if (this.timer !== null) {
238701
+ clearInterval(this.timer);
238702
+ this.timer = null;
238703
+ }
238704
+ this.backpressured = false;
238705
+ }
238706
+ tick() {
238707
+ let rss;
238708
+ try {
238709
+ rss = this.rssSampler();
238710
+ } catch (err) {
238711
+ logger.error("PackageMemoryGovernor: RSS sample failed", {
238712
+ error: err
238713
+ });
238714
+ return;
238715
+ }
238716
+ this.lastSampledRss = rss;
238717
+ this.lastSampledAt = Date.now();
238718
+ if (!this.config.backpressureEnabled) {
238719
+ return;
238720
+ }
238721
+ if (rss >= this.highWaterBytes && !this.backpressured) {
238722
+ this.backpressured = true;
238723
+ this.backpressureActivationsCounter.add(1);
238724
+ logger.warn(`PackageMemoryGovernor: activating back-pressure (rss=${rss}B >= high=${this.highWaterBytes}B). New package loads will be rejected with HTTP 503 until rss <= ${this.lowWaterBytes}B.`);
238725
+ } else if (rss <= this.lowWaterBytes && this.backpressured) {
238726
+ this.backpressured = false;
238727
+ logger.info(`PackageMemoryGovernor: clearing back-pressure (rss=${rss}B <= low=${this.lowWaterBytes}B).`);
238728
+ }
238729
+ }
238730
+ isBackpressured() {
238731
+ return this.backpressured;
238732
+ }
238733
+ getStatus() {
238734
+ return {
238735
+ rssBytes: this.lastSampledRss,
238736
+ maxMemoryBytes: this.config.maxMemoryBytes,
238737
+ highWaterBytes: this.highWaterBytes,
238738
+ lowWaterBytes: this.lowWaterBytes,
238739
+ backpressured: this.backpressured,
238740
+ lastSampledAt: this.lastSampledAt
238741
+ };
238742
+ }
238743
+ }
238744
+
238387
238745
  // src/server.ts
238388
238746
  function normalizeQueryArray(value) {
238389
238747
  if (value === undefined || value === null)
@@ -238465,6 +238823,10 @@ var manifestService = new ManifestService(environmentStore);
238465
238823
  var watchModeController = new WatchModeController(environmentStore);
238466
238824
  var connectionController = new ConnectionController(environmentStore);
238467
238825
  var modelController = new ModelController(environmentStore);
238826
+ var memoryGovernorConfig = getMemoryGovernorConfig();
238827
+ var memoryGovernor = memoryGovernorConfig ? new PackageMemoryGovernor(memoryGovernorConfig) : null;
238828
+ memoryGovernor?.start();
238829
+ environmentStore.setMemoryGovernor(memoryGovernor);
238468
238830
  var packageController = new PackageController(environmentStore, manifestService);
238469
238831
  var databaseController = new DatabaseController(environmentStore);
238470
238832
  var queryController = new QueryController(environmentStore);