@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/README.docker.md +46 -5
- package/dist/app/api-doc.yaml +17 -1
- package/dist/package_load_worker.mjs +136 -52
- package/dist/server.mjs +417 -241
- package/package.json +1 -1
package/dist/server.mjs
CHANGED
|
@@ -205143,9 +205143,54 @@ function logInternalFailure(summary, error2, level = "error") {
|
|
|
205143
205143
|
}
|
|
205144
205144
|
});
|
|
205145
205145
|
}
|
|
205146
|
-
function
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
294766
|
-
await
|
|
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
|
-
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
316559
|
+
var fs6;
|
|
316480
316560
|
try {
|
|
316481
|
-
|
|
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 (!
|
|
316571
|
+
if (!fs6)
|
|
316492
316572
|
return false;
|
|
316493
|
-
return (stream4 instanceof (
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
|
318021
|
-
const canonicalDestDir = await
|
|
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
|
|
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
|
|
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
|
|
318107
|
-
opts.dir = await
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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
|
-
|
|
364846
|
-
|
|
364847
|
-
|
|
364848
|
-
|
|
364849
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
373083
|
+
return fs7.readFile(fileURLToPath5(uri), "utf8");
|
|
372952
373084
|
}
|
|
372953
|
-
return
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
376167
|
+
await fs10.promises.mkdir(path12.dirname(target), { recursive: true });
|
|
376031
376168
|
const temporary = `${target}.${crypto4.randomUUID()}.tmp`;
|
|
376032
|
-
await
|
|
376033
|
-
await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
376379
|
+
const oldExistsOnDisk = await fs10.promises.access(canonicalPath).then(() => true).catch(() => false);
|
|
376243
376380
|
if (oldExistsOnDisk) {
|
|
376244
376381
|
retiredPath = this.allocateRetiredPath(packageName);
|
|
376245
|
-
await
|
|
376382
|
+
await fs10.promises.mkdir(path12.dirname(retiredPath), {
|
|
376246
376383
|
recursive: true
|
|
376247
376384
|
});
|
|
376248
|
-
await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
376766
|
+
await fs10.promises.mkdir(path12.dirname(retiredPath), {
|
|
376614
376767
|
recursive: true
|
|
376615
376768
|
});
|
|
376616
|
-
await
|
|
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
|
-
|
|
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
|
|
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.
|
|
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
|
|
376937
|
+
const stats = await fs11.promises.lstat(targetPath);
|
|
376782
376938
|
if (stats.isDirectory() && !stats.isSymbolicLink()) {
|
|
376783
|
-
await
|
|
376939
|
+
await fs11.promises.rm(targetPath, { recursive: true, force: true });
|
|
376784
376940
|
} else {
|
|
376785
|
-
await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
377623
|
-
dir: path13.resolve(
|
|
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 "${
|
|
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
|
|
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 "${
|
|
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
|
|
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
|
|
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
|
|
377894
|
+
await fs11.promises.mkdir(absoluteEnvironmentPath, { recursive: true });
|
|
377734
377895
|
if (environment.readme) {
|
|
377735
|
-
await
|
|
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(
|
|
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
|
|
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
|
|
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 (
|
|
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
|
|
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
|
|
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
|
|
378010
|
+
await fs11.promises.mkdir(absolutePackagePath, {
|
|
377847
378011
|
recursive: true
|
|
377848
378012
|
});
|
|
377849
|
-
await
|
|
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
|
|
378025
|
+
await fs11.promises.mkdir(absolutePackagePath, {
|
|
377860
378026
|
recursive: true
|
|
377861
378027
|
});
|
|
377862
|
-
await
|
|
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
|
|
378035
|
+
await fs11.promises.mkdir(absolutePackagePath, {
|
|
377870
378036
|
recursive: true
|
|
377871
378037
|
});
|
|
377872
|
-
await
|
|
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
|
|
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
|
-
|
|
377954
|
-
|
|
377955
|
-
|
|
377956
|
-
|
|
377957
|
-
|
|
377958
|
-
|
|
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
|
|
377963
|
-
await
|
|
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
|
|
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
|
|
378154
|
+
await fs11.promises.rm(absoluteDirPath, {
|
|
377983
378155
|
recursive: true,
|
|
377984
378156
|
force: true
|
|
377985
378157
|
});
|
|
377986
|
-
await
|
|
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
|
|
378168
|
+
await fs11.promises.mkdir(path13.dirname(absoluteFilePath), {
|
|
377997
378169
|
recursive: true
|
|
377998
378170
|
});
|
|
377999
|
-
return
|
|
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
|
|
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 =
|
|
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
|
|
378039
|
-
await
|
|
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
|
|
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 =
|
|
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
|
|
378253
|
+
await fs11.promises.rm(absoluteDirPath, {
|
|
378082
378254
|
recursive: true,
|
|
378083
378255
|
force: true
|
|
378084
378256
|
});
|
|
378085
|
-
await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
378296
|
+
const packageContents = await fs11.promises.readdir(packageFullPath);
|
|
378125
378297
|
for (const entry of packageContents) {
|
|
378126
|
-
await
|
|
378298
|
+
await fs11.promises.rename(safeJoinUnderRoot(packageFullPath, entry), safeJoinUnderRoot(absoluteDirPath, entry));
|
|
378127
378299
|
}
|
|
378128
|
-
await
|
|
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
|
-
-
|
|
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
|
|
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 (
|
|
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 =
|
|
395259
|
+
const stats = fs12.lstatSync(file);
|
|
395084
395260
|
if (!stats.isFile() || stats.size > 64 * 1024)
|
|
395085
395261
|
return;
|
|
395086
|
-
const parsed = JSON.parse(
|
|
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:
|
|
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
|
|
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:
|
|
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
|
-
|
|
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
|
|
399984
|
+
const fs13 = await import("fs/promises");
|
|
399809
399985
|
const out = [];
|
|
399810
399986
|
let realPublicRoot;
|
|
399811
399987
|
try {
|
|
399812
|
-
realPublicRoot = await
|
|
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
|
|
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
|
|
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
|
|
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);
|