@malloy-publisher/server 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/app/api-doc.yaml +140 -44
  2. package/dist/app/assets/{EnvironmentPage-D6kQraU3.js → EnvironmentPage-BnxD6uzV.js} +1 -1
  3. package/dist/app/assets/{HomePage-BZbuE5jv.js → HomePage-D_srvBnZ.js} +1 -1
  4. package/dist/app/assets/{LightMode-BxZdPcNr.js → LightMode-DCsTKw61.js} +1 -1
  5. package/dist/app/assets/MainPage-CzHkstrF.js +2 -0
  6. package/dist/app/assets/ModelPage-CoQ07DHX.js +2 -0
  7. package/dist/app/assets/PackagePage-CUeUHOnm.js +1 -0
  8. package/dist/app/assets/RenderedResult-BnPzJ9Jf.es-Dme58kt1.js +116 -0
  9. package/dist/app/assets/RouteError-gRAhsKGi.js +1 -0
  10. package/dist/app/assets/ThemeEditorPage-C2gOJTU1.js +1 -0
  11. package/dist/app/assets/ToggleButtonGroup-CoIPitu6.js +1 -0
  12. package/dist/app/assets/index-BhkeAzTe.js +453 -0
  13. package/dist/app/assets/index-BswZnpqD.js +1322 -0
  14. package/dist/app/assets/index-CRAwrhYM.js +2 -0
  15. package/dist/app/assets/index-DKvKsj6c.js +442 -0
  16. package/dist/app/assets/{index-By-g8wiC.js → index-DTfS9vNi.js} +1 -1
  17. package/dist/app/assets/index-hVLQwLRj.js +1 -0
  18. package/dist/app/assets/index.es-D0L4_L8o.js +106 -0
  19. package/dist/app/index.html +1 -1
  20. package/dist/package_load_worker.mjs +20 -1
  21. package/dist/server.mjs +1033 -683
  22. package/package.json +3 -3
  23. package/dist/app/assets/MainPage-DrczCw4J.js +0 -2
  24. package/dist/app/assets/MaterializationsPage-BFLHLEuk.js +0 -1
  25. package/dist/app/assets/ModelPage-CFnfQ6BL.js +0 -1
  26. package/dist/app/assets/PackagePage-DHsVf_mP.js +0 -1
  27. package/dist/app/assets/RouteError-CHq8ubhy.js +0 -1
  28. package/dist/app/assets/ThemeEditorPage-B2y8Y64Y.js +0 -1
  29. package/dist/app/assets/index-BVv6KQ93.js +0 -557
  30. package/dist/app/assets/index-Bqrhk3ff.js +0 -2
  31. package/dist/app/assets/index-CawCwLK3.js +0 -1774
package/dist/server.mjs CHANGED
@@ -176443,6 +176443,11 @@ function internalErrorToHttpError(error) {
176443
176443
  return httpError(409, error.message);
176444
176444
  } else if (error instanceof InvalidStateTransitionError) {
176445
176445
  return httpError(409, error.message);
176446
+ } else if (error instanceof WriteConflictError) {
176447
+ return httpError(409, error.message);
176448
+ } else if (error instanceof WriteRolledBackError) {
176449
+ logInternalFailure("Dashboard write rolled back", error, "warn");
176450
+ return httpError(500, error.message);
176446
176451
  } else if (error instanceof ServiceUnavailableError) {
176447
176452
  return httpError(503, error.message);
176448
176453
  } else if (error instanceof PayloadTooLargeError) {
@@ -176466,7 +176471,7 @@ function httpError(code, message, reason) {
176466
176471
  }
176467
176472
  };
176468
176473
  }
176469
- var GENERIC_INTERNAL_MESSAGE = "Internal server error.", GENERIC_UPSTREAM_MESSAGE = "Upstream connection error.", MAX_LOGGED_DETAIL_CHARS = 2000, NotImplementedError, BadRequestError, InvalidArgumentError, EnvironmentNotFoundError, PackageNotFoundError, ModelNotFoundError, DashboardNotFoundError, ConnectionNotFoundError, TableNotFoundError, ConnectionError, DestinationNotFoundError, ConnectionAuthError, UnsupportedCatalogFormatError, ModelCompilationError, MaterializationEligibilityError, PublisherConfigError, FrozenConfigError, AccessDeniedError, NotQueryableError, MaterializationNotFoundError, MaterializationConflictError, InvalidStateTransitionError, ServiceUnavailableError, PayloadTooLargeError, ResponseUnserializableError, QueryTimeoutError;
176474
+ var GENERIC_INTERNAL_MESSAGE = "Internal server error.", GENERIC_UPSTREAM_MESSAGE = "Upstream connection error.", MAX_LOGGED_DETAIL_CHARS = 2000, NotImplementedError, BadRequestError, InvalidArgumentError, CompileRefusedError, EnvironmentNotFoundError, PackageNotFoundError, ModelNotFoundError, DashboardNotFoundError, ConnectionNotFoundError, TableNotFoundError, ConnectionError, DestinationNotFoundError, ConnectionAuthError, UnsupportedCatalogFormatError, ModelCompilationError, MaterializationEligibilityError, PublisherConfigError, FrozenConfigError, AccessDeniedError, NotQueryableError, MaterializationNotFoundError, MaterializationConflictError, WriteConflictError, WriteRolledBackError, InvalidStateTransitionError, ServiceUnavailableError, PayloadTooLargeError, ResponseUnserializableError, QueryTimeoutError;
176470
176475
  var init_errors = __esm(() => {
176471
176476
  init_constants();
176472
176477
  init_logger();
@@ -176482,6 +176487,8 @@ var init_errors = __esm(() => {
176482
176487
  };
176483
176488
  InvalidArgumentError = class InvalidArgumentError extends BadRequestError {
176484
176489
  };
176490
+ CompileRefusedError = class CompileRefusedError extends BadRequestError {
176491
+ };
176485
176492
  EnvironmentNotFoundError = class EnvironmentNotFoundError extends Error {
176486
176493
  constructor(message) {
176487
176494
  super(message);
@@ -176581,6 +176588,18 @@ var init_errors = __esm(() => {
176581
176588
  super(message);
176582
176589
  }
176583
176590
  };
176591
+ WriteConflictError = class WriteConflictError extends Error {
176592
+ constructor(message) {
176593
+ super(message);
176594
+ this.name = "WriteConflictError";
176595
+ }
176596
+ };
176597
+ WriteRolledBackError = class WriteRolledBackError extends Error {
176598
+ constructor(message) {
176599
+ super(message);
176600
+ this.name = "WriteRolledBackError";
176601
+ }
176602
+ };
176584
176603
  InvalidStateTransitionError = class InvalidStateTransitionError extends Error {
176585
176604
  constructor(message) {
176586
176605
  super(message);
@@ -176654,6 +176673,65 @@ var init_query_cap_metrics = __esm(() => {
176654
176673
  init_config();
176655
176674
  });
176656
176675
 
176676
+ // src/path_safety.ts
176677
+ import * as path2 from "path";
176678
+ function assertSafePackageName(packageName) {
176679
+ if (typeof packageName !== "string" || !SAFE_NAME_RE.test(packageName)) {
176680
+ throw new BadRequestError(`Invalid package name: must be 1-255 characters of letters, digits, "-", "_", or "." and must not start with "."`);
176681
+ }
176682
+ }
176683
+ function assertSafeRelativeModelPath(modelPath) {
176684
+ if (typeof modelPath !== "string" || modelPath.length === 0 || modelPath.length > MAX_MODEL_PATH_LEN || modelPath.includes("\x00") || modelPath.includes("\\") || path2.isAbsolute(modelPath) || modelPath.startsWith("/")) {
176685
+ throw new BadRequestError(`Invalid model path`);
176686
+ }
176687
+ const segments = modelPath.split("/");
176688
+ for (const segment of segments) {
176689
+ if (segment === "" || segment === "." || segment === "..") {
176690
+ throw new BadRequestError(`Invalid model path`);
176691
+ }
176692
+ if (segment.startsWith(".")) {
176693
+ throw new BadRequestError(`Invalid model path`);
176694
+ }
176695
+ }
176696
+ }
176697
+ function assertSafeEnvironmentPath(environmentPath) {
176698
+ if (typeof environmentPath !== "string") {
176699
+ throw new BadRequestError(`Invalid environment path: must be a string`);
176700
+ }
176701
+ if (environmentPath.length === 0 || environmentPath.length > MAX_ENVIRONMENT_PATH_LEN) {
176702
+ throw new BadRequestError(`Invalid environment path: bad length`);
176703
+ }
176704
+ if (environmentPath.indexOf("\x00") !== -1) {
176705
+ throw new BadRequestError(`Invalid environment path: contains NUL byte`);
176706
+ }
176707
+ if (environmentPath.indexOf("..") !== -1) {
176708
+ throw new BadRequestError(`Invalid environment path: contains ".." traversal segment`);
176709
+ }
176710
+ if (!SAFE_ENVIRONMENT_PATH_RE.test(environmentPath)) {
176711
+ throw new BadRequestError(`Invalid environment path: must be an absolute path of printable ASCII characters`);
176712
+ }
176713
+ }
176714
+ function safeJoinUnderRoot(root, ...segments) {
176715
+ const resolvedRoot = path2.resolve(root);
176716
+ const joined = path2.resolve(resolvedRoot, ...segments);
176717
+ const rootWithSep = resolvedRoot.endsWith(path2.sep) ? resolvedRoot : resolvedRoot + path2.sep;
176718
+ if (joined !== resolvedRoot && !joined.startsWith(rootWithSep)) {
176719
+ throw new BadRequestError(`Resolved path is outside of root`);
176720
+ }
176721
+ return joined;
176722
+ }
176723
+ var SAFE_NAME_RE, MAX_MODEL_PATH_LEN = 1024, SAFE_ENVIRONMENT_PATH_RE, MAX_ENVIRONMENT_PATH_LEN = 4096;
176724
+ var init_path_safety = __esm(() => {
176725
+ init_errors();
176726
+ SAFE_NAME_RE = /^(?!\.\.?$)(?!\.)[A-Za-z0-9._-]{1,255}$/;
176727
+ SAFE_ENVIRONMENT_PATH_RE = /^(?:\/|[A-Za-z]:[\\/])[\x20-\x7E]*$/;
176728
+ });
176729
+
176730
+ // src/pg_helpers.ts
176731
+ function redactPgSecrets(s) {
176732
+ return s.replace(/([a-z][a-z0-9+.-]*:\/\/[^:/?#\s]*):([^/\s]+)@/gi, "$1:***@").replace(/((?:postgres|postgresql):\/\/[^:/?#\s]*):([^@\s]+)@/gi, "$1:***@").replace(/password=('(?:\\.|[^'\\])*'|"[^"]*"|\S+)/gi, "password=***");
176733
+ }
176734
+
176657
176735
  // ../../node_modules/delayed-stream/lib/delayed_stream.js
176658
176736
  var require_delayed_stream = __commonJS((exports, module) => {
176659
176737
  var Stream = __require("stream").Stream;
@@ -185494,11 +185572,11 @@ var require_mime_types3 = __commonJS((exports) => {
185494
185572
  }
185495
185573
  return exts[0];
185496
185574
  }
185497
- function lookup(path2) {
185498
- if (!path2 || typeof path2 !== "string") {
185575
+ function lookup(path3) {
185576
+ if (!path3 || typeof path3 !== "string") {
185499
185577
  return false;
185500
185578
  }
185501
- var extension2 = extname("x." + path2).toLowerCase().substr(1);
185579
+ var extension2 = extname("x." + path3).toLowerCase().substr(1);
185502
185580
  if (!extension2) {
185503
185581
  return false;
185504
185582
  }
@@ -185768,7 +185846,7 @@ var require_populate = __commonJS((exports, module) => {
185768
185846
  var require_form_data = __commonJS((exports, module) => {
185769
185847
  var CombinedStream = require_combined_stream();
185770
185848
  var util3 = __require("util");
185771
- var path2 = __require("path");
185849
+ var path3 = __require("path");
185772
185850
  var http = __require("http");
185773
185851
  var https = __require("https");
185774
185852
  var parseUrl = __require("url").parse;
@@ -185895,11 +185973,11 @@ var require_form_data = __commonJS((exports, module) => {
185895
185973
  FormData2.prototype._getContentDisposition = function(value, options) {
185896
185974
  var filename;
185897
185975
  if (typeof options.filepath === "string") {
185898
- filename = path2.normalize(options.filepath).replace(/\\/g, "/");
185976
+ filename = path3.normalize(options.filepath).replace(/\\/g, "/");
185899
185977
  } else if (options.filename || value && (value.name || value.path)) {
185900
- filename = path2.basename(options.filename || value && (value.name || value.path));
185978
+ filename = path3.basename(options.filename || value && (value.name || value.path));
185901
185979
  } else if (value && value.readable && hasOwn(value, "httpVersion")) {
185902
- filename = path2.basename(value.client._httpMessage.path || "");
185980
+ filename = path3.basename(value.client._httpMessage.path || "");
185903
185981
  }
185904
185982
  if (filename) {
185905
185983
  return 'filename="' + filename + '"';
@@ -186635,10 +186713,10 @@ var require_axios = __commonJS((exports, module) => {
186635
186713
  function removeBrackets(key) {
186636
186714
  return utils$1.endsWith(key, "[]") ? key.slice(0, -2) : key;
186637
186715
  }
186638
- function renderKey(path2, key, dots) {
186639
- if (!path2)
186716
+ function renderKey(path3, key, dots) {
186717
+ if (!path3)
186640
186718
  return key;
186641
- return path2.concat(key).map(function each(token, i) {
186719
+ return path3.concat(key).map(function each(token, i) {
186642
186720
  token = removeBrackets(token);
186643
186721
  return !dots && i ? "[" + token + "]" : token;
186644
186722
  }).join(dots ? "." : "");
@@ -186687,9 +186765,9 @@ var require_axios = __commonJS((exports, module) => {
186687
186765
  }
186688
186766
  return value;
186689
186767
  }
186690
- function defaultVisitor(value, key, path2) {
186768
+ function defaultVisitor(value, key, path3) {
186691
186769
  let arr = value;
186692
- if (value && !path2 && typeof value === "object") {
186770
+ if (value && !path3 && typeof value === "object") {
186693
186771
  if (utils$1.endsWith(key, "{}")) {
186694
186772
  key = metaTokens ? key : key.slice(0, -2);
186695
186773
  value = JSON.stringify(value);
@@ -186704,7 +186782,7 @@ var require_axios = __commonJS((exports, module) => {
186704
186782
  if (isVisitable(value)) {
186705
186783
  return true;
186706
186784
  }
186707
- formData.append(renderKey(path2, key, dots), convertValue(value));
186785
+ formData.append(renderKey(path3, key, dots), convertValue(value));
186708
186786
  return false;
186709
186787
  }
186710
186788
  const stack = [];
@@ -186713,17 +186791,17 @@ var require_axios = __commonJS((exports, module) => {
186713
186791
  convertValue,
186714
186792
  isVisitable
186715
186793
  });
186716
- function build(value, path2) {
186794
+ function build(value, path3) {
186717
186795
  if (utils$1.isUndefined(value))
186718
186796
  return;
186719
186797
  if (stack.indexOf(value) !== -1) {
186720
- throw Error("Circular reference detected in " + path2.join("."));
186798
+ throw Error("Circular reference detected in " + path3.join("."));
186721
186799
  }
186722
186800
  stack.push(value);
186723
186801
  utils$1.forEach(value, function each(el, key) {
186724
- const result = !(utils$1.isUndefined(el) || el === null) && visitor.call(formData, el, utils$1.isString(key) ? key.trim() : key, path2, exposedHelpers);
186802
+ const result = !(utils$1.isUndefined(el) || el === null) && visitor.call(formData, el, utils$1.isString(key) ? key.trim() : key, path3, exposedHelpers);
186725
186803
  if (result === true) {
186726
- build(el, path2 ? path2.concat(key) : [key]);
186804
+ build(el, path3 ? path3.concat(key) : [key]);
186727
186805
  }
186728
186806
  });
186729
186807
  stack.pop();
@@ -186881,7 +186959,7 @@ var require_axios = __commonJS((exports, module) => {
186881
186959
  };
186882
186960
  function toURLEncodedForm(data, options) {
186883
186961
  return toFormData(data, new platform.classes.URLSearchParams, {
186884
- visitor: function(value, key, path2, helpers) {
186962
+ visitor: function(value, key, path3, helpers) {
186885
186963
  if (platform.isNode && utils$1.isBuffer(value)) {
186886
186964
  this.append(key, value.toString("base64"));
186887
186965
  return false;
@@ -186909,12 +186987,12 @@ var require_axios = __commonJS((exports, module) => {
186909
186987
  return obj;
186910
186988
  }
186911
186989
  function formDataToJSON(formData) {
186912
- function buildPath(path2, value, target, index) {
186913
- let name = path2[index++];
186990
+ function buildPath(path3, value, target, index) {
186991
+ let name = path3[index++];
186914
186992
  if (name === "__proto__")
186915
186993
  return true;
186916
186994
  const isNumericKey = Number.isFinite(+name);
186917
- const isLast = index >= path2.length;
186995
+ const isLast = index >= path3.length;
186918
186996
  name = !name && utils$1.isArray(target) ? target.length : name;
186919
186997
  if (isLast) {
186920
186998
  if (utils$1.hasOwnProp(target, name)) {
@@ -186927,7 +187005,7 @@ var require_axios = __commonJS((exports, module) => {
186927
187005
  if (!target[name] || !utils$1.isObject(target[name])) {
186928
187006
  target[name] = [];
186929
187007
  }
186930
- const result = buildPath(path2, value, target[name], index);
187008
+ const result = buildPath(path3, value, target[name], index);
186931
187009
  if (result && utils$1.isArray(target[name])) {
186932
187010
  target[name] = arrayToObject(target[name]);
186933
187011
  }
@@ -187336,10 +187414,10 @@ var require_axios = __commonJS((exports, module) => {
187336
187414
  utils$1.inherits(CanceledError, AxiosError, {
187337
187415
  __CANCEL__: true
187338
187416
  });
187339
- function settle(resolve, reject, response) {
187417
+ function settle(resolve2, reject, response) {
187340
187418
  const validateStatus = response.config.validateStatus;
187341
187419
  if (!response.status || !validateStatus || validateStatus(response.status)) {
187342
- resolve(response);
187420
+ resolve2(response);
187343
187421
  } else {
187344
187422
  reject(new AxiosError("Request failed with status code " + response.status, [AxiosError.ERR_BAD_REQUEST, AxiosError.ERR_BAD_RESPONSE][Math.floor(response.status / 100) - 4], response.config, response.request, response));
187345
187423
  }
@@ -187836,7 +187914,7 @@ var require_axios = __commonJS((exports, module) => {
187836
187914
  }
187837
187915
  var isHttpAdapterSupported = typeof process !== "undefined" && utils$1.kindOf(process) === "process";
187838
187916
  var wrapAsync = (asyncExecutor) => {
187839
- return new Promise((resolve, reject) => {
187917
+ return new Promise((resolve2, reject) => {
187840
187918
  let onDone;
187841
187919
  let isDone;
187842
187920
  const done = (value, isRejected) => {
@@ -187847,7 +187925,7 @@ var require_axios = __commonJS((exports, module) => {
187847
187925
  };
187848
187926
  const _resolve = (value) => {
187849
187927
  done(value);
187850
- resolve(value);
187928
+ resolve2(value);
187851
187929
  };
187852
187930
  const _reject = (reason) => {
187853
187931
  done(reason, true);
@@ -187867,7 +187945,7 @@ var require_axios = __commonJS((exports, module) => {
187867
187945
  };
187868
187946
  var buildAddressEntry = (address, family) => resolveFamily(utils$1.isObject(address) ? address : { address, family });
187869
187947
  var httpAdapter = isHttpAdapterSupported && function httpAdapter2(config) {
187870
- return wrapAsync(async function dispatchHttpRequest(resolve, reject, onDone) {
187948
+ return wrapAsync(async function dispatchHttpRequest(resolve2, reject, onDone) {
187871
187949
  let { data, lookup, family } = config;
187872
187950
  const { responseType, responseEncoding } = config;
187873
187951
  const method = config.method.toUpperCase();
@@ -187926,7 +188004,7 @@ var require_axios = __commonJS((exports, module) => {
187926
188004
  }
187927
188005
  let convertedData;
187928
188006
  if (method !== "GET") {
187929
- return settle(resolve, reject, {
188007
+ return settle(resolve2, reject, {
187930
188008
  status: 405,
187931
188009
  statusText: "method not allowed",
187932
188010
  headers: {},
@@ -187948,7 +188026,7 @@ var require_axios = __commonJS((exports, module) => {
187948
188026
  } else if (responseType === "stream") {
187949
188027
  convertedData = stream__default["default"].Readable.from(convertedData);
187950
188028
  }
187951
- return settle(resolve, reject, {
188029
+ return settle(resolve2, reject, {
187952
188030
  data: convertedData,
187953
188031
  status: 200,
187954
188032
  statusText: "OK",
@@ -188028,9 +188106,9 @@ var require_axios = __commonJS((exports, module) => {
188028
188106
  auth = urlUsername + ":" + urlPassword;
188029
188107
  }
188030
188108
  auth && headers.delete("authorization");
188031
- let path2;
188109
+ let path3;
188032
188110
  try {
188033
- path2 = buildURL(parsed.pathname + parsed.search, config.params, config.paramsSerializer).replace(/^\?/, "");
188111
+ path3 = buildURL(parsed.pathname + parsed.search, config.params, config.paramsSerializer).replace(/^\?/, "");
188034
188112
  } catch (err) {
188035
188113
  const customErr = new Error(err.message);
188036
188114
  customErr.config = config;
@@ -188040,7 +188118,7 @@ var require_axios = __commonJS((exports, module) => {
188040
188118
  }
188041
188119
  headers.set("Accept-Encoding", "gzip, compress, deflate" + (isBrotliSupported ? ", br" : ""), false);
188042
188120
  const options = {
188043
- path: path2,
188121
+ path: path3,
188044
188122
  method,
188045
188123
  headers: headers.toJSON(),
188046
188124
  agents: { http: config.httpAgent, https: config.httpsAgent },
@@ -188134,7 +188212,7 @@ var require_axios = __commonJS((exports, module) => {
188134
188212
  };
188135
188213
  if (responseType === "stream") {
188136
188214
  response.data = responseStream;
188137
- settle(resolve, reject, response);
188215
+ settle(resolve2, reject, response);
188138
188216
  } else {
188139
188217
  const responseBuffer = [];
188140
188218
  let totalResponseBytes = 0;
@@ -188173,7 +188251,7 @@ var require_axios = __commonJS((exports, module) => {
188173
188251
  } catch (err) {
188174
188252
  return reject(AxiosError.from(err, null, config, response.request, response));
188175
188253
  }
188176
- settle(resolve, reject, response);
188254
+ settle(resolve2, reject, response);
188177
188255
  });
188178
188256
  }
188179
188257
  emitter.once("abort", (err) => {
@@ -188237,10 +188315,10 @@ var require_axios = __commonJS((exports, module) => {
188237
188315
  return origin2.protocol === url2.protocol && origin2.host === url2.host && (isMSIE || origin2.port === url2.port);
188238
188316
  })(new URL(platform.origin), platform.navigator && /(msie|trident)/i.test(platform.navigator.userAgent)) : () => true;
188239
188317
  var cookies = platform.hasStandardBrowserEnv ? {
188240
- write(name, value, expires, path2, domain, secure) {
188318
+ write(name, value, expires, path3, domain, secure) {
188241
188319
  const cookie = [name + "=" + encodeURIComponent(value)];
188242
188320
  utils$1.isNumber(expires) && cookie.push("expires=" + new Date(expires).toGMTString());
188243
- utils$1.isString(path2) && cookie.push("path=" + path2);
188321
+ utils$1.isString(path3) && cookie.push("path=" + path3);
188244
188322
  utils$1.isString(domain) && cookie.push("domain=" + domain);
188245
188323
  secure === true && cookie.push("secure");
188246
188324
  document.cookie = cookie.join("; ");
@@ -188371,7 +188449,7 @@ var require_axios = __commonJS((exports, module) => {
188371
188449
  };
188372
188450
  var isXHRAdapterSupported = typeof XMLHttpRequest !== "undefined";
188373
188451
  var xhrAdapter = isXHRAdapterSupported && function(config) {
188374
- return new Promise(function dispatchXhrRequest(resolve, reject) {
188452
+ return new Promise(function dispatchXhrRequest(resolve2, reject) {
188375
188453
  const _config = resolveConfig(config);
188376
188454
  let requestData = _config.data;
188377
188455
  const requestHeaders = AxiosHeaders$1.from(_config.headers).normalize();
@@ -188403,7 +188481,7 @@ var require_axios = __commonJS((exports, module) => {
188403
188481
  request
188404
188482
  };
188405
188483
  settle(function _resolve(value) {
188406
- resolve(value);
188484
+ resolve2(value);
188407
188485
  done();
188408
188486
  }, function _reject(err) {
188409
188487
  reject(err);
@@ -188754,8 +188832,8 @@ var require_axios = __commonJS((exports, module) => {
188754
188832
  responseType = responseType || "text";
188755
188833
  let responseData = await resolvers[utils$1.findKey(resolvers, responseType) || "text"](response, config);
188756
188834
  !isStreamResponse && unsubscribe && unsubscribe();
188757
- return await new Promise((resolve, reject) => {
188758
- settle(resolve, reject, {
188835
+ return await new Promise((resolve2, reject) => {
188836
+ settle(resolve2, reject, {
188759
188837
  data: responseData,
188760
188838
  headers: AxiosHeaders$1.from(response.headers),
188761
188839
  status: response.status,
@@ -189095,8 +189173,8 @@ var require_axios = __commonJS((exports, module) => {
189095
189173
  throw new TypeError("executor must be a function.");
189096
189174
  }
189097
189175
  let resolvePromise;
189098
- this.promise = new Promise(function promiseExecutor(resolve) {
189099
- resolvePromise = resolve;
189176
+ this.promise = new Promise(function promiseExecutor(resolve2) {
189177
+ resolvePromise = resolve2;
189100
189178
  });
189101
189179
  const token = this;
189102
189180
  this.promise.then((cancel) => {
@@ -189110,9 +189188,9 @@ var require_axios = __commonJS((exports, module) => {
189110
189188
  });
189111
189189
  this.promise.then = (onfulfilled) => {
189112
189190
  let _resolve;
189113
- const promise = new Promise((resolve) => {
189114
- token.subscribe(resolve);
189115
- _resolve = resolve;
189191
+ const promise = new Promise((resolve2) => {
189192
+ token.subscribe(resolve2);
189193
+ _resolve = resolve2;
189116
189194
  }).then(onfulfilled);
189117
189195
  promise.cancel = function reject() {
189118
189196
  token.unsubscribe(_resolve);
@@ -190420,12 +190498,12 @@ var require_api2 = __commonJS((exports) => {
190420
190498
  };
190421
190499
  var ModelsApiAxiosParamCreator = function(configuration) {
190422
190500
  return {
190423
- compileModelSource: async (projectName, packageName, path2, compileRequest, options = {}) => {
190501
+ compileModelSource: async (projectName, packageName, path3, compileRequest, options = {}) => {
190424
190502
  (0, common_1.assertParamExists)("compileModelSource", "projectName", projectName);
190425
190503
  (0, common_1.assertParamExists)("compileModelSource", "packageName", packageName);
190426
- (0, common_1.assertParamExists)("compileModelSource", "path", path2);
190504
+ (0, common_1.assertParamExists)("compileModelSource", "path", path3);
190427
190505
  (0, common_1.assertParamExists)("compileModelSource", "compileRequest", compileRequest);
190428
- const localVarPath = `/projects/{projectName}/packages/{packageName}/models/{path}/compile`.replace(`{${"projectName"}}`, encodeURIComponent(String(projectName))).replace(`{${"packageName"}}`, encodeURIComponent(String(packageName))).replace(`{${"path"}}`, encodeURIComponent(String(path2)));
190506
+ const localVarPath = `/projects/{projectName}/packages/{packageName}/models/{path}/compile`.replace(`{${"projectName"}}`, encodeURIComponent(String(projectName))).replace(`{${"packageName"}}`, encodeURIComponent(String(packageName))).replace(`{${"path"}}`, encodeURIComponent(String(path3)));
190429
190507
  const localVarUrlObj = new URL(localVarPath, common_1.DUMMY_BASE_URL);
190430
190508
  let baseOptions;
190431
190509
  if (configuration) {
@@ -190444,12 +190522,12 @@ var require_api2 = __commonJS((exports) => {
190444
190522
  options: localVarRequestOptions
190445
190523
  };
190446
190524
  },
190447
- executeQueryModel: async (projectName, packageName, path2, queryRequest, options = {}) => {
190525
+ executeQueryModel: async (projectName, packageName, path3, queryRequest, options = {}) => {
190448
190526
  (0, common_1.assertParamExists)("executeQueryModel", "projectName", projectName);
190449
190527
  (0, common_1.assertParamExists)("executeQueryModel", "packageName", packageName);
190450
- (0, common_1.assertParamExists)("executeQueryModel", "path", path2);
190528
+ (0, common_1.assertParamExists)("executeQueryModel", "path", path3);
190451
190529
  (0, common_1.assertParamExists)("executeQueryModel", "queryRequest", queryRequest);
190452
- const localVarPath = `/projects/{projectName}/packages/{packageName}/models/{path}/query`.replace(`{${"projectName"}}`, encodeURIComponent(String(projectName))).replace(`{${"packageName"}}`, encodeURIComponent(String(packageName))).replace(`{${"path"}}`, encodeURIComponent(String(path2)));
190530
+ const localVarPath = `/projects/{projectName}/packages/{packageName}/models/{path}/query`.replace(`{${"projectName"}}`, encodeURIComponent(String(projectName))).replace(`{${"packageName"}}`, encodeURIComponent(String(packageName))).replace(`{${"path"}}`, encodeURIComponent(String(path3)));
190453
190531
  const localVarUrlObj = new URL(localVarPath, common_1.DUMMY_BASE_URL);
190454
190532
  let baseOptions;
190455
190533
  if (configuration) {
@@ -190468,11 +190546,11 @@ var require_api2 = __commonJS((exports) => {
190468
190546
  options: localVarRequestOptions
190469
190547
  };
190470
190548
  },
190471
- getModel: async (projectName, packageName, path2, versionId, options = {}) => {
190549
+ getModel: async (projectName, packageName, path3, versionId, options = {}) => {
190472
190550
  (0, common_1.assertParamExists)("getModel", "projectName", projectName);
190473
190551
  (0, common_1.assertParamExists)("getModel", "packageName", packageName);
190474
- (0, common_1.assertParamExists)("getModel", "path", path2);
190475
- const localVarPath = `/projects/{projectName}/packages/{packageName}/models/{path}`.replace(`{${"projectName"}}`, encodeURIComponent(String(projectName))).replace(`{${"packageName"}}`, encodeURIComponent(String(packageName))).replace(`{${"path"}}`, encodeURIComponent(String(path2)));
190552
+ (0, common_1.assertParamExists)("getModel", "path", path3);
190553
+ const localVarPath = `/projects/{projectName}/packages/{packageName}/models/{path}`.replace(`{${"projectName"}}`, encodeURIComponent(String(projectName))).replace(`{${"packageName"}}`, encodeURIComponent(String(packageName))).replace(`{${"path"}}`, encodeURIComponent(String(path3)));
190476
190554
  const localVarUrlObj = new URL(localVarPath, common_1.DUMMY_BASE_URL);
190477
190555
  let baseOptions;
190478
190556
  if (configuration) {
@@ -190521,23 +190599,23 @@ var require_api2 = __commonJS((exports) => {
190521
190599
  var ModelsApiFp = function(configuration) {
190522
190600
  const localVarAxiosParamCreator = (0, exports.ModelsApiAxiosParamCreator)(configuration);
190523
190601
  return {
190524
- async compileModelSource(projectName, packageName, path2, compileRequest, options) {
190602
+ async compileModelSource(projectName, packageName, path3, compileRequest, options) {
190525
190603
  var _a, _b, _c;
190526
- const localVarAxiosArgs = await localVarAxiosParamCreator.compileModelSource(projectName, packageName, path2, compileRequest, options);
190604
+ const localVarAxiosArgs = await localVarAxiosParamCreator.compileModelSource(projectName, packageName, path3, compileRequest, options);
190527
190605
  const localVarOperationServerIndex = (_a = configuration === null || configuration === undefined ? undefined : configuration.serverIndex) !== null && _a !== undefined ? _a : 0;
190528
190606
  const localVarOperationServerBasePath = (_c = (_b = base_1.operationServerMap["ModelsApi.compileModelSource"]) === null || _b === undefined ? undefined : _b[localVarOperationServerIndex]) === null || _c === undefined ? undefined : _c.url;
190529
190607
  return (axios, basePath) => (0, common_1.createRequestFunction)(localVarAxiosArgs, axios_1.default, base_1.BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
190530
190608
  },
190531
- async executeQueryModel(projectName, packageName, path2, queryRequest, options) {
190609
+ async executeQueryModel(projectName, packageName, path3, queryRequest, options) {
190532
190610
  var _a, _b, _c;
190533
- const localVarAxiosArgs = await localVarAxiosParamCreator.executeQueryModel(projectName, packageName, path2, queryRequest, options);
190611
+ const localVarAxiosArgs = await localVarAxiosParamCreator.executeQueryModel(projectName, packageName, path3, queryRequest, options);
190534
190612
  const localVarOperationServerIndex = (_a = configuration === null || configuration === undefined ? undefined : configuration.serverIndex) !== null && _a !== undefined ? _a : 0;
190535
190613
  const localVarOperationServerBasePath = (_c = (_b = base_1.operationServerMap["ModelsApi.executeQueryModel"]) === null || _b === undefined ? undefined : _b[localVarOperationServerIndex]) === null || _c === undefined ? undefined : _c.url;
190536
190614
  return (axios, basePath) => (0, common_1.createRequestFunction)(localVarAxiosArgs, axios_1.default, base_1.BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
190537
190615
  },
190538
- async getModel(projectName, packageName, path2, versionId, options) {
190616
+ async getModel(projectName, packageName, path3, versionId, options) {
190539
190617
  var _a, _b, _c;
190540
- const localVarAxiosArgs = await localVarAxiosParamCreator.getModel(projectName, packageName, path2, versionId, options);
190618
+ const localVarAxiosArgs = await localVarAxiosParamCreator.getModel(projectName, packageName, path3, versionId, options);
190541
190619
  const localVarOperationServerIndex = (_a = configuration === null || configuration === undefined ? undefined : configuration.serverIndex) !== null && _a !== undefined ? _a : 0;
190542
190620
  const localVarOperationServerBasePath = (_c = (_b = base_1.operationServerMap["ModelsApi.getModel"]) === null || _b === undefined ? undefined : _b[localVarOperationServerIndex]) === null || _c === undefined ? undefined : _c.url;
190543
190621
  return (axios, basePath) => (0, common_1.createRequestFunction)(localVarAxiosArgs, axios_1.default, base_1.BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
@@ -190555,14 +190633,14 @@ var require_api2 = __commonJS((exports) => {
190555
190633
  var ModelsApiFactory = function(configuration, basePath, axios) {
190556
190634
  const localVarFp = (0, exports.ModelsApiFp)(configuration);
190557
190635
  return {
190558
- compileModelSource(projectName, packageName, path2, compileRequest, options) {
190559
- return localVarFp.compileModelSource(projectName, packageName, path2, compileRequest, options).then((request) => request(axios, basePath));
190636
+ compileModelSource(projectName, packageName, path3, compileRequest, options) {
190637
+ return localVarFp.compileModelSource(projectName, packageName, path3, compileRequest, options).then((request) => request(axios, basePath));
190560
190638
  },
190561
- executeQueryModel(projectName, packageName, path2, queryRequest, options) {
190562
- return localVarFp.executeQueryModel(projectName, packageName, path2, queryRequest, options).then((request) => request(axios, basePath));
190639
+ executeQueryModel(projectName, packageName, path3, queryRequest, options) {
190640
+ return localVarFp.executeQueryModel(projectName, packageName, path3, queryRequest, options).then((request) => request(axios, basePath));
190563
190641
  },
190564
- getModel(projectName, packageName, path2, versionId, options) {
190565
- return localVarFp.getModel(projectName, packageName, path2, versionId, options).then((request) => request(axios, basePath));
190642
+ getModel(projectName, packageName, path3, versionId, options) {
190643
+ return localVarFp.getModel(projectName, packageName, path3, versionId, options).then((request) => request(axios, basePath));
190566
190644
  },
190567
190645
  listModels(projectName, packageName, versionId, options) {
190568
190646
  return localVarFp.listModels(projectName, packageName, versionId, options).then((request) => request(axios, basePath));
@@ -190572,14 +190650,14 @@ var require_api2 = __commonJS((exports) => {
190572
190650
  exports.ModelsApiFactory = ModelsApiFactory;
190573
190651
 
190574
190652
  class ModelsApi extends base_1.BaseAPI {
190575
- compileModelSource(projectName, packageName, path2, compileRequest, options) {
190576
- return (0, exports.ModelsApiFp)(this.configuration).compileModelSource(projectName, packageName, path2, compileRequest, options).then((request) => request(this.axios, this.basePath));
190653
+ compileModelSource(projectName, packageName, path3, compileRequest, options) {
190654
+ return (0, exports.ModelsApiFp)(this.configuration).compileModelSource(projectName, packageName, path3, compileRequest, options).then((request) => request(this.axios, this.basePath));
190577
190655
  }
190578
- executeQueryModel(projectName, packageName, path2, queryRequest, options) {
190579
- return (0, exports.ModelsApiFp)(this.configuration).executeQueryModel(projectName, packageName, path2, queryRequest, options).then((request) => request(this.axios, this.basePath));
190656
+ executeQueryModel(projectName, packageName, path3, queryRequest, options) {
190657
+ return (0, exports.ModelsApiFp)(this.configuration).executeQueryModel(projectName, packageName, path3, queryRequest, options).then((request) => request(this.axios, this.basePath));
190580
190658
  }
190581
- getModel(projectName, packageName, path2, versionId, options) {
190582
- return (0, exports.ModelsApiFp)(this.configuration).getModel(projectName, packageName, path2, versionId, options).then((request) => request(this.axios, this.basePath));
190659
+ getModel(projectName, packageName, path3, versionId, options) {
190660
+ return (0, exports.ModelsApiFp)(this.configuration).getModel(projectName, packageName, path3, versionId, options).then((request) => request(this.axios, this.basePath));
190583
190661
  }
190584
190662
  listModels(projectName, packageName, versionId, options) {
190585
190663
  return (0, exports.ModelsApiFp)(this.configuration).listModels(projectName, packageName, versionId, options).then((request) => request(this.axios, this.basePath));
@@ -190588,12 +190666,12 @@ var require_api2 = __commonJS((exports) => {
190588
190666
  exports.ModelsApi = ModelsApi;
190589
190667
  var NotebooksApiAxiosParamCreator = function(configuration) {
190590
190668
  return {
190591
- executeNotebookCell: async (projectName, packageName, path2, cellIndex, versionId, filterParams, bypassFilters, options = {}) => {
190669
+ executeNotebookCell: async (projectName, packageName, path3, cellIndex, versionId, filterParams, bypassFilters, options = {}) => {
190592
190670
  (0, common_1.assertParamExists)("executeNotebookCell", "projectName", projectName);
190593
190671
  (0, common_1.assertParamExists)("executeNotebookCell", "packageName", packageName);
190594
- (0, common_1.assertParamExists)("executeNotebookCell", "path", path2);
190672
+ (0, common_1.assertParamExists)("executeNotebookCell", "path", path3);
190595
190673
  (0, common_1.assertParamExists)("executeNotebookCell", "cellIndex", cellIndex);
190596
- const localVarPath = `/projects/{projectName}/packages/{packageName}/notebooks/{path}/cells/{cellIndex}`.replace(`{${"projectName"}}`, encodeURIComponent(String(projectName))).replace(`{${"packageName"}}`, encodeURIComponent(String(packageName))).replace(`{${"path"}}`, encodeURIComponent(String(path2))).replace(`{${"cellIndex"}}`, encodeURIComponent(String(cellIndex)));
190674
+ const localVarPath = `/projects/{projectName}/packages/{packageName}/notebooks/{path}/cells/{cellIndex}`.replace(`{${"projectName"}}`, encodeURIComponent(String(projectName))).replace(`{${"packageName"}}`, encodeURIComponent(String(packageName))).replace(`{${"path"}}`, encodeURIComponent(String(path3))).replace(`{${"cellIndex"}}`, encodeURIComponent(String(cellIndex)));
190597
190675
  const localVarUrlObj = new URL(localVarPath, common_1.DUMMY_BASE_URL);
190598
190676
  let baseOptions;
190599
190677
  if (configuration) {
@@ -190619,11 +190697,11 @@ var require_api2 = __commonJS((exports) => {
190619
190697
  options: localVarRequestOptions
190620
190698
  };
190621
190699
  },
190622
- getNotebook: async (projectName, packageName, path2, versionId, options = {}) => {
190700
+ getNotebook: async (projectName, packageName, path3, versionId, options = {}) => {
190623
190701
  (0, common_1.assertParamExists)("getNotebook", "projectName", projectName);
190624
190702
  (0, common_1.assertParamExists)("getNotebook", "packageName", packageName);
190625
- (0, common_1.assertParamExists)("getNotebook", "path", path2);
190626
- const localVarPath = `/projects/{projectName}/packages/{packageName}/notebooks/{path}`.replace(`{${"projectName"}}`, encodeURIComponent(String(projectName))).replace(`{${"packageName"}}`, encodeURIComponent(String(packageName))).replace(`{${"path"}}`, encodeURIComponent(String(path2)));
190703
+ (0, common_1.assertParamExists)("getNotebook", "path", path3);
190704
+ const localVarPath = `/projects/{projectName}/packages/{packageName}/notebooks/{path}`.replace(`{${"projectName"}}`, encodeURIComponent(String(projectName))).replace(`{${"packageName"}}`, encodeURIComponent(String(packageName))).replace(`{${"path"}}`, encodeURIComponent(String(path3)));
190627
190705
  const localVarUrlObj = new URL(localVarPath, common_1.DUMMY_BASE_URL);
190628
190706
  let baseOptions;
190629
190707
  if (configuration) {
@@ -190672,16 +190750,16 @@ var require_api2 = __commonJS((exports) => {
190672
190750
  var NotebooksApiFp = function(configuration) {
190673
190751
  const localVarAxiosParamCreator = (0, exports.NotebooksApiAxiosParamCreator)(configuration);
190674
190752
  return {
190675
- async executeNotebookCell(projectName, packageName, path2, cellIndex, versionId, filterParams, bypassFilters, options) {
190753
+ async executeNotebookCell(projectName, packageName, path3, cellIndex, versionId, filterParams, bypassFilters, options) {
190676
190754
  var _a, _b, _c;
190677
- const localVarAxiosArgs = await localVarAxiosParamCreator.executeNotebookCell(projectName, packageName, path2, cellIndex, versionId, filterParams, bypassFilters, options);
190755
+ const localVarAxiosArgs = await localVarAxiosParamCreator.executeNotebookCell(projectName, packageName, path3, cellIndex, versionId, filterParams, bypassFilters, options);
190678
190756
  const localVarOperationServerIndex = (_a = configuration === null || configuration === undefined ? undefined : configuration.serverIndex) !== null && _a !== undefined ? _a : 0;
190679
190757
  const localVarOperationServerBasePath = (_c = (_b = base_1.operationServerMap["NotebooksApi.executeNotebookCell"]) === null || _b === undefined ? undefined : _b[localVarOperationServerIndex]) === null || _c === undefined ? undefined : _c.url;
190680
190758
  return (axios, basePath) => (0, common_1.createRequestFunction)(localVarAxiosArgs, axios_1.default, base_1.BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
190681
190759
  },
190682
- async getNotebook(projectName, packageName, path2, versionId, options) {
190760
+ async getNotebook(projectName, packageName, path3, versionId, options) {
190683
190761
  var _a, _b, _c;
190684
- const localVarAxiosArgs = await localVarAxiosParamCreator.getNotebook(projectName, packageName, path2, versionId, options);
190762
+ const localVarAxiosArgs = await localVarAxiosParamCreator.getNotebook(projectName, packageName, path3, versionId, options);
190685
190763
  const localVarOperationServerIndex = (_a = configuration === null || configuration === undefined ? undefined : configuration.serverIndex) !== null && _a !== undefined ? _a : 0;
190686
190764
  const localVarOperationServerBasePath = (_c = (_b = base_1.operationServerMap["NotebooksApi.getNotebook"]) === null || _b === undefined ? undefined : _b[localVarOperationServerIndex]) === null || _c === undefined ? undefined : _c.url;
190687
190765
  return (axios, basePath) => (0, common_1.createRequestFunction)(localVarAxiosArgs, axios_1.default, base_1.BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
@@ -190699,11 +190777,11 @@ var require_api2 = __commonJS((exports) => {
190699
190777
  var NotebooksApiFactory = function(configuration, basePath, axios) {
190700
190778
  const localVarFp = (0, exports.NotebooksApiFp)(configuration);
190701
190779
  return {
190702
- executeNotebookCell(projectName, packageName, path2, cellIndex, versionId, filterParams, bypassFilters, options) {
190703
- return localVarFp.executeNotebookCell(projectName, packageName, path2, cellIndex, versionId, filterParams, bypassFilters, options).then((request) => request(axios, basePath));
190780
+ executeNotebookCell(projectName, packageName, path3, cellIndex, versionId, filterParams, bypassFilters, options) {
190781
+ return localVarFp.executeNotebookCell(projectName, packageName, path3, cellIndex, versionId, filterParams, bypassFilters, options).then((request) => request(axios, basePath));
190704
190782
  },
190705
- getNotebook(projectName, packageName, path2, versionId, options) {
190706
- return localVarFp.getNotebook(projectName, packageName, path2, versionId, options).then((request) => request(axios, basePath));
190783
+ getNotebook(projectName, packageName, path3, versionId, options) {
190784
+ return localVarFp.getNotebook(projectName, packageName, path3, versionId, options).then((request) => request(axios, basePath));
190707
190785
  },
190708
190786
  listNotebooks(projectName, packageName, versionId, options) {
190709
190787
  return localVarFp.listNotebooks(projectName, packageName, versionId, options).then((request) => request(axios, basePath));
@@ -190713,11 +190791,11 @@ var require_api2 = __commonJS((exports) => {
190713
190791
  exports.NotebooksApiFactory = NotebooksApiFactory;
190714
190792
 
190715
190793
  class NotebooksApi extends base_1.BaseAPI {
190716
- executeNotebookCell(projectName, packageName, path2, cellIndex, versionId, filterParams, bypassFilters, options) {
190717
- return (0, exports.NotebooksApiFp)(this.configuration).executeNotebookCell(projectName, packageName, path2, cellIndex, versionId, filterParams, bypassFilters, options).then((request) => request(this.axios, this.basePath));
190794
+ executeNotebookCell(projectName, packageName, path3, cellIndex, versionId, filterParams, bypassFilters, options) {
190795
+ return (0, exports.NotebooksApiFp)(this.configuration).executeNotebookCell(projectName, packageName, path3, cellIndex, versionId, filterParams, bypassFilters, options).then((request) => request(this.axios, this.basePath));
190718
190796
  }
190719
- getNotebook(projectName, packageName, path2, versionId, options) {
190720
- return (0, exports.NotebooksApiFp)(this.configuration).getNotebook(projectName, packageName, path2, versionId, options).then((request) => request(this.axios, this.basePath));
190797
+ getNotebook(projectName, packageName, path3, versionId, options) {
190798
+ return (0, exports.NotebooksApiFp)(this.configuration).getNotebook(projectName, packageName, path3, versionId, options).then((request) => request(this.axios, this.basePath));
190721
190799
  }
190722
190800
  listNotebooks(projectName, packageName, versionId, options) {
190723
190801
  return (0, exports.NotebooksApiFp)(this.configuration).listNotebooks(projectName, packageName, versionId, options).then((request) => request(this.axios, this.basePath));
@@ -192019,10 +192097,10 @@ function isVisitable(thing) {
192019
192097
  function removeBrackets(key) {
192020
192098
  return utils_default.endsWith(key, "[]") ? key.slice(0, -2) : key;
192021
192099
  }
192022
- function renderKey(path2, key, dots) {
192023
- if (!path2)
192100
+ function renderKey(path3, key, dots) {
192101
+ if (!path3)
192024
192102
  return key;
192025
- return path2.concat(key).map(function each(token, i) {
192103
+ return path3.concat(key).map(function each(token, i) {
192026
192104
  token = removeBrackets(token);
192027
192105
  return !dots && i ? "[" + token + "]" : token;
192028
192106
  }).join(dots ? "." : "");
@@ -192068,9 +192146,9 @@ function toFormData(obj, formData, options) {
192068
192146
  }
192069
192147
  return value;
192070
192148
  }
192071
- function defaultVisitor(value, key, path2) {
192149
+ function defaultVisitor(value, key, path3) {
192072
192150
  let arr = value;
192073
- if (value && !path2 && typeof value === "object") {
192151
+ if (value && !path3 && typeof value === "object") {
192074
192152
  if (utils_default.endsWith(key, "{}")) {
192075
192153
  key = metaTokens ? key : key.slice(0, -2);
192076
192154
  value = JSON.stringify(value);
@@ -192085,7 +192163,7 @@ function toFormData(obj, formData, options) {
192085
192163
  if (isVisitable(value)) {
192086
192164
  return true;
192087
192165
  }
192088
- formData.append(renderKey(path2, key, dots), convertValue(value));
192166
+ formData.append(renderKey(path3, key, dots), convertValue(value));
192089
192167
  return false;
192090
192168
  }
192091
192169
  const stack = [];
@@ -192094,17 +192172,17 @@ function toFormData(obj, formData, options) {
192094
192172
  convertValue,
192095
192173
  isVisitable
192096
192174
  });
192097
- function build(value, path2) {
192175
+ function build(value, path3) {
192098
192176
  if (utils_default.isUndefined(value))
192099
192177
  return;
192100
192178
  if (stack.indexOf(value) !== -1) {
192101
- throw Error("Circular reference detected in " + path2.join("."));
192179
+ throw Error("Circular reference detected in " + path3.join("."));
192102
192180
  }
192103
192181
  stack.push(value);
192104
192182
  utils_default.forEach(value, function each(el, key) {
192105
- const result = !(utils_default.isUndefined(el) || el === null) && visitor.call(formData, el, utils_default.isString(key) ? key.trim() : key, path2, exposedHelpers);
192183
+ const result = !(utils_default.isUndefined(el) || el === null) && visitor.call(formData, el, utils_default.isString(key) ? key.trim() : key, path3, exposedHelpers);
192106
192184
  if (result === true) {
192107
- build(el, path2 ? path2.concat(key) : [key]);
192185
+ build(el, path3 ? path3.concat(key) : [key]);
192108
192186
  }
192109
192187
  });
192110
192188
  stack.pop();
@@ -192320,7 +192398,7 @@ var init_platform = __esm(() => {
192320
192398
  // ../../node_modules/axios/lib/helpers/toURLEncodedForm.js
192321
192399
  function toURLEncodedForm(data, options) {
192322
192400
  return toFormData_default(data, new platform_default.classes.URLSearchParams, {
192323
- visitor: function(value, key, path2, helpers) {
192401
+ visitor: function(value, key, path3, helpers) {
192324
192402
  if (platform_default.isNode && utils_default.isBuffer(value)) {
192325
192403
  this.append(key, value.toString("base64"));
192326
192404
  return false;
@@ -192355,12 +192433,12 @@ function arrayToObject(arr) {
192355
192433
  return obj;
192356
192434
  }
192357
192435
  function formDataToJSON(formData) {
192358
- function buildPath(path2, value, target, index) {
192359
- let name = path2[index++];
192436
+ function buildPath(path3, value, target, index) {
192437
+ let name = path3[index++];
192360
192438
  if (name === "__proto__")
192361
192439
  return true;
192362
192440
  const isNumericKey = Number.isFinite(+name);
192363
- const isLast = index >= path2.length;
192441
+ const isLast = index >= path3.length;
192364
192442
  name = !name && utils_default.isArray(target) ? target.length : name;
192365
192443
  if (isLast) {
192366
192444
  if (utils_default.hasOwnProp(target, name)) {
@@ -192373,7 +192451,7 @@ function formDataToJSON(formData) {
192373
192451
  if (!target[name] || !utils_default.isObject(target[name])) {
192374
192452
  target[name] = [];
192375
192453
  }
192376
- const result = buildPath(path2, value, target[name], index);
192454
+ const result = buildPath(path3, value, target[name], index);
192377
192455
  if (result && utils_default.isArray(target[name])) {
192378
192456
  target[name] = arrayToObject(target[name]);
192379
192457
  }
@@ -192828,10 +192906,10 @@ var init_CanceledError = __esm(() => {
192828
192906
  });
192829
192907
 
192830
192908
  // ../../node_modules/axios/lib/core/settle.js
192831
- function settle(resolve, reject, response) {
192909
+ function settle(resolve2, reject, response) {
192832
192910
  const validateStatus2 = response.config.validateStatus;
192833
192911
  if (!response.status || !validateStatus2 || validateStatus2(response.status)) {
192834
- resolve(response);
192912
+ resolve2(response);
192835
192913
  } else {
192836
192914
  reject(new AxiosError_default("Request failed with status code " + response.status, [AxiosError_default.ERR_BAD_REQUEST, AxiosError_default.ERR_BAD_RESPONSE][Math.floor(response.status / 100) - 4], response.config, response.request, response));
192837
192915
  }
@@ -193387,7 +193465,7 @@ var import_proxy_from_env, import_follow_redirects, zlibOptions, brotliOptions,
193387
193465
  stream4.on("end", flush).on("error", flush);
193388
193466
  return throttled;
193389
193467
  }, isHttpAdapterSupported, wrapAsync = (asyncExecutor) => {
193390
- return new Promise((resolve, reject) => {
193468
+ return new Promise((resolve2, reject) => {
193391
193469
  let onDone;
193392
193470
  let isDone;
193393
193471
  const done = (value, isRejected) => {
@@ -193398,7 +193476,7 @@ var import_proxy_from_env, import_follow_redirects, zlibOptions, brotliOptions,
193398
193476
  };
193399
193477
  const _resolve = (value) => {
193400
193478
  done(value);
193401
- resolve(value);
193479
+ resolve2(value);
193402
193480
  };
193403
193481
  const _reject = (reason) => {
193404
193482
  done(reason, true);
@@ -193450,7 +193528,7 @@ var init_http = __esm(() => {
193450
193528
  });
193451
193529
  isHttpAdapterSupported = typeof process !== "undefined" && utils_default.kindOf(process) === "process";
193452
193530
  http_default = isHttpAdapterSupported && function httpAdapter(config) {
193453
- return wrapAsync(async function dispatchHttpRequest(resolve, reject, onDone) {
193531
+ return wrapAsync(async function dispatchHttpRequest(resolve2, reject, onDone) {
193454
193532
  let { data, lookup, family } = config;
193455
193533
  const { responseType, responseEncoding } = config;
193456
193534
  const method = config.method.toUpperCase();
@@ -193509,7 +193587,7 @@ var init_http = __esm(() => {
193509
193587
  }
193510
193588
  let convertedData;
193511
193589
  if (method !== "GET") {
193512
- return settle(resolve, reject, {
193590
+ return settle(resolve2, reject, {
193513
193591
  status: 405,
193514
193592
  statusText: "method not allowed",
193515
193593
  headers: {},
@@ -193531,7 +193609,7 @@ var init_http = __esm(() => {
193531
193609
  } else if (responseType === "stream") {
193532
193610
  convertedData = stream3.Readable.from(convertedData);
193533
193611
  }
193534
- return settle(resolve, reject, {
193612
+ return settle(resolve2, reject, {
193535
193613
  data: convertedData,
193536
193614
  status: 200,
193537
193615
  statusText: "OK",
@@ -193609,9 +193687,9 @@ var init_http = __esm(() => {
193609
193687
  auth = urlUsername + ":" + urlPassword;
193610
193688
  }
193611
193689
  auth && headers.delete("authorization");
193612
- let path2;
193690
+ let path3;
193613
193691
  try {
193614
- path2 = buildURL(parsed.pathname + parsed.search, config.params, config.paramsSerializer).replace(/^\?/, "");
193692
+ path3 = buildURL(parsed.pathname + parsed.search, config.params, config.paramsSerializer).replace(/^\?/, "");
193615
193693
  } catch (err) {
193616
193694
  const customErr = new Error(err.message);
193617
193695
  customErr.config = config;
@@ -193621,7 +193699,7 @@ var init_http = __esm(() => {
193621
193699
  }
193622
193700
  headers.set("Accept-Encoding", "gzip, compress, deflate" + (isBrotliSupported ? ", br" : ""), false);
193623
193701
  const options = {
193624
- path: path2,
193702
+ path: path3,
193625
193703
  method,
193626
193704
  headers: headers.toJSON(),
193627
193705
  agents: { http: config.httpAgent, https: config.httpsAgent },
@@ -193715,7 +193793,7 @@ var init_http = __esm(() => {
193715
193793
  };
193716
193794
  if (responseType === "stream") {
193717
193795
  response.data = responseStream;
193718
- settle(resolve, reject, response);
193796
+ settle(resolve2, reject, response);
193719
193797
  } else {
193720
193798
  const responseBuffer = [];
193721
193799
  let totalResponseBytes = 0;
@@ -193754,7 +193832,7 @@ var init_http = __esm(() => {
193754
193832
  } catch (err) {
193755
193833
  return reject(AxiosError_default.from(err, null, config, response.request, response));
193756
193834
  }
193757
- settle(resolve, reject, response);
193835
+ settle(resolve2, reject, response);
193758
193836
  });
193759
193837
  }
193760
193838
  emitter.once("abort", (err) => {
@@ -193831,10 +193909,10 @@ var init_cookies = __esm(() => {
193831
193909
  init_utils();
193832
193910
  init_platform();
193833
193911
  cookies_default = platform_default.hasStandardBrowserEnv ? {
193834
- write(name, value, expires, path2, domain, secure) {
193912
+ write(name, value, expires, path3, domain, secure) {
193835
193913
  const cookie = [name + "=" + encodeURIComponent(value)];
193836
193914
  utils_default.isNumber(expires) && cookie.push("expires=" + new Date(expires).toGMTString());
193837
- utils_default.isString(path2) && cookie.push("path=" + path2);
193915
+ utils_default.isString(path3) && cookie.push("path=" + path3);
193838
193916
  utils_default.isString(domain) && cookie.push("domain=" + domain);
193839
193917
  secure === true && cookie.push("secure");
193840
193918
  document.cookie = cookie.join("; ");
@@ -193997,7 +194075,7 @@ var init_xhr = __esm(() => {
193997
194075
  init_resolveConfig();
193998
194076
  isXHRAdapterSupported = typeof XMLHttpRequest !== "undefined";
193999
194077
  xhr_default = isXHRAdapterSupported && function(config) {
194000
- return new Promise(function dispatchXhrRequest(resolve, reject) {
194078
+ return new Promise(function dispatchXhrRequest(resolve2, reject) {
194001
194079
  const _config = resolveConfig_default(config);
194002
194080
  let requestData = _config.data;
194003
194081
  const requestHeaders = AxiosHeaders_default.from(_config.headers).normalize();
@@ -194029,7 +194107,7 @@ var init_xhr = __esm(() => {
194029
194107
  request
194030
194108
  };
194031
194109
  settle(function _resolve(value) {
194032
- resolve(value);
194110
+ resolve2(value);
194033
194111
  done();
194034
194112
  }, function _reject(err) {
194035
194113
  reject(err);
@@ -194378,8 +194456,8 @@ var DEFAULT_CHUNK_SIZE, isFunction2, globalFetchAPI, ReadableStream2, TextEncode
194378
194456
  responseType = responseType || "text";
194379
194457
  let responseData = await resolvers[utils_default.findKey(resolvers, responseType) || "text"](response, config);
194380
194458
  !isStreamResponse && unsubscribe && unsubscribe();
194381
- return await new Promise((resolve, reject) => {
194382
- settle(resolve, reject, {
194459
+ return await new Promise((resolve2, reject) => {
194460
+ settle(resolve2, reject, {
194383
194461
  data: responseData,
194384
194462
  headers: AxiosHeaders_default.from(response.headers),
194385
194463
  status: response.status,
@@ -194772,8 +194850,8 @@ class CancelToken {
194772
194850
  throw new TypeError("executor must be a function.");
194773
194851
  }
194774
194852
  let resolvePromise;
194775
- this.promise = new Promise(function promiseExecutor(resolve) {
194776
- resolvePromise = resolve;
194853
+ this.promise = new Promise(function promiseExecutor(resolve2) {
194854
+ resolvePromise = resolve2;
194777
194855
  });
194778
194856
  const token = this;
194779
194857
  this.promise.then((cancel) => {
@@ -194787,9 +194865,9 @@ class CancelToken {
194787
194865
  });
194788
194866
  this.promise.then = (onfulfilled) => {
194789
194867
  let _resolve;
194790
- const promise = new Promise((resolve) => {
194791
- token.subscribe(resolve);
194792
- _resolve = resolve;
194868
+ const promise = new Promise((resolve2) => {
194869
+ token.subscribe(resolve2);
194870
+ _resolve = resolve2;
194793
194871
  }).then(onfulfilled);
194794
194872
  promise.cancel = function reject() {
194795
194873
  token.unsubscribe(_resolve);
@@ -195075,65 +195153,6 @@ var init_ducklake_version = __esm(() => {
195075
195153
  CATALOG_FORMAT_RE = /^(\d+)\.(\d+)(?:-([0-9A-Za-z.]+))?$/;
195076
195154
  });
195077
195155
 
195078
- // src/pg_helpers.ts
195079
- function redactPgSecrets(s) {
195080
- return s.replace(/([a-z][a-z0-9+.-]*:\/\/[^:/?#\s]*):([^/\s]+)@/gi, "$1:***@").replace(/((?:postgres|postgresql):\/\/[^:/?#\s]*):([^@\s]+)@/gi, "$1:***@").replace(/password=('[^']*'|"[^"]*"|\S+)/gi, "password=***");
195081
- }
195082
-
195083
- // src/path_safety.ts
195084
- import * as path2 from "path";
195085
- function assertSafePackageName(packageName) {
195086
- if (typeof packageName !== "string" || !SAFE_NAME_RE.test(packageName)) {
195087
- throw new BadRequestError(`Invalid package name: must be 1-255 characters of letters, digits, "-", "_", or "." and must not start with "."`);
195088
- }
195089
- }
195090
- function assertSafeRelativeModelPath(modelPath) {
195091
- if (typeof modelPath !== "string" || modelPath.length === 0 || modelPath.length > MAX_MODEL_PATH_LEN || modelPath.includes("\x00") || modelPath.includes("\\") || path2.isAbsolute(modelPath) || modelPath.startsWith("/")) {
195092
- throw new BadRequestError(`Invalid model path`);
195093
- }
195094
- const segments = modelPath.split("/");
195095
- for (const segment of segments) {
195096
- if (segment === "" || segment === "." || segment === "..") {
195097
- throw new BadRequestError(`Invalid model path`);
195098
- }
195099
- if (segment.startsWith(".")) {
195100
- throw new BadRequestError(`Invalid model path`);
195101
- }
195102
- }
195103
- }
195104
- function assertSafeEnvironmentPath(environmentPath) {
195105
- if (typeof environmentPath !== "string") {
195106
- throw new BadRequestError(`Invalid environment path: must be a string`);
195107
- }
195108
- if (environmentPath.length === 0 || environmentPath.length > MAX_ENVIRONMENT_PATH_LEN) {
195109
- throw new BadRequestError(`Invalid environment path: bad length`);
195110
- }
195111
- if (environmentPath.indexOf("\x00") !== -1) {
195112
- throw new BadRequestError(`Invalid environment path: contains NUL byte`);
195113
- }
195114
- if (environmentPath.indexOf("..") !== -1) {
195115
- throw new BadRequestError(`Invalid environment path: contains ".." traversal segment`);
195116
- }
195117
- if (!SAFE_ENVIRONMENT_PATH_RE.test(environmentPath)) {
195118
- throw new BadRequestError(`Invalid environment path: must be an absolute path of printable ASCII characters`);
195119
- }
195120
- }
195121
- function safeJoinUnderRoot(root, ...segments) {
195122
- const resolvedRoot = path2.resolve(root);
195123
- const joined = path2.resolve(resolvedRoot, ...segments);
195124
- const rootWithSep = resolvedRoot.endsWith(path2.sep) ? resolvedRoot : resolvedRoot + path2.sep;
195125
- if (joined !== resolvedRoot && !joined.startsWith(rootWithSep)) {
195126
- throw new BadRequestError(`Resolved path is outside of root`);
195127
- }
195128
- return joined;
195129
- }
195130
- var SAFE_NAME_RE, MAX_MODEL_PATH_LEN = 1024, SAFE_ENVIRONMENT_PATH_RE, MAX_ENVIRONMENT_PATH_LEN = 4096;
195131
- var init_path_safety = __esm(() => {
195132
- init_errors();
195133
- SAFE_NAME_RE = /^(?!\.\.?$)(?!\.)[A-Za-z0-9._-]{1,255}$/;
195134
- SAFE_ENVIRONMENT_PATH_RE = /^(?:\/|[A-Za-z]:[\\/])[\x20-\x7E]*$/;
195135
- });
195136
-
195137
195156
  // ../../node_modules/@smithy/types/dist-cjs/index.js
195138
195157
  var require_dist_cjs = __commonJS((exports) => {
195139
195158
  exports.HttpAuthLocation = undefined;
@@ -253350,7 +253369,12 @@ import {
253350
253369
  contextOverlay,
253351
253370
  MalloyConfig
253352
253371
  } from "@malloydata/malloy";
253372
+ import { createHash } from "crypto";
253373
+ import { mkdtempSync, readFileSync, writeFileSync } from "fs";
253353
253374
  import fs3 from "fs/promises";
253375
+ import os2 from "os";
253376
+ import path4 from "path";
253377
+ import tls from "tls";
253354
253378
  async function applyDuckLakeRowGroupBound(connection, dbName) {
253355
253379
  const bytes = getDuckLakeRowGroupSizeBytes();
253356
253380
  if (bytes === undefined) {
@@ -253358,7 +253382,7 @@ async function applyDuckLakeRowGroupBound(connection, dbName) {
253358
253382
  }
253359
253383
  try {
253360
253384
  await connection.runSQL("SET preserve_insertion_order=false");
253361
- await connection.runSQL(`CALL ${dbName}.set_option('parquet_row_group_size_bytes', '${escapeSQL(bytes)}')`);
253385
+ await connection.runSQL(`CALL ${quoteIdentifier(dbName, "duckdb")}.set_option('parquet_row_group_size_bytes', '${escapeSQL(bytes)}')`);
253362
253386
  logger.info(`DuckLake row group bound applied to ${dbName}: ${bytes}`);
253363
253387
  } catch (error) {
253364
253388
  logger.warn(`Could not set the DuckLake row group bound on ${dbName}; the lake keeps ` + `its existing value: ${error instanceof Error ? error.message : String(error)}`);
@@ -253370,7 +253394,7 @@ async function applyDuckLakeTargetFileSize(connection, dbName) {
253370
253394
  return;
253371
253395
  }
253372
253396
  try {
253373
- await connection.runSQL(`CALL ${dbName}.set_option('target_file_size', '${escapeSQL(bytes)}')`);
253397
+ await connection.runSQL(`CALL ${quoteIdentifier(dbName, "duckdb")}.set_option('target_file_size', '${escapeSQL(bytes)}')`);
253374
253398
  logger.info(`DuckLake target file size applied to ${dbName}: ${bytes}`);
253375
253399
  } catch (error) {
253376
253400
  logger.warn(`Could not set the DuckLake target file size on ${dbName}; the lake keeps ` + `its existing value: ${error instanceof Error ? error.message : String(error)}`);
@@ -253459,7 +253483,9 @@ async function isDatabaseAttached(connection, dbName) {
253459
253483
  });
253460
253484
  return rows.some((row) => Object.values(row).some((value) => typeof value === "string" && value === dbName));
253461
253485
  } catch (error) {
253462
- logger.warn(`Failed to check existing databases:`, error);
253486
+ logger.warn("Failed to check existing databases", {
253487
+ error: redactPgSecrets(error instanceof Error ? error.message : String(error))
253488
+ });
253463
253489
  return false;
253464
253490
  }
253465
253491
  }
@@ -253613,10 +253639,13 @@ async function attachPostgres(connection, attachedDb) {
253613
253639
  if (!attachedDb.postgresConnection) {
253614
253640
  throw new Error(`PostgreSQL connection configuration missing for: ${attachedDb.name}`);
253615
253641
  }
253642
+ if (!attachedDb.name) {
253643
+ throw new Error("Attached database name is required");
253644
+ }
253616
253645
  await installAndLoadExtension(connection, "postgres");
253617
253646
  const config = attachedDb.postgresConnection;
253618
253647
  const attachString = buildPgConnectionString(config);
253619
- const attachCommand = `ATTACH '${escapeSQL(attachString)}' AS ${attachedDb.name} (TYPE postgres, READ_ONLY);`;
253648
+ const attachCommand = `ATTACH '${escapeSQL(attachString)}' AS ${quoteIdentifier(attachedDb.name, "duckdb")} (TYPE postgres, READ_ONLY);`;
253620
253649
  await connection.runSQL(attachCommand);
253621
253650
  logger.info(`Successfully attached PostgreSQL database: ${attachedDb.name}`);
253622
253651
  }
@@ -253628,10 +253657,11 @@ function runSQLRows(result) {
253628
253657
  }
253629
253658
  async function preflightDuckLakeCatalogFormat(connection, dbName, pgConnString, metadataSchema) {
253630
253659
  const tempDb = `${dbName}_fmt_preflight_${++ducklakePreflightSeq}`;
253631
- const metadataRef = metadataSchema ? `${tempDb}."${metadataSchema}".ducklake_metadata` : `${tempDb}.ducklake_metadata`;
253660
+ const tempDbRef = quoteIdentifier(tempDb, "duckdb");
253661
+ const metadataRef = metadataSchema ? `${tempDbRef}."${metadataSchema}".ducklake_metadata` : `${tempDbRef}.ducklake_metadata`;
253632
253662
  let catalogFormat;
253633
253663
  try {
253634
- await connection.runSQL(`ATTACH '${escapeSQL(pgConnString)}' AS ${tempDb} (TYPE postgres, READ_ONLY);`);
253664
+ await connection.runSQL(`ATTACH '${escapeSQL(pgConnString)}' AS ${tempDbRef} (TYPE postgres, READ_ONLY);`);
253635
253665
  const result = await connection.runSQL(`SELECT value FROM ${metadataRef} WHERE key = 'version' LIMIT 1;`);
253636
253666
  const value = runSQLRows(result)[0]?.value;
253637
253667
  catalogFormat = typeof value === "string" ? value : undefined;
@@ -253645,7 +253675,7 @@ async function preflightDuckLakeCatalogFormat(connection, dbName, pgConnString,
253645
253675
  return;
253646
253676
  } finally {
253647
253677
  try {
253648
- await connection.runSQL(`DETACH ${tempDb};`);
253678
+ await connection.runSQL(`DETACH ${tempDbRef};`);
253649
253679
  } catch {}
253650
253680
  }
253651
253681
  if (!catalogFormat) {
@@ -253719,7 +253749,7 @@ async function attachDuckLakeWithMode(connection, dbName, ducklakeConfig, option
253719
253749
  await preflightDuckLakeCatalogFormat(connection, dbName, pgConnString, metadataSchema);
253720
253750
  const readOnlyClause = options.readOnly ? ", READ_ONLY true" : "";
253721
253751
  const metadataSchemaClause = metadataSchema ? `, METADATA_SCHEMA '${escapeSQL(metadataSchema)}'` : "";
253722
- const attachCommand = `ATTACH OR REPLACE 'ducklake:postgres:${escapedPgConnString}' AS ${dbName} (DATA_PATH '${escapedBucketUrl}', OVERRIDE_DATA_PATH true${readOnlyClause}${metadataSchemaClause});`;
253752
+ const attachCommand = `ATTACH OR REPLACE 'ducklake:postgres:${escapedPgConnString}' AS ${quoteIdentifier(dbName, "duckdb")} (DATA_PATH '${escapedBucketUrl}', OVERRIDE_DATA_PATH true${readOnlyClause}${metadataSchemaClause});`;
253723
253753
  logger.debug(`Attaching DuckLake database using command: ${redactPgSecrets(attachCommand)}`);
253724
253754
  try {
253725
253755
  await connection.runSQL(attachCommand);
@@ -253746,14 +253776,14 @@ async function attachDuckLakeReadWrite(connection, dbName, ducklakeConfig) {
253746
253776
  readOnly: false
253747
253777
  });
253748
253778
  }
253749
- async function federateSourceForPassthrough(connection, sourceType, config) {
253779
+ async function federateSourceForPassthrough(connection, sourceType, config, deps = {}) {
253750
253780
  switch (sourceType) {
253751
253781
  case "bigquery":
253752
253782
  return federateBigQuery(connection, config);
253753
253783
  case "snowflake":
253754
253784
  return federateSnowflake(connection, config);
253755
253785
  case "postgres":
253756
- return federatePostgres(connection, config);
253786
+ return federatePostgres(connection, config, deps);
253757
253787
  default: {
253758
253788
  const exhaustive = sourceType;
253759
253789
  throw new Error(`No native query-passthrough for source type '${String(exhaustive)}'`);
@@ -253856,17 +253886,113 @@ ${secretLines.join(`,
253856
253886
  logger.info(`Federated Snowflake source for passthrough: ${secretName}`);
253857
253887
  return { handle: secretName, sourceType: "snowflake" };
253858
253888
  }
253859
- async function federatePostgres(connection, config) {
253889
+ async function federatePostgres(connection, config, deps = {}) {
253860
253890
  const pg = config.postgresConnection;
253861
253891
  if (!pg) {
253862
253892
  throw new Error(`PostgreSQL connection configuration missing for: ${config.name}`);
253863
253893
  }
253864
253894
  await installAndLoadExtension(connection, "postgres");
253865
- const attachString = buildPgConnectionString(pg);
253866
253895
  const alias = config.name;
253867
- logger.info(`Federating Postgres source for passthrough as alias '${alias}': ${redactPgSecrets(attachString)}`);
253868
- await connection.runSQL(`ATTACH OR REPLACE '${escapeSQL(attachString)}' AS ${quoteIdentifier(alias, "duckdb")} (TYPE postgres, READ_ONLY);`);
253869
- return { handle: alias, sourceType: "postgres" };
253896
+ let endpoint;
253897
+ try {
253898
+ let attachString;
253899
+ if (config.proxy) {
253900
+ if (!pg.host || !pg.port) {
253901
+ throw new Error(`Connection proxy on '${config.name}' requires explicit host and port on the postgres connection.`);
253902
+ }
253903
+ endpoint = await (deps.openProxy ?? openProxy)(config.proxy, {
253904
+ host: pg.host,
253905
+ port: pg.port
253906
+ });
253907
+ attachString = buildProxiedPgAttachString(config.name, pg, endpoint);
253908
+ } else {
253909
+ attachString = buildPgConnectionString(pg);
253910
+ }
253911
+ logger.info(`Federating Postgres source for passthrough as alias '${alias}'${endpoint ? " through its SSH proxy" : ""}: ${redactPgSecrets(attachString)}`);
253912
+ await connection.runSQL(`ATTACH OR REPLACE '${escapeSQL(attachString)}' AS ${quoteIdentifier(alias, "duckdb")} (TYPE postgres, READ_ONLY);`);
253913
+ } catch (e) {
253914
+ await endpoint?.close().catch((closeErr) => logger.warn(`Failed to close the SSH proxy opened for Postgres source '${config.name}' after its federation failed: ${String(closeErr)}`));
253915
+ throw e;
253916
+ }
253917
+ return {
253918
+ handle: alias,
253919
+ sourceType: "postgres",
253920
+ ...endpoint ? { close: () => endpoint.close() } : {}
253921
+ };
253922
+ }
253923
+ function pgConninfoPair(key, value) {
253924
+ if (value !== "" && !/[\s'\\]/.test(value))
253925
+ return `${key}=${value}`;
253926
+ return `${key}='${value.replace(/([\\'])/g, "\\$1")}'`;
253927
+ }
253928
+ function defaultProxiedAttachTrust() {
253929
+ return {
253930
+ caBundle: process.env.NODE_EXTRA_CA_CERTS || undefined,
253931
+ ambientBundle: ambientTrustBundlePath
253932
+ };
253933
+ }
253934
+ function ambientTrustBundlePath() {
253935
+ const extra = process.env.NODE_EXTRA_CA_CERTS || undefined;
253936
+ const cached = ambientTrustBundles.get(extra);
253937
+ if (cached)
253938
+ return cached;
253939
+ let extraPem;
253940
+ if (extra) {
253941
+ try {
253942
+ extraPem = readFileSync(extra, "utf8").trim();
253943
+ } catch (err) {
253944
+ logger.warn(`Ignoring NODE_EXTRA_CA_CERTS for the storage build's trust bundle: ${extra} could not be read (${err instanceof Error ? err.message : String(err)}).`);
253945
+ }
253946
+ }
253947
+ const pem = [...tls.rootCertificates, ...extraPem ? [extraPem] : []].join(`
253948
+ `) + `
253949
+ `;
253950
+ const digest = createHash("sha256").update(pem).digest("hex").slice(0, 16);
253951
+ ambientTrustDir ??= mkdtempSync(path4.join(os2.tmpdir(), "publisher-ambient-ca-"));
253952
+ const file = path4.join(ambientTrustDir, `${digest}.pem`);
253953
+ writeFileSync(file, pem, { mode: 384 });
253954
+ ambientTrustBundles.set(extra, file);
253955
+ return file;
253956
+ }
253957
+ function buildProxiedPgAttachString(name, pg, endpoint, trust = defaultProxiedAttachTrust()) {
253958
+ if (!pg.host) {
253959
+ throw new Error(`Connection proxy on '${name}' requires an explicit host on the postgres connection.`);
253960
+ }
253961
+ const parts = [
253962
+ pgConninfoPair("host", pg.host),
253963
+ pgConninfoPair("hostaddr", endpoint.host),
253964
+ pgConninfoPair("port", String(endpoint.port))
253965
+ ];
253966
+ if (pg.databaseName)
253967
+ parts.push(pgConninfoPair("dbname", pg.databaseName));
253968
+ if (pg.userName)
253969
+ parts.push(pgConninfoPair("user", pg.userName));
253970
+ if (pg.password)
253971
+ parts.push(pgConninfoPair("password", pg.password));
253972
+ const mode = pg.sslmode ?? "no-verify";
253973
+ switch (mode) {
253974
+ case "disable":
253975
+ parts.push("sslmode=disable");
253976
+ break;
253977
+ case "no-verify":
253978
+ parts.push("sslmode=require");
253979
+ break;
253980
+ case "verify-ca": {
253981
+ if (!trust.caBundle) {
253982
+ throw new Error(`Connection proxy on '${name}' uses sslmode 'verify-ca' but no trusted CA bundle is available (NODE_EXTRA_CA_CERTS is unset).`);
253983
+ }
253984
+ parts.push("sslmode=verify-ca", pgConninfoPair("sslrootcert", trust.caBundle));
253985
+ break;
253986
+ }
253987
+ case "verify-full":
253988
+ parts.push("sslmode=verify-full", pgConninfoPair("sslrootcert", trust.ambientBundle()));
253989
+ break;
253990
+ default: {
253991
+ const unhandled = mode;
253992
+ throw new Error(`Connection proxy on '${name}' has unsupported sslmode '${String(unhandled)}' (expected ${PROXIED_SSLMODES.join(" | ")}).`);
253993
+ }
253994
+ }
253995
+ return parts.join(" ");
253870
253996
  }
253871
253997
  function shouldRenewStorageSecret(opts) {
253872
253998
  return opts.hasRenewer && !opts.alreadyRenewing && isExpiredCredentialError(opts.error);
@@ -254051,7 +254177,9 @@ async function attachDatabasesToDuckDB(duckdbConnection, attachedDatabases) {
254051
254177
  handleAlreadyAttachedError(attachError, attachedDb.name || "");
254052
254178
  }
254053
254179
  } catch (error) {
254054
- logger.error(`Failed to attach database ${attachedDb.name}:`, error);
254180
+ logger.error(`Failed to attach database ${attachedDb.name}`, {
254181
+ error: redactPgSecrets(error instanceof Error ? error.message : String(error))
254182
+ });
254055
254183
  throw new Error(`Failed to attach database ${attachedDb.name}: ${error.message}`);
254056
254184
  }
254057
254185
  }
@@ -254423,7 +254551,7 @@ async function testDuckDBConnection(duckdbConnection, connectionConfig) {
254423
254551
  }
254424
254552
  } catch (error) {
254425
254553
  const errorMessage = `Attached database '${attachedDb.name}' (${attachedDb.type}) test failed: ${error.message}`;
254426
- logger.error(errorMessage);
254554
+ logger.error(redactPgSecrets(errorMessage));
254427
254555
  failedAttachments.push(errorMessage);
254428
254556
  }
254429
254557
  }
@@ -254435,11 +254563,16 @@ ${failedAttachments.join(`
254435
254563
  }
254436
254564
  async function testConnectionConfig(connectionConfig) {
254437
254565
  let environmentConfig = null;
254566
+ let testRoot = null;
254438
254567
  try {
254439
254568
  if (!connectionConfig.name) {
254440
254569
  throw new Error("Connection name is required");
254441
254570
  }
254442
- environmentConfig = buildEnvironmentMalloyConfig([connectionConfig]);
254571
+ if (connectionConfig.type === "duckdb" || connectionConfig.type === "ducklake") {
254572
+ assertSafePackageName(connectionConfig.name);
254573
+ }
254574
+ testRoot = await fs3.mkdtemp(path4.join(os2.tmpdir(), "publisher-conn-test-"));
254575
+ environmentConfig = buildEnvironmentMalloyConfig([connectionConfig], testRoot);
254443
254576
  const connection = await environmentConfig.malloyConfig.connections.lookupConnection(connectionConfig.name);
254444
254577
  if (connectionConfig.type === "duckdb") {
254445
254578
  await testDuckDBConnection(connection, connectionConfig);
@@ -254462,11 +254595,13 @@ async function testConnectionConfig(connectionConfig) {
254462
254595
  if (error instanceof AxiosError2) {
254463
254596
  logAxiosError(error);
254464
254597
  } else {
254465
- logger.error(error);
254598
+ logger.error("Connection test failed", {
254599
+ error: redactPgSecrets(error instanceof Error ? error.stack ?? error.message : String(error))
254600
+ });
254466
254601
  }
254467
254602
  return {
254468
254603
  status: "failed",
254469
- errorMessage: error.message
254604
+ errorMessage: redactPgSecrets(error instanceof Error ? error.message : String(error))
254470
254605
  };
254471
254606
  } finally {
254472
254607
  if (environmentConfig) {
@@ -254478,12 +254613,18 @@ async function testConnectionConfig(connectionConfig) {
254478
254613
  });
254479
254614
  }
254480
254615
  }
254481
- if (connectionConfig.type === "ducklake" && connectionConfig.name) {
254482
- await deleteDuckLakeConnectionFile(connectionConfig.name, process.cwd());
254616
+ if (testRoot) {
254617
+ try {
254618
+ await fs3.rm(testRoot, { recursive: true, force: true });
254619
+ } catch (cleanupError) {
254620
+ logger.warn("Error cleaning up connection test directory", {
254621
+ error: cleanupError instanceof Error ? cleanupError.message : String(cleanupError)
254622
+ });
254623
+ }
254483
254624
  }
254484
254625
  }
254485
254626
  }
254486
- var import_db_publisher, extensionSessionPinned, sessionLimitsApplied, ducklakePreflightSeq = 0, AzureDuckDBConnection, DuckLakeConnection;
254627
+ var import_db_publisher, extensionSessionPinned, sessionLimitsApplied, ducklakePreflightSeq = 0, ambientTrustBundles, ambientTrustDir, AzureDuckDBConnection, DuckLakeConnection;
254487
254628
  var init_connection = __esm(() => {
254488
254629
  init_axios2();
254489
254630
  init_config();
@@ -254499,6 +254640,7 @@ var init_connection = __esm(() => {
254499
254640
  import_db_publisher = __toESM(require_dist5(), 1);
254500
254641
  extensionSessionPinned = new WeakSet;
254501
254642
  sessionLimitsApplied = new WeakMap;
254643
+ ambientTrustBundles = new Map;
254502
254644
  AzureDuckDBConnection = class AzureDuckDBConnection extends DuckDBConnection {
254503
254645
  azureDatabases;
254504
254646
  constructor(options, azureDatabases) {
@@ -262429,7 +262571,7 @@ var require_table = __commonJS((exports) => {
262429
262571
  var events_1 = __require("events");
262430
262572
  var fs4 = __require("fs");
262431
262573
  var is = require_is();
262432
- var path4 = __require("path");
262574
+ var path5 = __require("path");
262433
262575
  var streamEvents = require_stream_events();
262434
262576
  var uuid = require_dist10();
262435
262577
  var _1 = require_src139();
@@ -262675,7 +262817,7 @@ var require_table = __commonJS((exports) => {
262675
262817
  if (!common_1.util.isCustomType(dest, "storage/file")) {
262676
262818
  throw new Error("Destination must be a File object.");
262677
262819
  }
262678
- const format = path4.extname(dest.name).substr(1).toLowerCase();
262820
+ const format = path5.extname(dest.name).substr(1).toLowerCase();
262679
262821
  if (!options.destinationFormat && !options.format && FORMATS[format]) {
262680
262822
  options.destinationFormat = FORMATS[format];
262681
262823
  }
@@ -262733,7 +262875,7 @@ var require_table = __commonJS((exports) => {
262733
262875
  metadata.location = this.location;
262734
262876
  }
262735
262877
  if (typeof source === "string") {
262736
- const detectedFormat = FORMATS[path4.extname(source).substr(1).toLowerCase()];
262878
+ const detectedFormat = FORMATS[path5.extname(source).substr(1).toLowerCase()];
262737
262879
  if (!metadata.sourceFormat && detectedFormat) {
262738
262880
  metadata.sourceFormat = detectedFormat;
262739
262881
  }
@@ -262769,7 +262911,7 @@ var require_table = __commonJS((exports) => {
262769
262911
  if (!common_1.util.isCustomType(src, "storage/file")) {
262770
262912
  throw new Error("Source must be a File object.");
262771
262913
  }
262772
- const format = FORMATS[path4.extname(src.name).substr(1).toLowerCase()];
262914
+ const format = FORMATS[path5.extname(src.name).substr(1).toLowerCase()];
262773
262915
  if (!metadata.sourceFormat && format) {
262774
262916
  body.configuration.load.sourceFormat = format;
262775
262917
  }
@@ -267522,16 +267664,16 @@ function parseMotly(texts) {
267522
267664
  const after = parseGuarded(rescued);
267523
267665
  return { tag: after.tag, errors: [...envErrors, ...after.messages] };
267524
267666
  }
267525
- function tagText(tag, ...path5) {
267667
+ function tagText(tag, ...path6) {
267526
267668
  try {
267527
- return tag?.text(...path5);
267669
+ return tag?.text(...path6);
267528
267670
  } catch {
267529
267671
  return;
267530
267672
  }
267531
267673
  }
267532
- function tagNumeric(tag, ...path5) {
267674
+ function tagNumeric(tag, ...path6) {
267533
267675
  try {
267534
- const raw = tagText(tag, ...path5);
267676
+ const raw = tagText(tag, ...path6);
267535
267677
  if (raw === undefined)
267536
267678
  return;
267537
267679
  const DECIMAL = /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][-+]?\d+)?$/;
@@ -267595,8 +267737,8 @@ var init_motly = __esm(() => {
267595
267737
  import {
267596
267738
  isSourceDef
267597
267739
  } from "@malloydata/malloy";
267598
- function presentText(tag, ...path5) {
267599
- const raw = tagText(tag, ...path5);
267740
+ function presentText(tag, ...path6) {
267741
+ const raw = tagText(tag, ...path6);
267600
267742
  return raw !== undefined && raw.trim() !== "" ? raw : undefined;
267601
267743
  }
267602
267744
  function readGivenControlSpec(annotationTexts2) {
@@ -267877,8 +268019,8 @@ function readDrillTag(annotations) {
267877
268019
  function isString2(value) {
267878
268020
  return value !== undefined;
267879
268021
  }
267880
- function tagTextArray(tag, ...path5) {
267881
- const items = tag?.array(...path5);
268022
+ function tagTextArray(tag, ...path6) {
268023
+ const items = tag?.array(...path6);
267882
268024
  return items?.map((item) => tagText(item)).filter(isString2);
267883
268025
  }
267884
268026
  function resolveTileGivens(tile, facts) {
@@ -269057,7 +269199,7 @@ var require_yauzl = __commonJS((exports) => {
269057
269199
  exports.ZipFile = ZipFile;
269058
269200
  exports.Entry = Entry;
269059
269201
  exports.RandomAccessReader = RandomAccessReader;
269060
- function open2(path5, options, callback) {
269202
+ function open2(path6, options, callback) {
269061
269203
  if (typeof options === "function") {
269062
269204
  callback = options;
269063
269205
  options = null;
@@ -269076,7 +269218,7 @@ var require_yauzl = __commonJS((exports) => {
269076
269218
  options.strictFileNames = false;
269077
269219
  if (callback == null)
269078
269220
  callback = defaultCallback;
269079
- fs4.open(path5, "r", function(err, fd) {
269221
+ fs4.open(path6, "r", function(err, fd) {
269080
269222
  if (err)
269081
269223
  return callback(err);
269082
269224
  fromFd(fd, options, function(err2, zipfile) {
@@ -269740,7 +269882,7 @@ var require_extract_zip = __commonJS((exports, module) => {
269740
269882
  var debug = require_src5()("extract-zip");
269741
269883
  var { createWriteStream, promises: fs4 } = __require("fs");
269742
269884
  var getStream = require_get_stream();
269743
- var path5 = __require("path");
269885
+ var path6 = __require("path");
269744
269886
  var { promisify } = __require("util");
269745
269887
  var stream4 = __require("stream");
269746
269888
  var yauzl = require_yauzl();
@@ -269778,12 +269920,12 @@ var require_extract_zip = __commonJS((exports, module) => {
269778
269920
  this.zipfile.readEntry();
269779
269921
  return;
269780
269922
  }
269781
- const destDir = path5.dirname(path5.join(this.opts.dir, entry.fileName));
269923
+ const destDir = path6.dirname(path6.join(this.opts.dir, entry.fileName));
269782
269924
  try {
269783
269925
  await fs4.mkdir(destDir, { recursive: true });
269784
269926
  const canonicalDestDir = await fs4.realpath(destDir);
269785
- const relativeDestDir = path5.relative(this.opts.dir, canonicalDestDir);
269786
- if (relativeDestDir.split(path5.sep).includes("..")) {
269927
+ const relativeDestDir = path6.relative(this.opts.dir, canonicalDestDir);
269928
+ if (relativeDestDir.split(path6.sep).includes("..")) {
269787
269929
  throw new Error(`Out of bound path "${canonicalDestDir}" found while processing file ${entry.fileName}`);
269788
269930
  }
269789
269931
  await this.extractEntry(entry);
@@ -269805,7 +269947,7 @@ var require_extract_zip = __commonJS((exports, module) => {
269805
269947
  if (this.opts.onEntry) {
269806
269948
  this.opts.onEntry(entry, this.zipfile);
269807
269949
  }
269808
- const dest = path5.join(this.opts.dir, entry.fileName);
269950
+ const dest = path6.join(this.opts.dir, entry.fileName);
269809
269951
  const mode = entry.externalFileAttributes >> 16 & 65535;
269810
269952
  const IFMT = 61440;
269811
269953
  const IFDIR = 16384;
@@ -269820,7 +269962,7 @@ var require_extract_zip = __commonJS((exports, module) => {
269820
269962
  isDir = madeBy === 0 && entry.externalFileAttributes === 16;
269821
269963
  debug("extracting entry", { filename: entry.fileName, isDir, isSymlink: symlink });
269822
269964
  const procMode = this.getExtractedMode(mode, isDir) & 511;
269823
- const destDir = isDir ? dest : path5.dirname(dest);
269965
+ const destDir = isDir ? dest : path6.dirname(dest);
269824
269966
  const mkdirOptions = { recursive: true };
269825
269967
  if (isDir) {
269826
269968
  mkdirOptions.mode = procMode;
@@ -269863,7 +270005,7 @@ var require_extract_zip = __commonJS((exports, module) => {
269863
270005
  }
269864
270006
  module.exports = async function(zipPath, opts) {
269865
270007
  debug("creating target directory", opts.dir);
269866
- if (!path5.isAbsolute(opts.dir)) {
270008
+ if (!path6.isAbsolute(opts.dir)) {
269867
270009
  throw new Error("Target directory is expected to be absolute");
269868
270010
  }
269869
270011
  await fs4.mkdir(opts.dir, { recursive: true });
@@ -269881,10 +270023,10 @@ var require_src140 = __commonJS((exports) => {
269881
270023
  var fs_1 = __require("fs");
269882
270024
  var debug_1 = __importDefault(require_src5());
269883
270025
  var log = debug_1.default("@kwsites/file-exists");
269884
- function check(path5, isFile2, isDirectory) {
269885
- log(`checking %s`, path5);
270026
+ function check(path6, isFile2, isDirectory) {
270027
+ log(`checking %s`, path6);
269886
270028
  try {
269887
- const stat4 = fs_1.statSync(path5);
270029
+ const stat4 = fs_1.statSync(path6);
269888
270030
  if (stat4.isFile() && isFile2) {
269889
270031
  log(`[OK] path represents a file`);
269890
270032
  return true;
@@ -269904,8 +270046,8 @@ var require_src140 = __commonJS((exports) => {
269904
270046
  throw e;
269905
270047
  }
269906
270048
  }
269907
- function exists(path5, type = exports.READABLE) {
269908
- return check(path5, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
270049
+ function exists(path6, type = exports.READABLE) {
270050
+ return check(path6, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
269909
270051
  }
269910
270052
  exports.exists = exists;
269911
270053
  exports.FILE = 1;
@@ -270494,14 +270636,14 @@ var init_authorize_metrics = __esm(() => {
270494
270636
  });
270495
270637
 
270496
270638
  // src/materialization_metrics.ts
270497
- function lazyCounter2(name, description) {
270639
+ function lazyCounter3(name, description) {
270498
270640
  let instrument2 = null;
270499
- resetHooks2.push(() => instrument2 = null);
270641
+ resetHooks3.push(() => instrument2 = null);
270500
270642
  return () => instrument2 ??= publisherMeter().createCounter(name, { description });
270501
270643
  }
270502
- function lazyHistogram(name, description, unit) {
270644
+ function lazyHistogram2(name, description, unit) {
270503
270645
  let instrument2 = null;
270504
- resetHooks2.push(() => instrument2 = null);
270646
+ resetHooks3.push(() => instrument2 = null);
270505
270647
  return () => instrument2 ??= publisherMeter().createHistogram(name, {
270506
270648
  description,
270507
270649
  unit
@@ -270585,43 +270727,43 @@ function recordChainedStorageBuild(outcome) {
270585
270727
  function recordColocatedBindDropped(reason) {
270586
270728
  colocatedBindDroppedCounter().add(1, { reason });
270587
270729
  }
270588
- var resetHooks2, runCounter, runDuration, sourcesCounter, incrementalStepCounter, buildPlanComputeDuration, buildPlanComputeFailedCounter, autoLoadCounter, connectionDigestSkipCounter, manifestBindCounter, manifestBindDegradedCounter, duplicateTargetSkipCounter, sharedAddressInstructionCounter, tableCollisionCounter, sourceBuildDuration, dropTablesCounter, scheduledFireCounter, storageServeRoutingCounter, storageTableRetainedCounter, storageBuildFailureCounter, attributionSkippedCounter, eligibilityRefusedCounter, serveShapeTierDropCounter, serveShapeTypeFallbackCounter, chainedStorageBuildCounter, colocatedBindDroppedCounter;
270730
+ var resetHooks3, runCounter, runDuration, sourcesCounter, incrementalStepCounter, buildPlanComputeDuration, buildPlanComputeFailedCounter, autoLoadCounter, connectionDigestSkipCounter, manifestBindCounter, manifestBindDegradedCounter, duplicateTargetSkipCounter, sharedAddressInstructionCounter, tableCollisionCounter, sourceBuildDuration, dropTablesCounter, scheduledFireCounter, storageServeRoutingCounter, storageTableRetainedCounter, storageBuildFailureCounter, attributionSkippedCounter, eligibilityRefusedCounter, serveShapeTierDropCounter, serveShapeTypeFallbackCounter, chainedStorageBuildCounter, colocatedBindDroppedCounter;
270589
270731
  var init_materialization_metrics = __esm(() => {
270590
270732
  init_telemetry();
270591
- resetHooks2 = [];
270592
- runCounter = lazyCounter2("publisher_materialization_runs_total", "Materialization builds completed. Labels: mode ('auto'|'orchestrated'), outcome ('success'|'partial'|'failed'|'cancelled').");
270593
- runDuration = lazyHistogram("publisher_materialization_run_duration_ms", "Wall-clock duration of a materialization build. Label: mode ('auto'|'orchestrated').", "ms");
270594
- sourcesCounter = lazyCounter2("publisher_materialization_sources_total", "Persist sources processed by a materialization run. Label: outcome ('built'|'reused'|'failed').");
270595
- incrementalStepCounter = lazyCounter2("publisher_materialization_incremental_step_total", 'Refreshes of a source declared refresh="incremental". Labels: step ' + "('delta'|'seed'|'skip'), and for seed/skip a bounded reason code " + "(IncrementalStepReasonCode). A 'seed' is a full rebuild the delta path " + "declined, so a rising seed rate means the feature is not engaging — and " + "the reason label says why without a log dive.");
270596
- buildPlanComputeDuration = lazyHistogram("publisher_materialization_build_plan_compute_duration_ms", "Wall-clock duration of compiling a package's build plan (Package.buildPlan).", "ms");
270597
- buildPlanComputeFailedCounter = lazyCounter2("publisher_materialization_build_plan_compute_failed_total", "Package loads whose build plan failed to compute. The ROOT-CAUSE signal for " + "colocated_bind_dropped{reason='build_plan_unavailable'}, which fires only " + "per dropped entry per load -- a package that loads once and is never " + "reloaded ticks that counter once and then sits with its colocated tier " + "off and a flat total, indistinguishable from healthy.");
270598
- autoLoadCounter = lazyCounter2("publisher_materialization_auto_load_total", "Auto-run manifest auto-load attempts. Label: outcome ('success'|'failure').");
270599
- connectionDigestSkipCounter = lazyCounter2("publisher_materialization_connection_digest_skipped_total", "Connection digests skipped during build-plan compile because the connection did not resolve.");
270600
- manifestBindCounter = lazyCounter2("publisher_materialization_manifest_bind_total", "Manifest bind attempts. Label: outcome ('success'|'failure'|'timeout').");
270601
- manifestBindDegradedCounter = lazyCounter2("publisher_materialization_manifest_bind_degraded_total", "Manifest entries bound with an UNQUOTED table path because their connection " + "could not be resolved (serve-side bind) or is absent from the build " + "(build-side seed). A misconfiguration that breaks the source on a " + "case-folding engine (Snowflake); alertable.");
270602
- duplicateTargetSkipCounter = lazyCounter2("publisher_materialization_duplicate_target_skipped_total", "Sources skipped because the physical table they name was already built in " + "this run. Ordinary for a package that extends a persisted source; a " + "rising count against a package with no extension means the plan is " + "enumerating one table under more names than expected.");
270603
- sharedAddressInstructionCounter = lazyCounter2("publisher_materialization_shared_address_instructions_total", "Content addresses that arrived with more than one instruction naming a " + "DIFFERENT physical table. The host minted a table per source where " + "several sources share one artifact. With a sourceID on each instruction " + "every table is built and only one is recorded, so the rest are orphaned; " + "without one the last instruction wins and the earlier names are never " + "built. Wasteful, not wrong — the table's CONTENT is the same either way.");
270604
- tableCollisionCounter = lazyCounter2("publisher_materialization_table_collision_total", "Two definitions with DIFFERENT content addresses materializing into ONE " + "physical table. Each build overwrites the other's rows while both " + "addresses resolve to the table at serve time, so a query is answered " + "from another source's data. A wrong answer, not wasted work — page on " + "this one. Refused instead of counted-and-continued when " + "PERSIST_COLLISION_ENFORCE is set, so a non-zero rate here is also the " + "measure of what flipping that flag would start refusing.");
270605
- sourceBuildDuration = lazyHistogram("publisher_materialization_source_build_duration_ms", "Wall-clock duration of building a single persist source.", "ms");
270606
- dropTablesCounter = lazyCounter2("publisher_materialization_drop_tables_total", "Physical tables dropped on delete. Label: outcome ('success'|'failure').");
270607
- scheduledFireCounter = lazyCounter2("publisher_materialization_scheduled_fires_total", "Standalone-scheduler attempts to fire a package's materialization.schedule. " + "Label: outcome ('fired'|'conflict'|'error').");
270608
- storageServeRoutingCounter = lazyCounter2("publisher_storage_serve_routing_total", "storage= serve routing decisions. Label: outcome ('storage'|'live_fallback'|" + "'runtime_live_fallback'|'blocked_by_row_level_gate'). Covers the storage= " + "tier only; a colocated #@ persist hit is in neither the numerator nor the " + "denominator. NOTE 'live_fallback' here means the transform was INELIGIBLE, " + "which QueryResult.servedFrom reports as null - that field's " + "'live_fallback' is this counter's 'runtime_live_fallback'.");
270609
- storageTableRetainedCounter = lazyCounter2("publisher_storage_tables_retained_total", "Tables a FAILED run left in a storage= destination and deliberately did not " + "reclaim, because the source is refreshed incrementally and the name may be " + "the one it serves from. Label: destination. Not all of these are orphans — " + "a rebuild at a fresh generational name is, a seed on the live serving name " + "is not, and the manifest entry cannot separate them — so read this as an " + "upper bound on what is accumulating rather than a leak count. It is the " + "only accounting there is until reclaiming a destination exists, which is " + "why it is a counter and not just a log line: the question is a rate, not " + "whether it ever happened.");
270610
- storageBuildFailureCounter = lazyCounter2("publisher_storage_build_failures_total", "storage= build failures (federation/passthrough/attach/CTAS), distinct from " + "in-warehouse build failures. Labels: destination (connection name), " + "reason ('build_failed'|'billed_read_not_captured'). The second is the " + "expensive one: the warehouse read ran and was charged, and the rows could " + "not be captured — so a re-drive pays for it again. Worth alerting on " + "separately from a failure that costs only a retry.");
270611
- attributionSkippedCounter = lazyCounter2("publisher_storage_build_attribution_skipped_total", "storage= builds whose warehouse read went out UNATTRIBUTED while tagging was " + "on. Label: reason ('job_listing_unavailable'|'tag_failed'|" + "'read_row_not_found'|'read_row_ambiguous'|'cost_query_failed'). " + "The read still ran and the " + "build still succeeded — what was lost is the label in the customer's own " + "query history, and the cost on this side. Without this an operator who " + "turns tagging on and sees nothing has a single log line to go on.");
270612
- eligibilityRefusedCounter = lazyCounter2("publisher_materialization_eligibility_refused_total", "storage= materialization-eligibility refusals. Label: reason " + "('free_parameter'|'given'|'authorize'|'not_duckdb_portable'|" + "'public_surface_unknown').");
270613
- serveShapeTierDropCounter = lazyCounter2("publisher_storage_serve_shape_tier_drop_total", "storage serve-shape compile escalations: a refinement tier failed to " + "compile and the riskiest category was dropped. Label: tier (the failed " + "tier index, 0=full).");
270614
- serveShapeTypeFallbackCounter = lazyCounter2("publisher_storage_serve_shape_type_fallback_total", "Captured DuckDB column types mapped to json in the serve shape (type " + "fidelity loss). Label: kind ('array'|'unrecognized').");
270615
- chainedStorageBuildCounter = lazyCounter2("publisher_storage_chained_build_total", "Chained storage= source builds (a source reading a storage-materialized " + "upstream). Label: outcome ('parent_reuse'|'inline_fallback'|" + "'strict_refused'). The parent_reuse share is the headline signal for how " + "far the stack-on-the-parent path gets us vs recompute-from-raw.");
270616
- colocatedBindDroppedCounter = lazyCounter2("publisher_materialization_colocated_bind_dropped_total", "Colocated serve-manifest entries dropped by bindColocatedServeManifest. " + "Label: reason ('build_plan_unavailable' when the package's build plan " + "failed to compute, so no source was examined at all; 'refused' when the " + "source itself was examined and found ineligible). 'build_plan_unavailable' " + "is a whole-package regression -- colocated is the default tier and is NOT " + "gated by PERSIST_STORAGE_MODE, so every colocated binding for the package " + "reverts to live recompute until a load succeeds.");
270733
+ resetHooks3 = [];
270734
+ runCounter = lazyCounter3("publisher_materialization_runs_total", "Materialization builds completed. Labels: mode ('auto'|'orchestrated'), outcome ('success'|'partial'|'failed'|'cancelled').");
270735
+ runDuration = lazyHistogram2("publisher_materialization_run_duration_ms", "Wall-clock duration of a materialization build. Label: mode ('auto'|'orchestrated').", "ms");
270736
+ sourcesCounter = lazyCounter3("publisher_materialization_sources_total", "Persist sources processed by a materialization run. Label: outcome ('built'|'reused'|'failed').");
270737
+ incrementalStepCounter = lazyCounter3("publisher_materialization_incremental_step_total", 'Refreshes of a source declared refresh="incremental". Labels: step ' + "('delta'|'seed'|'skip'), and for seed/skip a bounded reason code " + "(IncrementalStepReasonCode). A 'seed' is a full rebuild the delta path " + "declined, so a rising seed rate means the feature is not engaging — and " + "the reason label says why without a log dive.");
270738
+ buildPlanComputeDuration = lazyHistogram2("publisher_materialization_build_plan_compute_duration_ms", "Wall-clock duration of compiling a package's build plan (Package.buildPlan).", "ms");
270739
+ buildPlanComputeFailedCounter = lazyCounter3("publisher_materialization_build_plan_compute_failed_total", "Package loads whose build plan failed to compute. The ROOT-CAUSE signal for " + "colocated_bind_dropped{reason='build_plan_unavailable'}, which fires only " + "per dropped entry per load -- a package that loads once and is never " + "reloaded ticks that counter once and then sits with its colocated tier " + "off and a flat total, indistinguishable from healthy.");
270740
+ autoLoadCounter = lazyCounter3("publisher_materialization_auto_load_total", "Auto-run manifest auto-load attempts. Label: outcome ('success'|'failure').");
270741
+ connectionDigestSkipCounter = lazyCounter3("publisher_materialization_connection_digest_skipped_total", "Connection digests skipped during build-plan compile because the connection did not resolve.");
270742
+ manifestBindCounter = lazyCounter3("publisher_materialization_manifest_bind_total", "Manifest bind attempts. Label: outcome ('success'|'failure'|'timeout').");
270743
+ manifestBindDegradedCounter = lazyCounter3("publisher_materialization_manifest_bind_degraded_total", "Manifest entries bound with an UNQUOTED table path because their connection " + "could not be resolved (serve-side bind) or is absent from the build " + "(build-side seed). A misconfiguration that breaks the source on a " + "case-folding engine (Snowflake); alertable.");
270744
+ duplicateTargetSkipCounter = lazyCounter3("publisher_materialization_duplicate_target_skipped_total", "Sources skipped because the physical table they name was already built in " + "this run. Ordinary for a package that extends a persisted source; a " + "rising count against a package with no extension means the plan is " + "enumerating one table under more names than expected.");
270745
+ sharedAddressInstructionCounter = lazyCounter3("publisher_materialization_shared_address_instructions_total", "Content addresses that arrived with more than one instruction naming a " + "DIFFERENT physical table. The host minted a table per source where " + "several sources share one artifact. With a sourceID on each instruction " + "every table is built and only one is recorded, so the rest are orphaned; " + "without one the last instruction wins and the earlier names are never " + "built. Wasteful, not wrong — the table's CONTENT is the same either way.");
270746
+ tableCollisionCounter = lazyCounter3("publisher_materialization_table_collision_total", "Two definitions with DIFFERENT content addresses materializing into ONE " + "physical table. Each build overwrites the other's rows while both " + "addresses resolve to the table at serve time, so a query is answered " + "from another source's data. A wrong answer, not wasted work — page on " + "this one. Refused instead of counted-and-continued when " + "PERSIST_COLLISION_ENFORCE is set, so a non-zero rate here is also the " + "measure of what flipping that flag would start refusing.");
270747
+ sourceBuildDuration = lazyHistogram2("publisher_materialization_source_build_duration_ms", "Wall-clock duration of building a single persist source.", "ms");
270748
+ dropTablesCounter = lazyCounter3("publisher_materialization_drop_tables_total", "Physical tables dropped on delete. Label: outcome ('success'|'failure').");
270749
+ scheduledFireCounter = lazyCounter3("publisher_materialization_scheduled_fires_total", "Standalone-scheduler attempts to fire a package's materialization.schedule. " + "Label: outcome ('fired'|'conflict'|'error').");
270750
+ storageServeRoutingCounter = lazyCounter3("publisher_storage_serve_routing_total", "storage= serve routing decisions. Label: outcome ('storage'|'live_fallback'|" + "'runtime_live_fallback'|'blocked_by_row_level_gate'). Covers the storage= " + "tier only; a colocated #@ persist hit is in neither the numerator nor the " + "denominator. NOTE 'live_fallback' here means the transform was INELIGIBLE, " + "which QueryResult.servedFrom reports as null - that field's " + "'live_fallback' is this counter's 'runtime_live_fallback'.");
270751
+ storageTableRetainedCounter = lazyCounter3("publisher_storage_tables_retained_total", "Tables a FAILED run left in a storage= destination and deliberately did not " + "reclaim, because the source is refreshed incrementally and the name may be " + "the one it serves from. Label: destination. Not all of these are orphans — " + "a rebuild at a fresh generational name is, a seed on the live serving name " + "is not, and the manifest entry cannot separate them — so read this as an " + "upper bound on what is accumulating rather than a leak count. It is the " + "only accounting there is until reclaiming a destination exists, which is " + "why it is a counter and not just a log line: the question is a rate, not " + "whether it ever happened.");
270752
+ storageBuildFailureCounter = lazyCounter3("publisher_storage_build_failures_total", "storage= build failures (federation/passthrough/attach/CTAS), distinct from " + "in-warehouse build failures. Labels: destination (connection name), " + "reason ('build_failed'|'billed_read_not_captured'). The second is the " + "expensive one: the warehouse read ran and was charged, and the rows could " + "not be captured — so a re-drive pays for it again. Worth alerting on " + "separately from a failure that costs only a retry.");
270753
+ attributionSkippedCounter = lazyCounter3("publisher_storage_build_attribution_skipped_total", "storage= builds whose warehouse read went out UNATTRIBUTED while tagging was " + "on. Label: reason ('job_listing_unavailable'|'tag_failed'|" + "'read_row_not_found'|'read_row_ambiguous'|'cost_query_failed'). " + "The read still ran and the " + "build still succeeded — what was lost is the label in the customer's own " + "query history, and the cost on this side. Without this an operator who " + "turns tagging on and sees nothing has a single log line to go on.");
270754
+ eligibilityRefusedCounter = lazyCounter3("publisher_materialization_eligibility_refused_total", "storage= materialization-eligibility refusals. Label: reason " + "('free_parameter'|'given'|'authorize'|'not_duckdb_portable'|" + "'public_surface_unknown').");
270755
+ serveShapeTierDropCounter = lazyCounter3("publisher_storage_serve_shape_tier_drop_total", "storage serve-shape compile escalations: a refinement tier failed to " + "compile and the riskiest category was dropped. Label: tier (the failed " + "tier index, 0=full).");
270756
+ serveShapeTypeFallbackCounter = lazyCounter3("publisher_storage_serve_shape_type_fallback_total", "Captured DuckDB column types mapped to json in the serve shape (type " + "fidelity loss). Label: kind ('array'|'unrecognized').");
270757
+ chainedStorageBuildCounter = lazyCounter3("publisher_storage_chained_build_total", "Chained storage= source builds (a source reading a storage-materialized " + "upstream). Label: outcome ('parent_reuse'|'inline_fallback'|" + "'strict_refused'). The parent_reuse share is the headline signal for how " + "far the stack-on-the-parent path gets us vs recompute-from-raw.");
270758
+ colocatedBindDroppedCounter = lazyCounter3("publisher_materialization_colocated_bind_dropped_total", "Colocated serve-manifest entries dropped by bindColocatedServeManifest. " + "Label: reason ('build_plan_unavailable' when the package's build plan " + "failed to compute, so no source was examined at all; 'refused' when the " + "source itself was examined and found ineligible). 'build_plan_unavailable' " + "is a whole-package regression -- colocated is the default tier and is NOT " + "gated by PERSIST_STORAGE_MODE, so every colocated binding for the package " + "reverts to live recompute until a load succeeds.");
270617
270759
  });
270618
270760
 
270619
270761
  // src/utils.ts
270620
270762
  import * as fs4 from "fs";
270621
- import * as path6 from "path";
270763
+ import * as path7 from "path";
270622
270764
  import { fileURLToPath as fileURLToPath3 } from "url";
270623
270765
  function ignoreDotfiles(file) {
270624
- return path6.basename(file).startsWith(".");
270766
+ return path7.basename(file).startsWith(".");
270625
270767
  }
270626
270768
  function errMessage(err) {
270627
270769
  return err instanceof Error ? err.message : String(err);
@@ -270630,11 +270772,11 @@ var URL_READER;
270630
270772
  var init_utils4 = __esm(() => {
270631
270773
  URL_READER = {
270632
270774
  readURL: (url2) => {
270633
- let path7 = url2.toString();
270775
+ let path8 = url2.toString();
270634
270776
  if (url2.protocol == "file:") {
270635
- path7 = fileURLToPath3(url2);
270777
+ path8 = fileURLToPath3(url2);
270636
270778
  }
270637
- return fs4.promises.readFile(path7, "utf8");
270779
+ return fs4.promises.readFile(path8, "utf8");
270638
270780
  }
270639
270781
  };
270640
270782
  });
@@ -270906,9 +271048,9 @@ var init_preaggregation_classifier = __esm(() => {
270906
271048
 
270907
271049
  // src/service/preaggregation_synthesis.ts
270908
271050
  import { Annotations as Annotations3 } from "@malloydata/malloy";
270909
- import { createHash as createHash2 } from "node:crypto";
271051
+ import { createHash as createHash4 } from "node:crypto";
270910
271052
  function grainDigest(grainDimensions) {
270911
- return createHash2("sha256").update(grainDimensions.join("\x00")).digest("hex").slice(0, 8);
271053
+ return createHash4("sha256").update(grainDimensions.join("\x00")).digest("hex").slice(0, 8);
270912
271054
  }
270913
271055
  function rollupSourceName(baseSourceName, grainDimensions) {
270914
271056
  const slug = grainDimensions.join("_").replace(/\./g, "_").slice(0, NAME_SLUG_LIMIT);
@@ -271265,6 +271407,10 @@ function serveShapeFragment(binding) {
271265
271407
  lines.push(` ${r.kind}: ${r.name} is ${r.code}`);
271266
271408
  }
271267
271409
  }
271410
+ for (const r of refinements) {
271411
+ if (r.kind === "filter")
271412
+ lines.push(` where: ${r.code}`);
271413
+ }
271268
271414
  for (const r of refinements) {
271269
271415
  if (r.kind === "view")
271270
271416
  lines.push(` view: ${r.text}`);
@@ -271303,6 +271449,22 @@ ${fragments}
271303
271449
  `
271304
271450
  };
271305
271451
  }
271452
+ function buildServeShapeTiers(rollupGroups) {
271453
+ const always = [...NEVER_THINNED];
271454
+ const keepKinds = [
271455
+ new Set([...always, "join", "dimension", "measure", "view"]),
271456
+ new Set([...always, "join", "dimension", "measure"]),
271457
+ new Set([...always, "dimension", "measure"]),
271458
+ new Set(always)
271459
+ ];
271460
+ const hasGroups = rollupGroups.length > 0;
271461
+ return [
271462
+ { keep: keepKinds[0], groups: rollupGroups },
271463
+ ...hasGroups ? [{ keep: keepKinds[0], groups: [] }] : [],
271464
+ ...keepKinds.slice(1).map((keep) => ({ keep, groups: rollupGroups })),
271465
+ ...hasGroups ? [{ keep: new Set(always), groups: [] }] : []
271466
+ ];
271467
+ }
271306
271468
  function rollupServeShapeFragment(group) {
271307
271469
  const members = group.members.map(serveShapeFragment).join(`
271308
271470
  `);
@@ -271405,6 +271567,17 @@ function narrowSchemaToPublic(schema, fields) {
271405
271567
  }
271406
271568
  return out;
271407
271569
  }
271570
+ function extractSourceFilters(filterList) {
271571
+ const out = [];
271572
+ for (const entry of filterList ?? []) {
271573
+ const code = entry?.code;
271574
+ out.push({
271575
+ kind: "filter",
271576
+ code: typeof code === "string" ? code : UNREPRODUCIBLE_FILTER
271577
+ });
271578
+ }
271579
+ return out;
271580
+ }
271408
271581
  function extractRefinements(fields) {
271409
271582
  const out = [];
271410
271583
  for (const field of fields ?? []) {
@@ -271517,13 +271690,14 @@ async function assertServesInDuckDB(sourceName, binding, connections) {
271517
271690
  });
271518
271691
  }
271519
271692
  }
271520
- var BARE_IDENTIFIER;
271693
+ var BARE_IDENTIFIER, NEVER_THINNED, UNREPRODUCIBLE_FILTER = "__unreproducible_filter__";
271521
271694
  var init_materialization_serve_transform = __esm(() => {
271522
271695
  init_errors();
271523
271696
  init_logger();
271524
271697
  init_materialization_metrics();
271525
271698
  init_quoting();
271526
271699
  BARE_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
271700
+ NEVER_THINNED = ["filter"];
271527
271701
  });
271528
271702
 
271529
271703
  // src/service/freshness.ts
@@ -271571,16 +271745,16 @@ import {
271571
271745
  isJoined,
271572
271746
  isSourceDef as isSourceDef3
271573
271747
  } from "@malloydata/malloy";
271574
- function resolveFieldUsagePath(struct, path7) {
271748
+ function resolveFieldUsagePath(struct, path8) {
271575
271749
  let current = struct;
271576
- for (let i = 0;i < path7.length - 1; i++) {
271577
- const seg = path7[i];
271750
+ for (let i = 0;i < path8.length - 1; i++) {
271751
+ const seg = path8[i];
271578
271752
  const joinField = (current.fields ?? []).find((f) => (f.as || f.name) === seg && isJoined(f) && (isSourceDef3(f) || f.type === "record" || f.type === "array"));
271579
271753
  if (!joinField)
271580
271754
  return;
271581
271755
  current = joinField;
271582
271756
  }
271583
- const leaf = path7[path7.length - 1];
271757
+ const leaf = path8[path8.length - 1];
271584
271758
  const field = (current.fields ?? []).find((f) => (f.as || f.name) === leaf);
271585
271759
  return field ? { struct: current, field } : undefined;
271586
271760
  }
@@ -272677,15 +272851,15 @@ __export(exports_preaggregation_compile, {
272677
272851
  synthesizedModelURL: () => synthesizedModelURL,
272678
272852
  compileSynthesizedPreaggregation: () => compileSynthesizedPreaggregation
272679
272853
  });
272680
- import * as path7 from "path";
272854
+ import * as path8 from "path";
272681
272855
  function synthesizedModelURL(packagePath, modelPath) {
272682
- return new URL(`file://${path7.join(packagePath, modelPath)}${SYNTHESIZED_SUFFIX}`);
272856
+ return new URL(`file://${path8.join(packagePath, modelPath)}${SYNTHESIZED_SUFFIX}`);
272683
272857
  }
272684
272858
  async function compileSynthesizedPreaggregation(args) {
272685
272859
  const plans = planModelPreaggregation(args.contents);
272686
272860
  if (plans.length === 0)
272687
272861
  return;
272688
- const text = synthesizePreaggregationModel(plans, path7.basename(args.modelPath));
272862
+ const text = synthesizePreaggregationModel(plans, path8.basename(args.modelPath));
272689
272863
  if (!text)
272690
272864
  return;
272691
272865
  const synthesizedURL = synthesizedModelURL(args.packagePath, args.modelPath);
@@ -274020,9 +274194,9 @@ import {
274020
274194
  MalloySQLStatementType
274021
274195
  } from "@malloydata/malloy-sql";
274022
274196
  import * as fs6 from "fs/promises";
274023
- import { readFileSync } from "fs";
274197
+ import { readFileSync as readFileSync2 } from "fs";
274024
274198
  import { createRequire as createRequire2 } from "module";
274025
- import * as path8 from "path";
274199
+ import * as path9 from "path";
274026
274200
  import { fileURLToPath as fileURLToPath5 } from "url";
274027
274201
  function quoteMalloyIdentifier2(name) {
274028
274202
  return "`" + (name ?? "").replace(/\\/g, "\\\\").replace(/`/g, "\\`") + "`";
@@ -275293,22 +275467,11 @@ var init_model = __esm(() => {
275293
275467
  const rollupPaths = [
275294
275468
  ...buildVirtualMap(groups.flatMap((g) => g.members))
275295
275469
  ].flatMap(([, byHandle]) => [...byHandle.values()]);
275296
- const origin2 = rollupPaths.some((path9) => probeSQL.includes(path9)) ? "preaggregate" : "persist";
275470
+ const origin2 = rollupPaths.some((path10) => probeSQL.includes(path10)) ? "preaggregate" : "persist";
275297
275471
  return { runnable, virtualMap, bindings: freshBindings, origin: origin2 };
275298
275472
  }
275299
- async compileServeShape(enriched, rollupGroups = []) {
275300
- const keepKinds = [
275301
- new Set(["join", "dimension", "measure", "view"]),
275302
- new Set(["join", "dimension", "measure"]),
275303
- new Set(["dimension", "measure"]),
275304
- new Set
275305
- ];
275306
- const tiers = [
275307
- { keep: keepKinds[0], groups: rollupGroups },
275308
- ...rollupGroups.length > 0 ? [{ keep: keepKinds[0], groups: [] }] : [],
275309
- ...keepKinds.slice(1).map((keep) => ({ keep, groups: rollupGroups })),
275310
- ...rollupGroups.length > 0 ? [{ keep: new Set, groups: [] }] : []
275311
- ];
275473
+ async compileServeShape(enriched, rollupGroups = [], isRetry = false) {
275474
+ const tiers = buildServeShapeTiers(rollupGroups);
275312
275475
  const nothingToEscalate = rollupGroups.length === 0 && !enriched.some((b) => (b.refinements ?? []).length > 0);
275313
275476
  const lastTier = tiers.length - 1;
275314
275477
  for (let tier = 0;tier <= lastTier; tier++) {
@@ -275318,7 +275481,32 @@ var init_model = __esm(() => {
275318
275481
  refinements: b.refinements.filter((r) => keep.has(r.kind))
275319
275482
  } : b);
275320
275483
  const materializer = this.buildServeShapeMaterializer(shaped, groups);
275321
- if (tier === lastTier || tier === 0 && nothingToEscalate) {
275484
+ if (tier === lastTier) {
275485
+ try {
275486
+ await materializer.getModel();
275487
+ return materializer;
275488
+ } catch (err) {
275489
+ if (isRetry)
275490
+ return materializer;
275491
+ const servable = await this.bindingsWhoseFiltersCompile(enriched, keep);
275492
+ const withheld = enriched.filter((b) => !servable.includes(b)).map((b) => b.sourceName);
275493
+ if (servable.length === 0 || withheld.length === 0) {
275494
+ logger.warn("Storage serve shape failed at its floor and no binding could be isolated; serving live", {
275495
+ model: this.modelPath,
275496
+ error: err instanceof Error ? err.message : String(err)
275497
+ });
275498
+ return materializer;
275499
+ }
275500
+ logger.warn("Withheld storage serve bindings whose filters cannot be reproduced; those sources serve live", {
275501
+ model: this.modelPath,
275502
+ withheld,
275503
+ stillServed: servable.map((b) => b.sourceName),
275504
+ error: err instanceof Error ? err.message : String(err)
275505
+ });
275506
+ return await this.compileServeShape(servable, rollupGroups, true);
275507
+ }
275508
+ }
275509
+ if (tier === 0 && nothingToEscalate) {
275322
275510
  return materializer;
275323
275511
  }
275324
275512
  try {
@@ -275333,7 +275521,25 @@ var init_model = __esm(() => {
275333
275521
  });
275334
275522
  }
275335
275523
  }
275336
- return this.buildServeShapeMaterializer(enriched.map((b) => ({ ...b, refinements: [] })), []);
275524
+ const floor = tiers[tiers.length - 1].keep;
275525
+ return this.buildServeShapeMaterializer(enriched.map((b) => ({
275526
+ ...b,
275527
+ refinements: (b.refinements ?? []).filter((r) => floor.has(r.kind))
275528
+ })), []);
275529
+ }
275530
+ async bindingsWhoseFiltersCompile(enriched, floorKeep) {
275531
+ const servable = [];
275532
+ for (const binding of enriched) {
275533
+ const floored = {
275534
+ ...binding,
275535
+ refinements: (binding.refinements ?? []).filter((r) => floorKeep.has(r.kind))
275536
+ };
275537
+ try {
275538
+ await this.buildServeShapeMaterializer([floored], []).getModel();
275539
+ servable.push(binding);
275540
+ } catch {}
275541
+ }
275542
+ return servable;
275337
275543
  }
275338
275544
  buildServeShapeMaterializer(bindings, rollupGroups = []) {
275339
275545
  const { modelText } = buildServeShapeModelForBindings(bindings, rollupGroups);
@@ -275365,7 +275571,7 @@ var init_model = __esm(() => {
275365
275571
  return;
275366
275572
  if (!fileCache.has(location.url)) {
275367
275573
  try {
275368
- fileCache.set(location.url, readFileSync(fileURLToPath5(location.url), "utf8"));
275574
+ fileCache.set(location.url, readFileSync2(fileURLToPath5(location.url), "utf8"));
275369
275575
  } catch {
275370
275576
  fileCache.set(location.url, null);
275371
275577
  }
@@ -275383,6 +275589,7 @@ var init_model = __esm(() => {
275383
275589
  liftText
275384
275590
  }),
275385
275591
  ...extractRefinements(fields),
275592
+ ...extractSourceFilters(contents?.[b.sourceName]?.filterList),
275386
275593
  ...extractViews(fields, liftText)
275387
275594
  ];
275388
275595
  return { ...b, schema, refinements };
@@ -276107,7 +276314,7 @@ run: ${sourceName ? `${quoteMalloyIdentifier2(sourceName)} -> ` : ""}${quoteMall
276107
276314
  return this.modelType;
276108
276315
  }
276109
276316
  async getFileText(packagePath) {
276110
- const fullPath = path8.join(packagePath, this.modelPath);
276317
+ const fullPath = path9.join(packagePath, this.modelPath);
276111
276318
  try {
276112
276319
  return await fs6.readFile(fullPath, "utf8");
276113
276320
  } catch {
@@ -276339,14 +276546,14 @@ var require_brace_expansion = __commonJS((exports, module) => {
276339
276546
  var require_minimatch = __commonJS((exports, module) => {
276340
276547
  module.exports = minimatch;
276341
276548
  minimatch.Minimatch = Minimatch;
276342
- var path9 = function() {
276549
+ var path10 = function() {
276343
276550
  try {
276344
276551
  return __require("path");
276345
276552
  } catch (e) {}
276346
276553
  }() || {
276347
276554
  sep: "/"
276348
276555
  };
276349
- minimatch.sep = path9.sep;
276556
+ minimatch.sep = path10.sep;
276350
276557
  var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {};
276351
276558
  var expand = require_brace_expansion();
276352
276559
  var plTypes = {
@@ -276437,8 +276644,8 @@ var require_minimatch = __commonJS((exports, module) => {
276437
276644
  if (!options)
276438
276645
  options = {};
276439
276646
  pattern = pattern.trim();
276440
- if (!options.allowWindowsEscape && path9.sep !== "/") {
276441
- pattern = pattern.split(path9.sep).join("/");
276647
+ if (!options.allowWindowsEscape && path10.sep !== "/") {
276648
+ pattern = pattern.split(path10.sep).join("/");
276442
276649
  }
276443
276650
  this.options = options;
276444
276651
  this.set = [];
@@ -276815,8 +277022,8 @@ var require_minimatch = __commonJS((exports, module) => {
276815
277022
  if (f === "/" && partial)
276816
277023
  return true;
276817
277024
  var options = this.options;
276818
- if (path9.sep !== "/") {
276819
- f = f.split(path9.sep).join("/");
277025
+ if (path10.sep !== "/") {
277026
+ f = f.split(path10.sep).join("/");
276820
277027
  }
276821
277028
  f = f.split(slashSplit);
276822
277029
  this.debug(this.pattern, "split", f);
@@ -276927,9 +277134,9 @@ var require_recursive_readdir = __commonJS((exports, module) => {
276927
277134
  var p = __require("path");
276928
277135
  var minimatch = require_minimatch();
276929
277136
  function patternMatcher(pattern) {
276930
- return function(path9, stats) {
277137
+ return function(path10, stats) {
276931
277138
  var minimatcher = new minimatch.Minimatch(pattern, { matchBase: true });
276932
- return (!minimatcher.negate || stats.isFile()) && minimatcher.match(path9);
277139
+ return (!minimatcher.negate || stats.isFile()) && minimatcher.match(path10);
276933
277140
  };
276934
277141
  }
276935
277142
  function toMatcherFunction(ignoreEntry) {
@@ -276939,14 +277146,14 @@ var require_recursive_readdir = __commonJS((exports, module) => {
276939
277146
  return patternMatcher(ignoreEntry);
276940
277147
  }
276941
277148
  }
276942
- function readdir3(path9, ignores, callback) {
277149
+ function readdir3(path10, ignores, callback) {
276943
277150
  if (typeof ignores == "function") {
276944
277151
  callback = ignores;
276945
277152
  ignores = [];
276946
277153
  }
276947
277154
  if (!callback) {
276948
277155
  return new Promise(function(resolve4, reject2) {
276949
- readdir3(path9, ignores || [], function(err, data) {
277156
+ readdir3(path10, ignores || [], function(err, data) {
276950
277157
  if (err) {
276951
277158
  reject2(err);
276952
277159
  } else {
@@ -276957,7 +277164,7 @@ var require_recursive_readdir = __commonJS((exports, module) => {
276957
277164
  }
276958
277165
  ignores = ignores.map(toMatcherFunction);
276959
277166
  var list = [];
276960
- fs7.readdir(path9, function(err, files) {
277167
+ fs7.readdir(path10, function(err, files) {
276961
277168
  if (err) {
276962
277169
  return callback(err);
276963
277170
  }
@@ -276966,7 +277173,7 @@ var require_recursive_readdir = __commonJS((exports, module) => {
276966
277173
  return callback(null, list);
276967
277174
  }
276968
277175
  files.forEach(function(file) {
276969
- var filePath = p.join(path9, file);
277176
+ var filePath = p.join(path10, file);
276970
277177
  fs7.stat(filePath, function(_err, stats) {
276971
277178
  if (_err) {
276972
277179
  return callback(_err);
@@ -283385,8 +283592,8 @@ var require_CronFileParser = __commonJS((exports) => {
283385
283592
  return CronFileParser.#parseContent(data);
283386
283593
  }
283387
283594
  static parseFileSync(filePath) {
283388
- const { readFileSync: readFileSync2 } = __require("fs");
283389
- const data = readFileSync2(filePath, "utf8");
283595
+ const { readFileSync: readFileSync3 } = __require("fs");
283596
+ const data = readFileSync3(filePath, "utf8");
283390
283597
  return CronFileParser.#parseContent(data);
283391
283598
  }
283392
283599
  static #parseContent(data) {
@@ -284284,8 +284491,8 @@ var require_uri_all = __commonJS((exports, module) => {
284284
284491
  wsComponents.secure = undefined;
284285
284492
  }
284286
284493
  if (wsComponents.resourceName) {
284287
- var _wsComponents$resourc = wsComponents.resourceName.split("?"), _wsComponents$resourc2 = slicedToArray(_wsComponents$resourc, 2), path13 = _wsComponents$resourc2[0], query = _wsComponents$resourc2[1];
284288
- wsComponents.path = path13 && path13 !== "/" ? path13 : undefined;
284494
+ var _wsComponents$resourc = wsComponents.resourceName.split("?"), _wsComponents$resourc2 = slicedToArray(_wsComponents$resourc, 2), path14 = _wsComponents$resourc2[0], query = _wsComponents$resourc2[1];
284495
+ wsComponents.path = path14 && path14 !== "/" ? path14 : undefined;
284289
284496
  wsComponents.query = query;
284290
284497
  wsComponents.resourceName = undefined;
284291
284498
  }
@@ -284678,12 +284885,12 @@ var require_util12 = __commonJS((exports, module) => {
284678
284885
  return "'" + escapeQuotes(str) + "'";
284679
284886
  }
284680
284887
  function getPathExpr(currentPath, expr, jsonPointers, isNumber2) {
284681
- var path13 = jsonPointers ? "'/' + " + expr + (isNumber2 ? "" : ".replace(/~/g, '~0').replace(/\\//g, '~1')") : isNumber2 ? "'[' + " + expr + " + ']'" : "'[\\'' + " + expr + " + '\\']'";
284682
- return joinPaths(currentPath, path13);
284888
+ var path14 = jsonPointers ? "'/' + " + expr + (isNumber2 ? "" : ".replace(/~/g, '~0').replace(/\\//g, '~1')") : isNumber2 ? "'[' + " + expr + " + ']'" : "'[\\'' + " + expr + " + '\\']'";
284889
+ return joinPaths(currentPath, path14);
284683
284890
  }
284684
284891
  function getPath(currentPath, prop, jsonPointers) {
284685
- var path13 = jsonPointers ? toQuotedString("/" + escapeJsonPointer(prop)) : toQuotedString(getProperty(prop));
284686
- return joinPaths(currentPath, path13);
284892
+ var path14 = jsonPointers ? toQuotedString("/" + escapeJsonPointer(prop)) : toQuotedString(getProperty(prop));
284893
+ return joinPaths(currentPath, path14);
284687
284894
  }
284688
284895
  var JSON_POINTER = /^\/(?:[^~]|~0|~1)*$/;
284689
284896
  var RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/;
@@ -296286,7 +296493,7 @@ var import_cors = __toESM(require_lib6(), 1);
296286
296493
  var import_express = __toESM(require_express(), 1);
296287
296494
  var import_http_proxy_middleware = __toESM(require_dist4(), 1);
296288
296495
  import * as http2 from "http";
296289
- import * as path15 from "path";
296496
+ import * as path16 from "path";
296290
296497
  import { fileURLToPath as fileURLToPath8 } from "url";
296291
296498
 
296292
296499
  // src/controller/compile.controller.ts
@@ -296312,6 +296519,7 @@ init_config();
296312
296519
  init_errors();
296313
296520
  init_query_cap_metrics();
296314
296521
  init_logger();
296522
+ init_path_safety();
296315
296523
 
296316
296524
  // src/query_timeout.ts
296317
296525
  init_telemetry();
@@ -296571,19 +296779,19 @@ function withoutWithheldFields(value) {
296571
296779
  }
296572
296780
  function flattenWithheld(hidden, prefix, out) {
296573
296781
  for (const [key, value] of Object.entries(hidden)) {
296574
- const path4 = prefix ? `${prefix}.${key}` : key;
296782
+ const path5 = prefix ? `${prefix}.${key}` : key;
296575
296783
  if (Array.isArray(value)) {
296576
296784
  for (const item of value) {
296577
296785
  if (!isPlainObject2(item))
296578
296786
  continue;
296579
296787
  const { name, ...rest } = item;
296580
- const label = typeof name === "string" ? `${path4}.${name}` : path4;
296788
+ const label = typeof name === "string" ? `${path5}.${name}` : path5;
296581
296789
  flattenWithheld(rest, label, out);
296582
296790
  }
296583
296791
  } else if (isPlainObject2(value)) {
296584
- flattenWithheld(value, path4, out);
296792
+ flattenWithheld(value, path5, out);
296585
296793
  } else if (value !== undefined && value !== null && value !== "") {
296586
- out.push(path4);
296794
+ out.push(path5);
296587
296795
  }
296588
296796
  }
296589
296797
  }
@@ -296684,22 +296892,22 @@ function isSupplied(value) {
296684
296892
  return Object.keys(value).length > 0;
296685
296893
  return true;
296686
296894
  }
296687
- function suppliedAt(patch, path4) {
296688
- const dot = path4.indexOf(".");
296895
+ function suppliedAt(patch, path5) {
296896
+ const dot = path5.indexOf(".");
296689
296897
  if (dot === -1) {
296690
- return Object.hasOwn(patch, path4) && isSupplied(patch[path4]);
296898
+ return Object.hasOwn(patch, path5) && isSupplied(patch[path5]);
296691
296899
  }
296692
- const parent = patch[path4.slice(0, dot)];
296900
+ const parent = patch[path5.slice(0, dot)];
296693
296901
  if (!isPlainObject2(parent))
296694
296902
  return false;
296695
- const leaf = path4.slice(dot + 1);
296903
+ const leaf = path5.slice(dot + 1);
296696
296904
  return Object.hasOwn(parent, leaf) && isSupplied(parent[leaf]);
296697
296905
  }
296698
296906
  function exclusionsFor(patch) {
296699
296907
  const skip = new Set;
296700
296908
  for (const slots of EXCLUSIVE_SLOTS) {
296701
296909
  const declared = slots.filter((slot) => slot.fields.some((field) => isPlainObject2(patch[field])));
296702
- const selected = declared.length === 1 ? declared : slots.filter((slot) => slot.selects.some((path4) => suppliedAt(patch, path4)));
296910
+ const selected = declared.length === 1 ? declared : slots.filter((slot) => slot.selects.some((path5) => suppliedAt(patch, path5)));
296703
296911
  if (selected.length !== 1)
296704
296912
  continue;
296705
296913
  for (const slot of slots) {
@@ -298227,12 +298435,15 @@ class ConnectionController {
298227
298435
  if (!connectionConfig.type || typeof connectionConfig.type !== "string") {
298228
298436
  throw new BadRequestError("Connection type is required and must be a string");
298229
298437
  }
298438
+ if ((connectionConfig.type === "duckdb" || connectionConfig.type === "ducklake") && connectionConfig.name) {
298439
+ assertSafePackageName(connectionConfig.name);
298440
+ }
298230
298441
  try {
298231
298442
  return await testConnectionConfig(connectionConfig);
298232
298443
  } catch (error) {
298233
298444
  return {
298234
298445
  status: "failed",
298235
- errorMessage: `Connection test failed: ${error.message}`
298446
+ errorMessage: redactPgSecrets(`Connection test failed: ${error instanceof Error ? error.message : String(error)}`)
298236
298447
  };
298237
298448
  }
298238
298449
  }
@@ -298277,6 +298488,48 @@ class ConnectionController {
298277
298488
 
298278
298489
  // src/controller/dashboard.controller.ts
298279
298490
  init_errors();
298491
+ import { createHash as createHash2 } from "node:crypto";
298492
+
298493
+ // src/dashboard_write_metrics.ts
298494
+ init_telemetry();
298495
+ var resetHooks2 = [];
298496
+ function lazyCounter2(name, description) {
298497
+ let instrument2 = null;
298498
+ resetHooks2.push(() => instrument2 = null);
298499
+ return () => instrument2 ??= publisherMeter().createCounter(name, { description });
298500
+ }
298501
+ function lazyHistogram(name, description, unit) {
298502
+ let instrument2 = null;
298503
+ resetHooks2.push(() => instrument2 = null);
298504
+ return () => instrument2 ??= publisherMeter().createHistogram(name, {
298505
+ description,
298506
+ unit
298507
+ });
298508
+ }
298509
+ var writeCounter = lazyCounter2("publisher_dashboard_writes_total", "Dashboard write attempts. Label: outcome ('created'|'replaced'|'conflict'|'compile_failed'|'refused'|'rolled_back').");
298510
+ var writeDuration = lazyHistogram("publisher_dashboard_write_duration_ms", "Wall-clock duration of a dashboard write, compile and package reload included. Label: outcome.", "ms");
298511
+ function recordDashboardWrite(outcome, durationMs) {
298512
+ writeCounter().add(1, { outcome });
298513
+ writeDuration().record(durationMs, { outcome });
298514
+ }
298515
+
298516
+ // src/controller/dashboard.controller.ts
298517
+ init_path_safety();
298518
+ function outcomeOf(error) {
298519
+ if (error instanceof WriteConflictError)
298520
+ return "conflict";
298521
+ if (error instanceof CompileRefusedError)
298522
+ return "compile_failed";
298523
+ if (error instanceof WriteRolledBackError)
298524
+ return "rolled_back";
298525
+ return "refused";
298526
+ }
298527
+ var DASHBOARD_FILE = /^dashboards\/[^/]+\.malloy$/;
298528
+ var describeProblem = (problem) => {
298529
+ const start = problem.at?.range?.start;
298530
+ return start?.line === undefined ? problem.message : `line ${start.line + 1}:${(start.character ?? 0) + 1} ${problem.message}`;
298531
+ };
298532
+ var contentHashOf = (text) => createHash2("sha256").update(text, "utf8").digest("hex");
298280
298533
 
298281
298534
  class DashboardController {
298282
298535
  environmentStore;
@@ -298297,6 +298550,57 @@ class DashboardController {
298297
298550
  }
298298
298551
  return dashboard;
298299
298552
  }
298553
+ async putDashboardSource(environmentName, packageName, modelPath, body) {
298554
+ const startedAt = Date.now();
298555
+ try {
298556
+ const result = await this.writeDashboardSource(environmentName, packageName, modelPath, body);
298557
+ recordDashboardWrite(result.created ? "created" : "replaced", Date.now() - startedAt);
298558
+ return result;
298559
+ } catch (error) {
298560
+ recordDashboardWrite(outcomeOf(error), Date.now() - startedAt);
298561
+ throw error;
298562
+ }
298563
+ }
298564
+ async writeDashboardSource(environmentName, packageName, modelPath, body) {
298565
+ if (this.environmentStore.publisherConfigIsFrozen) {
298566
+ throw new FrozenConfigError('Cannot write a dashboard: publisher.config.json has "frozenConfig": true.');
298567
+ }
298568
+ assertSafeRelativeModelPath(modelPath);
298569
+ if (!DASHBOARD_FILE.test(modelPath)) {
298570
+ throw new BadRequestError(`Only a dashboard file can be written here: \`dashboards/<slug>.malloy\`, ` + `not \`${modelPath}\`.`);
298571
+ }
298572
+ if (typeof body?.source !== "string") {
298573
+ throw new BadRequestError("The request body needs a `source`: the whole file's Malloy text.");
298574
+ }
298575
+ const environment = await this.environmentStore.getEnvironment(environmentName, false);
298576
+ await environment.getPackage(packageName, false);
298577
+ const { problems } = await environment.compileSource(packageName, modelPath, body.source, false, undefined, "file");
298578
+ const errors2 = problems.filter((problem) => problem.severity === "error");
298579
+ if (errors2.length > 0) {
298580
+ throw new CompileRefusedError(`The dashboard does not compile, so it was not written: ` + errors2.map(describeProblem).join("; "));
298581
+ }
298582
+ const { previous } = await environment.writeModelFileTransactional(packageName, modelPath, body.source, (current) => {
298583
+ if (body.expectedHash === undefined) {
298584
+ if (current !== undefined)
298585
+ throw new WriteConflictError(`\`${modelPath}\` already exists in the package. Send the ` + `\`expectedHash\` of the text you opened to replace it.`);
298586
+ return;
298587
+ }
298588
+ const currentHash = current === undefined ? undefined : contentHashOf(current);
298589
+ if (currentHash !== body.expectedHash)
298590
+ throw new WriteConflictError(current === undefined ? `\`${modelPath}\` no longer exists in the package, so the text you ` + `opened cannot be updated. Re-open it before saving.` : `\`${modelPath}\` changed in the package since you opened it. ` + `Re-open it and reapply your change; nothing was written.`);
298591
+ }, async (reloaded) => {
298592
+ const written = reloaded.getModel(modelPath);
298593
+ if (!written)
298594
+ throw new Error(`\`${modelPath}\` is not in the reloaded package`);
298595
+ await written.getModel();
298596
+ });
298597
+ return {
298598
+ resource: `/api/v0/environments/${environmentName}/packages/${packageName}/models/${modelPath}`,
298599
+ path: modelPath,
298600
+ contentHash: contentHashOf(body.source),
298601
+ created: previous === undefined
298602
+ };
298603
+ }
298300
298604
  }
298301
298605
 
298302
298606
  // src/controller/database.controller.ts
@@ -298408,7 +298712,7 @@ class ModelController {
298408
298712
  init_constants();
298409
298713
  init_errors();
298410
298714
  init_logger();
298411
- import * as path4 from "path";
298715
+ import * as path5 from "path";
298412
298716
 
298413
298717
  // src/mcp/tools/get_context_tool.ts
298414
298718
  var import_lunr = __toESM(require_lunr(), 1);
@@ -298743,22 +299047,22 @@ async function getModelForQuery(environmentStore, environmentName, packageName,
298743
299047
  }
298744
299048
  }
298745
299049
  function buildMalloyUri(components, fragment) {
298746
- let path4 = "/environment/";
299050
+ let path5 = "/environment/";
298747
299051
  if (components.environment) {
298748
- path4 += encodeURIComponent(components.environment);
299052
+ path5 += encodeURIComponent(components.environment);
298749
299053
  } else {
298750
- path4 += "home";
299054
+ path5 += "home";
298751
299055
  }
298752
299056
  if (components.package) {
298753
- path4 += "/package/" + encodeURIComponent(components.package);
299057
+ path5 += "/package/" + encodeURIComponent(components.package);
298754
299058
  }
298755
299059
  if (components.resourceType) {
298756
- path4 += "/" + components.resourceType;
299060
+ path5 += "/" + components.resourceType;
298757
299061
  if (components.resourceName) {
298758
- path4 += "/" + encodeURIComponent(components.resourceName);
299062
+ path5 += "/" + encodeURIComponent(components.resourceName);
298759
299063
  }
298760
299064
  }
298761
- let uriString = "malloy:/" + path4;
299065
+ let uriString = "malloy:/" + path5;
298762
299066
  if (fragment) {
298763
299067
  uriString += "#" + fragment;
298764
299068
  }
@@ -298809,7 +299113,7 @@ function jsonToolError(uri, details, extraPayload) {
298809
299113
  init_logger();
298810
299114
 
298811
299115
  // src/mcp/tools/embedding_index.ts
298812
- import { createHash } from "crypto";
299116
+ import { createHash as createHash3 } from "crypto";
298813
299117
 
298814
299118
  // ../../node_modules/async-mutex/index.mjs
298815
299119
  var E_TIMEOUT = new Error("timeout while waiting for mutex to become available");
@@ -299216,7 +299520,7 @@ function splitToFit(text, max) {
299216
299520
  return pieces;
299217
299521
  }
299218
299522
  function contentHash(text) {
299219
- return createHash("sha256").update(text).digest("hex");
299523
+ return createHash3("sha256").update(text).digest("hex");
299220
299524
  }
299221
299525
  function sourceColumn(source) {
299222
299526
  return source ?? "";
@@ -300800,7 +301104,7 @@ class PackageController {
300800
301104
  } else if (packageLocation.startsWith("s3://")) {
300801
301105
  await this.environmentStore.downloadS3Directory(packageLocation, environmentName, targetPath, isCompressedFile);
300802
301106
  }
300803
- if (packageLocation.startsWith("/") || path4.isAbsolute(packageLocation)) {
301107
+ if (packageLocation.startsWith("/") || path5.isAbsolute(packageLocation)) {
300804
301108
  await this.environmentStore.mountLocalDirectory(packageLocation, targetPath, environmentName, packageName);
300805
301109
  }
300806
301110
  }
@@ -300958,7 +301262,7 @@ class ReaddirpStream extends Readable2 {
300958
301262
  this._directoryFilter = normalizeFilter(opts.directoryFilter);
300959
301263
  const statMethod = opts.lstat ? lstat : stat;
300960
301264
  if (wantBigintFsStats) {
300961
- this._stat = (path5) => statMethod(path5, { bigint: true });
301265
+ this._stat = (path6) => statMethod(path6, { bigint: true });
300962
301266
  } else {
300963
301267
  this._stat = statMethod;
300964
301268
  }
@@ -300983,8 +301287,8 @@ class ReaddirpStream extends Readable2 {
300983
301287
  const par = this.parent;
300984
301288
  const fil = par && par.files;
300985
301289
  if (fil && fil.length > 0) {
300986
- const { path: path5, depth } = par;
300987
- const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path5));
301290
+ const { path: path6, depth } = par;
301291
+ const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path6));
300988
301292
  const awaited = await Promise.all(slice);
300989
301293
  for (const entry of awaited) {
300990
301294
  if (!entry)
@@ -301024,20 +301328,20 @@ class ReaddirpStream extends Readable2 {
301024
301328
  this.reading = false;
301025
301329
  }
301026
301330
  }
301027
- async _exploreDir(path5, depth) {
301331
+ async _exploreDir(path6, depth) {
301028
301332
  let files;
301029
301333
  try {
301030
- files = await readdir(path5, this._rdOptions);
301334
+ files = await readdir(path6, this._rdOptions);
301031
301335
  } catch (error) {
301032
301336
  this._onError(error);
301033
301337
  }
301034
- return { files, depth, path: path5 };
301338
+ return { files, depth, path: path6 };
301035
301339
  }
301036
- async _formatEntry(dirent, path5) {
301340
+ async _formatEntry(dirent, path6) {
301037
301341
  let entry;
301038
301342
  const basename = this._isDirent ? dirent.name : dirent;
301039
301343
  try {
301040
- const fullPath = presolve(pjoin(path5, basename));
301344
+ const fullPath = presolve(pjoin(path6, basename));
301041
301345
  entry = { path: prelative(this._root, fullPath), fullPath, basename };
301042
301346
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
301043
301347
  } catch (err) {
@@ -301436,16 +301740,16 @@ var delFromSet = (main, prop, item) => {
301436
301740
  };
301437
301741
  var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
301438
301742
  var FsWatchInstances = new Map;
301439
- function createFsWatchInstance(path5, options, listener, errHandler, emitRaw) {
301743
+ function createFsWatchInstance(path6, options, listener, errHandler, emitRaw) {
301440
301744
  const handleEvent = (rawEvent, evPath) => {
301441
- listener(path5);
301442
- emitRaw(rawEvent, evPath, { watchedPath: path5 });
301443
- if (evPath && path5 !== evPath) {
301444
- fsWatchBroadcast(sysPath.resolve(path5, evPath), KEY_LISTENERS, sysPath.join(path5, evPath));
301745
+ listener(path6);
301746
+ emitRaw(rawEvent, evPath, { watchedPath: path6 });
301747
+ if (evPath && path6 !== evPath) {
301748
+ fsWatchBroadcast(sysPath.resolve(path6, evPath), KEY_LISTENERS, sysPath.join(path6, evPath));
301445
301749
  }
301446
301750
  };
301447
301751
  try {
301448
- return fs_watch(path5, {
301752
+ return fs_watch(path6, {
301449
301753
  persistent: options.persistent
301450
301754
  }, handleEvent);
301451
301755
  } catch (error) {
@@ -301461,12 +301765,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
301461
301765
  listener(val1, val2, val3);
301462
301766
  });
301463
301767
  };
301464
- var setFsWatchListener = (path5, fullPath, options, handlers) => {
301768
+ var setFsWatchListener = (path6, fullPath, options, handlers) => {
301465
301769
  const { listener, errHandler, rawEmitter } = handlers;
301466
301770
  let cont = FsWatchInstances.get(fullPath);
301467
301771
  let watcher;
301468
301772
  if (!options.persistent) {
301469
- watcher = createFsWatchInstance(path5, options, listener, errHandler, rawEmitter);
301773
+ watcher = createFsWatchInstance(path6, options, listener, errHandler, rawEmitter);
301470
301774
  if (!watcher)
301471
301775
  return;
301472
301776
  return watcher.close.bind(watcher);
@@ -301476,7 +301780,7 @@ var setFsWatchListener = (path5, fullPath, options, handlers) => {
301476
301780
  addAndConvert(cont, KEY_ERR, errHandler);
301477
301781
  addAndConvert(cont, KEY_RAW, rawEmitter);
301478
301782
  } else {
301479
- watcher = createFsWatchInstance(path5, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, fsWatchBroadcast.bind(null, fullPath, KEY_RAW));
301783
+ watcher = createFsWatchInstance(path6, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, fsWatchBroadcast.bind(null, fullPath, KEY_RAW));
301480
301784
  if (!watcher)
301481
301785
  return;
301482
301786
  watcher.on(EV.ERROR, async (error) => {
@@ -301485,7 +301789,7 @@ var setFsWatchListener = (path5, fullPath, options, handlers) => {
301485
301789
  cont.watcherUnusable = true;
301486
301790
  if (isWindows && error.code === "EPERM") {
301487
301791
  try {
301488
- const fd = await open(path5, "r");
301792
+ const fd = await open(path6, "r");
301489
301793
  await fd.close();
301490
301794
  broadcastErr(error);
301491
301795
  } catch (err) {}
@@ -301515,7 +301819,7 @@ var setFsWatchListener = (path5, fullPath, options, handlers) => {
301515
301819
  };
301516
301820
  };
301517
301821
  var FsWatchFileInstances = new Map;
301518
- var setFsWatchFileListener = (path5, fullPath, options, handlers) => {
301822
+ var setFsWatchFileListener = (path6, fullPath, options, handlers) => {
301519
301823
  const { listener, rawEmitter } = handlers;
301520
301824
  let cont = FsWatchFileInstances.get(fullPath);
301521
301825
  const copts = cont && cont.options;
@@ -301537,7 +301841,7 @@ var setFsWatchFileListener = (path5, fullPath, options, handlers) => {
301537
301841
  });
301538
301842
  const currmtime = curr.mtimeMs;
301539
301843
  if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
301540
- foreach(cont.listeners, (listener2) => listener2(path5, curr));
301844
+ foreach(cont.listeners, (listener2) => listener2(path6, curr));
301541
301845
  }
301542
301846
  })
301543
301847
  };
@@ -301560,13 +301864,13 @@ class NodeFsHandler {
301560
301864
  this.fsw = fsW;
301561
301865
  this._boundHandleError = (error) => fsW._handleError(error);
301562
301866
  }
301563
- _watchWithNodeFs(path5, listener) {
301867
+ _watchWithNodeFs(path6, listener) {
301564
301868
  const opts = this.fsw.options;
301565
- const directory = sysPath.dirname(path5);
301566
- const basename2 = sysPath.basename(path5);
301869
+ const directory = sysPath.dirname(path6);
301870
+ const basename2 = sysPath.basename(path6);
301567
301871
  const parent = this.fsw._getWatchedDir(directory);
301568
301872
  parent.add(basename2);
301569
- const absolutePath = sysPath.resolve(path5);
301873
+ const absolutePath = sysPath.resolve(path6);
301570
301874
  const options = {
301571
301875
  persistent: opts.persistent
301572
301876
  };
@@ -301576,12 +301880,12 @@ class NodeFsHandler {
301576
301880
  if (opts.usePolling) {
301577
301881
  const enableBin = opts.interval !== opts.binaryInterval;
301578
301882
  options.interval = enableBin && isBinaryPath(basename2) ? opts.binaryInterval : opts.interval;
301579
- closer = setFsWatchFileListener(path5, absolutePath, options, {
301883
+ closer = setFsWatchFileListener(path6, absolutePath, options, {
301580
301884
  listener,
301581
301885
  rawEmitter: this.fsw._emitRaw
301582
301886
  });
301583
301887
  } else {
301584
- closer = setFsWatchListener(path5, absolutePath, options, {
301888
+ closer = setFsWatchListener(path6, absolutePath, options, {
301585
301889
  listener,
301586
301890
  errHandler: this._boundHandleError,
301587
301891
  rawEmitter: this.fsw._emitRaw
@@ -301599,7 +301903,7 @@ class NodeFsHandler {
301599
301903
  let prevStats = stats;
301600
301904
  if (parent.has(basename2))
301601
301905
  return;
301602
- const listener = async (path5, newStats) => {
301906
+ const listener = async (path6, newStats) => {
301603
301907
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
301604
301908
  return;
301605
301909
  if (!newStats || newStats.mtimeMs === 0) {
@@ -301613,11 +301917,11 @@ class NodeFsHandler {
301613
301917
  this.fsw._emit(EV.CHANGE, file, newStats2);
301614
301918
  }
301615
301919
  if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
301616
- this.fsw._closeFile(path5);
301920
+ this.fsw._closeFile(path6);
301617
301921
  prevStats = newStats2;
301618
301922
  const closer2 = this._watchWithNodeFs(file, listener);
301619
301923
  if (closer2)
301620
- this.fsw._addPathCloser(path5, closer2);
301924
+ this.fsw._addPathCloser(path6, closer2);
301621
301925
  } else {
301622
301926
  prevStats = newStats2;
301623
301927
  }
@@ -301641,7 +301945,7 @@ class NodeFsHandler {
301641
301945
  }
301642
301946
  return closer;
301643
301947
  }
301644
- async _handleSymlink(entry, directory, path5, item) {
301948
+ async _handleSymlink(entry, directory, path6, item) {
301645
301949
  if (this.fsw.closed) {
301646
301950
  return;
301647
301951
  }
@@ -301651,7 +301955,7 @@ class NodeFsHandler {
301651
301955
  this.fsw._incrReadyCount();
301652
301956
  let linkPath;
301653
301957
  try {
301654
- linkPath = await fsrealpath(path5);
301958
+ linkPath = await fsrealpath(path6);
301655
301959
  } catch (e) {
301656
301960
  this.fsw._emitReady();
301657
301961
  return true;
@@ -301661,12 +301965,12 @@ class NodeFsHandler {
301661
301965
  if (dir.has(item)) {
301662
301966
  if (this.fsw._symlinkPaths.get(full) !== linkPath) {
301663
301967
  this.fsw._symlinkPaths.set(full, linkPath);
301664
- this.fsw._emit(EV.CHANGE, path5, entry.stats);
301968
+ this.fsw._emit(EV.CHANGE, path6, entry.stats);
301665
301969
  }
301666
301970
  } else {
301667
301971
  dir.add(item);
301668
301972
  this.fsw._symlinkPaths.set(full, linkPath);
301669
- this.fsw._emit(EV.ADD, path5, entry.stats);
301973
+ this.fsw._emit(EV.ADD, path6, entry.stats);
301670
301974
  }
301671
301975
  this.fsw._emitReady();
301672
301976
  return true;
@@ -301695,9 +301999,9 @@ class NodeFsHandler {
301695
301999
  return;
301696
302000
  }
301697
302001
  const item = entry.path;
301698
- let path5 = sysPath.join(directory, item);
302002
+ let path6 = sysPath.join(directory, item);
301699
302003
  current.add(item);
301700
- if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path5, item)) {
302004
+ if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path6, item)) {
301701
302005
  return;
301702
302006
  }
301703
302007
  if (this.fsw.closed) {
@@ -301706,8 +302010,8 @@ class NodeFsHandler {
301706
302010
  }
301707
302011
  if (item === target || !target && !previous.has(item)) {
301708
302012
  this.fsw._incrReadyCount();
301709
- path5 = sysPath.join(dir, sysPath.relative(dir, path5));
301710
- this._addToNodeFs(path5, initialAdd, wh, depth + 1);
302013
+ path6 = sysPath.join(dir, sysPath.relative(dir, path6));
302014
+ this._addToNodeFs(path6, initialAdd, wh, depth + 1);
301711
302015
  }
301712
302016
  }).on(EV.ERROR, this._boundHandleError);
301713
302017
  return new Promise((resolve3, reject) => {
@@ -301756,13 +302060,13 @@ class NodeFsHandler {
301756
302060
  }
301757
302061
  return closer;
301758
302062
  }
301759
- async _addToNodeFs(path5, initialAdd, priorWh, depth, target) {
302063
+ async _addToNodeFs(path6, initialAdd, priorWh, depth, target) {
301760
302064
  const ready = this.fsw._emitReady;
301761
- if (this.fsw._isIgnored(path5) || this.fsw.closed) {
302065
+ if (this.fsw._isIgnored(path6) || this.fsw.closed) {
301762
302066
  ready();
301763
302067
  return false;
301764
302068
  }
301765
- const wh = this.fsw._getWatchHelpers(path5);
302069
+ const wh = this.fsw._getWatchHelpers(path6);
301766
302070
  if (priorWh) {
301767
302071
  wh.filterPath = (entry) => priorWh.filterPath(entry);
301768
302072
  wh.filterDir = (entry) => priorWh.filterDir(entry);
@@ -301778,8 +302082,8 @@ class NodeFsHandler {
301778
302082
  const follow = this.fsw.options.followSymlinks;
301779
302083
  let closer;
301780
302084
  if (stats.isDirectory()) {
301781
- const absPath = sysPath.resolve(path5);
301782
- const targetPath = follow ? await fsrealpath(path5) : path5;
302085
+ const absPath = sysPath.resolve(path6);
302086
+ const targetPath = follow ? await fsrealpath(path6) : path6;
301783
302087
  if (this.fsw.closed)
301784
302088
  return;
301785
302089
  closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
@@ -301789,29 +302093,29 @@ class NodeFsHandler {
301789
302093
  this.fsw._symlinkPaths.set(absPath, targetPath);
301790
302094
  }
301791
302095
  } else if (stats.isSymbolicLink()) {
301792
- const targetPath = follow ? await fsrealpath(path5) : path5;
302096
+ const targetPath = follow ? await fsrealpath(path6) : path6;
301793
302097
  if (this.fsw.closed)
301794
302098
  return;
301795
302099
  const parent = sysPath.dirname(wh.watchPath);
301796
302100
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
301797
302101
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
301798
- closer = await this._handleDir(parent, stats, initialAdd, depth, path5, wh, targetPath);
302102
+ closer = await this._handleDir(parent, stats, initialAdd, depth, path6, wh, targetPath);
301799
302103
  if (this.fsw.closed)
301800
302104
  return;
301801
302105
  if (targetPath !== undefined) {
301802
- this.fsw._symlinkPaths.set(sysPath.resolve(path5), targetPath);
302106
+ this.fsw._symlinkPaths.set(sysPath.resolve(path6), targetPath);
301803
302107
  }
301804
302108
  } else {
301805
302109
  closer = this._handleFile(wh.watchPath, stats, initialAdd);
301806
302110
  }
301807
302111
  ready();
301808
302112
  if (closer)
301809
- this.fsw._addPathCloser(path5, closer);
302113
+ this.fsw._addPathCloser(path6, closer);
301810
302114
  return false;
301811
302115
  } catch (error) {
301812
302116
  if (this.fsw._handleError(error)) {
301813
302117
  ready();
301814
- return path5;
302118
+ return path6;
301815
302119
  }
301816
302120
  }
301817
302121
  }
@@ -301855,26 +302159,26 @@ function createPattern(matcher) {
301855
302159
  }
301856
302160
  return () => false;
301857
302161
  }
301858
- function normalizePath(path5) {
301859
- if (typeof path5 !== "string")
302162
+ function normalizePath(path6) {
302163
+ if (typeof path6 !== "string")
301860
302164
  throw new Error("string expected");
301861
- path5 = sysPath2.normalize(path5);
301862
- path5 = path5.replace(/\\/g, "/");
302165
+ path6 = sysPath2.normalize(path6);
302166
+ path6 = path6.replace(/\\/g, "/");
301863
302167
  let prepend = false;
301864
- if (path5.startsWith("//"))
302168
+ if (path6.startsWith("//"))
301865
302169
  prepend = true;
301866
302170
  const DOUBLE_SLASH_RE2 = /\/\//;
301867
- while (path5.match(DOUBLE_SLASH_RE2))
301868
- path5 = path5.replace(DOUBLE_SLASH_RE2, "/");
302171
+ while (path6.match(DOUBLE_SLASH_RE2))
302172
+ path6 = path6.replace(DOUBLE_SLASH_RE2, "/");
301869
302173
  if (prepend)
301870
- path5 = "/" + path5;
301871
- return path5;
302174
+ path6 = "/" + path6;
302175
+ return path6;
301872
302176
  }
301873
302177
  function matchPatterns(patterns, testString, stats) {
301874
- const path5 = normalizePath(testString);
302178
+ const path6 = normalizePath(testString);
301875
302179
  for (let index = 0;index < patterns.length; index++) {
301876
302180
  const pattern = patterns[index];
301877
- if (pattern(path5, stats)) {
302181
+ if (pattern(path6, stats)) {
301878
302182
  return true;
301879
302183
  }
301880
302184
  }
@@ -301914,19 +302218,19 @@ var toUnix = (string) => {
301914
302218
  }
301915
302219
  return str;
301916
302220
  };
301917
- var normalizePathToUnix = (path5) => toUnix(sysPath2.normalize(toUnix(path5)));
301918
- var normalizeIgnored = (cwd = "") => (path5) => {
301919
- if (typeof path5 === "string") {
301920
- return normalizePathToUnix(sysPath2.isAbsolute(path5) ? path5 : sysPath2.join(cwd, path5));
302221
+ var normalizePathToUnix = (path6) => toUnix(sysPath2.normalize(toUnix(path6)));
302222
+ var normalizeIgnored = (cwd = "") => (path6) => {
302223
+ if (typeof path6 === "string") {
302224
+ return normalizePathToUnix(sysPath2.isAbsolute(path6) ? path6 : sysPath2.join(cwd, path6));
301921
302225
  } else {
301922
- return path5;
302226
+ return path6;
301923
302227
  }
301924
302228
  };
301925
- var getAbsolutePath = (path5, cwd) => {
301926
- if (sysPath2.isAbsolute(path5)) {
301927
- return path5;
302229
+ var getAbsolutePath = (path6, cwd) => {
302230
+ if (sysPath2.isAbsolute(path6)) {
302231
+ return path6;
301928
302232
  }
301929
- return sysPath2.join(cwd, path5);
302233
+ return sysPath2.join(cwd, path6);
301930
302234
  };
301931
302235
  var EMPTY_SET = Object.freeze(new Set);
301932
302236
 
@@ -301983,10 +302287,10 @@ var STAT_METHOD_F = "stat";
301983
302287
  var STAT_METHOD_L = "lstat";
301984
302288
 
301985
302289
  class WatchHelper {
301986
- constructor(path5, follow, fsw) {
302290
+ constructor(path6, follow, fsw) {
301987
302291
  this.fsw = fsw;
301988
- const watchPath = path5;
301989
- this.path = path5 = path5.replace(REPLACER_RE, "");
302292
+ const watchPath = path6;
302293
+ this.path = path6 = path6.replace(REPLACER_RE, "");
301990
302294
  this.watchPath = watchPath;
301991
302295
  this.fullWatchPath = sysPath2.resolve(watchPath);
301992
302296
  this.dirParts = [];
@@ -302099,20 +302403,20 @@ class FSWatcher extends EventEmitter2 {
302099
302403
  this._closePromise = undefined;
302100
302404
  let paths = unifyPaths(paths_);
302101
302405
  if (cwd) {
302102
- paths = paths.map((path5) => {
302103
- const absPath = getAbsolutePath(path5, cwd);
302406
+ paths = paths.map((path6) => {
302407
+ const absPath = getAbsolutePath(path6, cwd);
302104
302408
  return absPath;
302105
302409
  });
302106
302410
  }
302107
- paths.forEach((path5) => {
302108
- this._removeIgnoredPath(path5);
302411
+ paths.forEach((path6) => {
302412
+ this._removeIgnoredPath(path6);
302109
302413
  });
302110
302414
  this._userIgnored = undefined;
302111
302415
  if (!this._readyCount)
302112
302416
  this._readyCount = 0;
302113
302417
  this._readyCount += paths.length;
302114
- Promise.all(paths.map(async (path5) => {
302115
- const res = await this._nodeFsHandler._addToNodeFs(path5, !_internal, undefined, 0, _origAdd);
302418
+ Promise.all(paths.map(async (path6) => {
302419
+ const res = await this._nodeFsHandler._addToNodeFs(path6, !_internal, undefined, 0, _origAdd);
302116
302420
  if (res)
302117
302421
  this._emitReady();
302118
302422
  return res;
@@ -302131,17 +302435,17 @@ class FSWatcher extends EventEmitter2 {
302131
302435
  return this;
302132
302436
  const paths = unifyPaths(paths_);
302133
302437
  const { cwd } = this.options;
302134
- paths.forEach((path5) => {
302135
- if (!sysPath2.isAbsolute(path5) && !this._closers.has(path5)) {
302438
+ paths.forEach((path6) => {
302439
+ if (!sysPath2.isAbsolute(path6) && !this._closers.has(path6)) {
302136
302440
  if (cwd)
302137
- path5 = sysPath2.join(cwd, path5);
302138
- path5 = sysPath2.resolve(path5);
302441
+ path6 = sysPath2.join(cwd, path6);
302442
+ path6 = sysPath2.resolve(path6);
302139
302443
  }
302140
- this._closePath(path5);
302141
- this._addIgnoredPath(path5);
302142
- if (this._watched.has(path5)) {
302444
+ this._closePath(path6);
302445
+ this._addIgnoredPath(path6);
302446
+ if (this._watched.has(path6)) {
302143
302447
  this._addIgnoredPath({
302144
- path: path5,
302448
+ path: path6,
302145
302449
  recursive: true
302146
302450
  });
302147
302451
  }
@@ -302190,38 +302494,38 @@ class FSWatcher extends EventEmitter2 {
302190
302494
  if (event !== EVENTS.ERROR)
302191
302495
  this.emit(EVENTS.ALL, event, ...args);
302192
302496
  }
302193
- async _emit(event, path5, stats) {
302497
+ async _emit(event, path6, stats) {
302194
302498
  if (this.closed)
302195
302499
  return;
302196
302500
  const opts = this.options;
302197
302501
  if (isWindows)
302198
- path5 = sysPath2.normalize(path5);
302502
+ path6 = sysPath2.normalize(path6);
302199
302503
  if (opts.cwd)
302200
- path5 = sysPath2.relative(opts.cwd, path5);
302201
- const args = [path5];
302504
+ path6 = sysPath2.relative(opts.cwd, path6);
302505
+ const args = [path6];
302202
302506
  if (stats != null)
302203
302507
  args.push(stats);
302204
302508
  const awf = opts.awaitWriteFinish;
302205
302509
  let pw;
302206
- if (awf && (pw = this._pendingWrites.get(path5))) {
302510
+ if (awf && (pw = this._pendingWrites.get(path6))) {
302207
302511
  pw.lastChange = new Date;
302208
302512
  return this;
302209
302513
  }
302210
302514
  if (opts.atomic) {
302211
302515
  if (event === EVENTS.UNLINK) {
302212
- this._pendingUnlinks.set(path5, [event, ...args]);
302516
+ this._pendingUnlinks.set(path6, [event, ...args]);
302213
302517
  setTimeout(() => {
302214
- this._pendingUnlinks.forEach((entry, path6) => {
302518
+ this._pendingUnlinks.forEach((entry, path7) => {
302215
302519
  this.emit(...entry);
302216
302520
  this.emit(EVENTS.ALL, ...entry);
302217
- this._pendingUnlinks.delete(path6);
302521
+ this._pendingUnlinks.delete(path7);
302218
302522
  });
302219
302523
  }, typeof opts.atomic === "number" ? opts.atomic : 100);
302220
302524
  return this;
302221
302525
  }
302222
- if (event === EVENTS.ADD && this._pendingUnlinks.has(path5)) {
302526
+ if (event === EVENTS.ADD && this._pendingUnlinks.has(path6)) {
302223
302527
  event = EVENTS.CHANGE;
302224
- this._pendingUnlinks.delete(path5);
302528
+ this._pendingUnlinks.delete(path6);
302225
302529
  }
302226
302530
  }
302227
302531
  if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
@@ -302239,16 +302543,16 @@ class FSWatcher extends EventEmitter2 {
302239
302543
  this.emitWithAll(event, args);
302240
302544
  }
302241
302545
  };
302242
- this._awaitWriteFinish(path5, awf.stabilityThreshold, event, awfEmit);
302546
+ this._awaitWriteFinish(path6, awf.stabilityThreshold, event, awfEmit);
302243
302547
  return this;
302244
302548
  }
302245
302549
  if (event === EVENTS.CHANGE) {
302246
- const isThrottled = !this._throttle(EVENTS.CHANGE, path5, 50);
302550
+ const isThrottled = !this._throttle(EVENTS.CHANGE, path6, 50);
302247
302551
  if (isThrottled)
302248
302552
  return this;
302249
302553
  }
302250
302554
  if (opts.alwaysStat && stats === undefined && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
302251
- const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path5) : path5;
302555
+ const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path6) : path6;
302252
302556
  let stats2;
302253
302557
  try {
302254
302558
  stats2 = await stat3(fullPath);
@@ -302267,23 +302571,23 @@ class FSWatcher extends EventEmitter2 {
302267
302571
  }
302268
302572
  return error || this.closed;
302269
302573
  }
302270
- _throttle(actionType, path5, timeout) {
302574
+ _throttle(actionType, path6, timeout) {
302271
302575
  if (!this._throttled.has(actionType)) {
302272
302576
  this._throttled.set(actionType, new Map);
302273
302577
  }
302274
302578
  const action = this._throttled.get(actionType);
302275
302579
  if (!action)
302276
302580
  throw new Error("invalid throttle");
302277
- const actionPath = action.get(path5);
302581
+ const actionPath = action.get(path6);
302278
302582
  if (actionPath) {
302279
302583
  actionPath.count++;
302280
302584
  return false;
302281
302585
  }
302282
302586
  let timeoutObject;
302283
302587
  const clear = () => {
302284
- const item = action.get(path5);
302588
+ const item = action.get(path6);
302285
302589
  const count = item ? item.count : 0;
302286
- action.delete(path5);
302590
+ action.delete(path6);
302287
302591
  clearTimeout(timeoutObject);
302288
302592
  if (item)
302289
302593
  clearTimeout(item.timeoutObject);
@@ -302291,50 +302595,50 @@ class FSWatcher extends EventEmitter2 {
302291
302595
  };
302292
302596
  timeoutObject = setTimeout(clear, timeout);
302293
302597
  const thr = { timeoutObject, clear, count: 0 };
302294
- action.set(path5, thr);
302598
+ action.set(path6, thr);
302295
302599
  return thr;
302296
302600
  }
302297
302601
  _incrReadyCount() {
302298
302602
  return this._readyCount++;
302299
302603
  }
302300
- _awaitWriteFinish(path5, threshold, event, awfEmit) {
302604
+ _awaitWriteFinish(path6, threshold, event, awfEmit) {
302301
302605
  const awf = this.options.awaitWriteFinish;
302302
302606
  if (typeof awf !== "object")
302303
302607
  return;
302304
302608
  const pollInterval = awf.pollInterval;
302305
302609
  let timeoutHandler;
302306
- let fullPath = path5;
302307
- if (this.options.cwd && !sysPath2.isAbsolute(path5)) {
302308
- fullPath = sysPath2.join(this.options.cwd, path5);
302610
+ let fullPath = path6;
302611
+ if (this.options.cwd && !sysPath2.isAbsolute(path6)) {
302612
+ fullPath = sysPath2.join(this.options.cwd, path6);
302309
302613
  }
302310
302614
  const now = new Date;
302311
302615
  const writes = this._pendingWrites;
302312
302616
  function awaitWriteFinishFn(prevStat) {
302313
302617
  statcb(fullPath, (err, curStat) => {
302314
- if (err || !writes.has(path5)) {
302618
+ if (err || !writes.has(path6)) {
302315
302619
  if (err && err.code !== "ENOENT")
302316
302620
  awfEmit(err);
302317
302621
  return;
302318
302622
  }
302319
302623
  const now2 = Number(new Date);
302320
302624
  if (prevStat && curStat.size !== prevStat.size) {
302321
- writes.get(path5).lastChange = now2;
302625
+ writes.get(path6).lastChange = now2;
302322
302626
  }
302323
- const pw = writes.get(path5);
302627
+ const pw = writes.get(path6);
302324
302628
  const df = now2 - pw.lastChange;
302325
302629
  if (df >= threshold) {
302326
- writes.delete(path5);
302630
+ writes.delete(path6);
302327
302631
  awfEmit(undefined, curStat);
302328
302632
  } else {
302329
302633
  timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
302330
302634
  }
302331
302635
  });
302332
302636
  }
302333
- if (!writes.has(path5)) {
302334
- writes.set(path5, {
302637
+ if (!writes.has(path6)) {
302638
+ writes.set(path6, {
302335
302639
  lastChange: now,
302336
302640
  cancelWait: () => {
302337
- writes.delete(path5);
302641
+ writes.delete(path6);
302338
302642
  clearTimeout(timeoutHandler);
302339
302643
  return event;
302340
302644
  }
@@ -302342,8 +302646,8 @@ class FSWatcher extends EventEmitter2 {
302342
302646
  timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval);
302343
302647
  }
302344
302648
  }
302345
- _isIgnored(path5, stats) {
302346
- if (this.options.atomic && DOT_RE.test(path5))
302649
+ _isIgnored(path6, stats) {
302650
+ if (this.options.atomic && DOT_RE.test(path6))
302347
302651
  return true;
302348
302652
  if (!this._userIgnored) {
302349
302653
  const { cwd } = this.options;
@@ -302353,13 +302657,13 @@ class FSWatcher extends EventEmitter2 {
302353
302657
  const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
302354
302658
  this._userIgnored = anymatch(list, undefined);
302355
302659
  }
302356
- return this._userIgnored(path5, stats);
302660
+ return this._userIgnored(path6, stats);
302357
302661
  }
302358
- _isntIgnored(path5, stat4) {
302359
- return !this._isIgnored(path5, stat4);
302662
+ _isntIgnored(path6, stat4) {
302663
+ return !this._isIgnored(path6, stat4);
302360
302664
  }
302361
- _getWatchHelpers(path5) {
302362
- return new WatchHelper(path5, this.options.followSymlinks, this);
302665
+ _getWatchHelpers(path6) {
302666
+ return new WatchHelper(path6, this.options.followSymlinks, this);
302363
302667
  }
302364
302668
  _getWatchedDir(directory) {
302365
302669
  const dir = sysPath2.resolve(directory);
@@ -302373,57 +302677,57 @@ class FSWatcher extends EventEmitter2 {
302373
302677
  return Boolean(Number(stats.mode) & 256);
302374
302678
  }
302375
302679
  _remove(directory, item, isDirectory) {
302376
- const path5 = sysPath2.join(directory, item);
302377
- const fullPath = sysPath2.resolve(path5);
302378
- isDirectory = isDirectory != null ? isDirectory : this._watched.has(path5) || this._watched.has(fullPath);
302379
- if (!this._throttle("remove", path5, 100))
302680
+ const path6 = sysPath2.join(directory, item);
302681
+ const fullPath = sysPath2.resolve(path6);
302682
+ isDirectory = isDirectory != null ? isDirectory : this._watched.has(path6) || this._watched.has(fullPath);
302683
+ if (!this._throttle("remove", path6, 100))
302380
302684
  return;
302381
302685
  if (!isDirectory && this._watched.size === 1) {
302382
302686
  this.add(directory, item, true);
302383
302687
  }
302384
- const wp = this._getWatchedDir(path5);
302688
+ const wp = this._getWatchedDir(path6);
302385
302689
  const nestedDirectoryChildren = wp.getChildren();
302386
- nestedDirectoryChildren.forEach((nested) => this._remove(path5, nested));
302690
+ nestedDirectoryChildren.forEach((nested) => this._remove(path6, nested));
302387
302691
  const parent = this._getWatchedDir(directory);
302388
302692
  const wasTracked = parent.has(item);
302389
302693
  parent.remove(item);
302390
302694
  if (this._symlinkPaths.has(fullPath)) {
302391
302695
  this._symlinkPaths.delete(fullPath);
302392
302696
  }
302393
- let relPath = path5;
302697
+ let relPath = path6;
302394
302698
  if (this.options.cwd)
302395
- relPath = sysPath2.relative(this.options.cwd, path5);
302699
+ relPath = sysPath2.relative(this.options.cwd, path6);
302396
302700
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
302397
302701
  const event = this._pendingWrites.get(relPath).cancelWait();
302398
302702
  if (event === EVENTS.ADD)
302399
302703
  return;
302400
302704
  }
302401
- this._watched.delete(path5);
302705
+ this._watched.delete(path6);
302402
302706
  this._watched.delete(fullPath);
302403
302707
  const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
302404
- if (wasTracked && !this._isIgnored(path5))
302405
- this._emit(eventName, path5);
302406
- this._closePath(path5);
302708
+ if (wasTracked && !this._isIgnored(path6))
302709
+ this._emit(eventName, path6);
302710
+ this._closePath(path6);
302407
302711
  }
302408
- _closePath(path5) {
302409
- this._closeFile(path5);
302410
- const dir = sysPath2.dirname(path5);
302411
- this._getWatchedDir(dir).remove(sysPath2.basename(path5));
302712
+ _closePath(path6) {
302713
+ this._closeFile(path6);
302714
+ const dir = sysPath2.dirname(path6);
302715
+ this._getWatchedDir(dir).remove(sysPath2.basename(path6));
302412
302716
  }
302413
- _closeFile(path5) {
302414
- const closers = this._closers.get(path5);
302717
+ _closeFile(path6) {
302718
+ const closers = this._closers.get(path6);
302415
302719
  if (!closers)
302416
302720
  return;
302417
302721
  closers.forEach((closer) => closer());
302418
- this._closers.delete(path5);
302722
+ this._closers.delete(path6);
302419
302723
  }
302420
- _addPathCloser(path5, closer) {
302724
+ _addPathCloser(path6, closer) {
302421
302725
  if (!closer)
302422
302726
  return;
302423
- let list = this._closers.get(path5);
302727
+ let list = this._closers.get(path6);
302424
302728
  if (!list) {
302425
302729
  list = [];
302426
- this._closers.set(path5, list);
302730
+ this._closers.set(path6, list);
302427
302731
  }
302428
302732
  list.push(closer);
302429
302733
  }
@@ -302457,7 +302761,7 @@ init_errors();
302457
302761
  init_logger();
302458
302762
  init_path_safety();
302459
302763
  import { EventEmitter as EventEmitter4 } from "events";
302460
- import path12 from "path";
302764
+ import path13 from "path";
302461
302765
 
302462
302766
  // src/service/environment_store.ts
302463
302767
  var import_client_s33 = __toESM(require_dist_cjs75(), 1);
@@ -302465,8 +302769,8 @@ import { Storage as Storage2 } from "@google-cloud/storage";
302465
302769
  var import_extract_zip = __toESM(require_extract_zip(), 1);
302466
302770
  import crypto5 from "crypto";
302467
302771
  import * as fs9 from "fs";
302468
- import * as os2 from "os";
302469
- import * as path11 from "path";
302772
+ import * as os3 from "os";
302773
+ import * as path12 from "path";
302470
302774
 
302471
302775
  // ../../node_modules/simple-git/dist/esm/index.js
302472
302776
  var import_file_exists = __toESM(require_dist12(), 1);
@@ -302504,8 +302808,8 @@ function pathspec(...paths) {
302504
302808
  cache.set(key, paths);
302505
302809
  return key;
302506
302810
  }
302507
- function isPathSpec(path5) {
302508
- return path5 instanceof String && cache.has(path5);
302811
+ function isPathSpec(path6) {
302812
+ return path6 instanceof String && cache.has(path6);
302509
302813
  }
302510
302814
  function toPaths(pathSpec) {
302511
302815
  return cache.get(pathSpec) || [];
@@ -302591,8 +302895,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = `
302591
302895
  function forEachLineWithContent(input, callback) {
302592
302896
  return toLinesWithContent(input, true).map((line) => callback(line));
302593
302897
  }
302594
- function folderExists(path5) {
302595
- return import_file_exists.exists(path5, import_file_exists.FOLDER);
302898
+ function folderExists(path6) {
302899
+ return import_file_exists.exists(path6, import_file_exists.FOLDER);
302596
302900
  }
302597
302901
  function append2(target, item) {
302598
302902
  if (Array.isArray(target)) {
@@ -302973,8 +303277,8 @@ function checkIsRepoRootTask() {
302973
303277
  commands,
302974
303278
  format: "utf-8",
302975
303279
  onError,
302976
- parser(path5) {
302977
- return /^\.(git)?$/.test(path5.trim());
303280
+ parser(path6) {
303281
+ return /^\.(git)?$/.test(path6.trim());
302978
303282
  }
302979
303283
  };
302980
303284
  }
@@ -303385,11 +303689,11 @@ function parseGrep(grep) {
303385
303689
  const paths = /* @__PURE__ */ new Set;
303386
303690
  const results = {};
303387
303691
  forEachLineWithContent(grep, (input) => {
303388
- const [path5, line, preview] = input.split(NULL);
303389
- paths.add(path5);
303390
- (results[path5] = results[path5] || []).push({
303692
+ const [path6, line, preview] = input.split(NULL);
303693
+ paths.add(path6);
303694
+ (results[path6] = results[path6] || []).push({
303391
303695
  line: asNumber(line),
303392
- path: path5,
303696
+ path: path6,
303393
303697
  preview
303394
303698
  });
303395
303699
  });
@@ -304051,14 +304355,14 @@ var init_hash_object = __esm2({
304051
304355
  init_task();
304052
304356
  }
304053
304357
  });
304054
- function parseInit(bare, path5, text) {
304358
+ function parseInit(bare, path6, text) {
304055
304359
  const response = String(text).trim();
304056
304360
  let result;
304057
304361
  if (result = initResponseRegex.exec(response)) {
304058
- return new InitSummary(bare, path5, false, result[1]);
304362
+ return new InitSummary(bare, path6, false, result[1]);
304059
304363
  }
304060
304364
  if (result = reInitResponseRegex.exec(response)) {
304061
- return new InitSummary(bare, path5, true, result[1]);
304365
+ return new InitSummary(bare, path6, true, result[1]);
304062
304366
  }
304063
304367
  let gitDir = "";
304064
304368
  const tokens = response.split(" ");
@@ -304069,7 +304373,7 @@ function parseInit(bare, path5, text) {
304069
304373
  break;
304070
304374
  }
304071
304375
  }
304072
- return new InitSummary(bare, path5, /^re/i.test(response), gitDir);
304376
+ return new InitSummary(bare, path6, /^re/i.test(response), gitDir);
304073
304377
  }
304074
304378
  var InitSummary;
304075
304379
  var initResponseRegex;
@@ -304077,9 +304381,9 @@ var reInitResponseRegex;
304077
304381
  var init_InitSummary = __esm2({
304078
304382
  "src/lib/responses/InitSummary.ts"() {
304079
304383
  InitSummary = class {
304080
- constructor(bare, path5, existing, gitDir) {
304384
+ constructor(bare, path6, existing, gitDir) {
304081
304385
  this.bare = bare;
304082
- this.path = path5;
304386
+ this.path = path6;
304083
304387
  this.existing = existing;
304084
304388
  this.gitDir = gitDir;
304085
304389
  }
@@ -304091,7 +304395,7 @@ var init_InitSummary = __esm2({
304091
304395
  function hasBareCommand(command) {
304092
304396
  return command.includes(bareCommand);
304093
304397
  }
304094
- function initTask(bare = false, path5, customArgs) {
304398
+ function initTask(bare = false, path6, customArgs) {
304095
304399
  const commands = ["init", ...customArgs];
304096
304400
  if (bare && !hasBareCommand(commands)) {
304097
304401
  commands.splice(1, 0, bareCommand);
@@ -304100,7 +304404,7 @@ function initTask(bare = false, path5, customArgs) {
304100
304404
  commands,
304101
304405
  format: "utf-8",
304102
304406
  parser(text) {
304103
- return parseInit(commands.includes("--bare"), path5, text);
304407
+ return parseInit(commands.includes("--bare"), path6, text);
304104
304408
  }
304105
304409
  };
304106
304410
  }
@@ -304815,12 +305119,12 @@ var init_FileStatusSummary = __esm2({
304815
305119
  "src/lib/responses/FileStatusSummary.ts"() {
304816
305120
  fromPathRegex = /^(.+)\0(.+)$/;
304817
305121
  FileStatusSummary = class {
304818
- constructor(path5, index, working_dir) {
304819
- this.path = path5;
305122
+ constructor(path6, index, working_dir) {
305123
+ this.path = path6;
304820
305124
  this.index = index;
304821
305125
  this.working_dir = working_dir;
304822
305126
  if (index === "R" || working_dir === "R") {
304823
- const detail = fromPathRegex.exec(path5) || [null, path5, path5];
305127
+ const detail = fromPathRegex.exec(path6) || [null, path6, path6];
304824
305128
  this.from = detail[2] || "";
304825
305129
  this.path = detail[1] || "";
304826
305130
  }
@@ -304851,14 +305155,14 @@ function splitLine(result, lineStr) {
304851
305155
  default:
304852
305156
  return;
304853
305157
  }
304854
- function data(index, workingDir, path5) {
305158
+ function data(index, workingDir, path6) {
304855
305159
  const raw = `${index}${workingDir}`;
304856
305160
  const handler = parsers6.get(raw);
304857
305161
  if (handler) {
304858
- handler(result, path5);
305162
+ handler(result, path6);
304859
305163
  }
304860
305164
  if (raw !== "##" && raw !== "!!") {
304861
- result.files.push(new FileStatusSummary(path5, index, workingDir));
305165
+ result.files.push(new FileStatusSummary(path6, index, workingDir));
304862
305166
  }
304863
305167
  }
304864
305168
  }
@@ -305089,8 +305393,8 @@ var init_simple_git_api = __esm2({
305089
305393
  }
305090
305394
  return this._runTask(configurationErrorTask("Git.cwd: workingDirectory must be supplied as a string"), next);
305091
305395
  }
305092
- hashObject(path5, write) {
305093
- return this._runTask(hashObjectTask(path5, write === true), trailingFunctionArgument(arguments));
305396
+ hashObject(path6, write) {
305397
+ return this._runTask(hashObjectTask(path6, write === true), trailingFunctionArgument(arguments));
305094
305398
  }
305095
305399
  init(bare) {
305096
305400
  return this._runTask(initTask(bare === true, this._executor.cwd, getTrailingOptions(arguments)), trailingFunctionArgument(arguments));
@@ -305667,8 +305971,8 @@ __export2(sub_module_exports, {
305667
305971
  subModuleTask: () => subModuleTask,
305668
305972
  updateSubModuleTask: () => updateSubModuleTask
305669
305973
  });
305670
- function addSubModuleTask(repo, path5) {
305671
- return subModuleTask(["add", repo, path5]);
305974
+ function addSubModuleTask(repo, path6) {
305975
+ return subModuleTask(["add", repo, path6]);
305672
305976
  }
305673
305977
  function initSubModuleTask(customArgs) {
305674
305978
  return subModuleTask(["init", ...customArgs]);
@@ -305936,8 +306240,8 @@ var require_git = __commonJS2({
305936
306240
  }
305937
306241
  return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
305938
306242
  };
305939
- Git2.prototype.submoduleAdd = function(repo, path5, then) {
305940
- return this._runTask(addSubModuleTask2(repo, path5), trailingFunctionArgument2(arguments));
306243
+ Git2.prototype.submoduleAdd = function(repo, path6, then) {
306244
+ return this._runTask(addSubModuleTask2(repo, path6), trailingFunctionArgument2(arguments));
305941
306245
  };
305942
306246
  Git2.prototype.submoduleUpdate = function(args, then) {
305943
306247
  return this._runTask(updateSubModuleTask2(getTrailingOptions2(arguments, true)), trailingFunctionArgument2(arguments));
@@ -306570,7 +306874,7 @@ init_config();
306570
306874
  import {
306571
306875
  DuckDBInstance
306572
306876
  } from "@duckdb/node-api";
306573
- import * as path5 from "path";
306877
+ import * as path6 from "path";
306574
306878
  function duckDBInstanceResourceOptions() {
306575
306879
  const options = {};
306576
306880
  const memoryLimit = getDuckDBMemoryLimit();
@@ -306590,7 +306894,7 @@ class DuckDBConnection2 {
306590
306894
  dbPath;
306591
306895
  mutex = new Mutex;
306592
306896
  constructor(dbPath) {
306593
- this.dbPath = dbPath || path5.join(process.cwd(), "publisher.db");
306897
+ this.dbPath = dbPath || path6.join(process.cwd(), "publisher.db");
306594
306898
  }
306595
306899
  async initialize() {
306596
306900
  try {
@@ -307051,7 +307355,6 @@ var ACTIVE_STATUSES = [
307051
307355
  function activeKeyFor(environmentId, packageName) {
307052
307356
  return `${environmentId}|${packageName}`;
307053
307357
  }
307054
- var DEFAULT_ENVIRONMENT_LIST_LIMIT = 500;
307055
307358
 
307056
307359
  class DuplicateActiveMaterializationError extends Error {
307057
307360
  constructor(environmentId, packageName) {
@@ -307084,18 +307387,6 @@ class MaterializationRepository {
307084
307387
  const rows = await this.db.all(sql, params);
307085
307388
  return rows.map(this.mapRow);
307086
307389
  }
307087
- async listByEnvironment(environmentId, options) {
307088
- let sql = "SELECT * FROM materializations WHERE environment_id = ? ORDER BY created_at DESC";
307089
- const params = [environmentId];
307090
- sql += " LIMIT ?";
307091
- params.push(options?.limit ?? DEFAULT_ENVIRONMENT_LIST_LIMIT);
307092
- if (options?.offset !== undefined) {
307093
- sql += " OFFSET ?";
307094
- params.push(options.offset);
307095
- }
307096
- const rows = await this.db.all(sql, params);
307097
- return rows.map(this.mapRow);
307098
- }
307099
307390
  async getLatestScheduledFireAt(environmentId, packageName) {
307100
307391
  const row = await this.db.get(`SELECT created_at FROM materializations
307101
307392
  WHERE environment_id = ? AND package_name = ?
@@ -307426,9 +307717,6 @@ class DuckDBRepository {
307426
307717
  async listMaterializations(environmentId, packageName, options) {
307427
307718
  return this.materializationRepo.list(environmentId, packageName, options);
307428
307719
  }
307429
- async listMaterializationsByEnvironment(environmentId, options) {
307430
- return this.materializationRepo.listByEnvironment(environmentId, options);
307431
- }
307432
307720
  async getLatestScheduledFireAt(environmentId, packageName) {
307433
307721
  return this.materializationRepo.getLatestScheduledFireAt(environmentId, packageName);
307434
307722
  }
@@ -307899,7 +308187,7 @@ init_config();
307899
308187
  init_logger();
307900
308188
  import crypto4 from "crypto";
307901
308189
  import * as fs8 from "fs";
307902
- import * as path10 from "path";
308190
+ import * as path11 from "path";
307903
308191
  import { fileURLToPath as fileURLToPath6, pathToFileURL as pathToFileURL2 } from "url";
307904
308192
  init_materialization_metrics();
307905
308193
  init_path_safety();
@@ -308009,7 +308297,7 @@ init_logger();
308009
308297
  init_materialization_metrics();
308010
308298
  var import_recursive_readdir = __toESM(require_recursive_readdir(), 1);
308011
308299
  import * as fs7 from "fs/promises";
308012
- import * as path9 from "path";
308300
+ import * as path10 from "path";
308013
308301
  import"@malloydata/db-duckdb/native";
308014
308302
  import { DuckDBConnection as DuckDBConnection3 } from "@malloydata/db-duckdb";
308015
308303
  import {
@@ -309123,7 +309411,7 @@ class Package {
309123
309411
  });
309124
309412
  }
309125
309413
  if (sm.modelPath.endsWith(MODEL_FILE_SUFFIX)) {
309126
- const modelSource = await fs7.readFile(path9.join(packagePath, sm.modelPath), "utf-8");
309414
+ const modelSource = await fs7.readFile(path10.join(packagePath, sm.modelPath), "utf-8");
309127
309415
  assertPersistNamesQuoted(modelSource, sm.modelPath);
309128
309416
  }
309129
309417
  models.set(sm.modelPath, model);
@@ -310128,16 +310416,16 @@ class Package {
310128
310416
  static async getDatabasePaths(packagePath) {
310129
310417
  const files = await import_recursive_readdir.default(packagePath, [ignoreDotfiles]);
310130
310418
  return files.map((fullPath) => {
310131
- return path9.relative(packagePath, fullPath).replace(/\\/g, "/");
310419
+ return path10.relative(packagePath, fullPath).replace(/\\/g, "/");
310132
310420
  }).filter((modelPath) => {
310133
- if (path9.basename(modelPath).startsWith("~$")) {
310421
+ if (path10.basename(modelPath).startsWith("~$")) {
310134
310422
  return false;
310135
310423
  }
310136
310424
  return modelPath.endsWith(".parquet") || modelPath.endsWith(".csv") || modelPath.endsWith(".xlsx");
310137
310425
  });
310138
310426
  }
310139
310427
  static async getDatabaseInfo(packagePath, databasePath, conn) {
310140
- const fullPath = path9.join(packagePath, databasePath);
310428
+ const fullPath = path10.join(packagePath, databasePath);
310141
310429
  const runtime = new ConnectionRuntime({
310142
310430
  urlReader: new EmptyURLReader,
310143
310431
  connections: [conn]
@@ -310251,7 +310539,7 @@ class Environment {
310251
310539
  async writeEnvironmentReadme(readme) {
310252
310540
  if (readme === undefined)
310253
310541
  return;
310254
- const readmePath = path10.join(this.environmentPath, "README.md");
310542
+ const readmePath = path11.join(this.environmentPath, "README.md");
310255
310543
  try {
310256
310544
  await fs8.promises.writeFile(readmePath, readme, "utf-8");
310257
310545
  logger.info(`Updated README.md for environment ${this.environmentName}`);
@@ -310345,8 +310633,8 @@ class Environment {
310345
310633
  return this.withPackageLock(packageName, async () => {
310346
310634
  const modelPath = safeJoinUnderRoot(this.environmentPath, packageName, modelName);
310347
310635
  const packagePath = safeJoinUnderRoot(this.environmentPath, packageName);
310348
- const modelDir = path10.dirname(modelPath);
310349
- const virtualUrl = scope === "append" ? pathToFileURL2(path10.join(modelDir, "__compile_check.malloy")) : pathToFileURL2(modelPath);
310636
+ const modelDir = path11.dirname(modelPath);
310637
+ const virtualUrl = scope === "append" ? pathToFileURL2(path11.join(modelDir, "__compile_check.malloy")) : pathToFileURL2(modelPath);
310350
310638
  const virtualUri = virtualUrl.toString();
310351
310639
  let fullSource = source ?? "";
310352
310640
  if (scope === "append") {
@@ -310395,8 +310683,8 @@ ${source}` : source ?? "";
310395
310683
  let model;
310396
310684
  if (url2 && url2.startsWith("file:")) {
310397
310685
  try {
310398
- const rel = path10.relative(packagePath, fileURLToPath6(url2));
310399
- if (!rel.startsWith("..") && !path10.isAbsolute(rel)) {
310686
+ const rel = path11.relative(packagePath, fileURLToPath6(url2));
310687
+ if (!rel.startsWith("..") && !path11.isAbsolute(rel)) {
310400
310688
  model = rel;
310401
310689
  }
310402
310690
  } catch {}
@@ -310683,6 +310971,49 @@ ${source}` : source ?? "";
310683
310971
  assertSafePackageName(packageName);
310684
310972
  return this.getOrCreatePackageMutex(packageName).runExclusive(fn);
310685
310973
  }
310974
+ async _readModelFileLocked(target) {
310975
+ try {
310976
+ return await fs8.promises.readFile(target, "utf8");
310977
+ } catch (error) {
310978
+ if (error.code !== "ENOENT")
310979
+ throw error;
310980
+ return;
310981
+ }
310982
+ }
310983
+ async _writeModelFileLocked(target, source) {
310984
+ await fs8.promises.mkdir(path11.dirname(target), { recursive: true });
310985
+ const temporary = `${target}.${crypto4.randomUUID()}.tmp`;
310986
+ await fs8.promises.writeFile(temporary, source, "utf8");
310987
+ await fs8.promises.rename(temporary, target);
310988
+ }
310989
+ async writeModelFileTransactional(packageName, modelPath, source, check, verify) {
310990
+ assertSafePackageName(packageName);
310991
+ assertSafeRelativeModelPath(modelPath);
310992
+ return this.withPackageLock(packageName, async () => {
310993
+ const target = safeJoinUnderRoot(this.environmentPath, packageName, modelPath);
310994
+ const previous = await this._readModelFileLocked(target);
310995
+ check(previous);
310996
+ await this._writeModelFileLocked(target, source);
310997
+ try {
310998
+ const reloaded = await this._loadOrGetPackageLocked(packageName, true);
310999
+ return { previous, verified: await verify(reloaded) };
311000
+ } catch (error) {
311001
+ if (previous !== undefined)
311002
+ await this._writeModelFileLocked(target, previous);
311003
+ else
311004
+ await fs8.promises.rm(target, { force: true });
311005
+ await this._loadOrGetPackageLocked(packageName, true).catch(() => {
311006
+ return;
311007
+ });
311008
+ logger.warn("Dashboard write rolled back", {
311009
+ packageName,
311010
+ modelPath,
311011
+ error
311012
+ });
311013
+ throw new WriteRolledBackError(`The package did not reload with the new \`${modelPath}\`, so ` + `the previous text was put back and nothing changed.`);
311014
+ }
311015
+ });
311016
+ }
310686
311017
  allocateStagingPath(packageName) {
310687
311018
  return safeJoinUnderRoot(this.environmentPath, STAGING_DIR_NAME, `${packageName}-${crypto4.randomUUID()}`);
310688
311019
  }
@@ -310695,7 +311026,7 @@ ${source}` : source ?? "";
310695
311026
  const dir = safeJoinUnderRoot(environmentPath, dirName);
310696
311027
  if (dir.indexOf("..") !== -1)
310697
311028
  continue;
310698
- if (path10.basename(dir) !== dirName)
311029
+ if (path11.basename(dir) !== dirName)
310699
311030
  continue;
310700
311031
  try {
310701
311032
  await fs8.promises.rm(dir, { recursive: true, force: true });
@@ -310835,7 +311166,7 @@ ${source}` : source ?? "";
310835
311166
  async installPackage(packageName, downloader, validate) {
310836
311167
  assertSafePackageName(packageName);
310837
311168
  const stagingPath = this.allocateStagingPath(packageName);
310838
- await fs8.promises.mkdir(path10.dirname(stagingPath), { recursive: true });
311169
+ await fs8.promises.mkdir(path11.dirname(stagingPath), { recursive: true });
310839
311170
  logger.debug("install.phase1.download.started", {
310840
311171
  environmentName: this.environmentName,
310841
311172
  packageName,
@@ -310864,7 +311195,7 @@ ${source}` : source ?? "";
310864
311195
  const oldExistsOnDisk = await fs8.promises.access(canonicalPath).then(() => true).catch(() => false);
310865
311196
  if (oldExistsOnDisk) {
310866
311197
  retiredPath = this.allocateRetiredPath(packageName);
310867
- await fs8.promises.mkdir(path10.dirname(retiredPath), {
311198
+ await fs8.promises.mkdir(path11.dirname(retiredPath), {
310868
311199
  recursive: true
310869
311200
  });
310870
311201
  await fs8.promises.rename(canonicalPath, retiredPath);
@@ -311229,7 +311560,7 @@ ${source}` : source ?? "";
311229
311560
  const retiredPath = this.allocateRetiredPath(packageName);
311230
311561
  let renamed = false;
311231
311562
  try {
311232
- await fs8.promises.mkdir(path10.dirname(retiredPath), {
311563
+ await fs8.promises.mkdir(path11.dirname(retiredPath), {
311233
311564
  recursive: true
311234
311565
  });
311235
311566
  await fs8.promises.rename(canonicalPath, retiredPath);
@@ -311329,7 +311660,7 @@ ${source}` : source ?? "";
311329
311660
  };
311330
311661
  }
311331
311662
  async deleteDuckDBConnection(connectionName) {
311332
- const duckdbPath = path10.join(this.environmentPath, `${connectionName}.duckdb`);
311663
+ const duckdbPath = path11.join(this.environmentPath, `${connectionName}.duckdb`);
311333
311664
  try {
311334
311665
  await fs8.promises.rm(duckdbPath, { force: true });
311335
311666
  logger.info(`Removed DuckDB connection file ${connectionName} from environment ${this.environmentName}`);
@@ -311403,13 +311734,13 @@ async function clearMountTarget(targetPath) {
311403
311734
  function resolvePackageLocation(location, anchorDir, homeDir) {
311404
311735
  let expanded = location;
311405
311736
  if (location.startsWith("~/")) {
311406
- const home = homeDir ?? os2.homedir();
311737
+ const home = homeDir ?? os3.homedir();
311407
311738
  if (!home) {
311408
311739
  throw new Error(`Cannot expand "~" in location "${location}": home directory is not set`);
311409
311740
  }
311410
- expanded = path11.join(home, location.slice(2));
311741
+ expanded = path12.join(home, location.slice(2));
311411
311742
  }
311412
- return path11.isAbsolute(expanded) ? expanded : path11.join(anchorDir, expanded);
311743
+ return path12.isAbsolute(expanded) ? expanded : path12.join(anchorDir, expanded);
311413
311744
  }
311414
311745
  var GIT_CLONE_OPTIONS = {
311415
311746
  "--depth": 1,
@@ -311587,7 +311918,7 @@ class EnvironmentStore {
311587
311918
  const storageConfig = {
311588
311919
  type: "duckdb",
311589
311920
  duckdb: {
311590
- path: path11.join(serverRootPath, "publisher.db")
311921
+ path: path12.join(serverRootPath, "publisher.db")
311591
311922
  }
311592
311923
  };
311593
311924
  this.storageManager = new StorageManager(storageConfig);
@@ -312002,7 +312333,7 @@ class EnvironmentStore {
312002
312333
  const reInit = process.env.INITIALIZE_STORAGE === "true";
312003
312334
  await fs9.promises.mkdir(this.serverRootPath, { recursive: true });
312004
312335
  if (reInit) {
312005
- const uploadDocsPath2 = path11.join(this.serverRootPath, PUBLISHER_DATA_DIR);
312336
+ const uploadDocsPath2 = path12.join(this.serverRootPath, PUBLISHER_DATA_DIR);
312006
312337
  logger.info(`Reinitialization mode: Cleaning up upload documents path ${uploadDocsPath2}`);
312007
312338
  try {
312008
312339
  await fs9.promises.rm(uploadDocsPath2, {
@@ -312019,7 +312350,7 @@ class EnvironmentStore {
312019
312350
  } else {
312020
312351
  logger.info(`Using existing publisher path`);
312021
312352
  }
312022
- const uploadDocsPath = path11.join(this.serverRootPath, PUBLISHER_DATA_DIR);
312353
+ const uploadDocsPath = path12.join(this.serverRootPath, PUBLISHER_DATA_DIR);
312023
312354
  await fs9.promises.mkdir(uploadDocsPath, { recursive: true });
312024
312355
  }
312025
312356
  async listEnvironments(skipInitializationCheck = false) {
@@ -312197,9 +312528,9 @@ class EnvironmentStore {
312197
312528
  assertSafeEnvironmentPath(absoluteEnvironmentPath);
312198
312529
  const startedAt = Date.now();
312199
312530
  logger.info(`Detected zip file at "${absoluteEnvironmentPath}". Unzipping...`);
312200
- const archiveDir = path11.resolve(path11.dirname(absoluteEnvironmentPath));
312201
- const unzippedEnvironmentPath = path11.resolve(archiveDir, path11.basename(absoluteEnvironmentPath, ".zip"));
312202
- if (!unzippedEnvironmentPath.startsWith(archiveDir + path11.sep)) {
312531
+ const archiveDir = path12.resolve(path12.dirname(absoluteEnvironmentPath));
312532
+ const unzippedEnvironmentPath = path12.resolve(archiveDir, path12.basename(absoluteEnvironmentPath, ".zip"));
312533
+ if (!unzippedEnvironmentPath.startsWith(archiveDir + path12.sep)) {
312203
312534
  throw new BadRequestError(`Refusing to unzip "${absoluteEnvironmentPath}": target escapes its directory`);
312204
312535
  }
312205
312536
  await fs9.promises.rm(unzippedEnvironmentPath, {
@@ -312210,7 +312541,7 @@ class EnvironmentStore {
312210
312541
  let entryCount = 0;
312211
312542
  let totalUncompressedBytes = 0;
312212
312543
  await import_extract_zip.default(absoluteEnvironmentPath, {
312213
- dir: path11.resolve(unzippedEnvironmentPath),
312544
+ dir: path12.resolve(unzippedEnvironmentPath),
312214
312545
  onEntry: (entry) => {
312215
312546
  entryCount += 1;
312216
312547
  totalUncompressedBytes += entry.uncompressedSize ?? 0;
@@ -312317,7 +312648,7 @@ class EnvironmentStore {
312317
312648
  return absoluteEnvironmentPath;
312318
312649
  }
312319
312650
  isLocalPath(location) {
312320
- return location.startsWith("./") || location.startsWith("../") || location.startsWith("~/") || location.startsWith("/") || path11.isAbsolute(location);
312651
+ return location.startsWith("./") || location.startsWith("../") || location.startsWith("~/") || location.startsWith("/") || path12.isAbsolute(location);
312321
312652
  }
312322
312653
  resolveLocalPath(location) {
312323
312654
  return resolvePackageLocation(location, getPublisherConfigDir(this.serverRootPath) ?? this.serverRootPath);
@@ -312414,7 +312745,7 @@ class EnvironmentStore {
312414
312745
  const isInPlace = this.inPlaceEnvs.has(environmentName) && this.isLocalPath(_package.location);
312415
312746
  if (isInPlace) {
312416
312747
  await clearMountTarget(absolutePackagePath);
312417
- const absoluteSourcePath = path11.resolve(sourcePath);
312748
+ const absoluteSourcePath = path12.resolve(sourcePath);
312418
312749
  const linkType = process.platform === "win32" ? "junction" : "dir";
312419
312750
  try {
312420
312751
  await fs9.promises.symlink(absoluteSourcePath, absolutePackagePath, linkType);
@@ -312573,7 +312904,7 @@ class EnvironmentStore {
312573
312904
  if (file.name.endsWith("/")) {
312574
312905
  return;
312575
312906
  }
312576
- await fs9.promises.mkdir(path11.dirname(absoluteFilePath), {
312907
+ await fs9.promises.mkdir(path12.dirname(absoluteFilePath), {
312577
312908
  recursive: true
312578
312909
  });
312579
312910
  return fs9.promises.writeFile(absoluteFilePath, await file.download());
@@ -312590,7 +312921,7 @@ class EnvironmentStore {
312590
312921
  const prefix = prefixParts.join("/");
312591
312922
  if (isCompressedFile) {
312592
312923
  const zipFilePath = `${absoluteDirPath}.zip`;
312593
- await fs9.promises.mkdir(path11.dirname(zipFilePath), {
312924
+ await fs9.promises.mkdir(path12.dirname(zipFilePath), {
312594
312925
  recursive: true
312595
312926
  });
312596
312927
  const command = new import_client_s33.GetObjectCommand({
@@ -312630,7 +312961,7 @@ class EnvironmentStore {
312630
312961
  return;
312631
312962
  }
312632
312963
  const absoluteFilePath = safeJoinUnderRoot(absoluteDirPath, relativeFilePath);
312633
- await fs9.promises.mkdir(path11.dirname(absoluteFilePath), {
312964
+ await fs9.promises.mkdir(path12.dirname(absoluteFilePath), {
312634
312965
  recursive: true
312635
312966
  });
312636
312967
  const command = new import_client_s33.GetObjectCommand({
@@ -312784,7 +313115,7 @@ class WatchModeController {
312784
313115
  ignored: (filePath, stats) => {
312785
313116
  if (!stats?.isFile())
312786
313117
  return false;
312787
- const ext = path12.extname(filePath).toLowerCase();
313118
+ const ext = path13.extname(filePath).toLowerCase();
312788
313119
  return !MODEL_EXTS.has(ext) && !ASSET_EXTS.has(ext);
312789
313120
  },
312790
313121
  ignoreInitial: true
@@ -312802,12 +313133,12 @@ class WatchModeController {
312802
313133
  };
312803
313134
  const onEvent = (kind) => async (filePath) => {
312804
313135
  logger.info(`Watch ${kind}: ${filePath}; environment=${watchName}`);
312805
- const rel = path12.relative(this.watchingPath ?? "", filePath);
312806
- const segments = rel.split(path12.sep);
313136
+ const rel = path13.relative(this.watchingPath ?? "", filePath);
313137
+ const segments = rel.split(path13.sep);
312807
313138
  const pkgName = segments.length > 1 && segments[0] && !segments[0].startsWith("..") ? segments[0] : null;
312808
313139
  if (!pkgName)
312809
313140
  return;
312810
- const ext = path12.extname(filePath).toLowerCase();
313141
+ const ext = path13.extname(filePath).toLowerCase();
312811
313142
  if (MODEL_EXTS.has(ext)) {
312812
313143
  const recompiled = await reloadPackage(pkgName);
312813
313144
  if (!recompiled)
@@ -313207,9 +313538,6 @@ class MaterializationController {
313207
313538
  async listMaterializations(environmentName, packageName, options) {
313208
313539
  return this.materializationService.listMaterializations(environmentName, packageName, options);
313209
313540
  }
313210
- async listEnvironmentMaterializations(environmentName, options) {
313211
- return this.materializationService.listEnvironmentMaterializations(environmentName, options);
313212
- }
313213
313541
  async getMaterialization(environmentName, packageName, materializationId) {
313214
313542
  return this.materializationService.getMaterialization(environmentName, packageName, materializationId);
313215
313543
  }
@@ -316104,7 +316432,7 @@ init_logger();
316104
316432
  // src/mcp/tools/schema_index.ts
316105
316433
  init_logger();
316106
316434
  var import_lunr3 = __toESM(require_lunr(), 1);
316107
- import { createHash as createHash3 } from "crypto";
316435
+ import { createHash as createHash5 } from "crypto";
316108
316436
  var MAX_INDEXED_TABLES = 5000;
316109
316437
  var MAX_COLUMNS_IN_INDEX_TEXT = 60;
316110
316438
  var MAX_CACHED_SCHEMAS = 8;
@@ -316119,7 +316447,7 @@ function tableIndexText(entity) {
316119
316447
  }
316120
316448
  function schemaFingerprint(tables) {
316121
316449
  const canonical = tables.map((t) => `${t.resource}\x00${t.columns.map((c) => `${c.name}:${c.type ?? ""}`).join(",")}`).sort().join("\x01");
316122
- return createHash3("sha256").update(canonical).digest("hex");
316450
+ return createHash5("sha256").update(canonical).digest("hex");
316123
316451
  }
316124
316452
  function sanitizeQuery(query) {
316125
316453
  return query.replace(/[~^:*+\-"]/g, " ").trim();
@@ -320380,14 +320708,18 @@ Scanned at a glance is a dashboard; read top to bottom is a notebook.
320380
320708
  2. **PICK THE VIEWS TO SHOW.** A dashboard is \`## artifact { tiles=[…] }\` naming existing views, so
320381
320709
  this is the design step: which views, how wide each sits, what each is called. There is one form,
320382
320710
  so there is no form to choose.
320383
- 3. **DECLARE THE GIVENS** the dashboard will filter by, in the model (usually \`givens.malloy\`), with
320384
- their control tags: see "Filter controls" below for the syntax and what each tag renders as. Skip
320385
- if they already exist, since a given is a model concern and dashboards share them.
320711
+ 3. **DECLARE THE GIVENS** the dashboard will filter by, in the dashboard file itself, with their
320712
+ control tags: see "Filter controls" below for the syntax and what each tag renders as. That is
320713
+ the convention because the dashboard builder edits the dashboard file and nothing else, so a
320714
+ filter it can add, change or remove is a declaration in that file. Bind them on the tiles (step
320715
+ 4). Reuse the package's \`givens.malloy\` only for a control several surfaces genuinely share, and
320716
+ then import it whole, knowing the builder can bind those givens but not edit them.
320386
320717
  4. **COMPOSE THE FILE** for \`dashboards/\`, following the template below, but do not save it yet.
320387
- Import the package's givens file **whole**: \`import '../givens.malloy'\`, not a named list.
320388
- Only the givens the tiles reference become controls, so a whole-file import brings nothing
320389
- extra, and a named list is one more thing to forget; forgetting one costs you a missing control
320390
- rather than an error. Sources are the other way round: name the few you need. Then import every
320718
+ Name the sources you need: \`import { order_items, products } from '../storefront.malloy'\`.
320719
+ Each tile binds its controls with a refinement, \`view: t is v + { where: category ~ $CATEGORY }\`,
320720
+ one clause per given it answers to; a \`filter<...>\` binds with \`~\`, a plain \`date\` or \`number\`
320721
+ given is a value and binds with \`>=\`, \`<=\` or \`=\`. Only the givens some tile references become
320722
+ controls, so a declaration nothing binds shows nothing. Then import every
320391
320723
  source or query any referenced given names in a \`suggest\`. Both are per-file, and getting the
320392
320724
  suggest wrong does not error: the control still looks like a picker but has no options, and says
320393
320725
  so underneath, "Could not load the options for this control". The package warnings name it too. **A \`suggest\` naming a \`query=\` needs that
@@ -320422,33 +320754,31 @@ out by Publisher into the grid \`# dashboard { columns=N }\` names.
320422
320754
  \`\`\`malloy
320423
320755
  ##! experimental.givens
320424
320756
  ## artifact { title="Storefront overview" tiles=["overview -> kpis", "overview -> revenue_trend", "overview -> revenue_by_state"] } dashboard { columns=12 }
320425
- import { scoped_sales } from './_shared.malloy'
320426
- import { products } from '../storefront.malloy'
320427
- import '../givens.malloy'
320757
+ import { order_items, products } from '../storefront.malloy'
320758
+
320759
+ // The controls, declared here: the tags are each one's control contract.
320760
+ # label="Category" control=select suggest { source=products dimension=category }
320761
+ given: CATEGORY :: filter<string> is f''
320762
+ # label="Ordered since"
320763
+ given: SINCE :: date is @2023-01-01
320428
320764
 
320429
320765
  // Layout goes on the VIEW, and a thin re-declaration is the place to put it: the
320430
- // modelled view keeps its chart tag, and this decides how wide it sits here.
320431
- source: overview is scoped_sales extend {
320766
+ // modelled view keeps its chart tag, this decides how wide it sits here, and the
320767
+ // \`+ { where: ... }\` says which controls the tile answers to.
320768
+ source: overview is order_items extend {
320432
320769
  # colspan=12
320433
320770
  # label="Key figures"
320434
320771
  # big_value
320435
- view: kpis is {
320436
- aggregate:
320437
- # label="Revenue"
320438
- # currency
320439
- total_sales
320440
- # label="Orders"
320441
- order_count
320442
- }
320772
+ view: kpis is key_figures + { where: category ~ $CATEGORY, where: created_at >= $SINCE }
320443
320773
 
320444
320774
  # colspan=8
320445
320775
  # break
320446
320776
  # label="Revenue by month"
320447
- view: revenue_trend is sales_by_month
320777
+ view: revenue_trend is sales_by_month + { where: category ~ $CATEGORY, where: created_at >= $SINCE }
320448
320778
 
320449
320779
  # colspan=4
320450
320780
  # label="Revenue by state"
320451
- view: revenue_by_state is sales_by_state
320781
+ view: revenue_by_state is sales_by_state + { where: category ~ $CATEGORY, where: created_at >= $SINCE }
320452
320782
  }
320453
320783
  \`\`\`
320454
320784
 
@@ -320461,8 +320791,8 @@ Three things the form costs, so you are not surprised by them:
320461
320791
  - **A tile expression is a string in an annotation, so the compiler never checks it.** Rename a view
320462
320792
  and the file still compiles; the tile fails at package load. Read the lint (step 6).
320463
320793
  - **No per-parent-row grouping.** There is no parent query to repeat a grid over.
320464
- - **Filtering lives in what the tiles name**, not on the page. That is the shared include's job,
320465
- below.
320794
+ - **Filtering lives on the tiles**, not on the page: each view's \`+ { where: ... }\` names the
320795
+ controls it answers to. Below is why, and the one thing that does not work.
320466
320796
 
320467
320797
  ### Also served: \`# artifact\` on a \`query:\`
320468
320798
 
@@ -320522,23 +320852,24 @@ object", so a dashboard has no description as a result.
320522
320852
 
320523
320853
  ### Where the filtering goes
320524
320854
 
320525
- A dashboard has no query, so the filtering it applies must live in what it composes: a source that
320526
- already has the givens applied. Put it in an untagged \`dashboards/_shared.malloy\`, which discovery
320527
- treats as a shared include rather than a dashboard. **It has to apply every given the dashboard
320528
- imports**: a given the dashboard imports but nothing references gets no control, silently, at reload
320529
- 200 with no warning. Note \`SINCE\` is a \`date\` rather than a \`filter<>\`, so it compares with \`>=\`
320530
- rather than \`~\`. Save the include before you compile the dashboard that imports it, since an importer
320531
- compiled against a sibling that is not on disk fails with an \`import-error\`.
320532
-
320533
- \`\`\`malloy
320534
- ##! experimental.givens
320535
- import { order_items } from '../storefront.malloy'
320536
- import '../givens.malloy'
320537
-
320538
- source: scoped_sales is order_items extend {
320539
- where: products.category ~ $CATEGORY and created_at >= $SINCE
320540
- }
320541
- \`\`\`
320855
+ A dashboard has no query, so its filtering lives on the views it names: a \`+ { where: field ~ $GIVEN }\`
320856
+ refinement on each tile, one clause per control the tile answers to. A tile without the clause does
320857
+ not move when the control does, which is how a page keeps one tile fixed while the rest filter. The
320858
+ givens those clauses read are declared in the same file (step 3).
320859
+
320860
+ **Binding is per declaration, not per name.** Measured: a dashboard declaring its own \`CATEGORY\`
320861
+ over a source whose model-level \`where:\` reads the model's \`CATEGORY\` compiles, shows the control,
320862
+ and filters nothing when it moves, because the two declarations only share a name. So do not mix
320863
+ the two designs on one given. The other design still works on its own: a source with the givens
320864
+ already applied in an untagged \`dashboards/_shared.malloy\`, reading \`import '../givens.malloy'\`,
320865
+ which discovery treats as a shared include rather than a dashboard. Then the dashboard imports both
320866
+ and the controls render for the givens its tiles reach. A given the dashboard imports but nothing
320867
+ references gets no control, silently, at reload 200 with no warning. Save the include before you
320868
+ compile the dashboard that imports it, since an importer compiled against a sibling that is not on
320869
+ disk fails with an \`import-error\`. The builder can bind such a control but not add, change or
320870
+ remove it, since it never edits imports or model files.
320871
+
320872
+ Note \`SINCE\` is a \`date\` rather than a \`filter<>\`, so it compares with \`>=\` rather than \`~\`.
320542
320873
 
320543
320874
  **\`# dashboard { columns=N }\` is the one spelling of the grid width**, on both forms, beside the
320544
320875
  artifact tag. Anything else inside the artifact tag is a package warning naming it, which is what you
@@ -320620,9 +320951,10 @@ rows.
320620
320951
  - **The filename is the dashboard's name:** its URL slug, its listing name, and its \`# drill\`
320621
320952
  target. The query inside can be called anything, and sometimes must be (a query named \`regions\`
320622
320953
  collides with an imported \`regions\` source).
320623
- - **Importing a given is what makes it bindable.** Malloy's given namespace is per-file. A given the
320624
- dashboard file does not import gets no control and cannot be sent to it, even when the \`where:\`
320625
- that references it lives up an import chain. A dashboard must import the givens its tiles use.
320954
+ - **A given has to be in the dashboard file's scope to be bindable**: declared there (the
320955
+ convention) or imported. Malloy's given namespace is per-file. A given the file cannot see gets
320956
+ no control and cannot be sent to it, even when a \`where:\` that references it lives up an import
320957
+ chain. And a given declared here does not drive a \`where:\` in the model: bind on the tiles.
320626
320958
  - **A suggest's source or query has to resolve in the dashboard file too.** \`suggest { source=products … }\`
320627
320959
  means the dashboard imports \`products\`.
320628
320960
  - **A model-level \`##\` tag must be on one line.** Wrapping one always breaks it, but how you find
@@ -320641,9 +320973,10 @@ choosing them.
320641
320973
 
320642
320974
  ## Filter controls
320643
320975
 
320644
- Controls come from the \`given:\` declarations the query references, and the tags on the declaration
320645
- are the control contract, declared once and identical on every dashboard and in every notebook that
320646
- uses them:
320976
+ Controls come from the \`given:\` declarations the tiles reference. Declare them in the dashboard
320977
+ file, which is what the builder edits; a package \`givens.malloy\` is for controls the data app and
320978
+ notebooks share, and a dashboard importing it whole gets the same controls but cannot edit them.
320979
+ The tags on the declaration are the control contract:
320647
320980
 
320648
320981
  \`\`\`malloy
320649
320982
  ##! experimental.givens
@@ -322177,7 +322510,7 @@ Present coverage in this order:
322177
322510
  {
322178
322511
  name: "malloy-materialization-tuning",
322179
322512
  description: "Optimize a package's Malloy Persistence materializations for cost and performance using the malloy-pub CLI and the materialization history. Recommend what to persist, what to stop persisting, and how to schedule/scope it. Use when the user asks to make a package cheaper or faster, tune persistence, decide what to materialize, or review persist/schedule choices.",
322180
- body: "# Tuning materializations for cost and performance\n\nThis skill turns the signals the open-source Publisher already records (the materialization history, per-run timings, and which sources were built vs reused) into concrete, **recommendations-only** advice: which sources to persist, which to stop persisting, and how to schedule and scope them. It is the local counterpart to the platform's usage-driven optimization: the Publisher has the raw signals, and you read them with the `malloy-pub` CLI.\n\n> **Recommendations only. Never change a model, schedule, or scope without the user's explicit go-ahead.** Present the findings and the proposed edits, then apply them only when asked. Persisting the wrong source wastes storage and rebuild time; unpersisting a hot one makes queries slow. Let the user decide.\n\nAssumes the `malloy-pub` CLI is on PATH and points at the server (`--url` or `MALLOY_PUBLISHER_URL`, default `http://localhost:4000`). Substitute the real environment and package for `<env>` / `<pkg>`.\n\n## Step 1: Take inventory\n\nEstablish what the package persists today and how it is governed.\n\n- **Persist sources:** the sources annotated `#@ persist name=\"…\"` in the package's `.malloy` files. Read the models (or `get_context` the package) to list them.\n- **Schedule + scope:**\n\n ```bash\n malloy-pub schedule view --environment <env> --package <pkg>\n ```\n\n This prints the cron (or `none`, meaning publish / on-demand only), the persist **scope** (`package` = artifacts reused across versions; `version` = per published version), and whether a freshness policy is set. A control-plane-managed package (manifestLocation set) is refreshed by the control plane, not the standalone scheduler, so leave its cadence alone.\n\n## Step 2: Read the materialization history\n\nThe history is where cost lives. Each run records its trigger, timing, and how many sources were built vs reused.\n\n- **Across the whole environment** (all packages, newest first; the rows are interleaved and labeled by package, not grouped into contiguous per-package blocks):\n\n ```bash\n malloy-pub list materialization --environment <env>\n ```\n\n Columns: Package, ID, Status, **Trigger** (`SCHEDULER` vs `ON_DEMAND`), Started, Completed, Error.\n\n- **For one package:**\n\n ```bash\n malloy-pub list materialization --environment <env> --package <pkg>\n ```\n\n- **A single run's detail** (the cost signals):\n\n ```bash\n malloy-pub get materialization <id> --environment <env> --package <pkg>\n ```\n\n In the JSON, read:\n - `metadata.durationMs`: how long the build took.\n - `metadata.sourcesBuilt` vs `metadata.sourcesReused`: how much work each run actually did. A run that is nearly all _reused_ is cheap; one that is nearly all _built_ every time is where cost accumulates.\n - `metadata.trigger`: `SCHEDULER` (a cron fired it) or `ON_DEMAND`.\n - `manifest.entries[*]`: the persisted sources: `sourceName`, `physicalTableName`, `realization`.\n\nLook across several runs, not one: the pattern over the recent history (how often it rebuilds, how much it reuses, how long it takes) is the signal.\n\n## Step 3: Analyze and recommend\n\nWeigh rebuild cost against query benefit. Common findings:\n\n- **Persist candidate:** an expensive, frequently-queried source that is _not_ persisted (recomputed on every query). Recommend adding `#@ persist name=\"…\"`. Strongest when the source is a heavy aggregate/join reused by many queries and its inputs change slowly. If the source carries an `#(authorize)` gate, check which case it is first. A gate reached only through a `join_*`, or inherited from a base it cannot be attributed to, makes the colocated persist **refuse with a 422** - so do not recommend persisting it at all. Where the gate is provably the source's own row filter the persist is admitted, and then only recommend it alongside a freshness window (`freshness.fallback=\"live\"`): the gating column freezes at build time, so without one a revoked row can be served under its old access decision indefinitely (see `skill:malloy-materialization`, which also covers where that window does and does not bind).\n- **Removal candidate:** a persisted source that is cheap to compute, rarely queried, or rebuilt far more often than it is read. Recommend dropping the `#@ persist` annotation (and its table): the storage + rebuild cost is not buying anything.\n- **Cadence mismatch:** a `SCHEDULER` cadence out of step with how fast the data changes or how long a build takes. If most scheduled runs are all-reused (nothing changed), the cron is too frequent, so loosen it. If queries routinely read stale data, tighten it. If the build's `durationMs` approaches the interval, the cadence is too aggressive.\n- **Scope mismatch:** `scope: version` re-materializes per published version (right when versions must be isolated, e.g. a schedule); `scope: package` reuses one lineage across versions (cheaper when versions can share). A schedule _requires_ `version`. If a package carries a schedule it does not need, clearing the schedule frees it to use the cheaper package scope.\n\nFrame each recommendation with the evidence from Step 2 (the run IDs, timings, built/reused counts) so the user can judge it.\n\n## Step 4: Apply (only once approved)\n\n- **Add a persist source:** add the `#@ persist` annotation in the `.malloy` file (use the modeling workflow to validate and reload), then rebuild so it is materialized:\n\n ```bash\n malloy-pub materialize --environment <env> --package <pkg> --wait\n ```\n\n- **Remove a persist source:** delete the `#@ persist` annotation, then drop the old run's tables **before** rebuilding what remains:\n\n ```bash\n malloy-pub delete materialization <id> --environment <env> --package <pkg> --drop-tables\n malloy-pub materialize --environment <env> --package <pkg> --wait\n ```\n\n > `--drop-tables` drops **every** physical table in that run's manifest, not just the removed source's: auto-run assigns stable table names and carries unchanged sources forward, so an old run's manifest names tables a newer manifest still serves. Do the drop **first, then rebuild**: `materialize --wait` re-creates every source that is still persisted, ending in the desired state. Dropping a run whose tables the current serving manifest depends on, without an immediate rebuild, breaks queries (`Table ... does not exist`).\n\n- **Change the schedule / cadence:**\n\n ```bash\n malloy-pub schedule set \"0 6 * * *\" --environment <env> --package <pkg> # 5-field UTC cron\n malloy-pub schedule clear --environment <env> --package <pkg>\n ```\n\n `set` also sets `scope: version` (a schedule requires it); the server rejects an invalid cron or an illegal scope/freshness combination, so a rejection means the change was unsafe.\n\n- **Change the scope:** `scope` is declared in the package's `publisher.json` under `materialization` (`\"scope\": \"package\"` or `\"version\"`; the root-level form is deprecated but still read). Edit it there, then reload/republish the package. Remember a schedule pins scope to `version`, so clear the schedule first if moving to `package`.\n\nAfter applying, re-run Step 2 on the next few builds to confirm the change did what you predicted (more reuse, shorter builds, or a table that is actually read).\n\n## What this skill does not do\n\n- It does not decide for the user or apply changes silently; every edit needs an explicit go-ahead.\n- It cannot see per-query read counts (the open-source Publisher records build history, not query-level table usage), so \"rarely queried\" is a judgment from the model and the user's knowledge, not a measured metric. Say so when it matters."
322513
+ body: "# Tuning materializations for cost and performance\n\nThis skill turns the signals the open-source Publisher already records (the materialization history, per-run timings, and which sources were built vs reused) into concrete, **recommendations-only** advice: which sources to persist, which to stop persisting, and how to schedule and scope them. It is the local counterpart to the platform's usage-driven optimization: the Publisher has the raw signals, and you read them with the `malloy-pub` CLI.\n\n> **Recommendations only. Never change a model, schedule, or scope without the user's explicit go-ahead.** Present the findings and the proposed edits, then apply them only when asked. Persisting the wrong source wastes storage and rebuild time; unpersisting a hot one makes queries slow. Let the user decide.\n\nAssumes the `malloy-pub` CLI is on PATH and points at the server (`--url` or `MALLOY_PUBLISHER_URL`, default `http://localhost:4000`). Substitute the real environment and package for `<env>` / `<pkg>`.\n\n## Step 1: Take inventory\n\nEstablish what the package persists today and how it is governed.\n\n- **Persist sources:** the sources annotated `#@ persist name=\"…\"` in the package's `.malloy` files. Read the models (or `get_context` the package) to list them.\n- **Schedule + scope:**\n\n ```bash\n malloy-pub schedule view --environment <env> --package <pkg>\n ```\n\n This prints the cron (or `none`, meaning publish / on-demand only), the persist **scope** (`package` = artifacts reused across versions; `version` = per published version), and whether a freshness policy is set. A control-plane-managed package (manifestLocation set) is refreshed by the control plane, not the standalone scheduler, so leave its cadence alone.\n\n## Step 2: Read the materialization history\n\nThe history is where cost lives. Each run records its trigger, timing, and how many sources were built vs reused.\n\n- **For one package** (newest first). A materialization is a run of one package's persist sources, so this is the listing; to review a whole environment, read each package in turn (`malloy-pub list package --environment <env>` names them):\n\n ```bash\n malloy-pub list materialization --environment <env> --package <pkg>\n ```\n\n Columns: ID, Status, **Trigger** (`SCHEDULER` vs `ON_DEMAND`), Started, Completed, Error.\n\n- **A single run's detail** (the cost signals):\n\n ```bash\n malloy-pub get materialization <id> --environment <env> --package <pkg>\n ```\n\n In the JSON, read:\n - `metadata.durationMs`: how long the build took.\n - `metadata.sourcesBuilt` vs `metadata.sourcesReused`: how much work each run actually did. A run that is nearly all _reused_ is cheap; one that is nearly all _built_ every time is where cost accumulates.\n - `metadata.trigger`: `SCHEDULER` (a cron fired it) or `ON_DEMAND`.\n - `manifest.entries[*]`: the persisted sources: `sourceName`, `physicalTableName`, `realization`.\n\nLook across several runs, not one: the pattern over the recent history (how often it rebuilds, how much it reuses, how long it takes) is the signal.\n\n## Step 3: Analyze and recommend\n\nWeigh rebuild cost against query benefit. Common findings:\n\n- **Persist candidate:** an expensive, frequently-queried source that is _not_ persisted (recomputed on every query). Recommend adding `#@ persist name=\"…\"`. Strongest when the source is a heavy aggregate/join reused by many queries and its inputs change slowly. If the source carries an `#(authorize)` gate, check which case it is first. A gate reached only through a `join_*`, or inherited from a base it cannot be attributed to, makes the colocated persist **refuse with a 422** - so do not recommend persisting it at all. Where the gate is provably the source's own row filter the persist is admitted, and then only recommend it alongside a freshness window (`freshness.fallback=\"live\"`): the gating column freezes at build time, so without one a revoked row can be served under its old access decision indefinitely (see `skill:malloy-materialization`, which also covers where that window does and does not bind).\n- **Removal candidate:** a persisted source that is cheap to compute, rarely queried, or rebuilt far more often than it is read. Recommend dropping the `#@ persist` annotation (and its table): the storage + rebuild cost is not buying anything.\n- **Cadence mismatch:** a `SCHEDULER` cadence out of step with how fast the data changes or how long a build takes. If most scheduled runs are all-reused (nothing changed), the cron is too frequent, so loosen it. If queries routinely read stale data, tighten it. If the build's `durationMs` approaches the interval, the cadence is too aggressive.\n- **Scope mismatch:** `scope: version` re-materializes per published version (right when versions must be isolated, e.g. a schedule); `scope: package` reuses one lineage across versions (cheaper when versions can share). A schedule _requires_ `version`. If a package carries a schedule it does not need, clearing the schedule frees it to use the cheaper package scope.\n\nFrame each recommendation with the evidence from Step 2 (the run IDs, timings, built/reused counts) so the user can judge it.\n\n## Step 4: Apply (only once approved)\n\n- **Add a persist source:** add the `#@ persist` annotation in the `.malloy` file (use the modeling workflow to validate and reload), then rebuild so it is materialized:\n\n ```bash\n malloy-pub materialize --environment <env> --package <pkg> --wait\n ```\n\n- **Remove a persist source:** delete the `#@ persist` annotation, then drop the old run's tables **before** rebuilding what remains:\n\n ```bash\n malloy-pub delete materialization <id> --environment <env> --package <pkg> --drop-tables\n malloy-pub materialize --environment <env> --package <pkg> --wait\n ```\n\n > `--drop-tables` drops **every** physical table in that run's manifest, not just the removed source's: auto-run assigns stable table names and carries unchanged sources forward, so an old run's manifest names tables a newer manifest still serves. Do the drop **first, then rebuild**: `materialize --wait` re-creates every source that is still persisted, ending in the desired state. Dropping a run whose tables the current serving manifest depends on, without an immediate rebuild, breaks queries (`Table ... does not exist`).\n\n- **Change the schedule / cadence:**\n\n ```bash\n malloy-pub schedule set \"0 6 * * *\" --environment <env> --package <pkg> # 5-field UTC cron\n malloy-pub schedule clear --environment <env> --package <pkg>\n ```\n\n `set` also sets `scope: version` (a schedule requires it); the server rejects an invalid cron or an illegal scope/freshness combination, so a rejection means the change was unsafe.\n\n- **Change the scope:** `scope` is declared in the package's `publisher.json` under `materialization` (`\"scope\": \"package\"` or `\"version\"`; the root-level form is deprecated but still read). Edit it there, then reload/republish the package. Remember a schedule pins scope to `version`, so clear the schedule first if moving to `package`.\n\nAfter applying, re-run Step 2 on the next few builds to confirm the change did what you predicted (more reuse, shorter builds, or a table that is actually read).\n\n## What this skill does not do\n\n- It does not decide for the user or apply changes silently; every edit needs an explicit go-ahead.\n- It cannot see per-query read counts (the open-source Publisher records build history, not query-level table usage), so \"rarely queried\" is a judgment from the model and the user's knowledge, not a measured metric. Say so when it matters."
322181
322514
  },
322182
322515
  {
322183
322516
  name: "malloy-model",
@@ -324296,8 +324629,8 @@ function initializeMcpServer(environmentStore) {
324296
324629
  init_config();
324297
324630
  init_logger();
324298
324631
  import * as fs10 from "fs";
324299
- import * as os3 from "os";
324300
- import * as path13 from "path";
324632
+ import * as os4 from "os";
324633
+ import * as path14 from "path";
324301
324634
  var MCP_CONFIG_FILENAME = ".mcp.json";
324302
324635
  function malloyServer(endpoint) {
324303
324636
  return { type: "http", url: endpoint };
@@ -324321,11 +324654,11 @@ function mcpEndpoint(host, port) {
324321
324654
  return `http://${host}:${port}/mcp`;
324322
324655
  }
324323
324656
  function findGitWorkTreeRoot(dir) {
324324
- let current = path13.resolve(dir);
324657
+ let current = path14.resolve(dir);
324325
324658
  for (;; ) {
324326
- if (fs10.existsSync(path13.join(current, ".git")))
324659
+ if (fs10.existsSync(path14.join(current, ".git")))
324327
324660
  return current;
324328
- const parent = path13.dirname(current);
324661
+ const parent = path14.dirname(current);
324329
324662
  if (parent === current)
324330
324663
  return;
324331
324664
  current = parent;
@@ -324348,7 +324681,7 @@ function mcpConfigEnabled() {
324348
324681
  }
324349
324682
  function ensureMcpConfig(options) {
324350
324683
  const { dir, endpoint, requestedPort, boundPort, homeDir } = options;
324351
- const file = path13.join(dir, MCP_CONFIG_FILENAME);
324684
+ const file = path14.join(dir, MCP_CONFIG_FILENAME);
324352
324685
  try {
324353
324686
  const existing = (() => {
324354
324687
  try {
@@ -324375,18 +324708,18 @@ function ensureMcpConfig(options) {
324375
324708
  try {
324376
324709
  return fs10.realpathSync(p);
324377
324710
  } catch {
324378
- return path13.resolve(p);
324711
+ return path14.resolve(p);
324379
324712
  }
324380
324713
  };
324381
- if (realish(dir) === realish(homeDir ?? os3.homedir())) {
324714
+ if (realish(dir) === realish(homeDir ?? os4.homedir())) {
324382
324715
  return { action: "skipped-home", dir, endpoint, staleConfig };
324383
324716
  }
324384
- if (path13.resolve(dir) === path13.parse(path13.resolve(dir)).root) {
324717
+ if (path14.resolve(dir) === path14.parse(path14.resolve(dir)).root) {
324385
324718
  return { action: "skipped-root", dir, endpoint, staleConfig };
324386
324719
  }
324387
324720
  const gitRoot = findGitWorkTreeRoot(dir);
324388
324721
  if (gitRoot !== undefined) {
324389
- const rootCandidate = path13.join(gitRoot, MCP_CONFIG_FILENAME);
324722
+ const rootCandidate = path14.join(gitRoot, MCP_CONFIG_FILENAME);
324390
324723
  return {
324391
324724
  action: "skipped-git",
324392
324725
  dir,
@@ -325427,9 +325760,9 @@ import {
325427
325760
  InMemoryURLReader as InMemoryURLReader3,
325428
325761
  Runtime as Runtime4
325429
325762
  } from "@malloydata/malloy";
325430
- import { mkdirSync as mkdirSync3, mkdtempSync, rmSync } from "node:fs";
325431
- import os4 from "node:os";
325432
- import path14 from "node:path";
325763
+ import { mkdirSync as mkdirSync3, mkdtempSync as mkdtempSync2, rmSync } from "node:fs";
325764
+ import os5 from "node:os";
325765
+ import path15 from "node:path";
325433
325766
 
325434
325767
  // src/service/build_query_tag.ts
325435
325768
  var MAX_QUERY_TAG_LENGTH = 2000;
@@ -325671,14 +326004,14 @@ ${buildSQL};`;
325671
326004
  }
325672
326005
  return row;
325673
326006
  }, parentJobId);
325674
- const path15 = [
326007
+ const path16 = [
325675
326008
  str2(located.project) ?? handle,
325676
326009
  str2(located.dataset),
325677
326010
  str2(located.table)
325678
326011
  ].join(".");
325679
326012
  const jobId = str2(located.job_id);
325680
326013
  return {
325681
- selectSQL: `SELECT * FROM bigquery_scan('${escapeSQL(path15)}')`,
326014
+ selectSQL: `SELECT * FROM bigquery_scan('${escapeSQL(path16)}')`,
325682
326015
  jobId,
325683
326016
  cost: bigQueryReadCost(located, jobId, parentJobId)
325684
326017
  };
@@ -325741,7 +326074,7 @@ function passthroughSourceType(sourceConnection) {
325741
326074
  throw new BadRequestError(`Cannot materialize a '${type}' source into a storage destination: the ` + `native query-passthrough build supports source connections of type ` + `${PASSTHROUGH_SOURCE_TYPES.join(", ")} only.`);
325742
326075
  }
325743
326076
  function createIsolatedBuildSession(sessionName) {
325744
- const workDir = mkdtempSync(path14.join(os4.tmpdir(), "malloy-build-"));
326077
+ const workDir = mkdtempSync2(path15.join(os5.tmpdir(), "malloy-build-"));
325745
326078
  let session;
325746
326079
  try {
325747
326080
  session = new DuckDBConnection4(sessionName, ":memory:", workDir, {
@@ -325794,10 +326127,13 @@ async function buildSourceIntoStorage(params) {
325794
326127
  environmentPath,
325795
326128
  queryMetadata
325796
326129
  } = params;
326130
+ const federate = params.deps?.federate ?? federateSourceForPassthrough;
326131
+ const read = params.deps?.read ?? issuePassthroughRead;
325797
326132
  assertSupportedDestination(destinationName, destinationConnection);
325798
326133
  const sourceType = passthroughSourceType(sourceConnection);
325799
326134
  const { session, dispose, workDir } = createIsolatedBuildSession(`build_${destinationName}`);
325800
326135
  let federatedHandle;
326136
+ let federatedClose;
325801
326137
  try {
325802
326138
  await applySessionResourceLimits(session, { tempDirectory: workDir });
325803
326139
  await attachDestinationReadWrite(session, destinationName, destinationConnection, environmentPath);
@@ -325805,7 +326141,8 @@ async function buildSourceIntoStorage(params) {
325805
326141
  await session.runSQL("SET ducklake_default_data_inlining_row_limit=0");
325806
326142
  }
325807
326143
  await pinSessionToUTC(session);
325808
- const federated = await federateSourceForPassthrough(session, sourceType, sourceFederationConfig(sourceConnection));
326144
+ const federated = await federate(session, sourceType, sourceFederationConfig(sourceConnection));
326145
+ federatedClose = federated.close;
325809
326146
  await tagSnowflakeSession(session, sourceType, federated.handle, queryMetadata);
325810
326147
  const target = quoteManifestTablePath(`${destinationName}.${physicalTableName}`, STORAGE_TARGET_DIALECT);
325811
326148
  if (params.incremental) {
@@ -325824,8 +326161,8 @@ async function buildSourceIntoStorage(params) {
325824
326161
  };
325825
326162
  }
325826
326163
  }
325827
- const read = await issuePassthroughRead(session, sourceType, federated.handle, buildSQL, queryMetadata);
325828
- const schema = await createTableAndDescribe(session, target, read.selectSQL);
326164
+ const passthrough = await read(session, sourceType, federated.handle, buildSQL, queryMetadata);
326165
+ const schema = await createTableAndDescribe(session, target, passthrough.selectSQL);
325829
326166
  const seededThrough = await params.incremental?.afterSeed({
325830
326167
  session,
325831
326168
  quotedTablePath: target
@@ -325834,11 +326171,14 @@ async function buildSourceIntoStorage(params) {
325834
326171
  seededThrough,
325835
326172
  storageDestinationName: destinationName,
325836
326173
  schema,
325837
- readCost: read.cost ?? await snowflakeReadCostAfterBuild(session, sourceType, federated.handle, buildSQL, queryMetadata, sourceConnection.snowflakeConnection?.database)
326174
+ readCost: passthrough.cost ?? await snowflakeReadCostAfterBuild(session, sourceType, federated.handle, buildSQL, queryMetadata, sourceConnection.snowflakeConnection?.database)
325838
326175
  };
325839
326176
  } finally {
325840
326177
  await clearSnowflakeSessionTag(session, sourceType, federatedHandle);
325841
326178
  await dispose();
326179
+ if (federatedClose) {
326180
+ await federatedClose().catch((e) => logger.warn(`Failed to close the SSH proxy a storage build federated through: ${String(e)}`));
326181
+ }
325842
326182
  }
325843
326183
  }
325844
326184
  async function buildDownstreamIntoStorage(params) {
@@ -325943,7 +326283,7 @@ async function attachDestinationReadWrite(session, destinationName, destinationC
325943
326283
  }
325944
326284
  const destinationRoot = storageDestinationRoot(environmentPath);
325945
326285
  mkdirSync3(destinationRoot, { recursive: true });
325946
- const dbPath = path14.join(destinationRoot, `${destinationName}.duckdb`);
326286
+ const dbPath = path15.join(destinationRoot, `${destinationName}.duckdb`);
325947
326287
  await session.runSQL(`ATTACH '${escapeSQL(dbPath)}' AS ${quoteIdentifier(destinationName, STORAGE_TARGET_DIALECT)}`);
325948
326288
  }
325949
326289
  function assertSupportedDestination(destinationName, destinationConnection) {
@@ -325957,7 +326297,8 @@ function sourceFederationConfig(sourceConnection) {
325957
326297
  name: sourceConnection.name ?? "src",
325958
326298
  bigqueryConnection: sourceConnection.bigqueryConnection,
325959
326299
  snowflakeConnection: sourceConnection.snowflakeConnection,
325960
- postgresConnection: sourceConnection.postgresConnection
326300
+ postgresConnection: sourceConnection.postgresConnection,
326301
+ proxy: sourceConnection.proxy
325961
326302
  };
325962
326303
  }
325963
326304
  async function createTableAndDescribe(session, quotedTablePath, selectSQL) {
@@ -326053,7 +326394,7 @@ function storageDeltaTarget(params) {
326053
326394
  init_connection();
326054
326395
  init_materialization_serve_transform();
326055
326396
  init_quoting();
326056
- import { readFileSync as readFileSync3 } from "fs";
326397
+ import { readFileSync as readFileSync4 } from "fs";
326057
326398
  import { fileURLToPath as fileURLToPath7 } from "url";
326058
326399
 
326059
326400
  // src/service/resolve_environment.ts
@@ -326246,10 +326587,6 @@ class MaterializationService {
326246
326587
  const environmentId = await this.resolveEnvironmentId(environmentName);
326247
326588
  return this.repository.listMaterializations(environmentId, packageName, options);
326248
326589
  }
326249
- async listEnvironmentMaterializations(environmentName, options) {
326250
- const environmentId = await this.resolveEnvironmentId(environmentName);
326251
- return this.repository.listMaterializationsByEnvironment(environmentId, options);
326252
- }
326253
326590
  async getLatestScheduledFireAt(environmentName, packageName) {
326254
326591
  const environmentId = await this.resolveEnvironmentId(environmentName);
326255
326592
  return this.repository.getLatestScheduledFireAt(environmentId, packageName);
@@ -327352,7 +327689,7 @@ class MaterializationService {
327352
327689
  return;
327353
327690
  let text;
327354
327691
  try {
327355
- text = readFileSync3(fileURLToPath7(location.url), "utf8");
327692
+ text = readFileSync4(fileURLToPath7(location.url), "utf8");
327356
327693
  } catch {
327357
327694
  return;
327358
327695
  }
@@ -327869,7 +328206,7 @@ var import_debug2 = __toESM(require_src5(), 1);
327869
328206
  import { isIPv6 } from "node:net";
327870
328207
  import { isIPv6 as isIPv62 } from "node:net";
327871
328208
  import { Buffer as Buffer3 } from "node:buffer";
327872
- import { createHash as createHash4 } from "node:crypto";
328209
+ import { createHash as createHash6 } from "node:crypto";
327873
328210
  import { isIP } from "node:net";
327874
328211
  var ipv4CompatibleSubnet = new import_ip_address.Address6("::/96");
327875
328212
  function ipKeyGenerator(ip, ipv6Subnet = 56) {
@@ -327978,7 +328315,7 @@ var getResetSeconds = (windowMs, resetTime) => {
327978
328315
  return resetSeconds;
327979
328316
  };
327980
328317
  var getPartitionKey = (key) => {
327981
- const hash = createHash4("sha256");
328318
+ const hash = createHash6("sha256");
327982
328319
  hash.update(key);
327983
328320
  const partitionKey = hash.digest("hex").slice(0, 12);
327984
328321
  return Buffer3.from(partitionKey).toString("base64");
@@ -328660,8 +328997,8 @@ var MCP_ENDPOINT = "/mcp";
328660
328997
  var SHUTDOWN_DRAIN_DURATION_SECONDS = Number(process.env.SHUTDOWN_DRAIN_DURATION_SECONDS || 0);
328661
328998
  var SHUTDOWN_GRACEFUL_CLOSE_TIMEOUT_SECONDS = Number(process.env.SHUTDOWN_GRACEFUL_CLOSE_TIMEOUT_SECONDS || 0);
328662
328999
  var __filename_esm = fileURLToPath8(import.meta.url);
328663
- var ROOT = path15.join(path15.dirname(__filename_esm), "app");
328664
- var SERVER_ROOT = path15.resolve(process.cwd(), process.env.SERVER_ROOT || ".");
329000
+ var ROOT = path16.join(path16.dirname(__filename_esm), "app");
329001
+ var SERVER_ROOT = path16.resolve(process.cwd(), process.env.SERVER_ROOT || ".");
328665
329002
  var API_PREFIX2 = "/api/v0";
328666
329003
  var isDevelopment = process.env["NODE_ENV"] === "development";
328667
329004
  var app = import_express.default();
@@ -328768,7 +329105,7 @@ mcpApp.all(MCP_ENDPOINT, async (req, res) => {
328768
329105
  }
328769
329106
  }
328770
329107
  });
328771
- var PUBLISHER_RUNTIME_PATH = path15.join(path15.dirname(__filename_esm), "runtime", "publisher.js");
329108
+ var PUBLISHER_RUNTIME_PATH = path16.join(path16.dirname(__filename_esm), "runtime", "publisher.js");
328772
329109
  app.get("/sdk/publisher.js", (_req, res) => {
328773
329110
  res.type("application/javascript");
328774
329111
  res.setHeader("cache-control", "public, max-age=60");
@@ -328797,7 +329134,7 @@ async function serveFromPackage(req, res) {
328797
329134
  try {
328798
329135
  const environment = await environmentStore.getEnvironment(req.params.environmentName, false);
328799
329136
  const pkg = await environment.getPackage(req.params.packageName, false);
328800
- const publicRoot = path15.join(pkg.getPackagePath(), "public");
329137
+ const publicRoot = path16.join(pkg.getPackagePath(), "public");
328801
329138
  let subPath = subPathRaw;
328802
329139
  if (subPath === "" || subPath.endsWith("/")) {
328803
329140
  subPath = subPath + "index.html";
@@ -328815,12 +329152,12 @@ async function serveFromPackage(req, res) {
328815
329152
  }
328816
329153
  return;
328817
329154
  }
328818
- const rel = path15.relative(realPublicRoot, realFullPath);
328819
- if (rel.startsWith("..") || path15.isAbsolute(rel)) {
329155
+ const rel = path16.relative(realPublicRoot, realFullPath);
329156
+ if (rel.startsWith("..") || path16.isAbsolute(rel)) {
328820
329157
  res.status(403).end();
328821
329158
  return;
328822
329159
  }
328823
- const ext = path15.extname(realFullPath).toLowerCase();
329160
+ const ext = path16.extname(realFullPath).toLowerCase();
328824
329161
  if (ext === ".html" || ext === ".htm") {
328825
329162
  const frameAncestors = process.env.PUBLISHER_FRAME_ANCESTORS || "*";
328826
329163
  res.setHeader("Content-Security-Policy", `frame-ancestors ${frameAncestors}`);
@@ -328886,20 +329223,20 @@ async function listPackageDataApps(environmentName, packageName, publicRoot) {
328886
329223
  for (const entry of entries) {
328887
329224
  if (entry.name.startsWith(".") || entry.name === "node_modules")
328888
329225
  continue;
328889
- const full = path15.join(dir, entry.name);
329226
+ const full = path16.join(dir, entry.name);
328890
329227
  let realFull;
328891
329228
  try {
328892
329229
  realFull = await fs11.realpath(full);
328893
329230
  } catch {
328894
329231
  continue;
328895
329232
  }
328896
- const contained = path15.relative(realPublicRoot, realFull);
328897
- if (contained.startsWith("..") || path15.isAbsolute(contained))
329233
+ const contained = path16.relative(realPublicRoot, realFull);
329234
+ if (contained.startsWith("..") || path16.isAbsolute(contained))
328898
329235
  continue;
328899
329236
  if (entry.isDirectory()) {
328900
329237
  await walk2(full, depth + 1);
328901
329238
  } else if (entry.isFile() && (entry.name.endsWith(".html") || entry.name.endsWith(".htm"))) {
328902
- const rel = path15.relative(publicRoot, full).replace(/\\/g, "/");
329239
+ const rel = path16.relative(publicRoot, full).replace(/\\/g, "/");
328903
329240
  let title = rel;
328904
329241
  let fit;
328905
329242
  try {
@@ -328944,14 +329281,14 @@ async function listPackageDataApps(environmentName, packageName, publicRoot) {
328944
329281
  }
328945
329282
  if (!isDevelopment) {
328946
329283
  app.use("/", import_express.default.static(ROOT));
328947
- app.use("/api-doc.html", import_express.default.static(path15.join(ROOT, "api-doc.html")));
329284
+ app.use("/api-doc.html", import_express.default.static(path16.join(ROOT, "api-doc.html")));
328948
329285
  } else {
328949
329286
  app.use(`${API_PREFIX2}`, loggerMiddleware);
328950
329287
  app.use(import_http_proxy_middleware.createProxyMiddleware({
328951
329288
  target: "http://localhost:5173",
328952
329289
  changeOrigin: true,
328953
329290
  ws: true,
328954
- pathFilter: (path16) => !path16.startsWith("/api/") && !path16.startsWith("/metrics") && !path16.startsWith("/health")
329291
+ pathFilter: (path17) => !path17.startsWith("/api/") && !path17.startsWith("/metrics") && !path17.startsWith("/health")
328955
329292
  }));
328956
329293
  }
328957
329294
  var setVersionIdError2 = (res) => {
@@ -328976,7 +329313,7 @@ app.get(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/data
328976
329313
  try {
328977
329314
  const environment = await environmentStore.getEnvironment(req.params.environmentName, false);
328978
329315
  const pkg = await environment.getPackage(req.params.packageName, false);
328979
- const dataApps = await listPackageDataApps(req.params.environmentName, req.params.packageName, path15.join(pkg.getPackagePath(), "public"));
329316
+ const dataApps = await listPackageDataApps(req.params.environmentName, req.params.packageName, path16.join(pkg.getPackagePath(), "public"));
328980
329317
  res.json(dataApps);
328981
329318
  } catch (error) {
328982
329319
  logger.error("Failed to list package data apps", { error });
@@ -329349,17 +329686,6 @@ app.post(`${API_PREFIX2}/environments/:environmentName/packages`, async (req, re
329349
329686
  res.status(status).json(json);
329350
329687
  }
329351
329688
  });
329352
- app.get(`${API_PREFIX2}/environments/:environmentName/packages/materializations`, async (req, res) => {
329353
- try {
329354
- const limit = parseNonNegativeIntParam(req.query.limit);
329355
- const offset = parseNonNegativeIntParam(req.query.offset);
329356
- const builds = await materializationController.listEnvironmentMaterializations(req.params.environmentName, { limit, offset });
329357
- res.status(200).json(builds);
329358
- } catch (error) {
329359
- const { json, status } = internalErrorToHttpError(error);
329360
- res.status(status).json(json);
329361
- }
329362
- });
329363
329689
  app.get(`${API_PREFIX2}/environments/:environmentName/packages/:packageName`, async (req, res) => {
329364
329690
  if (req.query.versionId) {
329365
329691
  setVersionIdError2(res);
@@ -329422,6 +329748,30 @@ app.get(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/mode
329422
329748
  res.status(status).json(json);
329423
329749
  }
329424
329750
  });
329751
+ app.put(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/models/*?`, async (req, res) => {
329752
+ if (req.query.versionId) {
329753
+ setVersionIdError2(res);
329754
+ return;
329755
+ }
329756
+ try {
329757
+ const result = await dashboardController.putDashboardSource(req.params.environmentName, req.params.packageName, req.params["0"], req.body);
329758
+ res.status(result.created ? 201 : 200).json(result);
329759
+ } catch (error) {
329760
+ const { json, status } = internalErrorToHttpError(error);
329761
+ const detail = {
329762
+ environmentName: req.params.environmentName,
329763
+ packageName: req.params.packageName,
329764
+ modelPath: req.params["0"],
329765
+ status,
329766
+ error
329767
+ };
329768
+ if (status >= 500)
329769
+ logger.error("Dashboard write failed", detail);
329770
+ else
329771
+ logger.warn("Dashboard write refused", detail);
329772
+ res.status(status).json(json);
329773
+ }
329774
+ });
329425
329775
  app.get(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/dashboards`, async (req, res) => {
329426
329776
  if (req.query.versionId) {
329427
329777
  setVersionIdError2(res);
@@ -329641,7 +329991,7 @@ registerLegacyRoutes(app, {
329641
329991
  materializationController
329642
329992
  });
329643
329993
  if (!isDevelopment) {
329644
- const SPA_INDEX = path15.resolve(ROOT, "index.html");
329994
+ const SPA_INDEX = path16.resolve(ROOT, "index.html");
329645
329995
  const escapeHtml = (value) => value.replace(/[<>&]/g, (c) => ({ "<": "&lt;", ">": "&gt;", "&": "&amp;" })[c] ?? c);
329646
329996
  const decodeSegment = (segment) => {
329647
329997
  if (segment === undefined)