@malloy-publisher/server 0.9.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.mjs CHANGED
@@ -205143,9 +205143,54 @@ function logInternalFailure(summary, error2, level = "error") {
205143
205143
  }
205144
205144
  });
205145
205145
  }
205146
- function internalErrorToHttpError(error2) {
205146
+ function filesystemAccessFailure(error2) {
205147
+ let current = error2;
205148
+ for (let depth = 0;depth < 8 && current instanceof Error; depth++) {
205149
+ const errno = current;
205150
+ if (typeof errno.code === "string" && errno.code in FILESYSTEM_ACCESS_DESCRIPTIONS && typeof errno.syscall === "string") {
205151
+ return errno;
205152
+ }
205153
+ current = errno.cause;
205154
+ }
205155
+ return;
205156
+ }
205157
+ function describeFilesystemAccessFailure(errno) {
205158
+ const code = errno.code ?? "";
205159
+ const target = errno.path ? ` '${errno.path}'` : "";
205160
+ return `${code}: ${FILESYSTEM_ACCESS_DESCRIPTIONS[code] ?? code}, ${errno.syscall}${target}`;
205161
+ }
205162
+ function messageWithFilesystemCause(error2) {
205163
+ const message = error2 instanceof Error ? error2.message : String(error2);
205164
+ const access = filesystemAccessFailure(error2);
205165
+ if (!access || message.includes(access.code ?? ""))
205166
+ return message;
205167
+ return `${message}: ${describeFilesystemAccessFailure(access)}`;
205168
+ }
205169
+ function errnoWireFields(error2) {
205170
+ const { code, syscall, path } = error2;
205171
+ if (typeof code !== "string")
205172
+ return;
205173
+ return {
205174
+ code,
205175
+ ...typeof syscall === "string" ? { syscall } : {},
205176
+ ...typeof path === "string" ? { path } : {}
205177
+ };
205178
+ }
205179
+ function internalErrorToHttpError(error2, { log = true } = {}) {
205180
+ const logInternal = (...args) => {
205181
+ if (log)
205182
+ logInternalFailure(...args);
205183
+ };
205184
+ const access = filesystemAccessFailure(error2);
205185
+ if (access) {
205186
+ logInternal("Filesystem access refused", error2, "warn");
205187
+ return httpError(500, `The server cannot access a path it needs (${describeFilesystemAccessFailure(access)}). ` + `Give the user the server runs as access to it.`);
205188
+ }
205147
205189
  if (error2 instanceof BadRequestError) {
205148
205190
  return httpError(400, error2.message);
205191
+ } else if (error2 instanceof ServerConfigurationError) {
205192
+ logInternal("Server configuration error", error2, "warn");
205193
+ return httpError(500, error2.message);
205149
205194
  } else if (error2 instanceof FrozenConfigError) {
205150
205195
  return httpError(403, error2.message);
205151
205196
  } else if (error2 instanceof AccessDeniedError) {
@@ -205191,7 +205236,7 @@ function internalErrorToHttpError(error2) {
205191
205236
  if (error2.callerSafe) {
205192
205237
  return httpError(502, error2.message);
205193
205238
  }
205194
- logInternalFailure("Upstream connection error", error2, "warn");
205239
+ logInternal("Upstream connection error", error2, "warn");
205195
205240
  return httpError(502, GENERIC_UPSTREAM_MESSAGE);
205196
205241
  } else if (error2 instanceof MaterializationNotFoundError) {
205197
205242
  return httpError(404, error2.message);
@@ -205202,7 +205247,7 @@ function internalErrorToHttpError(error2) {
205202
205247
  } else if (error2 instanceof WriteConflictError) {
205203
205248
  return httpError(409, error2.message);
205204
205249
  } else if (error2 instanceof WriteRolledBackError) {
205205
- logInternalFailure("Dashboard write rolled back", error2, "warn");
205250
+ logInternal("Dashboard write rolled back", error2, "warn");
205206
205251
  return httpError(500, error2.message);
205207
205252
  } else if (error2 instanceof ServiceUnavailableError) {
205208
205253
  return httpError(503, error2.message);
@@ -205213,7 +205258,7 @@ function internalErrorToHttpError(error2) {
205213
205258
  } else if (error2 instanceof NotImplementedError) {
205214
205259
  return httpError(501, error2.message);
205215
205260
  } else {
205216
- logInternalFailure("Unhandled internal error", error2);
205261
+ logInternal("Unhandled internal error", error2);
205217
205262
  return httpError(500, GENERIC_INTERNAL_MESSAGE);
205218
205263
  }
205219
205264
  }
@@ -205235,10 +205280,15 @@ function toQueryTextProblem(problem) {
205235
205280
  ...problem.at ? { at: { range: problem.at.range } } : {}
205236
205281
  };
205237
205282
  }
205238
- 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, PackageManifestError, MaterializationEligibilityError, PublisherConfigError, FrozenConfigError, AccessDeniedError, QueryCompileError, NotQueryableError, OffSurfaceError, MaterializationNotFoundError, MaterializationConflictError, WriteConflictError, WriteRolledBackError, InvalidStateTransitionError, ServiceUnavailableError, PayloadTooLargeError, ResponseUnserializableError, QueryTimeoutError;
205283
+ var GENERIC_INTERNAL_MESSAGE = "Internal server error.", GENERIC_UPSTREAM_MESSAGE = "Upstream connection error.", MAX_LOGGED_DETAIL_CHARS = 2000, FILESYSTEM_ACCESS_DESCRIPTIONS, NotImplementedError, BadRequestError, InvalidArgumentError, CompileRefusedError, EnvironmentNotFoundError, PackageNotFoundError, ModelNotFoundError, DashboardNotFoundError, ConnectionNotFoundError, TableNotFoundError, ConnectionError, DestinationNotFoundError, ConnectionAuthError, UnsupportedCatalogFormatError, ModelCompilationError, PackageManifestError, MaterializationEligibilityError, PublisherConfigError, ServerConfigurationError, FrozenConfigError, AccessDeniedError, QueryCompileError, NotQueryableError, OffSurfaceError, MaterializationNotFoundError, MaterializationConflictError, WriteConflictError, WriteRolledBackError, InvalidStateTransitionError, ServiceUnavailableError, PayloadTooLargeError, ResponseUnserializableError, QueryTimeoutError;
205239
205284
  var init_errors = __esm(() => {
205240
205285
  init_constants();
205241
205286
  init_logger();
205287
+ FILESYSTEM_ACCESS_DESCRIPTIONS = {
205288
+ EACCES: "permission denied",
205289
+ EPERM: "operation not permitted",
205290
+ EROFS: "read-only file system"
205291
+ };
205242
205292
  NotImplementedError = class NotImplementedError extends Error {
205243
205293
  constructor(message) {
205244
205294
  super(message);
@@ -205259,8 +205309,8 @@ var init_errors = __esm(() => {
205259
205309
  }
205260
205310
  };
205261
205311
  PackageNotFoundError = class PackageNotFoundError extends Error {
205262
- constructor(message) {
205263
- super(message);
205312
+ constructor(message, options) {
205313
+ super(message, options);
205264
205314
  }
205265
205315
  };
205266
205316
  ModelNotFoundError = class ModelNotFoundError extends Error {
@@ -205331,6 +205381,12 @@ var init_errors = __esm(() => {
205331
205381
  this.cause = cause;
205332
205382
  }
205333
205383
  };
205384
+ ServerConfigurationError = class ServerConfigurationError extends Error {
205385
+ constructor(message) {
205386
+ super(message);
205387
+ this.name = "ServerConfigurationError";
205388
+ }
205389
+ };
205334
205390
  FrozenConfigError = class FrozenConfigError extends Error {
205335
205391
  constructor(message = `Publisher config can't be updated when ${PUBLISHER_CONFIG_NAME} has { "frozenConfig": true }`) {
205336
205392
  super(message);
@@ -205388,8 +205444,8 @@ var init_errors = __esm(() => {
205388
205444
  }
205389
205445
  };
205390
205446
  ServiceUnavailableError = class ServiceUnavailableError extends Error {
205391
- constructor(message) {
205392
- super(message);
205447
+ constructor(message, options) {
205448
+ super(message, options);
205393
205449
  }
205394
205450
  };
205395
205451
  PayloadTooLargeError = class PayloadTooLargeError extends Error {
@@ -293869,6 +293925,26 @@ var init_gcp_impersonation = __esm(() => {
293869
293925
  impersonatedClients = new Map;
293870
293926
  });
293871
293927
 
293928
+ // src/service/google_credentials.ts
293929
+ import * as fs4 from "fs";
293930
+ function assertGoogleCredentialsIsNotADirectory() {
293931
+ const keyFile = process.env.GOOGLE_APPLICATION_CREDENTIALS;
293932
+ if (!keyFile)
293933
+ return;
293934
+ let isDirectory = false;
293935
+ try {
293936
+ isDirectory = fs4.statSync(keyFile).isDirectory();
293937
+ } catch {
293938
+ return;
293939
+ }
293940
+ if (isDirectory) {
293941
+ throw new ServerConfigurationError(`GOOGLE_APPLICATION_CREDENTIALS names a directory, not a key file: '${keyFile}'. ` + `A bind mount whose source path does not exist creates a directory there; ` + `mount the key file itself.`);
293942
+ }
293943
+ }
293944
+ var init_google_credentials = __esm(() => {
293945
+ init_errors();
293946
+ });
293947
+
293872
293948
  // src/service/quoting.ts
293873
293949
  function bareTableName(tableName) {
293874
293950
  const lastDot = tableName.lastIndexOf(".");
@@ -293923,7 +293999,7 @@ import {
293923
293999
  } from "@malloydata/malloy";
293924
294000
  import { createHash } from "crypto";
293925
294001
  import { mkdtempSync, readFileSync, writeFileSync } from "fs";
293926
- import fs4 from "fs/promises";
294002
+ import fs5 from "fs/promises";
293927
294003
  import os2 from "os";
293928
294004
  import path4 from "path";
293929
294005
  import tls from "tls";
@@ -294762,8 +294838,8 @@ async function deleteDuckLakeConnectionFile(connectionName, environmentPath) {
294762
294838
  assertSafeEnvironmentPath(environmentPath);
294763
294839
  const ducklakePath = safeJoinUnderRoot(environmentPath, `${connectionName}_ducklake.duckdb`);
294764
294840
  try {
294765
- await fs4.access(ducklakePath);
294766
- await fs4.rm(ducklakePath);
294841
+ await fs5.access(ducklakePath);
294842
+ await fs5.rm(ducklakePath);
294767
294843
  logger.info(`Removed DuckLake connection file ${connectionName}_ducklake.duckdb from ${environmentPath}`);
294768
294844
  } catch (error2) {
294769
294845
  if (error2.code === "ENOENT") {
@@ -295154,7 +295230,10 @@ async function testConnectionConfig(connectionConfig) {
295154
295230
  if (connectionConfig.type === "duckdb" || connectionConfig.type === "ducklake") {
295155
295231
  assertSafePackageName(connectionConfig.name);
295156
295232
  }
295157
- testRoot = await fs4.mkdtemp(path4.join(os2.tmpdir(), "publisher-conn-test-"));
295233
+ if (connectionConfig.type === "bigquery" && !connectionConfig.bigqueryConnection?.serviceAccountKeyJson) {
295234
+ assertGoogleCredentialsIsNotADirectory();
295235
+ }
295236
+ testRoot = await fs5.mkdtemp(path4.join(os2.tmpdir(), "publisher-conn-test-"));
295158
295237
  environmentConfig = buildEnvironmentMalloyConfig([connectionConfig], testRoot);
295159
295238
  const connection = await environmentConfig.malloyConfig.connections.lookupConnection(connectionConfig.name);
295160
295239
  if (connectionConfig.type === "duckdb") {
@@ -295198,7 +295277,7 @@ async function testConnectionConfig(connectionConfig) {
295198
295277
  }
295199
295278
  if (testRoot) {
295200
295279
  try {
295201
- await fs4.rm(testRoot, { recursive: true, force: true });
295280
+ await fs5.rm(testRoot, { recursive: true, force: true });
295202
295281
  } catch (cleanupError) {
295203
295282
  logger.warn("Error cleaning up connection test directory", {
295204
295283
  error: cleanupError instanceof Error ? cleanupError.message : String(cleanupError)
@@ -295218,6 +295297,7 @@ var init_connection = __esm(() => {
295218
295297
  init_path_safety();
295219
295298
  init_connection_config();
295220
295299
  init_gcp_impersonation();
295300
+ init_google_credentials();
295221
295301
  init_gcs_s3_utils();
295222
295302
  init_proxy();
295223
295303
  init_quoting();
@@ -302725,7 +302805,7 @@ var require_table = __commonJS((exports) => {
302725
302805
  var Big = require_big();
302726
302806
  var extend3 = require_extend();
302727
302807
  var events_1 = __require("events");
302728
- var fs5 = __require("fs");
302808
+ var fs6 = __require("fs");
302729
302809
  var is = require_is();
302730
302810
  var path5 = __require("path");
302731
302811
  var streamEvents = require_stream_events();
@@ -303035,7 +303115,7 @@ var require_table = __commonJS((exports) => {
303035
303115
  if (!metadata.sourceFormat && detectedFormat) {
303036
303116
  metadata.sourceFormat = detectedFormat;
303037
303117
  }
303038
- const jobWritable = fs5.createReadStream(source).pipe(this.createWriteStream_(metadata));
303118
+ const jobWritable = fs6.createReadStream(source).pipe(this.createWriteStream_(metadata));
303039
303119
  const [jobResponse] = await (0, events_1.once)(jobWritable, "job");
303040
303120
  return [jobResponse, jobResponse.metadata];
303041
303121
  }
@@ -316476,9 +316556,9 @@ var init_dashboard = __esm(() => {
316476
316556
  var require_pump = __commonJS((exports, module) => {
316477
316557
  var once = require_once2();
316478
316558
  var eos = require_end_of_stream4();
316479
- var fs5;
316559
+ var fs6;
316480
316560
  try {
316481
- fs5 = __require("fs");
316561
+ fs6 = __require("fs");
316482
316562
  } catch (e2) {}
316483
316563
  var noop3 = function() {};
316484
316564
  var ancient = typeof process === "undefined" ? false : /^v?\.0/.test(process.version);
@@ -316488,9 +316568,9 @@ var require_pump = __commonJS((exports, module) => {
316488
316568
  var isFS = function(stream4) {
316489
316569
  if (!ancient)
316490
316570
  return false;
316491
- if (!fs5)
316571
+ if (!fs6)
316492
316572
  return false;
316493
- return (stream4 instanceof (fs5.ReadStream || noop3) || stream4 instanceof (fs5.WriteStream || noop3)) && isFn(stream4.close);
316573
+ return (stream4 instanceof (fs6.ReadStream || noop3) || stream4 instanceof (fs6.WriteStream || noop3)) && isFn(stream4.close);
316494
316574
  };
316495
316575
  var isRequest3 = function(stream4) {
316496
316576
  return stream4.setHeader && isFn(stream4.abort);
@@ -316705,7 +316785,7 @@ var require_pend = __commonJS((exports, module) => {
316705
316785
 
316706
316786
  // ../../node_modules/fd-slicer/index.js
316707
316787
  var require_fd_slicer = __commonJS((exports) => {
316708
- var fs5 = __require("fs");
316788
+ var fs6 = __require("fs");
316709
316789
  var util6 = __require("util");
316710
316790
  var stream4 = __require("stream");
316711
316791
  var Readable4 = stream4.Readable;
@@ -316730,7 +316810,7 @@ var require_fd_slicer = __commonJS((exports) => {
316730
316810
  FdSlicer.prototype.read = function(buffer, offset, length, position, callback) {
316731
316811
  var self2 = this;
316732
316812
  self2.pend.go(function(cb) {
316733
- fs5.read(self2.fd, buffer, offset, length, position, function(err, bytesRead, buffer2) {
316813
+ fs6.read(self2.fd, buffer, offset, length, position, function(err, bytesRead, buffer2) {
316734
316814
  cb();
316735
316815
  callback(err, bytesRead, buffer2);
316736
316816
  });
@@ -316739,7 +316819,7 @@ var require_fd_slicer = __commonJS((exports) => {
316739
316819
  FdSlicer.prototype.write = function(buffer, offset, length, position, callback) {
316740
316820
  var self2 = this;
316741
316821
  self2.pend.go(function(cb) {
316742
- fs5.write(self2.fd, buffer, offset, length, position, function(err, written, buffer2) {
316822
+ fs6.write(self2.fd, buffer, offset, length, position, function(err, written, buffer2) {
316743
316823
  cb();
316744
316824
  callback(err, written, buffer2);
316745
316825
  });
@@ -316762,7 +316842,7 @@ var require_fd_slicer = __commonJS((exports) => {
316762
316842
  if (self2.refCount < 0)
316763
316843
  throw new Error("invalid unref");
316764
316844
  if (self2.autoClose) {
316765
- fs5.close(self2.fd, onCloseDone);
316845
+ fs6.close(self2.fd, onCloseDone);
316766
316846
  }
316767
316847
  function onCloseDone(err) {
316768
316848
  if (err) {
@@ -316801,7 +316881,7 @@ var require_fd_slicer = __commonJS((exports) => {
316801
316881
  if (self2.destroyed)
316802
316882
  return cb();
316803
316883
  var buffer = new Buffer(toRead);
316804
- fs5.read(self2.context.fd, buffer, 0, toRead, self2.pos, function(err, bytesRead) {
316884
+ fs6.read(self2.context.fd, buffer, 0, toRead, self2.pos, function(err, bytesRead) {
316805
316885
  if (err) {
316806
316886
  self2.destroy(err);
316807
316887
  } else if (bytesRead === 0) {
@@ -316851,7 +316931,7 @@ var require_fd_slicer = __commonJS((exports) => {
316851
316931
  self2.context.pend.go(function(cb) {
316852
316932
  if (self2.destroyed)
316853
316933
  return cb();
316854
- fs5.write(self2.context.fd, buffer, 0, buffer.length, self2.pos, function(err2, bytes) {
316934
+ fs6.write(self2.context.fd, buffer, 0, buffer.length, self2.pos, function(err2, bytes) {
316855
316935
  if (err2) {
316856
316936
  self2.destroy();
316857
316937
  cb();
@@ -317276,7 +317356,7 @@ var require_buffer_crc32 = __commonJS((exports, module) => {
317276
317356
 
317277
317357
  // ../../node_modules/yauzl/index.js
317278
317358
  var require_yauzl = __commonJS((exports) => {
317279
- var fs5 = __require("fs");
317359
+ var fs6 = __require("fs");
317280
317360
  var zlib3 = __require("zlib");
317281
317361
  var fd_slicer = require_fd_slicer();
317282
317362
  var crc32 = require_buffer_crc32();
@@ -317313,12 +317393,12 @@ var require_yauzl = __commonJS((exports) => {
317313
317393
  options.strictFileNames = false;
317314
317394
  if (callback == null)
317315
317395
  callback = defaultCallback;
317316
- fs5.open(path7, "r", function(err, fd) {
317396
+ fs6.open(path7, "r", function(err, fd) {
317317
317397
  if (err)
317318
317398
  return callback(err);
317319
317399
  fromFd(fd, options, function(err2, zipfile) {
317320
317400
  if (err2)
317321
- fs5.close(fd, defaultCallback);
317401
+ fs6.close(fd, defaultCallback);
317322
317402
  callback(err2, zipfile);
317323
317403
  });
317324
317404
  });
@@ -317342,7 +317422,7 @@ var require_yauzl = __commonJS((exports) => {
317342
317422
  options.strictFileNames = false;
317343
317423
  if (callback == null)
317344
317424
  callback = defaultCallback;
317345
- fs5.fstat(fd, function(err, stats) {
317425
+ fs6.fstat(fd, function(err, stats) {
317346
317426
  if (err)
317347
317427
  return callback(err);
317348
317428
  var reader = fd_slicer.createFromFd(fd, { autoClose: true });
@@ -317975,7 +318055,7 @@ var require_yauzl = __commonJS((exports) => {
317975
318055
  // ../../node_modules/extract-zip/index.js
317976
318056
  var require_extract_zip = __commonJS((exports, module) => {
317977
318057
  var debug = require_src5()("extract-zip");
317978
- var { createWriteStream, promises: fs5 } = __require("fs");
318058
+ var { createWriteStream, promises: fs6 } = __require("fs");
317979
318059
  var getStream = require_get_stream();
317980
318060
  var path7 = __require("path");
317981
318061
  var { promisify: promisify2 } = __require("util");
@@ -318017,8 +318097,8 @@ var require_extract_zip = __commonJS((exports, module) => {
318017
318097
  }
318018
318098
  const destDir = path7.dirname(path7.join(this.opts.dir, entry.fileName));
318019
318099
  try {
318020
- await fs5.mkdir(destDir, { recursive: true });
318021
- const canonicalDestDir = await fs5.realpath(destDir);
318100
+ await fs6.mkdir(destDir, { recursive: true });
318101
+ const canonicalDestDir = await fs6.realpath(destDir);
318022
318102
  const relativeDestDir = path7.relative(this.opts.dir, canonicalDestDir);
318023
318103
  if (relativeDestDir.split(path7.sep).includes("..")) {
318024
318104
  throw new Error(`Out of bound path "${canonicalDestDir}" found while processing file ${entry.fileName}`);
@@ -318063,7 +318143,7 @@ var require_extract_zip = __commonJS((exports, module) => {
318063
318143
  mkdirOptions.mode = procMode;
318064
318144
  }
318065
318145
  debug("mkdir", { dir: destDir, ...mkdirOptions });
318066
- await fs5.mkdir(destDir, mkdirOptions);
318146
+ await fs6.mkdir(destDir, mkdirOptions);
318067
318147
  if (isDir)
318068
318148
  return;
318069
318149
  debug("opening read stream", dest);
@@ -318071,7 +318151,7 @@ var require_extract_zip = __commonJS((exports, module) => {
318071
318151
  if (symlink) {
318072
318152
  const link = await getStream(readStream2);
318073
318153
  debug("creating symlink", link, dest);
318074
- await fs5.symlink(link, dest);
318154
+ await fs6.symlink(link, dest);
318075
318155
  } else {
318076
318156
  await pipeline2(readStream2, createWriteStream(dest, { mode: procMode }));
318077
318157
  }
@@ -318103,8 +318183,8 @@ var require_extract_zip = __commonJS((exports, module) => {
318103
318183
  if (!path7.isAbsolute(opts.dir)) {
318104
318184
  throw new Error("Target directory is expected to be absolute");
318105
318185
  }
318106
- await fs5.mkdir(opts.dir, { recursive: true });
318107
- opts.dir = await fs5.realpath(opts.dir);
318186
+ await fs6.mkdir(opts.dir, { recursive: true });
318187
+ opts.dir = await fs6.realpath(opts.dir);
318108
318188
  return new Extractor(zipPath, opts).extract();
318109
318189
  };
318110
318190
  });
@@ -318200,9 +318280,80 @@ var require_dist17 = __commonJS((exports) => {
318200
318280
  exports.default = deferred;
318201
318281
  });
318202
318282
 
318283
+ // src/package_load/error_wire.ts
318284
+ import { MalloyError as MalloyError3 } from "@malloydata/malloy";
318285
+ function serializeError(error2) {
318286
+ const serialized = serializeErrorShape(error2);
318287
+ const errno = error2 instanceof Error ? errnoWireFields(error2) : undefined;
318288
+ return errno ? { ...serialized, errno } : serialized;
318289
+ }
318290
+ function serializeErrorShape(error2) {
318291
+ if (error2 instanceof MalloyError3) {
318292
+ return {
318293
+ name: error2.name,
318294
+ message: error2.message,
318295
+ stack: error2.stack,
318296
+ malloyProblems: error2.problems,
318297
+ isCompilationError: true
318298
+ };
318299
+ }
318300
+ if (error2 instanceof ModelCompilationError) {
318301
+ return {
318302
+ name: error2.name,
318303
+ message: error2.message,
318304
+ stack: error2.stack,
318305
+ isCompilationError: true
318306
+ };
318307
+ }
318308
+ if (error2 instanceof PackageManifestError) {
318309
+ return {
318310
+ name: error2.name,
318311
+ message: error2.message,
318312
+ stack: error2.stack,
318313
+ isManifestError: true
318314
+ };
318315
+ }
318316
+ if (error2 instanceof Error) {
318317
+ return {
318318
+ name: error2.name,
318319
+ message: error2.message,
318320
+ stack: error2.stack
318321
+ };
318322
+ }
318323
+ return { name: "Error", message: String(error2) };
318324
+ }
318325
+ function deserializeError(serialized) {
318326
+ const err = new Error(serialized.message);
318327
+ err.name = serialized.name;
318328
+ if (serialized.stack)
318329
+ err.stack = serialized.stack;
318330
+ if (serialized.errno)
318331
+ Object.assign(err, serialized.errno);
318332
+ if (serialized.malloyProblems) {
318333
+ err.problems = serialized.malloyProblems;
318334
+ }
318335
+ if (serialized.isCompilationError) {
318336
+ const wrapped = new ModelCompilationError(err);
318337
+ if (serialized.stack)
318338
+ wrapped.stack = serialized.stack;
318339
+ return wrapped;
318340
+ }
318341
+ if (serialized.isManifestError) {
318342
+ const manifestError = new PackageManifestError(serialized.message);
318343
+ if (serialized.stack)
318344
+ manifestError.stack = serialized.stack;
318345
+ return manifestError;
318346
+ }
318347
+ return err;
318348
+ }
318349
+ var init_error_wire = __esm(() => {
318350
+ init_errors();
318351
+ });
318352
+
318203
318353
  // src/package_load/package_load_pool.ts
318204
318354
  var exports_package_load_pool = {};
318205
318355
  __export(exports_package_load_pool, {
318356
+ serializeError: () => serializeError,
318206
318357
  getPackageLoadWorkerCount: () => getPackageLoadWorkerCount,
318207
318358
  getPackageLoadPool: () => getPackageLoadPool,
318208
318359
  deserializeError: () => deserializeError,
@@ -318636,38 +318787,6 @@ function adaptResult(result) {
318636
318787
  timings: result.timings
318637
318788
  };
318638
318789
  }
318639
- function serializeError(error2) {
318640
- if (error2 instanceof Error) {
318641
- return {
318642
- name: error2.name,
318643
- message: error2.message,
318644
- stack: error2.stack
318645
- };
318646
- }
318647
- return { name: "Error", message: String(error2) };
318648
- }
318649
- function deserializeError(serialized) {
318650
- const err = new Error(serialized.message);
318651
- err.name = serialized.name;
318652
- if (serialized.stack)
318653
- err.stack = serialized.stack;
318654
- if (serialized.malloyProblems) {
318655
- err.problems = serialized.malloyProblems;
318656
- }
318657
- if (serialized.isCompilationError) {
318658
- const wrapped = new ModelCompilationError(err);
318659
- if (serialized.stack)
318660
- wrapped.stack = serialized.stack;
318661
- return wrapped;
318662
- }
318663
- if (serialized.isManifestError) {
318664
- const manifestError = new PackageManifestError(serialized.message);
318665
- if (serialized.stack)
318666
- manifestError.stack = serialized.stack;
318667
- return manifestError;
318668
- }
318669
- return err;
318670
- }
318671
318790
  function getPackageLoadPool() {
318672
318791
  if (singleton === null) {
318673
318792
  const n = getPackageLoadWorkerCount();
@@ -318684,8 +318803,9 @@ async function __setPackageLoadPoolForTests(pool) {
318684
318803
  }
318685
318804
  var PACKAGE_LOAD_JOB_TIMEOUT_MS, WORKER_SPAWN_TIMEOUT_MS = 30000, defaultUrlReader, singleton = null;
318686
318805
  var init_package_load_pool = __esm(() => {
318687
- init_errors();
318688
318806
  init_logger();
318807
+ init_error_wire();
318808
+ init_error_wire();
318689
318809
  PACKAGE_LOAD_JOB_TIMEOUT_MS = (() => {
318690
318810
  const raw = process.env.PACKAGE_LOAD_JOB_TIMEOUT_MS;
318691
318811
  if (raw === undefined)
@@ -318697,10 +318817,10 @@ var init_package_load_pool = __esm(() => {
318697
318817
  })();
318698
318818
  defaultUrlReader = {
318699
318819
  readURL: async (url2) => {
318700
- const { promises: fs5 } = await import("fs");
318820
+ const { promises: fs6 } = await import("fs");
318701
318821
  const { fileURLToPath: fileURLToPath4 } = await import("url");
318702
318822
  const filePath = url2.protocol === "file:" ? fileURLToPath4(url2) : url2.toString();
318703
- return fs5.readFile(filePath, "utf8");
318823
+ return fs6.readFile(filePath, "utf8");
318704
318824
  }
318705
318825
  };
318706
318826
  });
@@ -318873,7 +318993,7 @@ var init_materialization_metrics = __esm(() => {
318873
318993
  });
318874
318994
 
318875
318995
  // src/utils.ts
318876
- import * as fs5 from "fs";
318996
+ import * as fs6 from "fs";
318877
318997
  import * as path8 from "path";
318878
318998
  import { fileURLToPath as fileURLToPath4 } from "url";
318879
318999
  function ignoreDotfiles(file) {
@@ -318890,7 +319010,7 @@ var init_utils4 = __esm(() => {
318890
319010
  if (url2.protocol == "file:") {
318891
319011
  path9 = fileURLToPath4(url2);
318892
319012
  }
318893
- return fs5.promises.readFile(path9, "utf8");
319013
+ return fs6.promises.readFile(path9, "utf8");
318894
319014
  }
318895
319015
  };
318896
319016
  });
@@ -324019,7 +324139,7 @@ import {
324019
324139
  InMemoryURLReader as InMemoryURLReader2,
324020
324140
  isSourceDef as isSourceDef9,
324021
324141
  MalloyConfig as MalloyConfig2,
324022
- MalloyError as MalloyError4,
324142
+ MalloyError as MalloyError5,
324023
324143
  Annotations as Annotations6,
324024
324144
  modelDefToModelInfo as modelDefToModelInfo2,
324025
324145
  Runtime as Runtime2
@@ -324028,7 +324148,7 @@ import {
324028
324148
  MalloySQLParser,
324029
324149
  MalloySQLStatementType
324030
324150
  } from "@malloydata/malloy-sql";
324031
- import * as fs7 from "fs/promises";
324151
+ import * as fs8 from "fs/promises";
324032
324152
  import { readFileSync as readFileSync2 } from "fs";
324033
324153
  import { createRequire as createRequire2 } from "module";
324034
324154
  import * as path10 from "path";
@@ -324086,7 +324206,7 @@ async function compileErrorOf(runnable) {
324086
324206
  await runnable.getPreparedQuery();
324087
324207
  return;
324088
324208
  } catch (error2) {
324089
- return error2 instanceof MalloyError4 ? error2 : undefined;
324209
+ return error2 instanceof MalloyError5 ? error2 : undefined;
324090
324210
  }
324091
324211
  }
324092
324212
  function bindingsAllowDegradeToLive(bindings) {
@@ -325418,7 +325538,7 @@ var init_model = __esm(() => {
325418
325538
  if (error2 instanceof Error && error2.stack) {
325419
325539
  logger.error("Error stack", error2.stack);
325420
325540
  }
325421
- if (error2 instanceof MalloyError4) {
325541
+ if (error2 instanceof MalloyError5) {
325422
325542
  const problems = error2.problems;
325423
325543
  for (const problem of problems) {
325424
325544
  logger.error("Problem", problem);
@@ -325704,7 +325824,7 @@ var init_model = __esm(() => {
325704
325824
  await runnable.getPreparedQuery();
325705
325825
  compiledSource = await this.resolveAuthorizeSourceFromRunnable(runnable);
325706
325826
  } catch (error2) {
325707
- if (error2 instanceof MalloyError4 || error2 instanceof ModelCompilationError) {
325827
+ if (error2 instanceof MalloyError5 || error2 instanceof ModelCompilationError) {
325708
325828
  return;
325709
325829
  }
325710
325830
  throw error2;
@@ -326269,7 +326389,7 @@ var init_model = __esm(() => {
326269
326389
  async getQueryResults(sourceName, queryName, query, filterParams, bypassFilters, givens, abortSignal, queryMetadataInput, responseShape = "full", bypassAuthorize = false, includeHiddenFilesAndSources = false) {
326270
326390
  const startTime = performance.now();
326271
326391
  if (this.compilationError) {
326272
- if (this.compilationError instanceof MalloyError4 || this.compilationError instanceof ModelCompilationError) {
326392
+ if (this.compilationError instanceof MalloyError5 || this.compilationError instanceof ModelCompilationError) {
326273
326393
  throw this.compilationError;
326274
326394
  }
326275
326395
  throw new BadRequestError(`Model compilation failed: ${this.compilationError.message}`);
@@ -326415,7 +326535,7 @@ run: ${sourceName ? `${quoteMalloyIdentifier2(sourceName)} -> ` : ""}${quoteMall
326415
326535
  if (error2 instanceof FilterValidationError) {
326416
326536
  throw new BadRequestError(error2.message);
326417
326537
  }
326418
- if (error2 instanceof MalloyError4) {
326538
+ if (error2 instanceof MalloyError5) {
326419
326539
  throw error2;
326420
326540
  }
326421
326541
  const errorMessage = error2 instanceof Error ? error2.message : String(error2);
@@ -326523,7 +326643,7 @@ run: ${sourceName ? `${quoteMalloyIdentifier2(sourceName)} -> ` : ""}${quoteMall
326523
326643
  });
326524
326644
  throw new BadRequestError(err instanceof Error ? err.message : String(err));
326525
326645
  }
326526
- if (err instanceof MalloyError4) {
326646
+ if (err instanceof MalloyError5) {
326527
326647
  throw err;
326528
326648
  }
326529
326649
  const errorMessage = err instanceof Error ? err.message : String(err);
@@ -326851,7 +326971,7 @@ run: ${sourceName ? `${quoteMalloyIdentifier2(sourceName)} -> ` : ""}${quoteMall
326851
326971
  recordNotebookCellExecution(this.notebookFormat(), kind, "ok", performance.now() - started);
326852
326972
  return result;
326853
326973
  } catch (error2) {
326854
- recordNotebookCellExecution(this.notebookFormat(), kind, error2 instanceof AccessDeniedError ? "denied" : error2 instanceof NotQueryableError ? "not_queryable" : error2 instanceof BadRequestError || error2 instanceof MalloyError4 ? "bad_request" : "error", performance.now() - started);
326974
+ recordNotebookCellExecution(this.notebookFormat(), kind, error2 instanceof AccessDeniedError ? "denied" : error2 instanceof NotQueryableError ? "not_queryable" : error2 instanceof BadRequestError || error2 instanceof MalloyError5 ? "bad_request" : "error", performance.now() - started);
326855
326975
  throw error2;
326856
326976
  }
326857
326977
  }
@@ -326963,7 +327083,7 @@ run: ${sourceName ? `${quoteMalloyIdentifier2(sourceName)} -> ` : ""}${quoteMall
326963
327083
  });
326964
327084
  throw new BadRequestError(error2 instanceof Error ? error2.message : String(error2));
326965
327085
  }
326966
- if (error2 instanceof MalloyError4) {
327086
+ if (error2 instanceof MalloyError5) {
326967
327087
  throw error2;
326968
327088
  }
326969
327089
  if (error2 instanceof PayloadTooLargeError) {
@@ -327007,7 +327127,7 @@ run: ${sourceName ? `${quoteMalloyIdentifier2(sourceName)} -> ` : ""}${quoteMall
327007
327127
  throw new ModelNotFoundError(`${modelPath} does not exist.`);
327008
327128
  }
327009
327129
  try {
327010
- if (!(await fs7.stat(fullModelPath)).isFile()) {
327130
+ if (!(await fs8.stat(fullModelPath)).isFile()) {
327011
327131
  throw new ModelNotFoundError(`${modelPath} is not a file.`);
327012
327132
  }
327013
327133
  } catch {
@@ -327111,7 +327231,7 @@ run: ${sourceName ? `${quoteMalloyIdentifier2(sourceName)} -> ` : ""}${quoteMall
327111
327231
  let fileContents = undefined;
327112
327232
  let parse5 = undefined;
327113
327233
  try {
327114
- fileContents = await fs7.readFile(modelURL, "utf8");
327234
+ fileContents = await fs8.readFile(modelURL, "utf8");
327115
327235
  } catch {
327116
327236
  throw new ModelNotFoundError("Model not found: " + modelPath);
327117
327237
  }
@@ -327205,7 +327325,7 @@ run: ${sourceName ? `${quoteMalloyIdentifier2(sourceName)} -> ` : ""}${quoteMall
327205
327325
  async getFileText(packagePath) {
327206
327326
  const fullPath = path10.join(packagePath, this.modelPath);
327207
327327
  try {
327208
- return await fs7.readFile(fullPath, "utf8");
327328
+ return await fs8.readFile(fullPath, "utf8");
327209
327329
  } catch {
327210
327330
  throw new ModelNotFoundError(`Model file not found: ${this.modelPath}`);
327211
327331
  }
@@ -328192,7 +328312,7 @@ var require_minimatch = __commonJS((exports, module) => {
328192
328312
 
328193
328313
  // ../../node_modules/recursive-readdir/index.js
328194
328314
  var require_recursive_readdir = __commonJS((exports, module) => {
328195
- var fs8 = __require("fs");
328315
+ var fs9 = __require("fs");
328196
328316
  var p2 = __require("path");
328197
328317
  var minimatch = require_minimatch();
328198
328318
  function patternMatcher(pattern) {
@@ -328226,7 +328346,7 @@ var require_recursive_readdir = __commonJS((exports, module) => {
328226
328346
  }
328227
328347
  ignores = ignores.map(toMatcherFunction);
328228
328348
  var list = [];
328229
- fs8.readdir(path11, function(err, files) {
328349
+ fs9.readdir(path11, function(err, files) {
328230
328350
  if (err) {
328231
328351
  return callback(err);
328232
328352
  }
@@ -328236,7 +328356,7 @@ var require_recursive_readdir = __commonJS((exports, module) => {
328236
328356
  }
328237
328357
  files.forEach(function(file) {
328238
328358
  var filePath = p2.join(path11, file);
328239
- fs8.stat(filePath, function(_err, stats) {
328359
+ fs9.stat(filePath, function(_err, stats) {
328240
328360
  if (_err) {
328241
328361
  return callback(_err);
328242
328362
  }
@@ -346985,12 +347105,12 @@ var require_dist19 = __commonJS((exports, module) => {
346985
347105
  throw new Error(`Unknown format "${name}"`);
346986
347106
  return f3;
346987
347107
  };
346988
- function addFormats(ajv, list, fs11, exportName) {
347108
+ function addFormats(ajv, list, fs12, exportName) {
346989
347109
  var _a2;
346990
347110
  var _b;
346991
347111
  (_a2 = (_b = ajv.opts.code).formats) !== null && _a2 !== undefined || (_b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`);
346992
347112
  for (const f3 of list)
346993
- ajv.addFormat(f3, fs11[f3]);
347113
+ ajv.addFormat(f3, fs12[f3]);
346994
347114
  }
346995
347115
  module.exports = exports = formatsPlugin;
346996
347116
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -356704,6 +356824,7 @@ init_errors();
356704
356824
  init_logger();
356705
356825
  init_gcs_s3_utils();
356706
356826
  init_gcp_impersonation();
356827
+ init_google_credentials();
356707
356828
  init_introspection_sql();
356708
356829
  var import_bigquery = __toESM(require_src144(), 1);
356709
356830
  import { ClientSecretCredential } from "@azure/identity";
@@ -356767,6 +356888,7 @@ async function createBigQueryClient(connection) {
356767
356888
  throw new Error("BigQuery project ID is required. Either set the defaultProjectId in the connection configuration or the project_id in the service account key JSON.");
356768
356889
  }
356769
356890
  } else if (Object.keys(connection.bigqueryConnection).length === 0 && process.env.GOOGLE_APPLICATION_CREDENTIALS) {
356891
+ assertGoogleCredentialsIsNotADirectory();
356770
356892
  config2.keyFilename = process.env.GOOGLE_APPLICATION_CREDENTIALS || "";
356771
356893
  } else {
356772
356894
  throw new Error("BigQuery connection is required, either set the bigqueryConnection in the connection configuration or set the GOOGLE_APPLICATION_CREDENTIALS environment variable.");
@@ -364842,11 +364964,21 @@ class PackageController {
364842
364964
  const packageName = body.name;
364843
364965
  const environment = await this.environmentStore.getEnvironment(environmentName, false);
364844
364966
  let result;
364845
- if (body.location) {
364846
- const bodyLocation = body.location;
364847
- result = await environment.installPackage(packageName, (stagingPath) => this.downloadInto(environmentName, packageName, bodyLocation, stagingPath), (pkg) => formatPublishRejections(pkg));
364848
- } else {
364849
- result = await environment.addPackage(packageName);
364967
+ try {
364968
+ if (body.location) {
364969
+ const bodyLocation = body.location;
364970
+ result = await environment.installPackage(packageName, (stagingPath) => this.downloadInto(environmentName, packageName, bodyLocation, stagingPath), (pkg) => formatPublishRejections(pkg));
364971
+ } else {
364972
+ result = await environment.addPackage(packageName);
364973
+ }
364974
+ } catch (error2) {
364975
+ const answered = internalErrorToHttpError(error2, {
364976
+ log: false
364977
+ });
364978
+ if (answered.status >= 500) {
364979
+ environment.recordPackageAddFailure(packageName, answered.json.message);
364980
+ }
364981
+ throw error2;
364850
364982
  }
364851
364983
  if (!result) {
364852
364984
  throw new Error(`Failed to create package ${packageName}`);
@@ -366556,7 +366688,7 @@ var import_client_s33 = __toESM(require_dist_cjs75(), 1);
366556
366688
  import { Storage as Storage2 } from "@google-cloud/storage";
366557
366689
  var import_extract_zip = __toESM(require_extract_zip(), 1);
366558
366690
  import crypto5 from "crypto";
366559
- import * as fs10 from "fs";
366691
+ import * as fs11 from "fs";
366560
366692
  import * as os3 from "os";
366561
366693
  import * as path13 from "path";
366562
366694
 
@@ -372408,7 +372540,7 @@ class StorageManager {
372408
372540
  // src/service/environment.ts
372409
372541
  init_notebook();
372410
372542
  init_dashboard();
372411
- import { MalloyError as MalloyError6, Runtime as Runtime3 } from "@malloydata/malloy";
372543
+ import { MalloyError as MalloyError7, Runtime as Runtime3 } from "@malloydata/malloy";
372412
372544
 
372413
372545
  // src/service/notebook_lint.ts
372414
372546
  init_dashboard();
@@ -372853,13 +372985,13 @@ init_errors();
372853
372985
  init_authorize();
372854
372986
  init_given();
372855
372987
  import crypto4 from "crypto";
372856
- import * as fs9 from "fs";
372988
+ import * as fs10 from "fs";
372857
372989
  import * as path12 from "path";
372858
372990
  import { fileURLToPath as fileURLToPath7, pathToFileURL as pathToFileURL3 } from "url";
372859
372991
 
372860
372992
  // src/service/compile_restriction.ts
372861
372993
  init_errors();
372862
- import { Malloy, MalloyError as MalloyError3 } from "@malloydata/malloy";
372994
+ import { Malloy, MalloyError as MalloyError4 } from "@malloydata/malloy";
372863
372995
  var RESTRICTED_CONSTRUCT_CODE = "restricted-construct-forbidden";
372864
372996
  var SYNTAX_ERROR_CODE = "syntax-error";
372865
372997
  function isParseFailure(problem) {
@@ -372882,7 +373014,7 @@ async function assertNoRestrictedConstructs(runtime, model, source) {
372882
373014
  });
372883
373015
  problems = compiled.problems ?? [];
372884
373016
  } catch (error2) {
372885
- if (!(error2 instanceof MalloyError3))
373017
+ if (!(error2 instanceof MalloyError4))
372886
373018
  throw error2;
372887
373019
  problems = error2.problems;
372888
373020
  }
@@ -372912,7 +373044,7 @@ init_connection_config();
372912
373044
  init_logger();
372913
373045
  var import_client_s32 = __toESM(require_dist_cjs75(), 1);
372914
373046
  import { Storage } from "@google-cloud/storage";
372915
- import * as fs6 from "fs/promises";
373047
+ import * as fs7 from "fs/promises";
372916
373048
  import { fileURLToPath as fileURLToPath5 } from "url";
372917
373049
 
372918
373050
  // src/storage/DatabaseInterface.ts
@@ -372948,9 +373080,9 @@ async function readManifestBytes(uri) {
372948
373080
  return res.Body.transformToString();
372949
373081
  }
372950
373082
  if (uri.startsWith("file://")) {
372951
- return fs6.readFile(fileURLToPath5(uri), "utf8");
373083
+ return fs7.readFile(fileURLToPath5(uri), "utf8");
372952
373084
  }
372953
- return fs6.readFile(uri, "utf8");
373085
+ return fs7.readFile(uri, "utf8");
372954
373086
  }
372955
373087
  async function fetchManifestEntries(uri) {
372956
373088
  const raw = await readManifestBytes(uri);
@@ -373009,7 +373141,7 @@ init_logger();
373009
373141
  init_notebook_metrics();
373010
373142
  init_materialization_metrics();
373011
373143
  var import_recursive_readdir = __toESM(require_recursive_readdir(), 1);
373012
- import * as fs8 from "fs/promises";
373144
+ import * as fs9 from "fs/promises";
373013
373145
  import * as path11 from "path";
373014
373146
  import { pathToFileURL as pathToFileURL2 } from "url";
373015
373147
  import"@malloydata/db-duckdb/native";
@@ -373020,7 +373152,7 @@ import {
373020
373152
  EmptyURLReader,
373021
373153
  FixedConnectionMap as FixedConnectionMap2,
373022
373154
  MalloyConfig as MalloyConfig3,
373023
- MalloyError as MalloyError5
373155
+ MalloyError as MalloyError6
373024
373156
  } from "@malloydata/malloy";
373025
373157
 
373026
373158
  // src/package_load_metrics.ts
@@ -373910,7 +374042,7 @@ function toTableNameManifest(entries) {
373910
374042
  return out;
373911
374043
  }
373912
374044
  function packageLoadFailureStatus(error2) {
373913
- if (error2 instanceof ModelCompilationError || error2 instanceof MalloyError5) {
374045
+ if (error2 instanceof ModelCompilationError || error2 instanceof MalloyError6) {
373914
374046
  return "compilation_error";
373915
374047
  }
373916
374048
  if (error2 instanceof BadRequestError || error2 instanceof PackageManifestError) {
@@ -374100,11 +374232,11 @@ class Package {
374100
374232
  if (!cleanupDirectoryOnFailure) {
374101
374233
  logger.info(`Preserving existing package directory after failed load: ${packagePath}`);
374102
374234
  } else {
374103
- const stat7 = await fs8.lstat(packagePath).catch(() => null);
374235
+ const stat7 = await fs9.lstat(packagePath).catch(() => null);
374104
374236
  if (stat7?.isSymbolicLink()) {
374105
374237
  logger.info(`Skipping cleanup of symlinked package path on failure: ${packagePath}`);
374106
374238
  } else {
374107
- await fs8.rm(packagePath, { recursive: true, force: true });
374239
+ await fs9.rm(packagePath, { recursive: true, force: true });
374108
374240
  logger.info(`Cleaned up failed package directory: ${packagePath}`);
374109
374241
  }
374110
374242
  }
@@ -374126,10 +374258,10 @@ class Package {
374126
374258
  defaultConnectionName: "duckdb"
374127
374259
  }).catch((err) => {
374128
374260
  const realError = err instanceof Error ? err : new Error(`Package-load worker pool failure: ${String(err)}`);
374129
- if (realError instanceof MalloyError5 || realError instanceof ModelCompilationError || realError instanceof PackageManifestError) {
374261
+ if (realError instanceof MalloyError6 || realError instanceof ModelCompilationError || realError instanceof PackageManifestError) {
374130
374262
  throw realError;
374131
374263
  }
374132
- throw new ServiceUnavailableError(`Package-load worker pool unavailable: ${realError.message}`);
374264
+ throw new ServiceUnavailableError(`Package-load worker pool unavailable: ${realError.message}`, { cause: realError });
374133
374265
  });
374134
374266
  const [outcome, databases] = await Promise.all([
374135
374267
  workerOutcome,
@@ -374184,7 +374316,7 @@ class Package {
374184
374316
  });
374185
374317
  }
374186
374318
  if (sm.modelPath.endsWith(MODEL_FILE_SUFFIX)) {
374187
- const modelSource = await fs8.readFile(path11.join(packagePath, sm.modelPath), "utf-8");
374319
+ const modelSource = await fs9.readFile(path11.join(packagePath, sm.modelPath), "utf-8");
374188
374320
  assertPersistNamesQuoted(modelSource, sm.modelPath);
374189
374321
  }
374190
374322
  models.set(sm.modelPath, model);
@@ -374804,10 +374936,10 @@ class Package {
374804
374936
  });
374805
374937
  } catch (err) {
374806
374938
  const realError = err instanceof Error ? err : new Error(`Package-load worker pool failure: ${String(err)}`);
374807
- if (realError instanceof MalloyError5 || realError instanceof ModelCompilationError || realError instanceof PackageManifestError) {
374939
+ if (realError instanceof MalloyError6 || realError instanceof ModelCompilationError || realError instanceof PackageManifestError) {
374808
374940
  throw realError;
374809
374941
  }
374810
- throw new ServiceUnavailableError(`Package-load worker pool unavailable: ${realError.message}`);
374942
+ throw new ServiceUnavailableError(`Package-load worker pool unavailable: ${realError.message}`, { cause: realError });
374811
374943
  }
374812
374944
  const nextModels = new Map;
374813
374945
  const renderTagWarnings = [];
@@ -374913,7 +375045,7 @@ class Package {
374913
375045
  }
374914
375046
  async claimsToBeADashboard(modelPath) {
374915
375047
  try {
374916
- const source = await fs8.readFile(safeJoinUnderRoot(this.packagePath, modelPath), "utf8");
375048
+ const source = await fs9.readFile(safeJoinUnderRoot(this.packagePath, modelPath), "utf8");
374917
375049
  return hasArtifactLineOutsideBlocks(source, /^##?[ \t]*artifact\b/);
374918
375050
  } catch {
374919
375051
  return false;
@@ -374925,7 +375057,7 @@ class Package {
374925
375057
  return model.carriesNotebookArtifactNote();
374926
375058
  if (!model.getCompilationError())
374927
375059
  return false;
374928
- const source = await fs8.readFile(safeJoinUnderRoot(this.packagePath, modelPath), "utf8");
375060
+ const source = await fs9.readFile(safeJoinUnderRoot(this.packagePath, modelPath), "utf8");
374929
375061
  return claimsToBeANotebook(source);
374930
375062
  } catch {
374931
375063
  return false;
@@ -375238,7 +375370,7 @@ class Package {
375238
375370
  const dir = safeJoinUnderRoot(this.packagePath, DASHBOARDS_DIR);
375239
375371
  let entries;
375240
375372
  try {
375241
- entries = await fs8.readdir(dir);
375373
+ entries = await fs9.readdir(dir);
375242
375374
  } catch {
375243
375375
  return [];
375244
375376
  }
@@ -375344,8 +375476,11 @@ class Package {
375344
375476
  static async validatePackageManifestExistsOrThrowError(packagePath) {
375345
375477
  const packageConfigPath = safeJoinUnderRoot(packagePath, PACKAGE_MANIFEST_NAME);
375346
375478
  try {
375347
- await fs8.stat(packageConfigPath);
375348
- } catch {
375479
+ await fs9.stat(packageConfigPath);
375480
+ } catch (error2) {
375481
+ const code = error2.code;
375482
+ if (code !== "ENOENT" && code !== "ENOTDIR")
375483
+ throw error2;
375349
375484
  logger.error(`Can't find ${packageConfigPath}`);
375350
375485
  throw new PackageNotFoundError(`Package manifest for ${packagePath} does not exist.`);
375351
375486
  }
@@ -375477,6 +375612,7 @@ async function denyHiddenAsNotQueryable(convert, gate) {
375477
375612
  throw error2;
375478
375613
  }
375479
375614
  }
375615
+ var MAX_RECORDED_ADD_FAILURES = 100;
375480
375616
 
375481
375617
  class Environment {
375482
375618
  packages = new Map;
@@ -375484,6 +375620,7 @@ class Environment {
375484
375620
  packageStatuses = new Map;
375485
375621
  failedPackages = new Map;
375486
375622
  mountErrors = new Map;
375623
+ recordedAddFailures = [];
375487
375624
  staleCompileErrors = new Map;
375488
375625
  malloyConfig;
375489
375626
  connectionMutex = new Mutex;
@@ -375523,11 +375660,11 @@ class Environment {
375523
375660
  return;
375524
375661
  const readmePath = path12.join(this.environmentPath, "README.md");
375525
375662
  try {
375526
- await fs9.promises.writeFile(readmePath, readme, "utf-8");
375663
+ await fs10.promises.writeFile(readmePath, readme, "utf-8");
375527
375664
  logger.info(`Updated README.md for environment ${this.environmentName}`);
375528
375665
  } catch (err) {
375529
375666
  logger.error(`Failed to write README.md`, { error: err });
375530
- throw new Error(`Failed to update environment README`);
375667
+ throw new Error(`Failed to update environment README`, { cause: err });
375531
375668
  }
375532
375669
  }
375533
375670
  async update(payload) {
@@ -375561,7 +375698,7 @@ class Environment {
375561
375698
  }
375562
375699
  static async create(environmentName, environmentPath, connections, storageDestinations = []) {
375563
375700
  assertSafeEnvironmentPath(environmentPath);
375564
- if (!(await fs9.promises.stat(environmentPath))?.isDirectory()) {
375701
+ if (!(await fs10.promises.stat(environmentPath))?.isDirectory()) {
375565
375702
  throw new EnvironmentNotFoundError(`Environment path ${environmentPath} not found`);
375566
375703
  }
375567
375704
  logger.info(`Creating environment with connection configuration`);
@@ -375579,7 +375716,7 @@ class Environment {
375579
375716
  async reloadEnvironmentMetadata() {
375580
375717
  let readme = "";
375581
375718
  try {
375582
- readme = (await fs9.promises.readFile(safeJoinUnderRoot(this.environmentPath, README_NAME))).toString();
375719
+ readme = (await fs10.promises.readFile(safeJoinUnderRoot(this.environmentPath, README_NAME))).toString();
375583
375720
  } catch {}
375584
375721
  this.metadata = {
375585
375722
  ...this.metadata,
@@ -375623,7 +375760,7 @@ class Environment {
375623
375760
  if (scope === "append") {
375624
375761
  let modelContent = "";
375625
375762
  try {
375626
- modelContent = await fs9.promises.readFile(modelPath, "utf8");
375763
+ modelContent = await fs10.promises.readFile(modelPath, "utf8");
375627
375764
  } catch {}
375628
375765
  fullSource = modelContent ? `${modelContent}
375629
375766
  ${source}` : source ?? "";
@@ -375647,7 +375784,7 @@ ${source}` : source ?? "";
375647
375784
  const pkg = await this._loadOrGetPackageLocked(packageName);
375648
375785
  let { model: gateModel, exact: hasExactGateModel } = pkg.getCompileAuthorizationModel(modelName);
375649
375786
  if (!hasExactGateModel && source !== undefined) {
375650
- const diskTarget = await fs9.promises.stat(modelPath).catch(() => {
375787
+ const diskTarget = await fs10.promises.stat(modelPath).catch(() => {
375651
375788
  return;
375652
375789
  });
375653
375790
  if (diskTarget?.isFile()) {
@@ -375701,7 +375838,7 @@ ${source}` : source ?? "";
375701
375838
  }, () => hasExactGateModel ? gateModel.assertAuthorizedForRunnable(finalQuery, givens ?? {}) : gateModel.assertAuthorizedFromCompiledRunnable(finalQuery, givens ?? {}));
375702
375839
  }
375703
375840
  } catch (error2) {
375704
- if (!(error2 instanceof MalloyError6))
375841
+ if (!(error2 instanceof MalloyError7))
375705
375842
  throw error2;
375706
375843
  }
375707
375844
  }
@@ -375717,7 +375854,7 @@ ${source}` : source ?? "";
375717
375854
  replacement: source === undefined ? undefined : { modelPath: modelName, source }
375718
375855
  });
375719
375856
  } catch (error2) {
375720
- if (error2 instanceof MalloyError6 || error2 instanceof ModelCompilationError || error2 instanceof PackageManifestError) {
375857
+ if (error2 instanceof MalloyError7 || error2 instanceof ModelCompilationError || error2 instanceof PackageManifestError) {
375721
375858
  throw error2;
375722
375859
  }
375723
375860
  throw new ServiceUnavailableError(`Package compile worker unavailable: ${error2 instanceof Error ? error2.message : String(error2)}`);
@@ -375756,7 +375893,7 @@ ${source}` : source ?? "";
375756
375893
  ], compiled.modelPath);
375757
375894
  }
375758
375895
  }
375759
- const lintText = !(isNotebookModelPath(compiled.modelPath) || isDashboardModelPath(compiled.modelPath)) ? undefined : compiled.modelSourceText ?? (compiled.modelPath === modelName && source !== undefined ? source : await fs9.promises.readFile(path12.join(packagePath, compiled.modelPath), "utf8").catch(() => {
375896
+ const lintText = !(isNotebookModelPath(compiled.modelPath) || isDashboardModelPath(compiled.modelPath)) ? undefined : compiled.modelSourceText ?? (compiled.modelPath === modelName && source !== undefined ? source : await fs10.promises.readFile(path12.join(packagePath, compiled.modelPath), "utf8").catch(() => {
375760
375897
  return;
375761
375898
  }));
375762
375899
  if (lintText !== undefined) {
@@ -375786,7 +375923,7 @@ ${source}` : source ?? "";
375786
375923
  environment: this.environmentName,
375787
375924
  reason: "base_model_load_failed"
375788
375925
  });
375789
- if (error2 instanceof MalloyError6) {
375926
+ if (error2 instanceof MalloyError7) {
375790
375927
  throw new CompileRefusedError(`Cannot validate the submitted source: the model ` + `"${modelName}" does not compile, so there is nothing ` + `to check the submitted source against. Problems: ` + error2.problems.map((p2) => p2.message).join("; "));
375791
375928
  }
375792
375929
  throw new CompileRefusedError(`Cannot validate the submitted source: the model ` + `"${modelName}" could not be loaded to check it against.`);
@@ -375829,7 +375966,7 @@ ${source}` : source ?? "";
375829
375966
  if (typeof givenCode === "string" && givenCode.startsWith("runtime-given-")) {
375830
375967
  throw new BadRequestError(error2 instanceof Error ? error2.message : String(error2));
375831
375968
  }
375832
- if (error2 instanceof MalloyError6) {
375969
+ if (error2 instanceof MalloyError7) {
375833
375970
  throw error2;
375834
375971
  }
375835
375972
  }
@@ -375845,7 +375982,7 @@ ${source}` : source ?? "";
375845
375982
  sql
375846
375983
  };
375847
375984
  } catch (error2) {
375848
- if (error2 instanceof MalloyError6) {
375985
+ if (error2 instanceof MalloyError7) {
375849
375986
  return {
375850
375987
  problems: tagProblems([
375851
375988
  ...error2.problems,
@@ -375898,7 +376035,7 @@ ${source}` : source ?? "";
375898
376035
  try {
375899
376036
  const destinationRoot = storageDestinationRoot(this.environmentPath);
375900
376037
  if (this.destinations.length > 0) {
375901
- fs9.mkdirSync(destinationRoot, { recursive: true });
376038
+ fs10.mkdirSync(destinationRoot, { recursive: true });
375902
376039
  }
375903
376040
  this.destinationMalloyConfig = buildEnvironmentMalloyConfig(this.destinations, destinationRoot);
375904
376041
  } catch (error2) {
@@ -376019,7 +376156,7 @@ ${source}` : source ?? "";
376019
376156
  }
376020
376157
  async _readModelFileLocked(target) {
376021
376158
  try {
376022
- return await fs9.promises.readFile(target, "utf8");
376159
+ return await fs10.promises.readFile(target, "utf8");
376023
376160
  } catch (error2) {
376024
376161
  if (error2.code !== "ENOENT")
376025
376162
  throw error2;
@@ -376027,10 +376164,10 @@ ${source}` : source ?? "";
376027
376164
  }
376028
376165
  }
376029
376166
  async _writeModelFileLocked(target, source) {
376030
- await fs9.promises.mkdir(path12.dirname(target), { recursive: true });
376167
+ await fs10.promises.mkdir(path12.dirname(target), { recursive: true });
376031
376168
  const temporary = `${target}.${crypto4.randomUUID()}.tmp`;
376032
- await fs9.promises.writeFile(temporary, source, "utf8");
376033
- await fs9.promises.rename(temporary, target);
376169
+ await fs10.promises.writeFile(temporary, source, "utf8");
376170
+ await fs10.promises.rename(temporary, target);
376034
376171
  }
376035
376172
  async writeModelFileTransactional(packageName, modelPath, source, check2, verify) {
376036
376173
  assertSafePackageName(packageName);
@@ -376047,7 +376184,7 @@ ${source}` : source ?? "";
376047
376184
  if (previous !== undefined)
376048
376185
  await this._writeModelFileLocked(target, previous);
376049
376186
  else
376050
- await fs9.promises.rm(target, { force: true });
376187
+ await fs10.promises.rm(target, { force: true });
376051
376188
  await this._loadOrGetPackageLocked(packageName, true).catch(() => {
376052
376189
  return;
376053
376190
  });
@@ -376075,7 +376212,7 @@ ${source}` : source ?? "";
376075
376212
  if (path12.basename(dir) !== dirName)
376076
376213
  continue;
376077
376214
  try {
376078
- await fs9.promises.rm(dir, { recursive: true, force: true });
376215
+ await fs10.promises.rm(dir, { recursive: true, force: true });
376079
376216
  } catch (err) {
376080
376217
  logger.warn(`Failed to sweep stale ${dirName} dir at ${dir}`, {
376081
376218
  error: err
@@ -376181,7 +376318,7 @@ ${source}` : source ?? "";
376181
376318
  async addPackage(packageName, options = {}) {
376182
376319
  assertSafePackageName(packageName);
376183
376320
  const packagePath = safeJoinUnderRoot(this.environmentPath, packageName);
376184
- if (!await fs9.promises.access(packagePath).then(() => true).catch(() => false) || !(await fs9.promises.stat(packagePath))?.isDirectory()) {
376321
+ if (!await fs10.promises.access(packagePath).then(() => true).catch(() => false) || !(await fs10.promises.stat(packagePath))?.isDirectory()) {
376185
376322
  throw new PackageNotFoundError(`Package ${packageName} not found`);
376186
376323
  }
376187
376324
  this.assertCanAdmitNewPackage(packageName, "add a new package", options.allowAdmission === true);
@@ -376213,7 +376350,7 @@ ${source}` : source ?? "";
376213
376350
  async installPackage(packageName, downloader, validate) {
376214
376351
  assertSafePackageName(packageName);
376215
376352
  const stagingPath = this.allocateStagingPath(packageName);
376216
- await fs9.promises.mkdir(path12.dirname(stagingPath), { recursive: true });
376353
+ await fs10.promises.mkdir(path12.dirname(stagingPath), { recursive: true });
376217
376354
  logger.debug("install.phase1.download.started", {
376218
376355
  environmentName: this.environmentName,
376219
376356
  packageName,
@@ -376223,7 +376360,7 @@ ${source}` : source ?? "";
376223
376360
  try {
376224
376361
  await downloader(stagingPath);
376225
376362
  } catch (err) {
376226
- await fs9.promises.rm(stagingPath, { recursive: true, force: true }).catch(() => {});
376363
+ await fs10.promises.rm(stagingPath, { recursive: true, force: true }).catch(() => {});
376227
376364
  throw err;
376228
376365
  }
376229
376366
  logger.debug("install.phase1.download.completed", {
@@ -376239,13 +376376,13 @@ ${source}` : source ?? "";
376239
376376
  const canonicalPath = safeJoinUnderRoot(this.environmentPath, packageName);
376240
376377
  let retiredPath;
376241
376378
  const oldPackage = this.packages.get(packageName);
376242
- const oldExistsOnDisk = await fs9.promises.access(canonicalPath).then(() => true).catch(() => false);
376379
+ const oldExistsOnDisk = await fs10.promises.access(canonicalPath).then(() => true).catch(() => false);
376243
376380
  if (oldExistsOnDisk) {
376244
376381
  retiredPath = this.allocateRetiredPath(packageName);
376245
- await fs9.promises.mkdir(path12.dirname(retiredPath), {
376382
+ await fs10.promises.mkdir(path12.dirname(retiredPath), {
376246
376383
  recursive: true
376247
376384
  });
376248
- await fs9.promises.rename(canonicalPath, retiredPath);
376385
+ await fs10.promises.rename(canonicalPath, retiredPath);
376249
376386
  logger.debug("install.phase2.retired_old", {
376250
376387
  environmentName: this.environmentName,
376251
376388
  packageName,
@@ -376254,7 +376391,7 @@ ${source}` : source ?? "";
376254
376391
  }
376255
376392
  let newPackage;
376256
376393
  try {
376257
- await fs9.promises.rename(stagingPath, canonicalPath);
376394
+ await fs10.promises.rename(stagingPath, canonicalPath);
376258
376395
  this.setPackageStatus(packageName, "loading" /* LOADING */);
376259
376396
  newPackage = await Package.create(this.environmentName, packageName, canonicalPath, () => this.malloyConfig.malloyConfig, true);
376260
376397
  this.attachDestinationServeConfig(newPackage);
@@ -376268,11 +376405,11 @@ ${source}` : source ?? "";
376268
376405
  canonicalPath
376269
376406
  });
376270
376407
  } catch (err) {
376271
- await fs9.promises.rm(canonicalPath, { recursive: true, force: true }).catch(() => {});
376408
+ await fs10.promises.rm(canonicalPath, { recursive: true, force: true }).catch(() => {});
376272
376409
  let restored = false;
376273
376410
  if (retiredPath) {
376274
376411
  try {
376275
- await fs9.promises.rename(retiredPath, canonicalPath);
376412
+ await fs10.promises.rename(retiredPath, canonicalPath);
376276
376413
  restored = true;
376277
376414
  } catch (restoreErr) {
376278
376415
  logger.error("Failed to restore retired package after install rollback", {
@@ -376282,7 +376419,7 @@ ${source}` : source ?? "";
376282
376419
  });
376283
376420
  }
376284
376421
  }
376285
- await fs9.promises.rm(stagingPath, { recursive: true, force: true }).catch(() => {});
376422
+ await fs10.promises.rm(stagingPath, { recursive: true, force: true }).catch(() => {});
376286
376423
  if (oldPackage && restored) {
376287
376424
  this.setPackageStatus(packageName, "serving" /* SERVING */);
376288
376425
  } else {
@@ -376316,7 +376453,7 @@ ${source}` : source ?? "";
376316
376453
  packageName,
376317
376454
  retiredPath: pathToClean
376318
376455
  });
376319
- fs9.promises.rm(pathToClean, { recursive: true, force: true }).catch((err) => {
376456
+ fs10.promises.rm(pathToClean, { recursive: true, force: true }).catch((err) => {
376320
376457
  logger.warn(`Failed to clean up retired package directory ${pathToClean}`, { error: err });
376321
376458
  });
376322
376459
  });
@@ -376449,7 +376586,7 @@ ${source}` : source ?? "";
376449
376586
  try {
376450
376587
  let existingManifest = {};
376451
376588
  try {
376452
- const content = await fs9.promises.readFile(manifestPath, "utf-8");
376589
+ const content = await fs10.promises.readFile(manifestPath, "utf-8");
376453
376590
  existingManifest = JSON.parse(content);
376454
376591
  } catch (_err) {
376455
376592
  logger.warn(`Could not read manifest for ${packageName}`);
@@ -376477,11 +376614,11 @@ ${source}` : source ?? "";
376477
376614
  }
376478
376615
  } : {}
376479
376616
  };
376480
- await fs9.promises.writeFile(manifestPath, JSON.stringify(updatedManifest, null, 2), "utf-8");
376617
+ await fs10.promises.writeFile(manifestPath, JSON.stringify(updatedManifest, null, 2), "utf-8");
376481
376618
  logger.info(`Updated publisher.json for ${packageName}`);
376482
376619
  } catch (error2) {
376483
376620
  logger.error(`Failed to update publisher.json`, { error: error2 });
376484
- throw new Error(`Failed to update package manifest`);
376621
+ throw new Error(`Failed to update package manifest`, { cause: error2 });
376485
376622
  }
376486
376623
  }
376487
376624
  async updatePackage(packageName, body) {
@@ -376563,9 +376700,25 @@ ${source}` : source ?? "";
376563
376700
  setPackageMountError(packageName, message) {
376564
376701
  this.mountErrors.set(packageName, message);
376565
376702
  }
376703
+ recordPackageAddFailure(packageName, message) {
376704
+ if (this.packageStatuses.has(packageName))
376705
+ return;
376706
+ if (!this.mountErrors.has(packageName)) {
376707
+ this.recordedAddFailures.push(packageName);
376708
+ while (this.recordedAddFailures.length > MAX_RECORDED_ADD_FAILURES) {
376709
+ const evicted = this.recordedAddFailures.shift();
376710
+ if (evicted !== undefined)
376711
+ this.mountErrors.delete(evicted);
376712
+ }
376713
+ }
376714
+ this.mountErrors.set(packageName, message);
376715
+ }
376566
376716
  clearPackageLoadFailure(packageName) {
376567
376717
  this.failedPackages.delete(packageName);
376568
376718
  this.mountErrors.delete(packageName);
376719
+ const recorded = this.recordedAddFailures.indexOf(packageName);
376720
+ if (recorded !== -1)
376721
+ this.recordedAddFailures.splice(recorded, 1);
376569
376722
  this.staleCompileErrors.delete(packageName);
376570
376723
  }
376571
376724
  getFailedPackages() {
@@ -376610,10 +376763,10 @@ ${source}` : source ?? "";
376610
376763
  const retiredPath = this.allocateRetiredPath(packageName);
376611
376764
  let renamed = false;
376612
376765
  try {
376613
- await fs9.promises.mkdir(path12.dirname(retiredPath), {
376766
+ await fs10.promises.mkdir(path12.dirname(retiredPath), {
376614
376767
  recursive: true
376615
376768
  });
376616
- await fs9.promises.rename(canonicalPath, retiredPath);
376769
+ await fs10.promises.rename(canonicalPath, retiredPath);
376617
376770
  renamed = true;
376618
376771
  } catch (err) {
376619
376772
  logger.error("Error renaming package directory to retired during unload", {
@@ -376626,7 +376779,7 @@ ${source}` : source ?? "";
376626
376779
  this.packageStatuses.delete(packageName);
376627
376780
  if (renamed) {
376628
376781
  setImmediate(() => {
376629
- fs9.promises.rm(retiredPath, { recursive: true, force: true }).catch((err) => {
376782
+ fs10.promises.rm(retiredPath, { recursive: true, force: true }).catch((err) => {
376630
376783
  logger.warn(`Failed to clean up retired package directory ${retiredPath}`, { error: err });
376631
376784
  });
376632
376785
  });
@@ -376712,7 +376865,7 @@ ${source}` : source ?? "";
376712
376865
  async deleteDuckDBConnection(connectionName) {
376713
376866
  const duckdbPath = path12.join(this.environmentPath, `${connectionName}.duckdb`);
376714
376867
  try {
376715
- await fs9.promises.rm(duckdbPath, { force: true });
376868
+ await fs10.promises.rm(duckdbPath, { force: true });
376716
376869
  logger.info(`Removed DuckDB connection file ${connectionName} from environment ${this.environmentName}`);
376717
376870
  } catch (error2) {
376718
376871
  logger.error(`Failed to remove DuckDB connection file ${connectionName} from environment ${this.environmentName}`, { error: error2 });
@@ -376723,8 +376876,11 @@ ${source}` : source ?? "";
376723
376876
  logger.info(`Removed DuckLake connection ${connectionName} from environment ${this.environmentName}`);
376724
376877
  }
376725
376878
  }
376879
+
376880
+ // src/service/environment_store.ts
376881
+ init_google_credentials();
376726
376882
  // package.json
376727
- var version2 = "0.9.0";
376883
+ var version2 = "0.9.1";
376728
376884
 
376729
376885
  // src/version.ts
376730
376886
  var SERVER_VERSION = version2;
@@ -376778,11 +376934,11 @@ function validateEnvironmentAzureUrls(environment) {
376778
376934
  }
376779
376935
  async function clearMountTarget(targetPath) {
376780
376936
  try {
376781
- const stats = await fs10.promises.lstat(targetPath);
376937
+ const stats = await fs11.promises.lstat(targetPath);
376782
376938
  if (stats.isDirectory() && !stats.isSymbolicLink()) {
376783
- await fs10.promises.rm(targetPath, { recursive: true, force: true });
376939
+ await fs11.promises.rm(targetPath, { recursive: true, force: true });
376784
376940
  } else {
376785
- await fs10.promises.unlink(targetPath);
376941
+ await fs11.promises.unlink(targetPath);
376786
376942
  }
376787
376943
  } catch {}
376788
376944
  }
@@ -376954,6 +377110,7 @@ class EnvironmentStore {
376954
377110
  environments = new Map;
376955
377111
  failedEnvironments = new Map;
376956
377112
  unconfiguredNotice = null;
377113
+ initError = null;
376957
377114
  environmentMutexes = new Map;
376958
377115
  publisherConfigIsFrozen;
376959
377116
  finishedInitialization;
@@ -377037,7 +377194,7 @@ class EnvironmentStore {
377037
377194
  if (existingEnvironments.length > 0) {
377038
377195
  await Promise.all(existingEnvironments.map(async (dbEnvironment) => {
377039
377196
  try {
377040
- const environmentExists = await fs10.promises.access(dbEnvironment.path).then(() => true).catch(() => false);
377197
+ const environmentExists = await fs11.promises.access(dbEnvironment.path).then(() => true).catch(() => false);
377041
377198
  const environmentConfig = environmentManifest.environments.find((p2) => p2.name === dbEnvironment.name);
377042
377199
  if (!environmentExists) {
377043
377200
  if (environmentConfig) {
@@ -377113,6 +377270,7 @@ class EnvironmentStore {
377113
377270
  this.emitReadinessLine();
377114
377271
  } catch (error2) {
377115
377272
  markNotReady();
377273
+ this.initError = redactPgSecrets(messageWithFilesystemCause(error2));
377116
377274
  const errorData = this.extractErrorDataFromError(error2);
377117
377275
  logger.error("Error initializing environment store", errorData);
377118
377276
  try {
@@ -377405,12 +377563,12 @@ class EnvironmentStore {
377405
377563
  }
377406
377564
  async cleanupAndCreatePublisherPath() {
377407
377565
  const reInit = process.env.INITIALIZE_STORAGE === "true";
377408
- await fs10.promises.mkdir(this.serverRootPath, { recursive: true });
377566
+ await fs11.promises.mkdir(this.serverRootPath, { recursive: true });
377409
377567
  if (reInit) {
377410
377568
  const uploadDocsPath2 = path13.join(this.serverRootPath, PUBLISHER_DATA_DIR);
377411
377569
  logger.info(`Reinitialization mode: Cleaning up upload documents path ${uploadDocsPath2}`);
377412
377570
  try {
377413
- await fs10.promises.rm(uploadDocsPath2, {
377571
+ await fs11.promises.rm(uploadDocsPath2, {
377414
377572
  recursive: true,
377415
377573
  force: true
377416
377574
  });
@@ -377425,7 +377583,7 @@ class EnvironmentStore {
377425
377583
  logger.info(`Using existing publisher path`);
377426
377584
  }
377427
377585
  const uploadDocsPath = path13.join(this.serverRootPath, PUBLISHER_DATA_DIR);
377428
- await fs10.promises.mkdir(uploadDocsPath, { recursive: true });
377586
+ await fs11.promises.mkdir(uploadDocsPath, { recursive: true });
377429
377587
  }
377430
377588
  async listEnvironments(skipInitializationCheck = false) {
377431
377589
  if (!skipInitializationCheck) {
@@ -377503,6 +377661,9 @@ class EnvironmentStore {
377503
377661
  if (this.unconfiguredNotice && status.environments.length === 0) {
377504
377662
  status.emptyReason = this.unconfiguredNotice;
377505
377663
  }
377664
+ if (this.initError) {
377665
+ status.initError = this.initError;
377666
+ }
377506
377667
  return status;
377507
377668
  }
377508
377669
  async getEnvironment(environmentName, reload = false) {
@@ -377575,9 +377736,6 @@ class EnvironmentStore {
377575
377736
  const loaded = await this.loadEnvironmentIntoDisk(environmentName, packagesToProcess);
377576
377737
  absoluteEnvironmentPath = loaded.path;
377577
377738
  mountErrors = loaded.mountErrors;
377578
- if (absoluteEnvironmentPath.endsWith(".zip")) {
377579
- absoluteEnvironmentPath = await this.unzipEnvironment(absoluteEnvironmentPath);
377580
- }
377581
377739
  } else {
377582
377740
  absoluteEnvironmentPath = await this.scaffoldEnvironment(environment);
377583
377741
  }
@@ -377604,41 +377762,44 @@ class EnvironmentStore {
377604
377762
  }
377605
377763
  async unzipEnvironment(absoluteEnvironmentPath) {
377606
377764
  assertSafeEnvironmentPath(absoluteEnvironmentPath);
377607
- const startedAt = Date.now();
377608
- logger.info(`Detected zip file at "${absoluteEnvironmentPath}". Unzipping...`);
377609
377765
  const archiveDir = path13.resolve(path13.dirname(absoluteEnvironmentPath));
377610
377766
  const unzippedEnvironmentPath = path13.resolve(archiveDir, path13.basename(absoluteEnvironmentPath, ".zip"));
377611
377767
  if (!unzippedEnvironmentPath.startsWith(archiveDir + path13.sep)) {
377612
377768
  throw new BadRequestError(`Refusing to unzip "${absoluteEnvironmentPath}": target escapes its directory`);
377613
377769
  }
377614
- await fs10.promises.rm(unzippedEnvironmentPath, {
377770
+ await this.extractZipInto(absoluteEnvironmentPath, unzippedEnvironmentPath);
377771
+ return unzippedEnvironmentPath;
377772
+ }
377773
+ async extractZipInto(archivePath, targetDir) {
377774
+ const startedAt = Date.now();
377775
+ logger.info(`Detected zip file at "${archivePath}". Unzipping...`);
377776
+ await fs11.promises.rm(targetDir, {
377615
377777
  recursive: true,
377616
377778
  force: true
377617
377779
  });
377618
- await fs10.promises.mkdir(unzippedEnvironmentPath, { recursive: true });
377780
+ await fs11.promises.mkdir(targetDir, { recursive: true });
377619
377781
  let entryCount = 0;
377620
377782
  let totalUncompressedBytes = 0;
377621
377783
  try {
377622
- await import_extract_zip.default(absoluteEnvironmentPath, {
377623
- dir: path13.resolve(unzippedEnvironmentPath),
377784
+ await import_extract_zip.default(archivePath, {
377785
+ dir: path13.resolve(targetDir),
377624
377786
  onEntry: (entry) => {
377625
377787
  if ((entry.externalFileAttributes >>> 16 & 61440) === 40960) {
377626
- throw new BadRequestError(`Refusing to unzip "${absoluteEnvironmentPath}": entry "${entry.fileName}" is a symbolic link`);
377788
+ throw new BadRequestError(`Refusing to unzip "${archivePath}": entry "${entry.fileName}" is a symbolic link`);
377627
377789
  }
377628
377790
  entryCount += 1;
377629
377791
  totalUncompressedBytes += entry.uncompressedSize ?? 0;
377630
377792
  }
377631
377793
  });
377632
377794
  } catch (error2) {
377633
- await fs10.promises.rm(unzippedEnvironmentPath, {
377795
+ await fs11.promises.rm(targetDir, {
377634
377796
  recursive: true,
377635
377797
  force: true
377636
377798
  });
377637
377799
  throw error2;
377638
377800
  }
377639
377801
  const mib = (totalUncompressedBytes / (1024 * 1024)).toFixed(1);
377640
- logger.info(`Unzipped "${absoluteEnvironmentPath}" -> "${unzippedEnvironmentPath}" ` + `(${entryCount} entries, ${mib} MiB uncompressed) in ` + `${formatDuration(Date.now() - startedAt)}`);
377641
- return unzippedEnvironmentPath;
377802
+ logger.info(`Unzipped "${archivePath}" -> "${targetDir}" ` + `(${entryCount} entries, ${mib} MiB uncompressed) in ` + `${formatDuration(Date.now() - startedAt)}`);
377642
377803
  }
377643
377804
  async updateEnvironment(environment) {
377644
377805
  await this.finishedInitialization;
@@ -377676,7 +377837,7 @@ class EnvironmentStore {
377676
377837
  await this.deleteEnvironmentFromDatabase(environmentName);
377677
377838
  if (environmentPath) {
377678
377839
  try {
377679
- await fs10.promises.rm(environmentPath, {
377840
+ await fs11.promises.rm(environmentPath, {
377680
377841
  recursive: true,
377681
377842
  force: true
377682
377843
  });
@@ -377697,7 +377858,7 @@ class EnvironmentStore {
377697
377858
  throw new PublisherConfigError(PUBLISHER_CONFIG_NAME, error2);
377698
377859
  } else {
377699
377860
  try {
377700
- const entries = await fs10.promises.readdir(serverRootPath, {
377861
+ const entries = await fs11.promises.readdir(serverRootPath, {
377701
377862
  withFileTypes: true
377702
377863
  });
377703
377864
  const environments = [];
@@ -377730,9 +377891,9 @@ class EnvironmentStore {
377730
377891
  assertSafePackageName(environment.name);
377731
377892
  const environmentName = environment.name;
377732
377893
  const absoluteEnvironmentPath = safeJoinUnderRoot(this.serverRootPath, PUBLISHER_DATA_DIR, environmentName);
377733
- await fs10.promises.mkdir(absoluteEnvironmentPath, { recursive: true });
377894
+ await fs11.promises.mkdir(absoluteEnvironmentPath, { recursive: true });
377734
377895
  if (environment.readme) {
377735
- await fs10.promises.writeFile(safeJoinUnderRoot(absoluteEnvironmentPath, "README.md"), environment.readme);
377896
+ await fs11.promises.writeFile(safeJoinUnderRoot(absoluteEnvironmentPath, "README.md"), environment.readme);
377736
377897
  }
377737
377898
  return absoluteEnvironmentPath;
377738
377899
  }
@@ -377753,7 +377914,7 @@ class EnvironmentStore {
377753
377914
  }
377754
377915
  recordMountFailure(error2, location, packageNames, mountErrors) {
377755
377916
  logger.error(`Failed to download or mount location "${location}"`, this.extractErrorDataFromError(error2));
377756
- const message = redactPgSecrets(error2 instanceof Error ? error2.message : String(error2));
377917
+ const message = redactPgSecrets(messageWithFilesystemCause(error2));
377757
377918
  for (const packageName of packageNames) {
377758
377919
  mountErrors.set(packageName, message);
377759
377920
  }
@@ -377762,7 +377923,7 @@ class EnvironmentStore {
377762
377923
  assertSafePackageName(environmentName);
377763
377924
  const absoluteTargetPath = safeJoinUnderRoot(this.serverRootPath, PUBLISHER_DATA_DIR, environmentName);
377764
377925
  const mountErrors = new Map;
377765
- await fs10.promises.mkdir(absoluteTargetPath, { recursive: true });
377926
+ await fs11.promises.mkdir(absoluteTargetPath, { recursive: true });
377766
377927
  if (!packages || packages.length === 0) {
377767
377928
  throw new PackageNotFoundError(`No packages found for environment ${environmentName}`);
377768
377929
  }
@@ -377794,7 +377955,7 @@ class EnvironmentStore {
377794
377955
  for (const [groupedLocation, packagesForLocation] of locationGroups) {
377795
377956
  const locationHash = crypto5.createHash("sha256").update(groupedLocation).digest("hex").substring(0, 16);
377796
377957
  const tempDownloadPath = safeJoinUnderRoot(absoluteTargetPath, `.temp_${locationHash}`);
377797
- await fs10.promises.mkdir(tempDownloadPath, { recursive: true });
377958
+ await fs11.promises.mkdir(tempDownloadPath, { recursive: true });
377798
377959
  logger.info(`Created temporary directory: ${tempDownloadPath}`);
377799
377960
  let downloaded = true;
377800
377961
  try {
@@ -377809,6 +377970,7 @@ class EnvironmentStore {
377809
377970
  const packageDir = _package.name;
377810
377971
  assertSafePackageName(packageDir);
377811
377972
  absolutePackagePath = safeJoinUnderRoot(absoluteTargetPath, packageDir);
377973
+ const isLocalArchive = this.isLocalPath(_package.location) && _package.location.endsWith(".zip");
377812
377974
  let sourcePath;
377813
377975
  if (this.isGitHubURL(_package.location)) {
377814
377976
  const githubInfo = parseGitHubUrl(_package.location);
@@ -377823,30 +377985,32 @@ class EnvironmentStore {
377823
377985
  sourcePath = tempDownloadPath;
377824
377986
  }
377825
377987
  } else {
377826
- if (this.isLocalPath(_package.location)) {
377988
+ if (isLocalArchive) {
377989
+ sourcePath = tempDownloadPath;
377990
+ } else if (this.isLocalPath(_package.location)) {
377827
377991
  sourcePath = this.resolveLocalPath(_package.location);
377828
377992
  } else {
377829
377993
  sourcePath = safeJoinUnderRoot(tempDownloadPath, groupedLocation);
377830
377994
  }
377831
377995
  }
377832
- const sourceExists = await fs10.promises.access(sourcePath).then(() => true).catch(() => false);
377996
+ const sourceExists = await fs11.promises.access(sourcePath).then(() => true).catch(() => false);
377833
377997
  if (sourceExists) {
377834
- const isInPlace = this.inPlaceEnvs.has(environmentName) && this.isLocalPath(_package.location);
377998
+ const isInPlace = this.inPlaceEnvs.has(environmentName) && this.isLocalPath(_package.location) && !isLocalArchive;
377835
377999
  if (isInPlace) {
377836
378000
  await clearMountTarget(absolutePackagePath);
377837
378001
  const absoluteSourcePath = path13.resolve(sourcePath);
377838
378002
  const linkType = process.platform === "win32" ? "junction" : "dir";
377839
378003
  try {
377840
- await fs10.promises.symlink(absoluteSourcePath, absolutePackagePath, linkType);
378004
+ await fs11.promises.symlink(absoluteSourcePath, absolutePackagePath, linkType);
377841
378005
  logger.info(`In-place mount (watch mode): linked package "${packageDir}" -> "${absoluteSourcePath}" (${++mountedCount}/${totalPackages})`);
377842
378006
  } catch (linkError) {
377843
378007
  const code = linkError?.code ?? String(linkError);
377844
378008
  logger.warn(`In-place mount failed for package "${packageDir}" (${code}); falling back to a copy. Source-edit live reload is disabled for this package.`);
377845
378009
  await clearMountTarget(absolutePackagePath);
377846
- await fs10.promises.mkdir(absolutePackagePath, {
378010
+ await fs11.promises.mkdir(absolutePackagePath, {
377847
378011
  recursive: true
377848
378012
  });
377849
- await fs10.promises.cp(sourcePath, absolutePackagePath, {
378013
+ await fs11.promises.cp(sourcePath, absolutePackagePath, {
377850
378014
  recursive: true
377851
378015
  });
377852
378016
  logger.info(`Copied package "${packageDir}" (${++mountedCount}/${totalPackages})`);
@@ -377854,22 +378018,24 @@ class EnvironmentStore {
377854
378018
  } else {
377855
378019
  if (this.inPlaceEnvs.has(environmentName) && !this.isLocalPath(_package.location)) {
377856
378020
  logger.warn(`Watch mode: package "${packageDir}" has remote location "${_package.location}" — falling back to copy. Source-edit live reload won't work for this package; clone the source locally and use a local-dir location to enable it.`);
378021
+ } else if (this.inPlaceEnvs.has(environmentName) && isLocalArchive) {
378022
+ logger.warn(`Watch mode: package "${packageDir}" is an archive "${_package.location}" — extracted and copied. Source-edit live reload won't work for this package; use an unpacked local-dir location to enable it.`);
377857
378023
  }
377858
378024
  await clearMountTarget(absolutePackagePath);
377859
- await fs10.promises.mkdir(absolutePackagePath, {
378025
+ await fs11.promises.mkdir(absolutePackagePath, {
377860
378026
  recursive: true
377861
378027
  });
377862
- await fs10.promises.cp(sourcePath, absolutePackagePath, {
378028
+ await fs11.promises.cp(sourcePath, absolutePackagePath, {
377863
378029
  recursive: true
377864
378030
  });
377865
378031
  logger.info(`Extracted package "${packageDir}" from ${groupedLocation.startsWith("https://github.com/") && _package.location.includes("/tree/") ? "GitHub subdirectory" : "shared download"} (${++mountedCount}/${totalPackages})`);
377866
378032
  }
377867
378033
  } else {
377868
378034
  await clearMountTarget(absolutePackagePath);
377869
- await fs10.promises.mkdir(absolutePackagePath, {
378035
+ await fs11.promises.mkdir(absolutePackagePath, {
377870
378036
  recursive: true
377871
378037
  });
377872
- await fs10.promises.cp(tempDownloadPath, absolutePackagePath, {
378038
+ await fs11.promises.cp(tempDownloadPath, absolutePackagePath, {
377873
378039
  recursive: true
377874
378040
  });
377875
378041
  logger.info(`Copied entire download as package "${packageDir}" (${++mountedCount}/${totalPackages})`);
@@ -377882,7 +378048,7 @@ class EnvironmentStore {
377882
378048
  }
377883
378049
  }
377884
378050
  try {
377885
- await fs10.promises.rm(tempDownloadPath, {
378051
+ await fs11.promises.rm(tempDownloadPath, {
377886
378052
  recursive: true,
377887
378053
  force: true
377888
378054
  });
@@ -377904,7 +378070,7 @@ class EnvironmentStore {
377904
378070
  } catch (error2) {
377905
378071
  const errorData = this.extractErrorDataFromError(error2);
377906
378072
  logger.error(`Failed to download GCS directory "${location}"`, errorData);
377907
- throw new PackageNotFoundError(`Failed to download GCS directory: ${location}`);
378073
+ throw new PackageNotFoundError(`Failed to download GCS directory: ${location}`, { cause: error2 });
377908
378074
  }
377909
378075
  }
377910
378076
  if (this.isGitHubURL(location)) {
@@ -377918,7 +378084,7 @@ class EnvironmentStore {
377918
378084
  } catch (error2) {
377919
378085
  const errorData = this.extractErrorDataFromError(error2);
377920
378086
  logger.error(`Failed to clone GitHub repository "${location}"`, errorData);
377921
- throw new PackageNotFoundError(`Failed to clone GitHub repository: ${location}`);
378087
+ throw new PackageNotFoundError(`Failed to clone GitHub repository: ${location}`, { cause: error2 });
377922
378088
  }
377923
378089
  }
377924
378090
  if (this.isS3URL(location)) {
@@ -377929,7 +378095,7 @@ class EnvironmentStore {
377929
378095
  } catch (error2) {
377930
378096
  const errorData = this.extractErrorDataFromError(error2);
377931
378097
  logger.error(`Failed to download S3 directory "${location}"`, errorData);
377932
- throw new PackageNotFoundError(`Failed to download S3 directory: ${location}`);
378098
+ throw new PackageNotFoundError(`Failed to download S3 directory: ${location}`, { cause: error2 });
377933
378099
  }
377934
378100
  }
377935
378101
  if (this.isLocalPath(location)) {
@@ -377941,7 +378107,7 @@ class EnvironmentStore {
377941
378107
  } catch (error2) {
377942
378108
  const errorData = this.extractErrorDataFromError(error2);
377943
378109
  logger.error(`Failed to mount local directory "${packagePath}"`, errorData);
377944
- throw new PackageNotFoundError(`Failed to mount local directory: ${packagePath}`);
378110
+ throw new PackageNotFoundError(`Failed to mount local directory: ${packagePath}`, { cause: error2 });
377945
378111
  }
377946
378112
  }
377947
378113
  const errorMsg = `Invalid package path: "${location}". Must be an absolute mounted path or a GCS/S3/GitHub URI.`;
@@ -377950,25 +378116,31 @@ class EnvironmentStore {
377950
378116
  }
377951
378117
  async mountLocalDirectory(environmentPath, absoluteTargetPath, environmentName, packageName) {
377952
378118
  assertSafeEnvironmentPath(absoluteTargetPath);
377953
- if (environmentPath.endsWith(".zip")) {
377954
- environmentPath = await this.unzipEnvironment(environmentPath);
377955
- }
377956
- const environmentDirExists = (await fs10.promises.stat(environmentPath))?.isDirectory() ?? false;
377957
- if (environmentDirExists) {
377958
- await fs10.promises.rm(absoluteTargetPath, {
378119
+ const notFound = () => new PackageNotFoundError(`Package ${packageName} for environment ${environmentName} not found in "${environmentPath}"`);
378120
+ const source = await fs11.promises.stat(environmentPath).catch((error2) => {
378121
+ if (error2.code === "ENOENT") {
378122
+ throw notFound();
378123
+ }
378124
+ throw error2;
378125
+ });
378126
+ if (environmentPath.endsWith(".zip") && source.isFile()) {
378127
+ await this.extractZipInto(environmentPath, absoluteTargetPath);
378128
+ } else if (source.isDirectory()) {
378129
+ await fs11.promises.rm(absoluteTargetPath, {
377959
378130
  recursive: true,
377960
378131
  force: true
377961
378132
  });
377962
- await fs10.promises.mkdir(absoluteTargetPath, { recursive: true });
377963
- await fs10.promises.cp(environmentPath, absoluteTargetPath, {
378133
+ await fs11.promises.mkdir(absoluteTargetPath, { recursive: true });
378134
+ await fs11.promises.cp(environmentPath, absoluteTargetPath, {
377964
378135
  recursive: true
377965
378136
  });
377966
378137
  } else {
377967
- throw new PackageNotFoundError(`Package ${packageName} for environment ${environmentName} not found in "${environmentPath}"`);
378138
+ throw notFound();
377968
378139
  }
377969
378140
  }
377970
378141
  async downloadGcsDirectory(gcsPath, environmentName, absoluteDirPath, isCompressedFile) {
377971
378142
  assertSafeEnvironmentPath(absoluteDirPath);
378143
+ assertGoogleCredentialsIsNotADirectory();
377972
378144
  const trimmedPath = gcsPath.slice(5);
377973
378145
  const [bucketName, ...prefixParts] = trimmedPath.split("/");
377974
378146
  const prefix = prefixParts.join("/");
@@ -377979,11 +378151,11 @@ class EnvironmentStore {
377979
378151
  throw new EnvironmentNotFoundError(`Environment ${environmentName} not found in ${gcsPath}`);
377980
378152
  }
377981
378153
  if (!isCompressedFile) {
377982
- await fs10.promises.rm(absoluteDirPath, {
378154
+ await fs11.promises.rm(absoluteDirPath, {
377983
378155
  recursive: true,
377984
378156
  force: true
377985
378157
  });
377986
- await fs10.promises.mkdir(absoluteDirPath, { recursive: true });
378158
+ await fs11.promises.mkdir(absoluteDirPath, { recursive: true });
377987
378159
  } else {
377988
378160
  absoluteDirPath = `${absoluteDirPath}.zip`;
377989
378161
  }
@@ -377993,10 +378165,10 @@ class EnvironmentStore {
377993
378165
  if (file.name.endsWith("/")) {
377994
378166
  return;
377995
378167
  }
377996
- await fs10.promises.mkdir(path13.dirname(absoluteFilePath), {
378168
+ await fs11.promises.mkdir(path13.dirname(absoluteFilePath), {
377997
378169
  recursive: true
377998
378170
  });
377999
- return fs10.promises.writeFile(absoluteFilePath, await file.download());
378171
+ return fs11.promises.writeFile(absoluteFilePath, await file.download());
378000
378172
  }));
378001
378173
  if (isCompressedFile) {
378002
378174
  await this.unzipEnvironment(absoluteDirPath);
@@ -378010,7 +378182,7 @@ class EnvironmentStore {
378010
378182
  const prefix = prefixParts.join("/");
378011
378183
  if (isCompressedFile) {
378012
378184
  const zipFilePath = `${absoluteDirPath}.zip`;
378013
- await fs10.promises.mkdir(path13.dirname(zipFilePath), {
378185
+ await fs11.promises.mkdir(path13.dirname(zipFilePath), {
378014
378186
  recursive: true
378015
378187
  });
378016
378188
  const command = new import_client_s33.GetObjectCommand({
@@ -378021,7 +378193,7 @@ class EnvironmentStore {
378021
378193
  if (!item.Body) {
378022
378194
  throw new EnvironmentNotFoundError(`Environment ${environmentName} not found in ${s3Path}`);
378023
378195
  }
378024
- const file = fs10.createWriteStream(zipFilePath);
378196
+ const file = fs11.createWriteStream(zipFilePath);
378025
378197
  item.Body.transformToWebStream().pipeTo(Writable.toWeb(file));
378026
378198
  await new Promise((resolve6, reject2) => {
378027
378199
  file.on("error", reject2);
@@ -378035,8 +378207,8 @@ class EnvironmentStore {
378035
378207
  Bucket: bucketName,
378036
378208
  Prefix: prefix
378037
378209
  });
378038
- await fs10.promises.rm(absoluteDirPath, { recursive: true, force: true });
378039
- await fs10.promises.mkdir(absoluteDirPath, { recursive: true });
378210
+ await fs11.promises.rm(absoluteDirPath, { recursive: true, force: true });
378211
+ await fs11.promises.mkdir(absoluteDirPath, { recursive: true });
378040
378212
  if (!objects.Contents || objects.Contents.length === 0) {
378041
378213
  throw new EnvironmentNotFoundError(`Environment ${environmentName} not found in ${s3Path}`);
378042
378214
  }
@@ -378050,7 +378222,7 @@ class EnvironmentStore {
378050
378222
  return;
378051
378223
  }
378052
378224
  const absoluteFilePath = safeJoinUnderRoot(absoluteDirPath, relativeFilePath);
378053
- await fs10.promises.mkdir(path13.dirname(absoluteFilePath), {
378225
+ await fs11.promises.mkdir(path13.dirname(absoluteFilePath), {
378054
378226
  recursive: true
378055
378227
  });
378056
378228
  const command = new import_client_s33.GetObjectCommand({
@@ -378061,7 +378233,7 @@ class EnvironmentStore {
378061
378233
  if (!item.Body) {
378062
378234
  return;
378063
378235
  }
378064
- const file = fs10.createWriteStream(absoluteFilePath);
378236
+ const file = fs11.createWriteStream(absoluteFilePath);
378065
378237
  item.Body.transformToWebStream().pipeTo(Writable.toWeb(file));
378066
378238
  await new Promise((resolve6, reject2) => {
378067
378239
  file.on("error", reject2);
@@ -378078,11 +378250,11 @@ class EnvironmentStore {
378078
378250
  }
378079
378251
  const { owner, repoName, packagePath } = githubInfo;
378080
378252
  const cleanPackagePath = (packagePath?.replace("/tree/main", "") || "").replace(/^\/+/, "");
378081
- await fs10.promises.rm(absoluteDirPath, {
378253
+ await fs11.promises.rm(absoluteDirPath, {
378082
378254
  recursive: true,
378083
378255
  force: true
378084
378256
  });
378085
- await fs10.promises.mkdir(absoluteDirPath, { recursive: true });
378257
+ await fs11.promises.mkdir(absoluteDirPath, { recursive: true });
378086
378258
  const repoUrl = `https://github.com/${owner}/${repoName}`;
378087
378259
  const reporter = new CloneProgressReporter(cloneProgressLabel(`${owner}/${repoName}`, progressContext));
378088
378260
  await new Promise((resolve6, reject2) => {
@@ -378108,24 +378280,24 @@ class EnvironmentStore {
378108
378280
  return;
378109
378281
  }
378110
378282
  const packageFullPath = safeJoinUnderRoot(absoluteDirPath, cleanPackagePath);
378111
- const packageExists = await fs10.promises.access(packageFullPath).then(() => true).catch(() => false);
378283
+ const packageExists = await fs11.promises.access(packageFullPath).then(() => true).catch(() => false);
378112
378284
  if (!packageExists) {
378113
378285
  throw new Error(`Package path "${cleanPackagePath}" does not exist in the cloned repository.`);
378114
378286
  }
378115
- const dirContents = await fs10.promises.readdir(absoluteDirPath);
378287
+ const dirContents = await fs11.promises.readdir(absoluteDirPath);
378116
378288
  for (const entry of dirContents) {
378117
378289
  if (entry !== cleanPackagePath.replace(/^\/+/, "").split("/")[0]) {
378118
- await fs10.promises.rm(safeJoinUnderRoot(absoluteDirPath, entry), {
378290
+ await fs11.promises.rm(safeJoinUnderRoot(absoluteDirPath, entry), {
378119
378291
  recursive: true,
378120
378292
  force: true
378121
378293
  });
378122
378294
  }
378123
378295
  }
378124
- const packageContents = await fs10.promises.readdir(packageFullPath);
378296
+ const packageContents = await fs11.promises.readdir(packageFullPath);
378125
378297
  for (const entry of packageContents) {
378126
- await fs10.promises.rename(safeJoinUnderRoot(packageFullPath, entry), safeJoinUnderRoot(absoluteDirPath, entry));
378298
+ await fs11.promises.rename(safeJoinUnderRoot(packageFullPath, entry), safeJoinUnderRoot(absoluteDirPath, entry));
378127
378299
  }
378128
- await fs10.promises.rm(packageFullPath, { recursive: true, force: true });
378300
+ await fs11.promises.rm(packageFullPath, { recursive: true, force: true });
378129
378301
  }
378130
378302
  extractErrorDataFromError(error2) {
378131
378303
  const errorMessage = error2 instanceof Error ? error2.message : String(error2);
@@ -383337,7 +383509,8 @@ A JSON object with:
383337
383509
  - version: this server's release version.
383338
383510
  - environments: each environment's name with its loaded package names.
383339
383511
  - emptyReason (only present when the server found no config at startup, or the --config path was missing): why environments is empty, and the path it checked. The server still reports serving in that state.
383340
- - loadErrors (only present when something failed): entries of {environment, package?, message, stale?, failedAt?}. An entry WITHOUT stale means the package (or whole environment, when package is absent) did not load and is missing from environments. An entry WITH stale: true means the package IS serving, but its most recent reload failed to compile, so the model answering queries is OLDER than the files on disk; the message says why. Fix the file and reload (reload_package) to clear it.
383512
+ - initError (only present when startup failed): why. The server stays at "initializing" and never serves; the cause is usually a config file it cannot read or parse, or a server root it cannot write (publisher.db). A package or environment that failed to load is under loadErrors instead.
383513
+ - loadErrors (only present when something failed): entries of {environment, package?, message, stale?, failedAt?}. An entry WITHOUT stale means the package (or whole environment, when package is absent) did not load and is missing from environments; that includes a package add that failed on the server's side. An entry WITH stale: true means the package IS serving, but its most recent reload failed to compile, so the model answering queries is OLDER than the files on disk; the message says why. Fix the file and reload (reload_package) to clear it.
383341
383514
 
383342
383515
  No loadErrors key means everything configured loaded and nothing is stale.`;
383343
383516
  function registerGetStatusTool(mcpServer, environmentStore) {
@@ -383356,6 +383529,9 @@ function registerGetStatusTool(mcpServer, environmentStore) {
383356
383529
  ...status.emptyReason !== undefined && {
383357
383530
  emptyReason: status.emptyReason
383358
383531
  },
383532
+ ...status.initError !== undefined && {
383533
+ initError: status.initError
383534
+ },
383359
383535
  ...status.loadErrors !== undefined && {
383360
383536
  loadErrors: status.loadErrors
383361
383537
  }
@@ -395042,7 +395218,7 @@ function initializeMcpServer(environmentStore) {
395042
395218
  // src/mcp_config.ts
395043
395219
  init_config();
395044
395220
  init_logger();
395045
- import * as fs11 from "fs";
395221
+ import * as fs12 from "fs";
395046
395222
  import * as os4 from "os";
395047
395223
  import * as path15 from "path";
395048
395224
  var MCP_CONFIG_FILENAME = ".mcp.json";
@@ -395070,7 +395246,7 @@ function mcpEndpoint(host, port) {
395070
395246
  function findGitWorkTreeRoot(dir) {
395071
395247
  let current = path15.resolve(dir);
395072
395248
  for (;; ) {
395073
- if (fs11.existsSync(path15.join(current, ".git")))
395249
+ if (fs12.existsSync(path15.join(current, ".git")))
395074
395250
  return current;
395075
395251
  const parent = path15.dirname(current);
395076
395252
  if (parent === current)
@@ -395080,10 +395256,10 @@ function findGitWorkTreeRoot(dir) {
395080
395256
  }
395081
395257
  function conflictingMalloyUrl(file, endpoint) {
395082
395258
  try {
395083
- const stats = fs11.lstatSync(file);
395259
+ const stats = fs12.lstatSync(file);
395084
395260
  if (!stats.isFile() || stats.size > 64 * 1024)
395085
395261
  return;
395086
- const parsed = JSON.parse(fs11.readFileSync(file, "utf8"));
395262
+ const parsed = JSON.parse(fs12.readFileSync(file, "utf8"));
395087
395263
  const url2 = parsed?.mcpServers?.malloy?.url;
395088
395264
  return typeof url2 === "string" && url2 !== endpoint ? url2 : undefined;
395089
395265
  } catch {
@@ -395101,7 +395277,7 @@ function ensureMcpConfig(options) {
395101
395277
  try {
395102
395278
  return {
395103
395279
  path: file,
395104
- isSymlink: fs11.lstatSync(file).isSymbolicLink()
395280
+ isSymlink: fs12.lstatSync(file).isSymbolicLink()
395105
395281
  };
395106
395282
  } catch {
395107
395283
  return;
@@ -395120,7 +395296,7 @@ function ensureMcpConfig(options) {
395120
395296
  }
395121
395297
  const realish = (p2) => {
395122
395298
  try {
395123
- return fs11.realpathSync(p2);
395299
+ return fs12.realpathSync(p2);
395124
395300
  } catch {
395125
395301
  return path15.resolve(p2);
395126
395302
  }
@@ -395138,7 +395314,7 @@ function ensureMcpConfig(options) {
395138
395314
  action: "skipped-git",
395139
395315
  dir,
395140
395316
  gitRoot,
395141
- rootConfig: fs11.existsSync(rootCandidate) ? rootCandidate : undefined,
395317
+ rootConfig: fs12.existsSync(rootCandidate) ? rootCandidate : undefined,
395142
395318
  endpoint,
395143
395319
  staleConfig
395144
395320
  };
@@ -395147,7 +395323,7 @@ function ensureMcpConfig(options) {
395147
395323
  return { action: "exists", file, endpoint };
395148
395324
  const body = JSON.stringify({ mcpServers: { malloy: malloyServer(endpoint) } }, null, 2) + `
395149
395325
  `;
395150
- fs11.writeFileSync(file, body, { encoding: "utf8", flag: "wx" });
395326
+ fs12.writeFileSync(file, body, { encoding: "utf8", flag: "wx" });
395151
395327
  return { action: "created", file };
395152
395328
  } catch (error2) {
395153
395329
  const code = error2?.code;
@@ -399805,11 +399981,11 @@ function stripNonTagText(input) {
399805
399981
  return current;
399806
399982
  }
399807
399983
  async function listPackageDataApps(environmentName, packageName, publicRoot) {
399808
- const fs12 = await import("fs/promises");
399984
+ const fs13 = await import("fs/promises");
399809
399985
  const out = [];
399810
399986
  let realPublicRoot;
399811
399987
  try {
399812
- realPublicRoot = await fs12.realpath(publicRoot);
399988
+ realPublicRoot = await fs13.realpath(publicRoot);
399813
399989
  } catch {
399814
399990
  return out;
399815
399991
  }
@@ -399818,7 +399994,7 @@ async function listPackageDataApps(environmentName, packageName, publicRoot) {
399818
399994
  return;
399819
399995
  let entries;
399820
399996
  try {
399821
- entries = await fs12.readdir(dir, { withFileTypes: true });
399997
+ entries = await fs13.readdir(dir, { withFileTypes: true });
399822
399998
  } catch {
399823
399999
  return;
399824
400000
  }
@@ -399828,7 +400004,7 @@ async function listPackageDataApps(environmentName, packageName, publicRoot) {
399828
400004
  const full = path17.join(dir, entry.name);
399829
400005
  let realFull;
399830
400006
  try {
399831
- realFull = await fs12.realpath(full);
400007
+ realFull = await fs13.realpath(full);
399832
400008
  } catch {
399833
400009
  continue;
399834
400010
  }
@@ -399842,7 +400018,7 @@ async function listPackageDataApps(environmentName, packageName, publicRoot) {
399842
400018
  let title = rel;
399843
400019
  let fit;
399844
400020
  try {
399845
- const fh = await fs12.open(full, "r");
400021
+ const fh = await fs13.open(full, "r");
399846
400022
  try {
399847
400023
  const buf = Buffer.alloc(4096);
399848
400024
  const { bytesRead } = await fh.read(buf, 0, 4096, 0);