@malloy-publisher/server 0.0.236 → 0.0.237
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/api-doc.yaml +36 -10
- package/dist/app/assets/{EnvironmentPage-BsAnavYN.js → EnvironmentPage-DaP6CpgK.js} +1 -1
- package/dist/app/assets/{HomePage-CADE138j.js → HomePage-C9yNw3iu.js} +1 -1
- package/dist/app/assets/{LightMode-Cfh7KzN8.js → LightMode-Be4-G-dX.js} +1 -1
- package/dist/app/assets/{MainPage-CO3pRlnV.js → MainPage-J_rU2SgI.js} +2 -2
- package/dist/app/assets/{MaterializationsPage-p9YjkRXZ.js → MaterializationsPage-DHgPI4MO.js} +1 -1
- package/dist/app/assets/ModelPage-BzXfjTu5.js +1 -0
- package/dist/app/assets/{PackagePage-e4kN75YR.js → PackagePage-ByoSTLJ4.js} +1 -1
- package/dist/app/assets/RouteError-CrSeKN2r.js +1 -0
- package/dist/app/assets/{ThemeEditorPage-CciagFTq.js → ThemeEditorPage-Btxnmhtk.js} +1 -1
- package/dist/app/assets/{WorkbookPage-DNWmkCXa.js → WorkbookPage-D6JLPnWO.js} +1 -1
- package/dist/app/assets/{core-Rj_4rRnA.es-BZyvITuO.js → core-BSRgt1mG.es-Bc_D2Lq4.js} +1 -1
- package/dist/app/assets/{index-CH2AcDzc.js → index-BRijWj6K.js} +15 -15
- package/dist/app/assets/{index-DQa463gC.js → index-BX4D94xw.js} +1 -1
- package/dist/app/assets/{index-VBbcc8s6.js → index-Cvy0xtb7.js} +1 -1
- package/dist/app/assets/{index-DQpV7MyA.js → index-DMAhIJNC.js} +1 -1
- package/dist/app/index.html +1 -1
- package/dist/package_load_worker.mjs +52 -20
- package/dist/server.mjs +873 -564
- package/package.json +4 -1
- package/dist/app/assets/ModelPage-C1OSTv-x.js +0 -1
- package/dist/app/assets/RouteError-CzbfOkng.js +0 -1
package/dist/server.mjs
CHANGED
|
@@ -120280,8 +120280,8 @@ var require_node42 = __commonJS((exports, module) => {
|
|
|
120280
120280
|
}
|
|
120281
120281
|
break;
|
|
120282
120282
|
case "FILE":
|
|
120283
|
-
var
|
|
120284
|
-
stream2 = new
|
|
120283
|
+
var fs2 = __require("fs");
|
|
120284
|
+
stream2 = new fs2.SyncWriteStream(fd2, { autoClose: false });
|
|
120285
120285
|
stream2._type = "fs";
|
|
120286
120286
|
break;
|
|
120287
120287
|
case "PIPE":
|
|
@@ -136347,8 +136347,8 @@ var require_node43 = __commonJS((exports, module) => {
|
|
|
136347
136347
|
}
|
|
136348
136348
|
break;
|
|
136349
136349
|
case "FILE":
|
|
136350
|
-
var
|
|
136351
|
-
stream2 = new
|
|
136350
|
+
var fs2 = __require("fs");
|
|
136351
|
+
stream2 = new fs2.SyncWriteStream(fd2, { autoClose: false });
|
|
136352
136352
|
stream2._type = "fs";
|
|
136353
136353
|
break;
|
|
136354
136354
|
case "PIPE":
|
|
@@ -137073,8 +137073,8 @@ var require_node44 = __commonJS((exports, module) => {
|
|
|
137073
137073
|
}
|
|
137074
137074
|
break;
|
|
137075
137075
|
case "FILE":
|
|
137076
|
-
var
|
|
137077
|
-
stream2 = new
|
|
137076
|
+
var fs2 = __require("fs");
|
|
137077
|
+
stream2 = new fs2.SyncWriteStream(fd2, { autoClose: false });
|
|
137078
137078
|
stream2._type = "fs";
|
|
137079
137079
|
break;
|
|
137080
137080
|
case "PIPE":
|
|
@@ -137986,7 +137986,7 @@ var require_view = __commonJS((exports, module) => {
|
|
|
137986
137986
|
*/
|
|
137987
137987
|
var debug = require_src109()("express:view");
|
|
137988
137988
|
var path = __require("path");
|
|
137989
|
-
var
|
|
137989
|
+
var fs2 = __require("fs");
|
|
137990
137990
|
var dirname = path.dirname;
|
|
137991
137991
|
var basename = path.basename;
|
|
137992
137992
|
var extname = path.extname;
|
|
@@ -138052,7 +138052,7 @@ var require_view = __commonJS((exports, module) => {
|
|
|
138052
138052
|
function tryStat(path2) {
|
|
138053
138053
|
debug('stat "%s"', path2);
|
|
138054
138054
|
try {
|
|
138055
|
-
return
|
|
138055
|
+
return fs2.statSync(path2);
|
|
138056
138056
|
} catch (e) {
|
|
138057
138057
|
return;
|
|
138058
138058
|
}
|
|
@@ -138595,8 +138595,8 @@ var require_node45 = __commonJS((exports, module) => {
|
|
|
138595
138595
|
}
|
|
138596
138596
|
break;
|
|
138597
138597
|
case "FILE":
|
|
138598
|
-
var
|
|
138599
|
-
stream2 = new
|
|
138598
|
+
var fs2 = __require("fs");
|
|
138599
|
+
stream2 = new fs2.SyncWriteStream(fd2, { autoClose: false });
|
|
138600
138600
|
stream2._type = "fs";
|
|
138601
138601
|
break;
|
|
138602
138602
|
case "PIPE":
|
|
@@ -138784,7 +138784,7 @@ var require_types45 = __commonJS((exports, module) => {
|
|
|
138784
138784
|
// ../../node_modules/send/node_modules/mime/mime.js
|
|
138785
138785
|
var require_mime = __commonJS((exports, module) => {
|
|
138786
138786
|
var path = __require("path");
|
|
138787
|
-
var
|
|
138787
|
+
var fs2 = __require("fs");
|
|
138788
138788
|
function Mime() {
|
|
138789
138789
|
this.types = Object.create(null);
|
|
138790
138790
|
this.extensions = Object.create(null);
|
|
@@ -138805,7 +138805,7 @@ var require_mime = __commonJS((exports, module) => {
|
|
|
138805
138805
|
};
|
|
138806
138806
|
Mime.prototype.load = function(file) {
|
|
138807
138807
|
this._loading = file;
|
|
138808
|
-
var map = {}, content =
|
|
138808
|
+
var map = {}, content = fs2.readFileSync(file, "ascii"), lines = content.split(/[\r\n]+/);
|
|
138809
138809
|
lines.forEach(function(line) {
|
|
138810
138810
|
var fields = line.replace(/\s*#.*|^\s*|\s*$/g, "").split(/\s+/);
|
|
138811
138811
|
map[fields.shift()] = fields;
|
|
@@ -138933,7 +138933,7 @@ var require_send = __commonJS((exports, module) => {
|
|
|
138933
138933
|
var escapeHtml = require_escape_html();
|
|
138934
138934
|
var etag = require_etag();
|
|
138935
138935
|
var fresh = require_fresh();
|
|
138936
|
-
var
|
|
138936
|
+
var fs2 = __require("fs");
|
|
138937
138937
|
var mime = require_mime();
|
|
138938
138938
|
var ms = require_ms();
|
|
138939
138939
|
var onFinished = require_on_finished();
|
|
@@ -139261,7 +139261,7 @@ var require_send = __commonJS((exports, module) => {
|
|
|
139261
139261
|
var i = 0;
|
|
139262
139262
|
var self2 = this;
|
|
139263
139263
|
debug('stat "%s"', path2);
|
|
139264
|
-
|
|
139264
|
+
fs2.stat(path2, function onstat(err, stat) {
|
|
139265
139265
|
if (err && err.code === "ENOENT" && !extname(path2) && path2[path2.length - 1] !== sep) {
|
|
139266
139266
|
return next(err);
|
|
139267
139267
|
}
|
|
@@ -139278,7 +139278,7 @@ var require_send = __commonJS((exports, module) => {
|
|
|
139278
139278
|
}
|
|
139279
139279
|
var p = path2 + "." + self2._extensions[i++];
|
|
139280
139280
|
debug('stat "%s"', p);
|
|
139281
|
-
|
|
139281
|
+
fs2.stat(p, function(err2, stat) {
|
|
139282
139282
|
if (err2)
|
|
139283
139283
|
return next(err2);
|
|
139284
139284
|
if (stat.isDirectory())
|
|
@@ -139299,7 +139299,7 @@ var require_send = __commonJS((exports, module) => {
|
|
|
139299
139299
|
}
|
|
139300
139300
|
var p = join(path2, self2._index[i]);
|
|
139301
139301
|
debug('stat "%s"', p);
|
|
139302
|
-
|
|
139302
|
+
fs2.stat(p, function(err2, stat) {
|
|
139303
139303
|
if (err2)
|
|
139304
139304
|
return next(err2);
|
|
139305
139305
|
if (stat.isDirectory())
|
|
@@ -139313,7 +139313,7 @@ var require_send = __commonJS((exports, module) => {
|
|
|
139313
139313
|
SendStream.prototype.stream = function stream(path2, options) {
|
|
139314
139314
|
var self2 = this;
|
|
139315
139315
|
var res = this.res;
|
|
139316
|
-
var stream2 =
|
|
139316
|
+
var stream2 = fs2.createReadStream(path2, options);
|
|
139317
139317
|
this.emit("stream", stream2);
|
|
139318
139318
|
stream2.pipe(res);
|
|
139319
139319
|
function cleanup() {
|
|
@@ -156057,7 +156057,7 @@ function httpError(code, message) {
|
|
|
156057
156057
|
}
|
|
156058
156058
|
};
|
|
156059
156059
|
}
|
|
156060
|
-
var NotImplementedError, BadRequestError, EnvironmentNotFoundError, PackageNotFoundError, ModelNotFoundError, ConnectionNotFoundError, ConnectionError, DestinationNotFoundError, ConnectionAuthError, UnsupportedCatalogFormatError, ModelCompilationError, MaterializationEligibilityError, FrozenConfigError, AccessDeniedError, NotQueryableError, MaterializationNotFoundError, MaterializationConflictError, InvalidStateTransitionError, ServiceUnavailableError, PayloadTooLargeError, QueryTimeoutError;
|
|
156060
|
+
var NotImplementedError, BadRequestError, EnvironmentNotFoundError, PackageNotFoundError, ModelNotFoundError, ConnectionNotFoundError, ConnectionError, DestinationNotFoundError, ConnectionAuthError, UnsupportedCatalogFormatError, ModelCompilationError, MaterializationEligibilityError, FrozenConfigError, AccessDeniedError, NotQueryableError, MaterializationNotFoundError, MaterializationConflictError, InvalidStateTransitionError, ServiceUnavailableError, PayloadTooLargeError, ResponseUnserializableError, QueryTimeoutError;
|
|
156061
156061
|
var init_errors = __esm(() => {
|
|
156062
156062
|
init_constants();
|
|
156063
156063
|
NotImplementedError = class NotImplementedError extends Error {
|
|
@@ -156161,6 +156161,13 @@ var init_errors = __esm(() => {
|
|
|
156161
156161
|
PayloadTooLargeError = class PayloadTooLargeError extends Error {
|
|
156162
156162
|
constructor(message) {
|
|
156163
156163
|
super(message);
|
|
156164
|
+
this.name = "PayloadTooLargeError";
|
|
156165
|
+
}
|
|
156166
|
+
};
|
|
156167
|
+
ResponseUnserializableError = class ResponseUnserializableError extends PayloadTooLargeError {
|
|
156168
|
+
constructor(message) {
|
|
156169
|
+
super(message);
|
|
156170
|
+
this.name = "ResponseUnserializableError";
|
|
156164
156171
|
}
|
|
156165
156172
|
};
|
|
156166
156173
|
QueryTimeoutError = class QueryTimeoutError extends Error {
|
|
@@ -165288,7 +165295,7 @@ var require_form_data = __commonJS((exports, module) => {
|
|
|
165288
165295
|
var http = __require("http");
|
|
165289
165296
|
var https = __require("https");
|
|
165290
165297
|
var parseUrl = __require("url").parse;
|
|
165291
|
-
var
|
|
165298
|
+
var fs3 = __require("fs");
|
|
165292
165299
|
var Stream = __require("stream").Stream;
|
|
165293
165300
|
var crypto2 = __require("crypto");
|
|
165294
165301
|
var mime = require_mime_types3();
|
|
@@ -165356,7 +165363,7 @@ var require_form_data = __commonJS((exports, module) => {
|
|
|
165356
165363
|
if (value.end != null && value.end != Infinity && value.start != null) {
|
|
165357
165364
|
callback(null, value.end + 1 - (value.start ? value.start : 0));
|
|
165358
165365
|
} else {
|
|
165359
|
-
|
|
165366
|
+
fs3.stat(value.path, function(err, stat) {
|
|
165360
165367
|
if (err) {
|
|
165361
165368
|
callback(err);
|
|
165362
165369
|
return;
|
|
@@ -183157,8 +183164,8 @@ ${suffix}`;
|
|
|
183157
183164
|
// ../../node_modules/ssh2/lib/protocol/SFTP.js
|
|
183158
183165
|
var require_SFTP = __commonJS((exports, module) => {
|
|
183159
183166
|
var EventEmitter2 = __require("events");
|
|
183160
|
-
var
|
|
183161
|
-
var { constants } =
|
|
183167
|
+
var fs3 = __require("fs");
|
|
183168
|
+
var { constants } = fs3;
|
|
183162
183169
|
var {
|
|
183163
183170
|
Readable: ReadableStream3,
|
|
183164
183171
|
Writable: WritableStream
|
|
@@ -183557,12 +183564,12 @@ var require_SFTP = __commonJS((exports, module) => {
|
|
|
183557
183564
|
fastGet(remotePath, localPath, opts, cb) {
|
|
183558
183565
|
if (this.server)
|
|
183559
183566
|
throw new Error("Client-only method called in server mode");
|
|
183560
|
-
fastXfer(this,
|
|
183567
|
+
fastXfer(this, fs3, remotePath, localPath, opts, cb);
|
|
183561
183568
|
}
|
|
183562
183569
|
fastPut(localPath, remotePath, opts, cb) {
|
|
183563
183570
|
if (this.server)
|
|
183564
183571
|
throw new Error("Client-only method called in server mode");
|
|
183565
|
-
fastXfer(
|
|
183572
|
+
fastXfer(fs3, this, localPath, remotePath, opts, cb);
|
|
183566
183573
|
}
|
|
183567
183574
|
readFile(path3, options, callback_) {
|
|
183568
183575
|
if (this.server)
|
|
@@ -184771,13 +184778,13 @@ var require_SFTP = __commonJS((exports, module) => {
|
|
|
184771
184778
|
if (--left === 0)
|
|
184772
184779
|
cb(err);
|
|
184773
184780
|
};
|
|
184774
|
-
if (srcHandle && (src ===
|
|
184781
|
+
if (srcHandle && (src === fs3 || src.outgoing.state === "open"))
|
|
184775
184782
|
++left;
|
|
184776
|
-
if (dstHandle && (dst ===
|
|
184783
|
+
if (dstHandle && (dst === fs3 || dst.outgoing.state === "open"))
|
|
184777
184784
|
++left;
|
|
184778
|
-
if (srcHandle && (src ===
|
|
184785
|
+
if (srcHandle && (src === fs3 || src.outgoing.state === "open"))
|
|
184779
184786
|
src.close(srcHandle, cbfinal);
|
|
184780
|
-
if (dstHandle && (dst ===
|
|
184787
|
+
if (dstHandle && (dst === fs3 || dst.outgoing.state === "open"))
|
|
184781
184788
|
dst.close(dstHandle, cbfinal);
|
|
184782
184789
|
} else {
|
|
184783
184790
|
cb(err);
|
|
@@ -184793,7 +184800,7 @@ var require_SFTP = __commonJS((exports, module) => {
|
|
|
184793
184800
|
tryStat(null, { size: fileSize });
|
|
184794
184801
|
function tryStat(err2, attrs) {
|
|
184795
184802
|
if (err2) {
|
|
184796
|
-
if (src !==
|
|
184803
|
+
if (src !== fs3) {
|
|
184797
184804
|
src.stat(srcPath, (err_, attrs_) => {
|
|
184798
184805
|
if (err_)
|
|
184799
184806
|
return onerror(err2);
|
|
@@ -190365,23 +190372,23 @@ var require_crypto2 = __commonJS((exports) => {
|
|
|
190365
190372
|
var require_crypto3 = __commonJS((exports) => {
|
|
190366
190373
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
190367
190374
|
exports.NodeCrypto = undefined;
|
|
190368
|
-
var
|
|
190375
|
+
var crypto4 = __require("crypto");
|
|
190369
190376
|
|
|
190370
190377
|
class NodeCrypto {
|
|
190371
190378
|
async sha256DigestBase64(str) {
|
|
190372
|
-
return
|
|
190379
|
+
return crypto4.createHash("sha256").update(str).digest("base64");
|
|
190373
190380
|
}
|
|
190374
190381
|
randomBytesBase64(count) {
|
|
190375
|
-
return
|
|
190382
|
+
return crypto4.randomBytes(count).toString("base64");
|
|
190376
190383
|
}
|
|
190377
190384
|
async verify(pubkey, data, signature) {
|
|
190378
|
-
const verifier =
|
|
190385
|
+
const verifier = crypto4.createVerify("RSA-SHA256");
|
|
190379
190386
|
verifier.update(data);
|
|
190380
190387
|
verifier.end();
|
|
190381
190388
|
return verifier.verify(pubkey, signature, "base64");
|
|
190382
190389
|
}
|
|
190383
190390
|
async sign(privateKey, data) {
|
|
190384
|
-
const signer =
|
|
190391
|
+
const signer = crypto4.createSign("RSA-SHA256");
|
|
190385
190392
|
signer.update(data);
|
|
190386
190393
|
signer.end();
|
|
190387
190394
|
return signer.sign(privateKey, "base64");
|
|
@@ -190393,11 +190400,11 @@ var require_crypto3 = __commonJS((exports) => {
|
|
|
190393
190400
|
return Buffer.from(text, "utf-8").toString("base64");
|
|
190394
190401
|
}
|
|
190395
190402
|
async sha256DigestHex(str) {
|
|
190396
|
-
return
|
|
190403
|
+
return crypto4.createHash("sha256").update(str).digest("hex");
|
|
190397
190404
|
}
|
|
190398
190405
|
async signWithHmacSha256(key, msg) {
|
|
190399
190406
|
const cryptoKey = typeof key === "string" ? key : toBuffer(key);
|
|
190400
|
-
return toArrayBuffer(
|
|
190407
|
+
return toArrayBuffer(crypto4.createHmac("sha256", cryptoKey).update(msg).digest());
|
|
190401
190408
|
}
|
|
190402
190409
|
}
|
|
190403
190410
|
exports.NodeCrypto = NodeCrypto;
|
|
@@ -191013,10 +191020,10 @@ var require_oauth2client = __commonJS((exports) => {
|
|
|
191013
191020
|
throw new Error("generateCodeVerifier is removed, please use generateCodeVerifierAsync instead.");
|
|
191014
191021
|
}
|
|
191015
191022
|
async generateCodeVerifierAsync() {
|
|
191016
|
-
const
|
|
191017
|
-
const randomString =
|
|
191023
|
+
const crypto4 = (0, crypto_1.createCrypto)();
|
|
191024
|
+
const randomString = crypto4.randomBytesBase64(96);
|
|
191018
191025
|
const codeVerifier = randomString.replace(/\+/g, "~").replace(/=/g, "_").replace(/\//g, "-");
|
|
191019
|
-
const unencodedCodeChallenge = await
|
|
191026
|
+
const unencodedCodeChallenge = await crypto4.sha256DigestBase64(codeVerifier);
|
|
191020
191027
|
const codeChallenge = unencodedCodeChallenge.split("=")[0].replace(/\+/g, "-").replace(/\//g, "_");
|
|
191021
191028
|
return { codeVerifier, codeChallenge };
|
|
191022
191029
|
}
|
|
@@ -191418,7 +191425,7 @@ var require_oauth2client = __commonJS((exports) => {
|
|
|
191418
191425
|
throw new Error("verifySignedJwtWithCerts is removed, please use verifySignedJwtWithCertsAsync instead.");
|
|
191419
191426
|
}
|
|
191420
191427
|
async verifySignedJwtWithCertsAsync(jwt, certs, requiredAudience, issuers, maxExpiry) {
|
|
191421
|
-
const
|
|
191428
|
+
const crypto4 = (0, crypto_1.createCrypto)();
|
|
191422
191429
|
if (!maxExpiry) {
|
|
191423
191430
|
maxExpiry = OAuth2Client.DEFAULT_MAX_TOKEN_LIFETIME_SECS_;
|
|
191424
191431
|
}
|
|
@@ -191431,7 +191438,7 @@ var require_oauth2client = __commonJS((exports) => {
|
|
|
191431
191438
|
let envelope;
|
|
191432
191439
|
let payload;
|
|
191433
191440
|
try {
|
|
191434
|
-
envelope = JSON.parse(
|
|
191441
|
+
envelope = JSON.parse(crypto4.decodeBase64StringUtf8(segments[0]));
|
|
191435
191442
|
} catch (err) {
|
|
191436
191443
|
if (err instanceof Error) {
|
|
191437
191444
|
err.message = `Can't parse token envelope: ${segments[0]}': ${err.message}`;
|
|
@@ -191442,7 +191449,7 @@ var require_oauth2client = __commonJS((exports) => {
|
|
|
191442
191449
|
throw new Error("Can't parse token envelope: " + segments[0]);
|
|
191443
191450
|
}
|
|
191444
191451
|
try {
|
|
191445
|
-
payload = JSON.parse(
|
|
191452
|
+
payload = JSON.parse(crypto4.decodeBase64StringUtf8(segments[1]));
|
|
191446
191453
|
} catch (err) {
|
|
191447
191454
|
if (err instanceof Error) {
|
|
191448
191455
|
err.message = `Can't parse token payload '${segments[0]}`;
|
|
@@ -191459,7 +191466,7 @@ var require_oauth2client = __commonJS((exports) => {
|
|
|
191459
191466
|
if (envelope.alg === "ES256") {
|
|
191460
191467
|
signature = formatEcdsa.joseToDer(signature, "ES256").toString("base64");
|
|
191461
191468
|
}
|
|
191462
|
-
const verified = await
|
|
191469
|
+
const verified = await crypto4.verify(cert, signed, signature);
|
|
191463
191470
|
if (!verified) {
|
|
191464
191471
|
throw new Error("Invalid token signature: " + jwt);
|
|
191465
191472
|
}
|
|
@@ -191783,7 +191790,7 @@ var require_buffer_equal_constant_time = __commonJS((exports, module) => {
|
|
|
191783
191790
|
// ../../node_modules/jwa/index.js
|
|
191784
191791
|
var require_jwa = __commonJS((exports, module) => {
|
|
191785
191792
|
var Buffer2 = require_safe_buffer().Buffer;
|
|
191786
|
-
var
|
|
191793
|
+
var crypto4 = __require("crypto");
|
|
191787
191794
|
var formatEcdsa = require_ecdsa_sig_formatter();
|
|
191788
191795
|
var util5 = __require("util");
|
|
191789
191796
|
var MSG_INVALID_ALGORITHM = `"%s" is not a valid algorithm.
|
|
@@ -191792,7 +191799,7 @@ var require_jwa = __commonJS((exports, module) => {
|
|
|
191792
191799
|
var MSG_INVALID_SECRET = "secret must be a string or buffer";
|
|
191793
191800
|
var MSG_INVALID_VERIFIER_KEY = "key must be a string or a buffer";
|
|
191794
191801
|
var MSG_INVALID_SIGNER_KEY = "key must be a string, a buffer or an object";
|
|
191795
|
-
var supportsKeyObjects = typeof
|
|
191802
|
+
var supportsKeyObjects = typeof crypto4.createPublicKey === "function";
|
|
191796
191803
|
if (supportsKeyObjects) {
|
|
191797
191804
|
MSG_INVALID_VERIFIER_KEY += " or a KeyObject";
|
|
191798
191805
|
MSG_INVALID_SECRET += "or a KeyObject";
|
|
@@ -191882,17 +191889,17 @@ var require_jwa = __commonJS((exports, module) => {
|
|
|
191882
191889
|
return function sign(thing, secret) {
|
|
191883
191890
|
checkIsSecretKey(secret);
|
|
191884
191891
|
thing = normalizeInput(thing);
|
|
191885
|
-
var hmac =
|
|
191892
|
+
var hmac = crypto4.createHmac("sha" + bits, secret);
|
|
191886
191893
|
var sig = (hmac.update(thing), hmac.digest("base64"));
|
|
191887
191894
|
return fromBase64(sig);
|
|
191888
191895
|
};
|
|
191889
191896
|
}
|
|
191890
191897
|
var bufferEqual;
|
|
191891
|
-
var timingSafeEqual = "timingSafeEqual" in
|
|
191898
|
+
var timingSafeEqual = "timingSafeEqual" in crypto4 ? function timingSafeEqual2(a, b) {
|
|
191892
191899
|
if (a.byteLength !== b.byteLength) {
|
|
191893
191900
|
return false;
|
|
191894
191901
|
}
|
|
191895
|
-
return
|
|
191902
|
+
return crypto4.timingSafeEqual(a, b);
|
|
191896
191903
|
} : function timingSafeEqual2(a, b) {
|
|
191897
191904
|
if (!bufferEqual) {
|
|
191898
191905
|
bufferEqual = require_buffer_equal_constant_time();
|
|
@@ -191909,7 +191916,7 @@ var require_jwa = __commonJS((exports, module) => {
|
|
|
191909
191916
|
return function sign(thing, privateKey) {
|
|
191910
191917
|
checkIsPrivateKey(privateKey);
|
|
191911
191918
|
thing = normalizeInput(thing);
|
|
191912
|
-
var signer =
|
|
191919
|
+
var signer = crypto4.createSign("RSA-SHA" + bits);
|
|
191913
191920
|
var sig = (signer.update(thing), signer.sign(privateKey, "base64"));
|
|
191914
191921
|
return fromBase64(sig);
|
|
191915
191922
|
};
|
|
@@ -191919,7 +191926,7 @@ var require_jwa = __commonJS((exports, module) => {
|
|
|
191919
191926
|
checkIsPublicKey(publicKey);
|
|
191920
191927
|
thing = normalizeInput(thing);
|
|
191921
191928
|
signature = toBase64(signature);
|
|
191922
|
-
var verifier =
|
|
191929
|
+
var verifier = crypto4.createVerify("RSA-SHA" + bits);
|
|
191923
191930
|
verifier.update(thing);
|
|
191924
191931
|
return verifier.verify(publicKey, signature, "base64");
|
|
191925
191932
|
};
|
|
@@ -191928,11 +191935,11 @@ var require_jwa = __commonJS((exports, module) => {
|
|
|
191928
191935
|
return function sign(thing, privateKey) {
|
|
191929
191936
|
checkIsPrivateKey(privateKey);
|
|
191930
191937
|
thing = normalizeInput(thing);
|
|
191931
|
-
var signer =
|
|
191938
|
+
var signer = crypto4.createSign("RSA-SHA" + bits);
|
|
191932
191939
|
var sig = (signer.update(thing), signer.sign({
|
|
191933
191940
|
key: privateKey,
|
|
191934
|
-
padding:
|
|
191935
|
-
saltLength:
|
|
191941
|
+
padding: crypto4.constants.RSA_PKCS1_PSS_PADDING,
|
|
191942
|
+
saltLength: crypto4.constants.RSA_PSS_SALTLEN_DIGEST
|
|
191936
191943
|
}, "base64"));
|
|
191937
191944
|
return fromBase64(sig);
|
|
191938
191945
|
};
|
|
@@ -191942,12 +191949,12 @@ var require_jwa = __commonJS((exports, module) => {
|
|
|
191942
191949
|
checkIsPublicKey(publicKey);
|
|
191943
191950
|
thing = normalizeInput(thing);
|
|
191944
191951
|
signature = toBase64(signature);
|
|
191945
|
-
var verifier =
|
|
191952
|
+
var verifier = crypto4.createVerify("RSA-SHA" + bits);
|
|
191946
191953
|
verifier.update(thing);
|
|
191947
191954
|
return verifier.verify({
|
|
191948
191955
|
key: publicKey,
|
|
191949
|
-
padding:
|
|
191950
|
-
saltLength:
|
|
191956
|
+
padding: crypto4.constants.RSA_PKCS1_PSS_PADDING,
|
|
191957
|
+
saltLength: crypto4.constants.RSA_PSS_SALTLEN_DIGEST
|
|
191951
191958
|
}, signature, "base64");
|
|
191952
191959
|
};
|
|
191953
191960
|
}
|
|
@@ -192251,12 +192258,12 @@ var require_src113 = __commonJS((exports) => {
|
|
|
192251
192258
|
var _GoogleToken_requestToken;
|
|
192252
192259
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
192253
192260
|
exports.GoogleToken = undefined;
|
|
192254
|
-
var
|
|
192261
|
+
var fs4 = __require("fs");
|
|
192255
192262
|
var gaxios_1 = require_src53();
|
|
192256
192263
|
var jws = require_jws();
|
|
192257
192264
|
var path4 = __require("path");
|
|
192258
192265
|
var util_1 = __require("util");
|
|
192259
|
-
var readFile =
|
|
192266
|
+
var readFile = fs4.readFile ? (0, util_1.promisify)(fs4.readFile) : async () => {
|
|
192260
192267
|
throw new ErrorWithCode("use key rather than keyFile.", "MISSING_CREDENTIALS");
|
|
192261
192268
|
};
|
|
192262
192269
|
var GOOGLE_TOKEN_URL = "https://www.googleapis.com/oauth2/v4/token";
|
|
@@ -193469,10 +193476,10 @@ var require_filesubjecttokensupplier = __commonJS((exports) => {
|
|
|
193469
193476
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
193470
193477
|
exports.FileSubjectTokenSupplier = undefined;
|
|
193471
193478
|
var util_1 = __require("util");
|
|
193472
|
-
var
|
|
193473
|
-
var readFile = (0, util_1.promisify)((_a =
|
|
193474
|
-
var realpath = (0, util_1.promisify)((_b =
|
|
193475
|
-
var lstat = (0, util_1.promisify)((_c =
|
|
193479
|
+
var fs4 = __require("fs");
|
|
193480
|
+
var readFile = (0, util_1.promisify)((_a = fs4.readFile) !== null && _a !== undefined ? _a : () => {});
|
|
193481
|
+
var realpath = (0, util_1.promisify)((_b = fs4.realpath) !== null && _b !== undefined ? _b : () => {});
|
|
193482
|
+
var lstat = (0, util_1.promisify)((_c = fs4.lstat) !== null && _c !== undefined ? _c : () => {});
|
|
193476
193483
|
|
|
193477
193484
|
class FileSubjectTokenSupplier {
|
|
193478
193485
|
constructor(opts) {
|
|
@@ -193673,14 +193680,14 @@ var require_awsrequestsigner = __commonJS((exports) => {
|
|
|
193673
193680
|
}
|
|
193674
193681
|
}
|
|
193675
193682
|
exports.AwsRequestSigner = AwsRequestSigner;
|
|
193676
|
-
async function sign(
|
|
193677
|
-
return await
|
|
193678
|
-
}
|
|
193679
|
-
async function getSigningKey(
|
|
193680
|
-
const kDate = await sign(
|
|
193681
|
-
const kRegion = await sign(
|
|
193682
|
-
const kService = await sign(
|
|
193683
|
-
const kSigning = await sign(
|
|
193683
|
+
async function sign(crypto4, key, msg) {
|
|
193684
|
+
return await crypto4.signWithHmacSha256(key, msg);
|
|
193685
|
+
}
|
|
193686
|
+
async function getSigningKey(crypto4, key, dateStamp, region, serviceName) {
|
|
193687
|
+
const kDate = await sign(crypto4, `AWS4${key}`, dateStamp);
|
|
193688
|
+
const kRegion = await sign(crypto4, kDate, region);
|
|
193689
|
+
const kService = await sign(crypto4, kRegion, serviceName);
|
|
193690
|
+
const kSigning = await sign(crypto4, kService, "aws4_request");
|
|
193684
193691
|
return kSigning;
|
|
193685
193692
|
}
|
|
193686
193693
|
async function generateAuthenticationHeaderMap(options) {
|
|
@@ -194036,7 +194043,7 @@ var require_pluggable_auth_handler = __commonJS((exports) => {
|
|
|
194036
194043
|
var pluggable_auth_client_1 = require_pluggable_auth_client();
|
|
194037
194044
|
var executable_response_1 = require_executable_response();
|
|
194038
194045
|
var childProcess = __require("child_process");
|
|
194039
|
-
var
|
|
194046
|
+
var fs4 = __require("fs");
|
|
194040
194047
|
|
|
194041
194048
|
class PluggableAuthHandler {
|
|
194042
194049
|
constructor(options) {
|
|
@@ -194092,14 +194099,14 @@ var require_pluggable_auth_handler = __commonJS((exports) => {
|
|
|
194092
194099
|
}
|
|
194093
194100
|
let filePath;
|
|
194094
194101
|
try {
|
|
194095
|
-
filePath = await
|
|
194102
|
+
filePath = await fs4.promises.realpath(this.outputFile);
|
|
194096
194103
|
} catch (_a) {
|
|
194097
194104
|
return;
|
|
194098
194105
|
}
|
|
194099
|
-
if (!(await
|
|
194106
|
+
if (!(await fs4.promises.lstat(filePath)).isFile()) {
|
|
194100
194107
|
return;
|
|
194101
194108
|
}
|
|
194102
|
-
const responseString = await
|
|
194109
|
+
const responseString = await fs4.promises.readFile(filePath, {
|
|
194103
194110
|
encoding: "utf8"
|
|
194104
194111
|
});
|
|
194105
194112
|
if (responseString === "") {
|
|
@@ -194426,7 +194433,7 @@ var require_googleauth = __commonJS((exports) => {
|
|
|
194426
194433
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
194427
194434
|
exports.GoogleAuth = exports.GoogleAuthExceptionMessages = exports.CLOUD_SDK_CLIENT_ID = undefined;
|
|
194428
194435
|
var child_process_1 = __require("child_process");
|
|
194429
|
-
var
|
|
194436
|
+
var fs4 = __require("fs");
|
|
194430
194437
|
var gcpMetadata = require_src55();
|
|
194431
194438
|
var os2 = __require("os");
|
|
194432
194439
|
var path4 = __require("path");
|
|
@@ -194630,7 +194637,7 @@ var require_googleauth = __commonJS((exports) => {
|
|
|
194630
194637
|
}
|
|
194631
194638
|
if (location) {
|
|
194632
194639
|
location = path4.join(location, "gcloud", "application_default_credentials.json");
|
|
194633
|
-
if (!
|
|
194640
|
+
if (!fs4.existsSync(location)) {
|
|
194634
194641
|
location = null;
|
|
194635
194642
|
}
|
|
194636
194643
|
}
|
|
@@ -194645,8 +194652,8 @@ var require_googleauth = __commonJS((exports) => {
|
|
|
194645
194652
|
throw new Error("The file path is invalid.");
|
|
194646
194653
|
}
|
|
194647
194654
|
try {
|
|
194648
|
-
filePath =
|
|
194649
|
-
if (!
|
|
194655
|
+
filePath = fs4.realpathSync(filePath);
|
|
194656
|
+
if (!fs4.lstatSync(filePath).isFile()) {
|
|
194650
194657
|
throw new Error;
|
|
194651
194658
|
}
|
|
194652
194659
|
} catch (err) {
|
|
@@ -194655,7 +194662,7 @@ var require_googleauth = __commonJS((exports) => {
|
|
|
194655
194662
|
}
|
|
194656
194663
|
throw err;
|
|
194657
194664
|
}
|
|
194658
|
-
const readStream2 =
|
|
194665
|
+
const readStream2 = fs4.createReadStream(filePath);
|
|
194659
194666
|
return this.fromStream(readStream2, options);
|
|
194660
194667
|
}
|
|
194661
194668
|
fromImpersonatedJSON(json) {
|
|
@@ -194907,24 +194914,24 @@ var require_googleauth = __commonJS((exports) => {
|
|
|
194907
194914
|
const signed = await client.sign(data);
|
|
194908
194915
|
return signed.signedBlob;
|
|
194909
194916
|
}
|
|
194910
|
-
const
|
|
194917
|
+
const crypto4 = (0, crypto_1.createCrypto)();
|
|
194911
194918
|
if (client instanceof jwtclient_1.JWT && client.key) {
|
|
194912
|
-
const sign = await
|
|
194919
|
+
const sign = await crypto4.sign(client.key, data);
|
|
194913
194920
|
return sign;
|
|
194914
194921
|
}
|
|
194915
194922
|
const creds = await this.getCredentials();
|
|
194916
194923
|
if (!creds.client_email) {
|
|
194917
194924
|
throw new Error("Cannot sign data without `client_email`.");
|
|
194918
194925
|
}
|
|
194919
|
-
return this.signBlob(
|
|
194926
|
+
return this.signBlob(crypto4, creds.client_email, data, endpoint);
|
|
194920
194927
|
}
|
|
194921
|
-
async signBlob(
|
|
194928
|
+
async signBlob(crypto4, emailOrUniqueId, data, endpoint) {
|
|
194922
194929
|
const url2 = new URL(endpoint + `${emailOrUniqueId}:signBlob`);
|
|
194923
194930
|
const res = await this.request({
|
|
194924
194931
|
method: "POST",
|
|
194925
194932
|
url: url2.href,
|
|
194926
194933
|
data: {
|
|
194927
|
-
payload:
|
|
194934
|
+
payload: crypto4.encodeBase64StringUtf8(data)
|
|
194928
194935
|
},
|
|
194929
194936
|
retry: true,
|
|
194930
194937
|
retryConfig: {
|
|
@@ -194947,7 +194954,7 @@ var require_googleauth = __commonJS((exports) => {
|
|
|
194947
194954
|
return this._cacheClientFromJSON(this.jsonContent, this.clientOptions);
|
|
194948
194955
|
} else if (this.keyFilename) {
|
|
194949
194956
|
const filePath = path4.resolve(this.keyFilename);
|
|
194950
|
-
const stream4 =
|
|
194957
|
+
const stream4 = fs4.createReadStream(filePath);
|
|
194951
194958
|
return await this.fromStreamAsync(stream4, this.clientOptions);
|
|
194952
194959
|
} else if (this.apiKey) {
|
|
194953
194960
|
const client = await this.fromAPIKey(this.apiKey, this.clientOptions);
|
|
@@ -202701,7 +202708,7 @@ var require_table = __commonJS((exports) => {
|
|
|
202701
202708
|
var Big = require_big();
|
|
202702
202709
|
var extend2 = require_extend();
|
|
202703
202710
|
var events_1 = __require("events");
|
|
202704
|
-
var
|
|
202711
|
+
var fs4 = __require("fs");
|
|
202705
202712
|
var is = require_is();
|
|
202706
202713
|
var path4 = __require("path");
|
|
202707
202714
|
var streamEvents = require_stream_events();
|
|
@@ -203011,7 +203018,7 @@ var require_table = __commonJS((exports) => {
|
|
|
203011
203018
|
if (!metadata.sourceFormat && detectedFormat) {
|
|
203012
203019
|
metadata.sourceFormat = detectedFormat;
|
|
203013
203020
|
}
|
|
203014
|
-
const jobWritable =
|
|
203021
|
+
const jobWritable = fs4.createReadStream(source).pipe(this.createWriteStream_(metadata));
|
|
203015
203022
|
const [jobResponse] = await (0, events_1.once)(jobWritable, "job");
|
|
203016
203023
|
return [jobResponse, jobResponse.metadata];
|
|
203017
203024
|
}
|
|
@@ -208811,11 +208818,11 @@ var require_randomUUID = __commonJS((exports) => {
|
|
|
208811
208818
|
|
|
208812
208819
|
// ../../node_modules/@smithy/uuid/dist-cjs/index.js
|
|
208813
208820
|
var require_dist_cjs16 = __commonJS((exports) => {
|
|
208814
|
-
var
|
|
208821
|
+
var randomUUID3 = require_randomUUID();
|
|
208815
208822
|
var decimalToHex = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
|
|
208816
208823
|
var v4 = () => {
|
|
208817
|
-
if (
|
|
208818
|
-
return
|
|
208824
|
+
if (randomUUID3.randomUUID) {
|
|
208825
|
+
return randomUUID3.randomUUID();
|
|
208819
208826
|
}
|
|
208820
208827
|
const rnds = new Uint8Array(16);
|
|
208821
208828
|
crypto.getRandomValues(rnds);
|
|
@@ -223136,7 +223143,7 @@ var require_dist_cjs55 = __commonJS((exports) => {
|
|
|
223136
223143
|
var utilBufferFrom = require_dist_cjs7();
|
|
223137
223144
|
var utilUtf8 = require_dist_cjs8();
|
|
223138
223145
|
var buffer = __require("buffer");
|
|
223139
|
-
var
|
|
223146
|
+
var crypto4 = __require("crypto");
|
|
223140
223147
|
|
|
223141
223148
|
class Hash {
|
|
223142
223149
|
algorithmIdentifier;
|
|
@@ -223154,7 +223161,7 @@ var require_dist_cjs55 = __commonJS((exports) => {
|
|
|
223154
223161
|
return Promise.resolve(this.hash.digest());
|
|
223155
223162
|
}
|
|
223156
223163
|
reset() {
|
|
223157
|
-
this.hash = this.secret ?
|
|
223164
|
+
this.hash = this.secret ? crypto4.createHmac(this.algorithmIdentifier, castSourceData(this.secret)) : crypto4.createHash(this.algorithmIdentifier);
|
|
223158
223165
|
}
|
|
223159
223166
|
}
|
|
223160
223167
|
function castSourceData(toCast, encoding) {
|
|
@@ -225794,7 +225801,7 @@ var require_dist_cjs59 = __commonJS((exports) => {
|
|
|
225794
225801
|
var httpAuthSchemes = require_httpAuthSchemes();
|
|
225795
225802
|
var propertyProvider = require_dist_cjs18();
|
|
225796
225803
|
var sharedIniFileLoader = require_dist_cjs44();
|
|
225797
|
-
var
|
|
225804
|
+
var fs4 = __require("fs");
|
|
225798
225805
|
var fromEnvSigningName = ({ logger: logger2, signingName } = {}) => async () => {
|
|
225799
225806
|
logger2?.debug?.("@aws-sdk/token-providers - fromEnvSigningName");
|
|
225800
225807
|
if (!signingName) {
|
|
@@ -225840,7 +225847,7 @@ var require_dist_cjs59 = __commonJS((exports) => {
|
|
|
225840
225847
|
throw new propertyProvider.TokenProviderError(`Value not present for '${key}' in SSO Token${forRefresh ? ". Cannot refresh" : ""}. ${REFRESH_MESSAGE}`, false);
|
|
225841
225848
|
}
|
|
225842
225849
|
};
|
|
225843
|
-
var { writeFile } =
|
|
225850
|
+
var { writeFile } = fs4.promises;
|
|
225844
225851
|
var writeSSOTokenToFile = (id, ssoToken) => {
|
|
225845
225852
|
const tokenFilepath = sharedIniFileLoader.getSSOTokenFilepath(id);
|
|
225846
225853
|
const tokenString = JSON.stringify(ssoToken, null, 2);
|
|
@@ -230052,7 +230059,7 @@ var require_dist_cjs70 = __commonJS((exports) => {
|
|
|
230052
230059
|
|
|
230053
230060
|
// ../../node_modules/@smithy/hash-stream-node/dist-cjs/index.js
|
|
230054
230061
|
var require_dist_cjs71 = __commonJS((exports) => {
|
|
230055
|
-
var
|
|
230062
|
+
var fs4 = __require("fs");
|
|
230056
230063
|
var utilUtf8 = require_dist_cjs8();
|
|
230057
230064
|
var stream4 = __require("stream");
|
|
230058
230065
|
|
|
@@ -230076,7 +230083,7 @@ var require_dist_cjs71 = __commonJS((exports) => {
|
|
|
230076
230083
|
reject(new Error("Unable to calculate hash for non-file streams."));
|
|
230077
230084
|
return;
|
|
230078
230085
|
}
|
|
230079
|
-
const fileStreamTee =
|
|
230086
|
+
const fileStreamTee = fs4.createReadStream(fileStream.path, {
|
|
230080
230087
|
start: fileStream.start,
|
|
230081
230088
|
end: fileStream.end
|
|
230082
230089
|
});
|
|
@@ -238485,9 +238492,9 @@ var require_dist11 = __commonJS((exports) => {
|
|
|
238485
238492
|
var require_pump = __commonJS((exports, module) => {
|
|
238486
238493
|
var once = require_once2();
|
|
238487
238494
|
var eos = require_end_of_stream4();
|
|
238488
|
-
var
|
|
238495
|
+
var fs4;
|
|
238489
238496
|
try {
|
|
238490
|
-
|
|
238497
|
+
fs4 = __require("fs");
|
|
238491
238498
|
} catch (e) {}
|
|
238492
238499
|
var noop2 = function() {};
|
|
238493
238500
|
var ancient = typeof process === "undefined" ? false : /^v?\.0/.test(process.version);
|
|
@@ -238497,9 +238504,9 @@ var require_pump = __commonJS((exports, module) => {
|
|
|
238497
238504
|
var isFS = function(stream4) {
|
|
238498
238505
|
if (!ancient)
|
|
238499
238506
|
return false;
|
|
238500
|
-
if (!
|
|
238507
|
+
if (!fs4)
|
|
238501
238508
|
return false;
|
|
238502
|
-
return (stream4 instanceof (
|
|
238509
|
+
return (stream4 instanceof (fs4.ReadStream || noop2) || stream4 instanceof (fs4.WriteStream || noop2)) && isFn(stream4.close);
|
|
238503
238510
|
};
|
|
238504
238511
|
var isRequest2 = function(stream4) {
|
|
238505
238512
|
return stream4.setHeader && isFn(stream4.abort);
|
|
@@ -238714,7 +238721,7 @@ var require_pend = __commonJS((exports, module) => {
|
|
|
238714
238721
|
|
|
238715
238722
|
// ../../node_modules/fd-slicer/index.js
|
|
238716
238723
|
var require_fd_slicer = __commonJS((exports) => {
|
|
238717
|
-
var
|
|
238724
|
+
var fs4 = __require("fs");
|
|
238718
238725
|
var util5 = __require("util");
|
|
238719
238726
|
var stream4 = __require("stream");
|
|
238720
238727
|
var Readable3 = stream4.Readable;
|
|
@@ -238739,7 +238746,7 @@ var require_fd_slicer = __commonJS((exports) => {
|
|
|
238739
238746
|
FdSlicer.prototype.read = function(buffer, offset, length, position, callback) {
|
|
238740
238747
|
var self2 = this;
|
|
238741
238748
|
self2.pend.go(function(cb) {
|
|
238742
|
-
|
|
238749
|
+
fs4.read(self2.fd, buffer, offset, length, position, function(err, bytesRead, buffer2) {
|
|
238743
238750
|
cb();
|
|
238744
238751
|
callback(err, bytesRead, buffer2);
|
|
238745
238752
|
});
|
|
@@ -238748,7 +238755,7 @@ var require_fd_slicer = __commonJS((exports) => {
|
|
|
238748
238755
|
FdSlicer.prototype.write = function(buffer, offset, length, position, callback) {
|
|
238749
238756
|
var self2 = this;
|
|
238750
238757
|
self2.pend.go(function(cb) {
|
|
238751
|
-
|
|
238758
|
+
fs4.write(self2.fd, buffer, offset, length, position, function(err, written, buffer2) {
|
|
238752
238759
|
cb();
|
|
238753
238760
|
callback(err, written, buffer2);
|
|
238754
238761
|
});
|
|
@@ -238771,7 +238778,7 @@ var require_fd_slicer = __commonJS((exports) => {
|
|
|
238771
238778
|
if (self2.refCount < 0)
|
|
238772
238779
|
throw new Error("invalid unref");
|
|
238773
238780
|
if (self2.autoClose) {
|
|
238774
|
-
|
|
238781
|
+
fs4.close(self2.fd, onCloseDone);
|
|
238775
238782
|
}
|
|
238776
238783
|
function onCloseDone(err) {
|
|
238777
238784
|
if (err) {
|
|
@@ -238810,7 +238817,7 @@ var require_fd_slicer = __commonJS((exports) => {
|
|
|
238810
238817
|
if (self2.destroyed)
|
|
238811
238818
|
return cb();
|
|
238812
238819
|
var buffer = new Buffer(toRead);
|
|
238813
|
-
|
|
238820
|
+
fs4.read(self2.context.fd, buffer, 0, toRead, self2.pos, function(err, bytesRead) {
|
|
238814
238821
|
if (err) {
|
|
238815
238822
|
self2.destroy(err);
|
|
238816
238823
|
} else if (bytesRead === 0) {
|
|
@@ -238860,7 +238867,7 @@ var require_fd_slicer = __commonJS((exports) => {
|
|
|
238860
238867
|
self2.context.pend.go(function(cb) {
|
|
238861
238868
|
if (self2.destroyed)
|
|
238862
238869
|
return cb();
|
|
238863
|
-
|
|
238870
|
+
fs4.write(self2.context.fd, buffer, 0, buffer.length, self2.pos, function(err2, bytes) {
|
|
238864
238871
|
if (err2) {
|
|
238865
238872
|
self2.destroy();
|
|
238866
238873
|
cb();
|
|
@@ -239285,7 +239292,7 @@ var require_buffer_crc32 = __commonJS((exports, module) => {
|
|
|
239285
239292
|
|
|
239286
239293
|
// ../../node_modules/yauzl/index.js
|
|
239287
239294
|
var require_yauzl = __commonJS((exports) => {
|
|
239288
|
-
var
|
|
239295
|
+
var fs4 = __require("fs");
|
|
239289
239296
|
var zlib2 = __require("zlib");
|
|
239290
239297
|
var fd_slicer = require_fd_slicer();
|
|
239291
239298
|
var crc32 = require_buffer_crc32();
|
|
@@ -239322,12 +239329,12 @@ var require_yauzl = __commonJS((exports) => {
|
|
|
239322
239329
|
options.strictFileNames = false;
|
|
239323
239330
|
if (callback == null)
|
|
239324
239331
|
callback = defaultCallback;
|
|
239325
|
-
|
|
239332
|
+
fs4.open(path4, "r", function(err, fd) {
|
|
239326
239333
|
if (err)
|
|
239327
239334
|
return callback(err);
|
|
239328
239335
|
fromFd(fd, options, function(err2, zipfile) {
|
|
239329
239336
|
if (err2)
|
|
239330
|
-
|
|
239337
|
+
fs4.close(fd, defaultCallback);
|
|
239331
239338
|
callback(err2, zipfile);
|
|
239332
239339
|
});
|
|
239333
239340
|
});
|
|
@@ -239351,7 +239358,7 @@ var require_yauzl = __commonJS((exports) => {
|
|
|
239351
239358
|
options.strictFileNames = false;
|
|
239352
239359
|
if (callback == null)
|
|
239353
239360
|
callback = defaultCallback;
|
|
239354
|
-
|
|
239361
|
+
fs4.fstat(fd, function(err, stats) {
|
|
239355
239362
|
if (err)
|
|
239356
239363
|
return callback(err);
|
|
239357
239364
|
var reader = fd_slicer.createFromFd(fd, { autoClose: true });
|
|
@@ -239984,7 +239991,7 @@ var require_yauzl = __commonJS((exports) => {
|
|
|
239984
239991
|
// ../../node_modules/extract-zip/index.js
|
|
239985
239992
|
var require_extract_zip = __commonJS((exports, module) => {
|
|
239986
239993
|
var debug = require_src5()("extract-zip");
|
|
239987
|
-
var { createWriteStream, promises:
|
|
239994
|
+
var { createWriteStream, promises: fs4 } = __require("fs");
|
|
239988
239995
|
var getStream = require_get_stream();
|
|
239989
239996
|
var path4 = __require("path");
|
|
239990
239997
|
var { promisify } = __require("util");
|
|
@@ -240026,8 +240033,8 @@ var require_extract_zip = __commonJS((exports, module) => {
|
|
|
240026
240033
|
}
|
|
240027
240034
|
const destDir = path4.dirname(path4.join(this.opts.dir, entry.fileName));
|
|
240028
240035
|
try {
|
|
240029
|
-
await
|
|
240030
|
-
const canonicalDestDir = await
|
|
240036
|
+
await fs4.mkdir(destDir, { recursive: true });
|
|
240037
|
+
const canonicalDestDir = await fs4.realpath(destDir);
|
|
240031
240038
|
const relativeDestDir = path4.relative(this.opts.dir, canonicalDestDir);
|
|
240032
240039
|
if (relativeDestDir.split(path4.sep).includes("..")) {
|
|
240033
240040
|
throw new Error(`Out of bound path "${canonicalDestDir}" found while processing file ${entry.fileName}`);
|
|
@@ -240072,7 +240079,7 @@ var require_extract_zip = __commonJS((exports, module) => {
|
|
|
240072
240079
|
mkdirOptions.mode = procMode;
|
|
240073
240080
|
}
|
|
240074
240081
|
debug("mkdir", { dir: destDir, ...mkdirOptions });
|
|
240075
|
-
await
|
|
240082
|
+
await fs4.mkdir(destDir, mkdirOptions);
|
|
240076
240083
|
if (isDir)
|
|
240077
240084
|
return;
|
|
240078
240085
|
debug("opening read stream", dest);
|
|
@@ -240080,7 +240087,7 @@ var require_extract_zip = __commonJS((exports, module) => {
|
|
|
240080
240087
|
if (symlink) {
|
|
240081
240088
|
const link = await getStream(readStream2);
|
|
240082
240089
|
debug("creating symlink", link, dest);
|
|
240083
|
-
await
|
|
240090
|
+
await fs4.symlink(link, dest);
|
|
240084
240091
|
} else {
|
|
240085
240092
|
await pipeline(readStream2, createWriteStream(dest, { mode: procMode }));
|
|
240086
240093
|
}
|
|
@@ -240112,8 +240119,8 @@ var require_extract_zip = __commonJS((exports, module) => {
|
|
|
240112
240119
|
if (!path4.isAbsolute(opts.dir)) {
|
|
240113
240120
|
throw new Error("Target directory is expected to be absolute");
|
|
240114
240121
|
}
|
|
240115
|
-
await
|
|
240116
|
-
opts.dir = await
|
|
240122
|
+
await fs4.mkdir(opts.dir, { recursive: true });
|
|
240123
|
+
opts.dir = await fs4.realpath(opts.dir);
|
|
240117
240124
|
return new Extractor(zipPath, opts).extract();
|
|
240118
240125
|
};
|
|
240119
240126
|
});
|
|
@@ -240697,10 +240704,10 @@ var init_package_load_pool = __esm(() => {
|
|
|
240697
240704
|
})();
|
|
240698
240705
|
defaultUrlReader = {
|
|
240699
240706
|
readURL: async (url2) => {
|
|
240700
|
-
const { promises:
|
|
240707
|
+
const { promises: fs4 } = await import("fs");
|
|
240701
240708
|
const { fileURLToPath: fileURLToPath3 } = await import("url");
|
|
240702
240709
|
const filePath = url2.protocol === "file:" ? fileURLToPath3(url2) : url2.toString();
|
|
240703
|
-
return
|
|
240710
|
+
return fs4.readFile(filePath, "utf8");
|
|
240704
240711
|
}
|
|
240705
240712
|
};
|
|
240706
240713
|
});
|
|
@@ -241511,7 +241518,7 @@ globstar while`, file, fr, pattern, pr, swallowee);
|
|
|
241511
241518
|
|
|
241512
241519
|
// ../../node_modules/recursive-readdir/index.js
|
|
241513
241520
|
var require_recursive_readdir = __commonJS((exports, module) => {
|
|
241514
|
-
var
|
|
241521
|
+
var fs6 = __require("fs");
|
|
241515
241522
|
var p = __require("path");
|
|
241516
241523
|
var minimatch = require_minimatch();
|
|
241517
241524
|
function patternMatcher(pattern) {
|
|
@@ -241545,7 +241552,7 @@ var require_recursive_readdir = __commonJS((exports, module) => {
|
|
|
241545
241552
|
}
|
|
241546
241553
|
ignores = ignores.map(toMatcherFunction);
|
|
241547
241554
|
var list = [];
|
|
241548
|
-
|
|
241555
|
+
fs6.readdir(path6, function(err, files) {
|
|
241549
241556
|
if (err) {
|
|
241550
241557
|
return callback(err);
|
|
241551
241558
|
}
|
|
@@ -241555,7 +241562,7 @@ var require_recursive_readdir = __commonJS((exports, module) => {
|
|
|
241555
241562
|
}
|
|
241556
241563
|
files.forEach(function(file) {
|
|
241557
241564
|
var filePath = p.join(path6, file);
|
|
241558
|
-
|
|
241565
|
+
fs6.stat(filePath, function(_err, stats) {
|
|
241559
241566
|
if (_err) {
|
|
241560
241567
|
return callback(_err);
|
|
241561
241568
|
}
|
|
@@ -256141,6 +256148,68 @@ function httpMetricsMiddleware(req, res, next) {
|
|
|
256141
256148
|
next();
|
|
256142
256149
|
}
|
|
256143
256150
|
|
|
256151
|
+
// src/node_version_check.ts
|
|
256152
|
+
import * as fs from "node:fs";
|
|
256153
|
+
var MIN_NODE_MAJOR = 20;
|
|
256154
|
+
var REQUIRED_NODE_RANGE = `>=${MIN_NODE_MAJOR}`;
|
|
256155
|
+
var UNSUPPORTED_NODE_TOKEN = "PUBLISHER_UNSUPPORTED_NODE";
|
|
256156
|
+
function evaluateRuntime(versions) {
|
|
256157
|
+
if (versions.bunVersion) {
|
|
256158
|
+
return { supported: true };
|
|
256159
|
+
}
|
|
256160
|
+
const major = parseMajor(versions.nodeVersion);
|
|
256161
|
+
if (major === undefined || major >= MIN_NODE_MAJOR) {
|
|
256162
|
+
return { supported: true };
|
|
256163
|
+
}
|
|
256164
|
+
return {
|
|
256165
|
+
supported: false,
|
|
256166
|
+
message: unsupportedMessage(versions.nodeVersion)
|
|
256167
|
+
};
|
|
256168
|
+
}
|
|
256169
|
+
function parseMajor(version) {
|
|
256170
|
+
const match = /^v?(\d+)\./.exec(version.trim());
|
|
256171
|
+
if (!match) {
|
|
256172
|
+
return;
|
|
256173
|
+
}
|
|
256174
|
+
const major = Number(match[1]);
|
|
256175
|
+
return Number.isFinite(major) ? major : undefined;
|
|
256176
|
+
}
|
|
256177
|
+
function unsupportedMessage(nodeVersion) {
|
|
256178
|
+
return [
|
|
256179
|
+
`${UNSUPPORTED_NODE_TOKEN} required=${REQUIRED_NODE_RANGE} detected=${nodeVersion}`,
|
|
256180
|
+
`Malloy Publisher supports Node.js ${MIN_NODE_MAJOR} and newer, but this process is running Node.js ${nodeVersion}.`,
|
|
256181
|
+
`Publisher and every Malloy library it depends on declare Node ${REQUIRED_NODE_RANGE}, so this`,
|
|
256182
|
+
`runtime is untested and has failed in ways that never mention Node.`,
|
|
256183
|
+
`Upgrade Node, then run the command again: https://nodejs.org`,
|
|
256184
|
+
` nvm: nvm install ${MIN_NODE_MAJOR} && nvm use ${MIN_NODE_MAJOR}`,
|
|
256185
|
+
` mise: mise use -g node@${MIN_NODE_MAJOR} then open a new shell before running the command`,
|
|
256186
|
+
""
|
|
256187
|
+
].join(`
|
|
256188
|
+
`);
|
|
256189
|
+
}
|
|
256190
|
+
function assertSupportedNodeVersion(options = {}) {
|
|
256191
|
+
const verdict = evaluateRuntime({
|
|
256192
|
+
nodeVersion: "nodeVersion" in options && options.nodeVersion !== undefined ? options.nodeVersion : process.version,
|
|
256193
|
+
bunVersion: "bunVersion" in options ? options.bunVersion : process.versions.bun
|
|
256194
|
+
});
|
|
256195
|
+
if (verdict.supported) {
|
|
256196
|
+
return;
|
|
256197
|
+
}
|
|
256198
|
+
const write = options.write ?? writeToStderr;
|
|
256199
|
+
const exit = options.exit ?? ((code) => process.exit(code));
|
|
256200
|
+
try {
|
|
256201
|
+
write(verdict.message ?? "");
|
|
256202
|
+
} catch {}
|
|
256203
|
+
exit(1);
|
|
256204
|
+
}
|
|
256205
|
+
function writeToStderr(text) {
|
|
256206
|
+
try {
|
|
256207
|
+
fs.writeSync(2, text);
|
|
256208
|
+
} catch {
|
|
256209
|
+
process.stderr.write(text);
|
|
256210
|
+
}
|
|
256211
|
+
}
|
|
256212
|
+
|
|
256144
256213
|
// ../../node_modules/zod/v3/external.js
|
|
256145
256214
|
var exports_external = {};
|
|
256146
256215
|
__export(exports_external, {
|
|
@@ -261182,23 +261251,23 @@ class CompileController {
|
|
|
261182
261251
|
// src/config.ts
|
|
261183
261252
|
init_constants();
|
|
261184
261253
|
init_logger();
|
|
261185
|
-
import
|
|
261254
|
+
import fs2 from "fs";
|
|
261186
261255
|
import path from "path";
|
|
261187
261256
|
import { fileURLToPath } from "url";
|
|
261188
261257
|
var BUNDLED_DEFAULT_CONFIG_PATH = path.join(path.dirname(fileURLToPath(import.meta.url)), "default-publisher.config.json");
|
|
261189
261258
|
function resolvePublisherConfigPath(serverRoot) {
|
|
261190
261259
|
const explicitPath = process.env.PUBLISHER_CONFIG_PATH;
|
|
261191
261260
|
if (explicitPath && explicitPath.length > 0) {
|
|
261192
|
-
if (!
|
|
261261
|
+
if (!fs2.existsSync(explicitPath)) {
|
|
261193
261262
|
return null;
|
|
261194
261263
|
}
|
|
261195
261264
|
return { path: explicitPath, isBundledDefault: false };
|
|
261196
261265
|
}
|
|
261197
261266
|
const serverRootPath = path.join(serverRoot, PUBLISHER_CONFIG_NAME);
|
|
261198
|
-
if (
|
|
261267
|
+
if (fs2.existsSync(serverRootPath)) {
|
|
261199
261268
|
return { path: serverRootPath, isBundledDefault: false };
|
|
261200
261269
|
}
|
|
261201
|
-
if (process.env.PUBLISHER_USE_BUNDLED_DEFAULT === "true" &&
|
|
261270
|
+
if (process.env.PUBLISHER_USE_BUNDLED_DEFAULT === "true" && fs2.existsSync(BUNDLED_DEFAULT_CONFIG_PATH)) {
|
|
261202
261271
|
return { path: BUNDLED_DEFAULT_CONFIG_PATH, isBundledDefault: true };
|
|
261203
261272
|
}
|
|
261204
261273
|
return null;
|
|
@@ -261430,7 +261499,7 @@ var getPublisherConfigDir = (serverRoot) => {
|
|
|
261430
261499
|
return null;
|
|
261431
261500
|
}
|
|
261432
261501
|
try {
|
|
261433
|
-
if (!
|
|
261502
|
+
if (!fs2.statSync(resolved.path).isFile()) {
|
|
261434
261503
|
return null;
|
|
261435
261504
|
}
|
|
261436
261505
|
} catch {
|
|
@@ -261455,7 +261524,7 @@ var getPublisherConfig = (serverRoot) => {
|
|
|
261455
261524
|
}
|
|
261456
261525
|
let rawConfig;
|
|
261457
261526
|
try {
|
|
261458
|
-
const fileContent =
|
|
261527
|
+
const fileContent = fs2.readFileSync(publisherConfigPath, "utf8");
|
|
261459
261528
|
rawConfig = JSON.parse(fileContent);
|
|
261460
261529
|
} catch (error) {
|
|
261461
261530
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -265072,7 +265141,7 @@ var {
|
|
|
265072
265141
|
} = axios_default;
|
|
265073
265142
|
|
|
265074
265143
|
// src/service/connection.ts
|
|
265075
|
-
import
|
|
265144
|
+
import fs3 from "fs/promises";
|
|
265076
265145
|
|
|
265077
265146
|
// src/ducklake_version.ts
|
|
265078
265147
|
var MIN_CATALOG_FORMAT = "1.0";
|
|
@@ -265326,6 +265395,9 @@ function openSshProxy(ssh, target) {
|
|
|
265326
265395
|
});
|
|
265327
265396
|
}
|
|
265328
265397
|
|
|
265398
|
+
// src/service/query_metadata.ts
|
|
265399
|
+
import * as crypto3 from "node:crypto";
|
|
265400
|
+
|
|
265329
265401
|
// src/query_metadata_metrics.ts
|
|
265330
265402
|
var resetHooks = [];
|
|
265331
265403
|
function lazyCounter(name, description) {
|
|
@@ -265408,7 +265480,7 @@ function queryMetadataBudgetWarning(declared) {
|
|
|
265408
265480
|
return `queryMetadata declares ${declared} properties; the server adds up to ` + `${RESERVED_CONTEXT_PROPERTIES} of its own to every statement, so a bag over ` + `${authorBudget} loses its least specific properties at query time`;
|
|
265409
265481
|
}
|
|
265410
265482
|
function mintCorrelationId() {
|
|
265411
|
-
return
|
|
265483
|
+
return crypto3.randomUUID();
|
|
265412
265484
|
}
|
|
265413
265485
|
var CONTEXT_SHED_ORDER = [
|
|
265414
265486
|
"version",
|
|
@@ -266896,8 +266968,8 @@ async function deleteDuckLakeConnectionFile(connectionName, environmentPath) {
|
|
|
266896
266968
|
assertSafeEnvironmentPath(environmentPath);
|
|
266897
266969
|
const ducklakePath = safeJoinUnderRoot(environmentPath, `${connectionName}_ducklake.duckdb`);
|
|
266898
266970
|
try {
|
|
266899
|
-
await
|
|
266900
|
-
await
|
|
266971
|
+
await fs3.access(ducklakePath);
|
|
266972
|
+
await fs3.rm(ducklakePath);
|
|
266901
266973
|
logger.info(`Removed DuckLake connection file ${connectionName}_ducklake.duckdb from ${environmentPath}`);
|
|
266902
266974
|
} catch (error) {
|
|
266903
266975
|
if (error.code === "ENOENT") {
|
|
@@ -269203,6 +269275,7 @@ class QueryController {
|
|
|
269203
269275
|
} else {
|
|
269204
269276
|
const {
|
|
269205
269277
|
result,
|
|
269278
|
+
serializedResult,
|
|
269206
269279
|
compactResult,
|
|
269207
269280
|
rowLimit,
|
|
269208
269281
|
rowLimitSource,
|
|
@@ -269228,7 +269301,7 @@ class QueryController {
|
|
|
269228
269301
|
}), getQueryTimeoutMs());
|
|
269229
269302
|
const renderLogs = import_render_validator.validateRenderTags(result);
|
|
269230
269303
|
return {
|
|
269231
|
-
result: compactJson ? JSON.stringify(compactResult, bigIntReplacer) :
|
|
269304
|
+
result: compactJson ? JSON.stringify(compactResult, bigIntReplacer) : serializedResult,
|
|
269232
269305
|
resource: `${API_PREFIX}/environments/${environmentName}/packages/${packageName}/models/${modelPath}/query`,
|
|
269233
269306
|
renderLogs: renderLogs.length > 0 ? renderLogs : undefined,
|
|
269234
269307
|
queryRowLimit: rowLimit,
|
|
@@ -271148,8 +271221,8 @@ function tryAcquire(sync, alreadyAcquiredError = E_ALREADY_LOCKED) {
|
|
|
271148
271221
|
|
|
271149
271222
|
// src/service/environment_store.ts
|
|
271150
271223
|
var import_extract_zip = __toESM(require_extract_zip(), 1);
|
|
271151
|
-
import
|
|
271152
|
-
import * as
|
|
271224
|
+
import crypto5 from "crypto";
|
|
271225
|
+
import * as fs9 from "fs";
|
|
271153
271226
|
import * as os2 from "os";
|
|
271154
271227
|
import * as path9 from "path";
|
|
271155
271228
|
|
|
@@ -276692,10 +276765,221 @@ class StorageManager {
|
|
|
276692
276765
|
import { MalloyError as MalloyError4, Runtime as Runtime3 } from "@malloydata/malloy";
|
|
276693
276766
|
init_constants();
|
|
276694
276767
|
init_errors();
|
|
276695
|
-
import
|
|
276696
|
-
import * as
|
|
276768
|
+
import crypto4 from "crypto";
|
|
276769
|
+
import * as fs8 from "fs";
|
|
276697
276770
|
import * as path8 from "path";
|
|
276698
276771
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
276772
|
+
|
|
276773
|
+
// src/service/authorize.ts
|
|
276774
|
+
init_errors();
|
|
276775
|
+
var AUTHORIZE_TAG = String.raw`##?\(\s*authorize\s*\)`;
|
|
276776
|
+
var AUTHORIZE_ANNOTATION_ANYWHERE = new RegExp(AUTHORIZE_TAG);
|
|
276777
|
+
var AUTHORIZE_ANNOTATION_PREFIX = new RegExp(`^${AUTHORIZE_TAG}`);
|
|
276778
|
+
function assertNoCallerAuthorizeAnnotation(callerText) {
|
|
276779
|
+
if (!AUTHORIZE_ANNOTATION_ANYWHERE.test(callerText))
|
|
276780
|
+
return;
|
|
276781
|
+
throw new BadRequestError("An `authorize` annotation is not permitted in caller-submitted Malloy " + "text. Access gates are declared by the model author on the source; a " + "request cannot introduce, replace, or relax one. To validate a gate " + "you are authoring, save it to the package's model file and reload the " + "package — model load validates every `#(authorize)` annotation it " + "declares.");
|
|
276782
|
+
}
|
|
276783
|
+
function buildAuthorizeProbe(exprs, givenDecls = []) {
|
|
276784
|
+
const selects = exprs.map((expr, i) => `__auth_${i} is (${expr})`).join(`
|
|
276785
|
+
`);
|
|
276786
|
+
const givenBlock = givenDecls.length > 0 ? `given:
|
|
276787
|
+
${givenDecls.map((g) => ` ${g.name} :: ${g.type}`).join(`
|
|
276788
|
+
`)}
|
|
276789
|
+
|
|
276790
|
+
` : "";
|
|
276791
|
+
return `${givenBlock}run: duckdb.sql("SELECT 1 AS __authorize_probe_row") -> {
|
|
276792
|
+
select:
|
|
276793
|
+
${selects}
|
|
276794
|
+
limit: 1
|
|
276795
|
+
}`;
|
|
276796
|
+
}
|
|
276797
|
+
var GIVEN_REF_PATTERN = /\$([A-Za-z_][A-Za-z0-9_]*)/g;
|
|
276798
|
+
var STRING_LITERAL_PATTERN = /'(?:\\.|[^'\\])*'/g;
|
|
276799
|
+
function referencedGivenNames(expr) {
|
|
276800
|
+
const scanned = expr.replace(STRING_LITERAL_PATTERN, "''");
|
|
276801
|
+
const names = [];
|
|
276802
|
+
const seen = new Set;
|
|
276803
|
+
for (const match of scanned.matchAll(GIVEN_REF_PATTERN)) {
|
|
276804
|
+
const name = match[1];
|
|
276805
|
+
if (!seen.has(name)) {
|
|
276806
|
+
seen.add(name);
|
|
276807
|
+
names.push(name);
|
|
276808
|
+
}
|
|
276809
|
+
}
|
|
276810
|
+
return names;
|
|
276811
|
+
}
|
|
276812
|
+
function inferGivenType(value) {
|
|
276813
|
+
if (typeof value === "string")
|
|
276814
|
+
return "string";
|
|
276815
|
+
if (typeof value === "number" || typeof value === "bigint")
|
|
276816
|
+
return "number";
|
|
276817
|
+
if (typeof value === "boolean")
|
|
276818
|
+
return "boolean";
|
|
276819
|
+
if (value instanceof Date)
|
|
276820
|
+
return "timestamp";
|
|
276821
|
+
if (Array.isArray(value)) {
|
|
276822
|
+
if (value.length === 0)
|
|
276823
|
+
return null;
|
|
276824
|
+
const elementType = inferGivenType(value[0]);
|
|
276825
|
+
return elementType ? `${elementType}[]` : null;
|
|
276826
|
+
}
|
|
276827
|
+
return null;
|
|
276828
|
+
}
|
|
276829
|
+
function bindProbeGivens(expr, givens, declaredTypes) {
|
|
276830
|
+
const decls = [];
|
|
276831
|
+
const bound = {};
|
|
276832
|
+
for (const name of referencedGivenNames(expr)) {
|
|
276833
|
+
if (!(name in givens))
|
|
276834
|
+
continue;
|
|
276835
|
+
const value = givens[name];
|
|
276836
|
+
const type = declaredTypes?.get(name) ?? inferGivenType(value);
|
|
276837
|
+
if (!type)
|
|
276838
|
+
continue;
|
|
276839
|
+
decls.push({ name, type });
|
|
276840
|
+
bound[name] = value;
|
|
276841
|
+
}
|
|
276842
|
+
return { decls, bound };
|
|
276843
|
+
}
|
|
276844
|
+
function isProbeTrue(cell) {
|
|
276845
|
+
return cell === true || cell === 1 || cell === "true";
|
|
276846
|
+
}
|
|
276847
|
+
async function runProbe(executor, probeText, givens) {
|
|
276848
|
+
const result = await executor.loadQuery(probeText).run({ rowLimit: 1, givens });
|
|
276849
|
+
const row = result?.data?.value?.[0];
|
|
276850
|
+
return !!(row && isProbeTrue(row.__auth_0));
|
|
276851
|
+
}
|
|
276852
|
+
async function evaluateAuthorize(executor, exprs, givens, declaredTypes, options) {
|
|
276853
|
+
const selfContainedFirst = options?.selfContainedFirst ?? false;
|
|
276854
|
+
const ambientPrefix = options?.ambientPrefix ?? 0;
|
|
276855
|
+
for (const [index, expr] of exprs.entries()) {
|
|
276856
|
+
if (selfContainedFirst && index >= ambientPrefix) {
|
|
276857
|
+
if (await evaluateSelfContainedFirst(executor, expr, givens, declaredTypes)) {
|
|
276858
|
+
return true;
|
|
276859
|
+
}
|
|
276860
|
+
continue;
|
|
276861
|
+
}
|
|
276862
|
+
try {
|
|
276863
|
+
if (await runProbe(executor, buildAuthorizeProbe([expr]), givens)) {
|
|
276864
|
+
return true;
|
|
276865
|
+
}
|
|
276866
|
+
continue;
|
|
276867
|
+
} catch {}
|
|
276868
|
+
try {
|
|
276869
|
+
const { decls, bound } = bindProbeGivens(expr, givens, declaredTypes);
|
|
276870
|
+
if (decls.length === 0)
|
|
276871
|
+
continue;
|
|
276872
|
+
if (await runProbe(executor, buildAuthorizeProbe([expr], decls), bound)) {
|
|
276873
|
+
return true;
|
|
276874
|
+
}
|
|
276875
|
+
} catch {
|
|
276876
|
+
continue;
|
|
276877
|
+
}
|
|
276878
|
+
}
|
|
276879
|
+
return false;
|
|
276880
|
+
}
|
|
276881
|
+
async function evaluateSelfContainedFirst(executor, expr, givens, declaredTypes) {
|
|
276882
|
+
const referenced = referencedGivenNames(expr);
|
|
276883
|
+
if (referenced.length === 0) {
|
|
276884
|
+
try {
|
|
276885
|
+
return await runProbe(executor, buildAuthorizeProbe([expr]), {});
|
|
276886
|
+
} catch {
|
|
276887
|
+
return false;
|
|
276888
|
+
}
|
|
276889
|
+
}
|
|
276890
|
+
const { decls, bound } = bindProbeGivens(expr, givens, declaredTypes);
|
|
276891
|
+
if (decls.length !== referenced.length) {
|
|
276892
|
+
return false;
|
|
276893
|
+
}
|
|
276894
|
+
try {
|
|
276895
|
+
return await runProbe(executor, buildAuthorizeProbe([expr], decls), bound);
|
|
276896
|
+
} catch {
|
|
276897
|
+
try {
|
|
276898
|
+
return await runProbe(executor, buildAuthorizeProbe([expr]), givens);
|
|
276899
|
+
} catch {
|
|
276900
|
+
return false;
|
|
276901
|
+
}
|
|
276902
|
+
}
|
|
276903
|
+
}
|
|
276904
|
+
async function validateAuthorizeProbes(compiler, sources) {
|
|
276905
|
+
for (const source of sources) {
|
|
276906
|
+
const exprs = source.authorize;
|
|
276907
|
+
if (!exprs || exprs.length === 0)
|
|
276908
|
+
continue;
|
|
276909
|
+
try {
|
|
276910
|
+
await compiler.loadQuery(buildAuthorizeProbe(exprs)).getPreparedQuery();
|
|
276911
|
+
} catch (err) {
|
|
276912
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
276913
|
+
throw new ModelCompilationError({
|
|
276914
|
+
message: `Invalid #(authorize) annotation on source "${source.name ?? "(unnamed)"}" [${exprs.join(" | ")}]: ${detail}`
|
|
276915
|
+
});
|
|
276916
|
+
}
|
|
276917
|
+
}
|
|
276918
|
+
}
|
|
276919
|
+
function parseAuthorizeAnnotation(annotation) {
|
|
276920
|
+
const trimmed2 = annotation.trim();
|
|
276921
|
+
const prefix = AUTHORIZE_ANNOTATION_PREFIX.exec(trimmed2);
|
|
276922
|
+
if (!prefix)
|
|
276923
|
+
return null;
|
|
276924
|
+
return unwrapQuotedExpression(trimmed2.slice(prefix[0].length).trim());
|
|
276925
|
+
}
|
|
276926
|
+
function collectAuthorizeExprs(annotations) {
|
|
276927
|
+
const exprs = [];
|
|
276928
|
+
for (const annotation of annotations) {
|
|
276929
|
+
const expr = parseAuthorizeAnnotation(annotation);
|
|
276930
|
+
if (expr !== null) {
|
|
276931
|
+
exprs.push(expr);
|
|
276932
|
+
}
|
|
276933
|
+
}
|
|
276934
|
+
return exprs;
|
|
276935
|
+
}
|
|
276936
|
+
function unwrapQuotedExpression(body) {
|
|
276937
|
+
if (body.length < 2 || body[0] !== '"') {
|
|
276938
|
+
throw new Error(`authorize annotation expression must be a double-quoted string, got: ${body || "(empty)"}`);
|
|
276939
|
+
}
|
|
276940
|
+
let expr = "";
|
|
276941
|
+
let i = 1;
|
|
276942
|
+
let closed = false;
|
|
276943
|
+
for (;i < body.length; i++) {
|
|
276944
|
+
const ch = body[i];
|
|
276945
|
+
if (ch === "\\" && i + 1 < body.length) {
|
|
276946
|
+
const next = body[i + 1];
|
|
276947
|
+
if (next === '"' || next === "\\") {
|
|
276948
|
+
expr += next;
|
|
276949
|
+
i++;
|
|
276950
|
+
continue;
|
|
276951
|
+
}
|
|
276952
|
+
}
|
|
276953
|
+
if (ch === '"') {
|
|
276954
|
+
closed = true;
|
|
276955
|
+
i++;
|
|
276956
|
+
break;
|
|
276957
|
+
}
|
|
276958
|
+
expr += ch;
|
|
276959
|
+
}
|
|
276960
|
+
if (!closed) {
|
|
276961
|
+
throw new Error(`authorize annotation has mismatched quotes: ${body}`);
|
|
276962
|
+
}
|
|
276963
|
+
const rest = body.slice(i).trim();
|
|
276964
|
+
if (rest.length > 0) {
|
|
276965
|
+
throw new Error(`authorize annotation has unexpected content after the expression: ${rest}`);
|
|
276966
|
+
}
|
|
276967
|
+
if (expr.trim().length === 0) {
|
|
276968
|
+
throw new Error("authorize annotation has an empty expression body");
|
|
276969
|
+
}
|
|
276970
|
+
return expr;
|
|
276971
|
+
}
|
|
276972
|
+
|
|
276973
|
+
// src/authorize_metrics.ts
|
|
276974
|
+
var guardRejectionCounter = null;
|
|
276975
|
+
function recordAuthorizeGuardRejection(field) {
|
|
276976
|
+
guardRejectionCounter ??= publisherMeter().createCounter("publisher_authorize_guard_rejected_total", {
|
|
276977
|
+
description: "Requests rejected with 400 for declaring an `#(authorize)` annotation in caller-submitted Malloy text. Label: field ('query'|'source_name'|'query_name'|'compile_source')."
|
|
276978
|
+
});
|
|
276979
|
+
guardRejectionCounter.add(1, { field });
|
|
276980
|
+
}
|
|
276981
|
+
|
|
276982
|
+
// src/service/environment.ts
|
|
276699
276983
|
init_logger();
|
|
276700
276984
|
|
|
276701
276985
|
// src/materialization_metrics.ts
|
|
@@ -276783,7 +277067,7 @@ function recordChainedStorageBuild(outcome) {
|
|
|
276783
277067
|
}
|
|
276784
277068
|
|
|
276785
277069
|
// src/utils.ts
|
|
276786
|
-
import * as
|
|
277070
|
+
import * as fs4 from "fs";
|
|
276787
277071
|
import * as path5 from "path";
|
|
276788
277072
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
276789
277073
|
var URL_READER = {
|
|
@@ -276792,7 +277076,7 @@ var URL_READER = {
|
|
|
276792
277076
|
if (url2.protocol == "file:") {
|
|
276793
277077
|
path6 = fileURLToPath3(url2);
|
|
276794
277078
|
}
|
|
276795
|
-
return
|
|
277079
|
+
return fs4.promises.readFile(path6, "utf8");
|
|
276796
277080
|
}
|
|
276797
277081
|
};
|
|
276798
277082
|
function ignoreDotfiles(file) {
|
|
@@ -276806,7 +277090,7 @@ function errMessage(err) {
|
|
|
276806
277090
|
init_logger();
|
|
276807
277091
|
var import_client_s32 = __toESM(require_dist_cjs75(), 1);
|
|
276808
277092
|
import { Storage } from "@google-cloud/storage";
|
|
276809
|
-
import * as
|
|
277093
|
+
import * as fs5 from "fs/promises";
|
|
276810
277094
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
276811
277095
|
var gcsClient;
|
|
276812
277096
|
var s3Client;
|
|
@@ -276835,9 +277119,9 @@ async function readManifestBytes(uri) {
|
|
|
276835
277119
|
return res.Body.transformToString();
|
|
276836
277120
|
}
|
|
276837
277121
|
if (uri.startsWith("file://")) {
|
|
276838
|
-
return
|
|
277122
|
+
return fs5.readFile(fileURLToPath4(uri), "utf8");
|
|
276839
277123
|
}
|
|
276840
|
-
return
|
|
277124
|
+
return fs5.readFile(uri, "utf8");
|
|
276841
277125
|
}
|
|
276842
277126
|
async function fetchManifestEntries(uri) {
|
|
276843
277127
|
const raw = await readManifestBytes(uri);
|
|
@@ -276877,7 +277161,7 @@ function splitManifestEntries(entries, source) {
|
|
|
276877
277161
|
}
|
|
276878
277162
|
|
|
276879
277163
|
// src/service/package.ts
|
|
276880
|
-
import * as
|
|
277164
|
+
import * as fs7 from "fs/promises";
|
|
276881
277165
|
import * as path7 from "path";
|
|
276882
277166
|
import"@malloydata/db-duckdb/native";
|
|
276883
277167
|
import { DuckDBConnection as DuckDBConnection3 } from "@malloydata/db-duckdb";
|
|
@@ -277271,206 +277555,6 @@ import { Annotations as Annotations3 } from "@malloydata/malloy";
|
|
|
277271
277555
|
|
|
277272
277556
|
// src/service/materialization_eligibility.ts
|
|
277273
277557
|
init_errors();
|
|
277274
|
-
|
|
277275
|
-
// src/service/authorize.ts
|
|
277276
|
-
init_errors();
|
|
277277
|
-
var SOURCE_PREFIX = "#(authorize)";
|
|
277278
|
-
var FILE_PREFIX = "##(authorize)";
|
|
277279
|
-
function buildAuthorizeProbe(exprs, givenDecls = []) {
|
|
277280
|
-
const selects = exprs.map((expr, i) => `__auth_${i} is (${expr})`).join(`
|
|
277281
|
-
`);
|
|
277282
|
-
const givenBlock = givenDecls.length > 0 ? `given:
|
|
277283
|
-
${givenDecls.map((g) => ` ${g.name} :: ${g.type}`).join(`
|
|
277284
|
-
`)}
|
|
277285
|
-
|
|
277286
|
-
` : "";
|
|
277287
|
-
return `${givenBlock}run: duckdb.sql("SELECT 1 AS __authorize_probe_row") -> {
|
|
277288
|
-
select:
|
|
277289
|
-
${selects}
|
|
277290
|
-
limit: 1
|
|
277291
|
-
}`;
|
|
277292
|
-
}
|
|
277293
|
-
var GIVEN_REF_PATTERN = /\$([A-Za-z_][A-Za-z0-9_]*)/g;
|
|
277294
|
-
var STRING_LITERAL_PATTERN = /'(?:\\.|[^'\\])*'/g;
|
|
277295
|
-
function referencedGivenNames(expr) {
|
|
277296
|
-
const scanned = expr.replace(STRING_LITERAL_PATTERN, "''");
|
|
277297
|
-
const names = [];
|
|
277298
|
-
const seen = new Set;
|
|
277299
|
-
for (const match of scanned.matchAll(GIVEN_REF_PATTERN)) {
|
|
277300
|
-
const name = match[1];
|
|
277301
|
-
if (!seen.has(name)) {
|
|
277302
|
-
seen.add(name);
|
|
277303
|
-
names.push(name);
|
|
277304
|
-
}
|
|
277305
|
-
}
|
|
277306
|
-
return names;
|
|
277307
|
-
}
|
|
277308
|
-
function inferGivenType(value) {
|
|
277309
|
-
if (typeof value === "string")
|
|
277310
|
-
return "string";
|
|
277311
|
-
if (typeof value === "number" || typeof value === "bigint")
|
|
277312
|
-
return "number";
|
|
277313
|
-
if (typeof value === "boolean")
|
|
277314
|
-
return "boolean";
|
|
277315
|
-
if (value instanceof Date)
|
|
277316
|
-
return "timestamp";
|
|
277317
|
-
if (Array.isArray(value)) {
|
|
277318
|
-
if (value.length === 0)
|
|
277319
|
-
return null;
|
|
277320
|
-
const elementType = inferGivenType(value[0]);
|
|
277321
|
-
return elementType ? `${elementType}[]` : null;
|
|
277322
|
-
}
|
|
277323
|
-
return null;
|
|
277324
|
-
}
|
|
277325
|
-
function bindProbeGivens(expr, givens, declaredTypes) {
|
|
277326
|
-
const decls = [];
|
|
277327
|
-
const bound = {};
|
|
277328
|
-
for (const name of referencedGivenNames(expr)) {
|
|
277329
|
-
if (!(name in givens))
|
|
277330
|
-
continue;
|
|
277331
|
-
const value = givens[name];
|
|
277332
|
-
const type = declaredTypes?.get(name) ?? inferGivenType(value);
|
|
277333
|
-
if (!type)
|
|
277334
|
-
continue;
|
|
277335
|
-
decls.push({ name, type });
|
|
277336
|
-
bound[name] = value;
|
|
277337
|
-
}
|
|
277338
|
-
return { decls, bound };
|
|
277339
|
-
}
|
|
277340
|
-
function isProbeTrue(cell) {
|
|
277341
|
-
return cell === true || cell === 1 || cell === "true";
|
|
277342
|
-
}
|
|
277343
|
-
async function runProbe(executor, probeText, givens) {
|
|
277344
|
-
const result = await executor.loadQuery(probeText).run({ rowLimit: 1, givens });
|
|
277345
|
-
const row = result?.data?.value?.[0];
|
|
277346
|
-
return !!(row && isProbeTrue(row.__auth_0));
|
|
277347
|
-
}
|
|
277348
|
-
async function evaluateAuthorize(executor, exprs, givens, declaredTypes, options) {
|
|
277349
|
-
const selfContainedFirst = options?.selfContainedFirst ?? false;
|
|
277350
|
-
for (const expr of exprs) {
|
|
277351
|
-
if (selfContainedFirst) {
|
|
277352
|
-
if (await evaluateSelfContainedFirst(executor, expr, givens, declaredTypes)) {
|
|
277353
|
-
return true;
|
|
277354
|
-
}
|
|
277355
|
-
continue;
|
|
277356
|
-
}
|
|
277357
|
-
try {
|
|
277358
|
-
if (await runProbe(executor, buildAuthorizeProbe([expr]), givens)) {
|
|
277359
|
-
return true;
|
|
277360
|
-
}
|
|
277361
|
-
continue;
|
|
277362
|
-
} catch {}
|
|
277363
|
-
try {
|
|
277364
|
-
const { decls, bound } = bindProbeGivens(expr, givens, declaredTypes);
|
|
277365
|
-
if (decls.length === 0)
|
|
277366
|
-
continue;
|
|
277367
|
-
if (await runProbe(executor, buildAuthorizeProbe([expr], decls), bound)) {
|
|
277368
|
-
return true;
|
|
277369
|
-
}
|
|
277370
|
-
} catch {
|
|
277371
|
-
continue;
|
|
277372
|
-
}
|
|
277373
|
-
}
|
|
277374
|
-
return false;
|
|
277375
|
-
}
|
|
277376
|
-
async function evaluateSelfContainedFirst(executor, expr, givens, declaredTypes) {
|
|
277377
|
-
const referenced = referencedGivenNames(expr);
|
|
277378
|
-
if (referenced.length === 0) {
|
|
277379
|
-
try {
|
|
277380
|
-
return await runProbe(executor, buildAuthorizeProbe([expr]), {});
|
|
277381
|
-
} catch {
|
|
277382
|
-
return false;
|
|
277383
|
-
}
|
|
277384
|
-
}
|
|
277385
|
-
const { decls, bound } = bindProbeGivens(expr, givens, declaredTypes);
|
|
277386
|
-
if (decls.length !== referenced.length) {
|
|
277387
|
-
return false;
|
|
277388
|
-
}
|
|
277389
|
-
try {
|
|
277390
|
-
return await runProbe(executor, buildAuthorizeProbe([expr], decls), bound);
|
|
277391
|
-
} catch {
|
|
277392
|
-
try {
|
|
277393
|
-
return await runProbe(executor, buildAuthorizeProbe([expr]), givens);
|
|
277394
|
-
} catch {
|
|
277395
|
-
return false;
|
|
277396
|
-
}
|
|
277397
|
-
}
|
|
277398
|
-
}
|
|
277399
|
-
async function validateAuthorizeProbes(compiler, sources) {
|
|
277400
|
-
for (const source of sources) {
|
|
277401
|
-
const exprs = source.authorize;
|
|
277402
|
-
if (!exprs || exprs.length === 0)
|
|
277403
|
-
continue;
|
|
277404
|
-
try {
|
|
277405
|
-
await compiler.loadQuery(buildAuthorizeProbe(exprs)).getPreparedQuery();
|
|
277406
|
-
} catch (err) {
|
|
277407
|
-
const detail = err instanceof Error ? err.message : String(err);
|
|
277408
|
-
throw new ModelCompilationError({
|
|
277409
|
-
message: `Invalid #(authorize) annotation on source "${source.name ?? "(unnamed)"}" [${exprs.join(" | ")}]: ${detail}`
|
|
277410
|
-
});
|
|
277411
|
-
}
|
|
277412
|
-
}
|
|
277413
|
-
}
|
|
277414
|
-
function parseAuthorizeAnnotation(annotation) {
|
|
277415
|
-
const trimmed2 = annotation.trim();
|
|
277416
|
-
let body;
|
|
277417
|
-
if (trimmed2.startsWith(FILE_PREFIX)) {
|
|
277418
|
-
body = trimmed2.slice(FILE_PREFIX.length).trim();
|
|
277419
|
-
} else if (trimmed2.startsWith(SOURCE_PREFIX)) {
|
|
277420
|
-
body = trimmed2.slice(SOURCE_PREFIX.length).trim();
|
|
277421
|
-
} else {
|
|
277422
|
-
return null;
|
|
277423
|
-
}
|
|
277424
|
-
return unwrapQuotedExpression(body);
|
|
277425
|
-
}
|
|
277426
|
-
function collectAuthorizeExprs(annotations) {
|
|
277427
|
-
const exprs = [];
|
|
277428
|
-
for (const annotation of annotations) {
|
|
277429
|
-
const expr = parseAuthorizeAnnotation(annotation);
|
|
277430
|
-
if (expr !== null) {
|
|
277431
|
-
exprs.push(expr);
|
|
277432
|
-
}
|
|
277433
|
-
}
|
|
277434
|
-
return exprs;
|
|
277435
|
-
}
|
|
277436
|
-
function unwrapQuotedExpression(body) {
|
|
277437
|
-
if (body.length < 2 || body[0] !== '"') {
|
|
277438
|
-
throw new Error(`authorize annotation expression must be a double-quoted string, got: ${body || "(empty)"}`);
|
|
277439
|
-
}
|
|
277440
|
-
let expr = "";
|
|
277441
|
-
let i = 1;
|
|
277442
|
-
let closed = false;
|
|
277443
|
-
for (;i < body.length; i++) {
|
|
277444
|
-
const ch = body[i];
|
|
277445
|
-
if (ch === "\\" && i + 1 < body.length) {
|
|
277446
|
-
const next = body[i + 1];
|
|
277447
|
-
if (next === '"' || next === "\\") {
|
|
277448
|
-
expr += next;
|
|
277449
|
-
i++;
|
|
277450
|
-
continue;
|
|
277451
|
-
}
|
|
277452
|
-
}
|
|
277453
|
-
if (ch === '"') {
|
|
277454
|
-
closed = true;
|
|
277455
|
-
i++;
|
|
277456
|
-
break;
|
|
277457
|
-
}
|
|
277458
|
-
expr += ch;
|
|
277459
|
-
}
|
|
277460
|
-
if (!closed) {
|
|
277461
|
-
throw new Error(`authorize annotation has mismatched quotes: ${body}`);
|
|
277462
|
-
}
|
|
277463
|
-
const rest = body.slice(i).trim();
|
|
277464
|
-
if (rest.length > 0) {
|
|
277465
|
-
throw new Error(`authorize annotation has unexpected content after the expression: ${rest}`);
|
|
277466
|
-
}
|
|
277467
|
-
if (expr.trim().length === 0) {
|
|
277468
|
-
throw new Error("authorize annotation has an empty expression body");
|
|
277469
|
-
}
|
|
277470
|
-
return expr;
|
|
277471
|
-
}
|
|
277472
|
-
|
|
277473
|
-
// src/service/materialization_eligibility.ts
|
|
277474
277558
|
function assertMaterializationEligible(persistSource) {
|
|
277475
277559
|
const sourceName = persistSource.name;
|
|
277476
277560
|
let unbound;
|
|
@@ -277616,9 +277700,6 @@ import {
|
|
|
277616
277700
|
API,
|
|
277617
277701
|
FixedConnectionMap,
|
|
277618
277702
|
InMemoryURLReader as InMemoryURLReader2,
|
|
277619
|
-
isBasicArray,
|
|
277620
|
-
isJoined,
|
|
277621
|
-
isRepeatedRecord,
|
|
277622
277703
|
isSourceDef as isSourceDef2,
|
|
277623
277704
|
MalloyConfig as MalloyConfig2,
|
|
277624
277705
|
MalloyError as MalloyError2,
|
|
@@ -277629,7 +277710,7 @@ import {
|
|
|
277629
277710
|
MalloySQLParser,
|
|
277630
277711
|
MalloySQLStatementType
|
|
277631
277712
|
} from "@malloydata/malloy-sql";
|
|
277632
|
-
import * as
|
|
277713
|
+
import * as fs6 from "fs/promises";
|
|
277633
277714
|
import { readFileSync } from "fs";
|
|
277634
277715
|
import { createRequire as createRequire2 } from "module";
|
|
277635
277716
|
import * as path6 from "path";
|
|
@@ -277994,12 +278075,23 @@ function assertWithinModelResponseLimits(rowCount, serializedBytes, { maxRows, m
|
|
|
277994
278075
|
throw new PayloadTooLargeError(`Query response exceeded ${maxBytes} bytes (was ${serializedBytes}). Project fewer columns, add a LIMIT, or raise PUBLISHER_MAX_RESPONSE_BYTES.`);
|
|
277995
278076
|
}
|
|
277996
278077
|
}
|
|
278078
|
+
function stringifyQueryResponse(response, rowCount, maxBytes, source) {
|
|
278079
|
+
try {
|
|
278080
|
+
return JSON.stringify(response);
|
|
278081
|
+
} catch (error) {
|
|
278082
|
+
if (!(error instanceof RangeError) || /call stack/i.test(error.message)) {
|
|
278083
|
+
throw error;
|
|
278084
|
+
}
|
|
278085
|
+
recordQueryCapExceeded("unserializable", source);
|
|
278086
|
+
throw new ResponseUnserializableError(`Query response could not be serialized: the ${rowCount}-row result is too large to turn into JSON${maxBytes > 0 ? ` (byte cap: ${maxBytes})` : ""}. Project fewer columns, add a LIMIT, or filter wide values.`);
|
|
278087
|
+
}
|
|
278088
|
+
}
|
|
277997
278089
|
|
|
277998
278090
|
// src/service/query_text.ts
|
|
277999
278091
|
function extractRunTargetSourceName(query) {
|
|
278000
278092
|
if (!query)
|
|
278001
278093
|
return;
|
|
278002
|
-
const runMatch = query.match(/run\s*:\s*(?:`([^`]+)`|(\w+))
|
|
278094
|
+
const runMatch = query.match(/run\s*:\s*(?:`([^`]+)`|(\w+))/);
|
|
278003
278095
|
const arrowMatch = query.match(/^\s*(?:`([^`]+)`|(\w+))\s*->/m);
|
|
278004
278096
|
return runMatch?.[1] ?? runMatch?.[2] ?? arrowMatch?.[1] ?? arrowMatch?.[2];
|
|
278005
278097
|
}
|
|
@@ -278020,6 +278112,7 @@ import {
|
|
|
278020
278112
|
function extractSourcesFromModelDef(modelDef, givens, onParseError) {
|
|
278021
278113
|
const filterMap = new Map;
|
|
278022
278114
|
const authorizeMap = new Map;
|
|
278115
|
+
const ownAuthorizeSources = [];
|
|
278023
278116
|
const fileLevelAuthorize = collectAuthorizeExprs((modelAnnotations(modelDef).notes ?? []).map((note) => note.text));
|
|
278024
278117
|
const sources = Object.values(modelDef.contents).filter((obj) => isSourceDef(obj)).map((sourceObj) => {
|
|
278025
278118
|
const struct = sourceObj;
|
|
@@ -278058,15 +278151,33 @@ function extractSourcesFromModelDef(modelDef, givens, onParseError) {
|
|
|
278058
278151
|
}
|
|
278059
278152
|
}
|
|
278060
278153
|
const ownNotes = (struct.annotations?.blockNotes ?? []).map((note) => note.text);
|
|
278154
|
+
const ownGates = collectAuthorizeExprs(ownNotes);
|
|
278155
|
+
let inheritedGates = [];
|
|
278156
|
+
if (ownGates.length === 0) {
|
|
278157
|
+
for (let cur2 = struct.annotations?.inherits;cur2; cur2 = cur2.inherits) {
|
|
278158
|
+
const exprs = collectAuthorizeExprs((cur2.blockNotes ?? []).map((note) => note.text));
|
|
278159
|
+
if (exprs.length > 0) {
|
|
278160
|
+
inheritedGates = exprs;
|
|
278161
|
+
break;
|
|
278162
|
+
}
|
|
278163
|
+
}
|
|
278164
|
+
}
|
|
278061
278165
|
const effective = [
|
|
278062
278166
|
...fileLevelAuthorize,
|
|
278063
|
-
...
|
|
278167
|
+
...ownGates.length > 0 ? ownGates : inheritedGates
|
|
278064
278168
|
];
|
|
278065
278169
|
let authorize;
|
|
278066
278170
|
if (effective.length > 0) {
|
|
278067
278171
|
authorizeMap.set(sourceName, effective);
|
|
278068
278172
|
authorize = effective;
|
|
278069
278173
|
}
|
|
278174
|
+
const ownEffective = [...fileLevelAuthorize, ...ownGates];
|
|
278175
|
+
if (ownEffective.length > 0) {
|
|
278176
|
+
ownAuthorizeSources.push({
|
|
278177
|
+
name: sourceName,
|
|
278178
|
+
authorize: ownEffective
|
|
278179
|
+
});
|
|
278180
|
+
}
|
|
278070
278181
|
const views = struct.fields.filter((field) => field.type === "turtle").filter((turtle) => turtle.pipeline.map((stage) => stage.type).every((type) => type === "reduce")).map((turtle) => ({
|
|
278071
278182
|
name: turtle.as || turtle.name,
|
|
278072
278183
|
annotations: annotationTexts(turtle.annotations)
|
|
@@ -278080,7 +278191,7 @@ function extractSourcesFromModelDef(modelDef, givens, onParseError) {
|
|
|
278080
278191
|
authorize
|
|
278081
278192
|
};
|
|
278082
278193
|
});
|
|
278083
|
-
return { sources, filterMap, authorizeMap };
|
|
278194
|
+
return { sources, filterMap, authorizeMap, ownAuthorizeSources };
|
|
278084
278195
|
}
|
|
278085
278196
|
function extractQueriesFromModelDef(modelDef) {
|
|
278086
278197
|
const isNamedQuery = (obj) => obj.type === "query";
|
|
@@ -278093,9 +278204,7 @@ function extractQueriesFromModelDef(modelDef) {
|
|
|
278093
278204
|
|
|
278094
278205
|
// src/service/model.ts
|
|
278095
278206
|
var MALLOY_VERSION = createRequire2(import.meta.url)("@malloydata/malloy/package.json").version;
|
|
278096
|
-
|
|
278097
|
-
return field.type === "record" || isBasicArray(field) || isRepeatedRecord(field);
|
|
278098
|
-
}
|
|
278207
|
+
var ANCESTOR_WALK_MAX_DEPTH = 32;
|
|
278099
278208
|
function quoteMalloyIdentifier(name) {
|
|
278100
278209
|
return "`" + (name ?? "").replace(/\\/g, "\\\\").replace(/`/g, "\\`") + "`";
|
|
278101
278210
|
}
|
|
@@ -278123,6 +278232,7 @@ class Model {
|
|
|
278123
278232
|
discoveryCurationEnabled = false;
|
|
278124
278233
|
queryBoundary = { mode: "all", exploresDeclared: false, isQueryEntryPoint: true };
|
|
278125
278234
|
freshnessResolver;
|
|
278235
|
+
entryPointGatesBySource = new Map;
|
|
278126
278236
|
meter = publisherMeter();
|
|
278127
278237
|
queryExecutionHistogram = this.meter.createHistogram("malloy_model_query_duration", {
|
|
278128
278238
|
description: "How long it takes to execute a Malloy model query",
|
|
@@ -278147,6 +278257,18 @@ class Model {
|
|
|
278147
278257
|
} catch {
|
|
278148
278258
|
this.fileLevelAuthorize = [];
|
|
278149
278259
|
}
|
|
278260
|
+
try {
|
|
278261
|
+
this.entryPointGatesBySource = this.computeEntryPointGatesBySource();
|
|
278262
|
+
} catch {
|
|
278263
|
+
this.entryPointGatesBySource = new Map;
|
|
278264
|
+
}
|
|
278265
|
+
for (const source of this.sources ?? []) {
|
|
278266
|
+
if (!source.name)
|
|
278267
|
+
continue;
|
|
278268
|
+
const exprs = this.entryPointGatesBySource.get(source.name)?.flatMap((g) => g.exprs);
|
|
278269
|
+
if (exprs && exprs.length > 0)
|
|
278270
|
+
source.authorize = exprs;
|
|
278271
|
+
}
|
|
278150
278272
|
try {
|
|
278151
278273
|
this.authorizeReferencedGivenNames = this.computeAuthorizeReferencedGivenNames();
|
|
278152
278274
|
} catch {
|
|
@@ -278191,17 +278313,24 @@ class Model {
|
|
|
278191
278313
|
}
|
|
278192
278314
|
};
|
|
278193
278315
|
addExprs(this.fileLevelAuthorize);
|
|
278316
|
+
for (const gates of this.entryPointGatesBySource.values()) {
|
|
278317
|
+
for (const { exprs } of gates)
|
|
278318
|
+
addExprs(exprs);
|
|
278319
|
+
}
|
|
278320
|
+
return names;
|
|
278321
|
+
}
|
|
278322
|
+
computeEntryPointGatesBySource() {
|
|
278323
|
+
const byName = new Map;
|
|
278194
278324
|
const modelDef = this.modelDef;
|
|
278195
278325
|
if (!modelDef)
|
|
278196
|
-
return
|
|
278326
|
+
return byName;
|
|
278197
278327
|
for (const entry of Object.values(modelDef.contents)) {
|
|
278198
278328
|
if (!isSourceDef2(entry))
|
|
278199
278329
|
continue;
|
|
278200
|
-
|
|
278201
|
-
|
|
278202
|
-
}
|
|
278330
|
+
const name = entry.as ?? entry.name;
|
|
278331
|
+
byName.set(name, this.collectEntryPointGates(entry, modelDef, new Set, true));
|
|
278203
278332
|
}
|
|
278204
|
-
return
|
|
278333
|
+
return byName;
|
|
278205
278334
|
}
|
|
278206
278335
|
hasAuthorize() {
|
|
278207
278336
|
return this.fileLevelAuthorize.length > 0 || (this.sources?.some((s) => (s.authorize?.length ?? 0) > 0) ?? false);
|
|
@@ -278213,9 +278342,16 @@ class Model {
|
|
|
278213
278342
|
return this.fileLevelAuthorize;
|
|
278214
278343
|
}
|
|
278215
278344
|
async assertAuthorized(sourceName, givens) {
|
|
278345
|
+
const gates = sourceName ? this.entryPointGatesBySource.get(sourceName) : undefined;
|
|
278346
|
+
if (gates) {
|
|
278347
|
+
for (const { label, exprs, selfContained, ambientPrefix } of gates) {
|
|
278348
|
+
await this.assertAuthorizedExprs(label, exprs, givens, selfContained, ambientPrefix);
|
|
278349
|
+
}
|
|
278350
|
+
return;
|
|
278351
|
+
}
|
|
278216
278352
|
await this.assertAuthorizedExprs(sourceName ?? "(query)", this.effectiveAuthorizeFor(sourceName), givens);
|
|
278217
278353
|
}
|
|
278218
|
-
async assertAuthorizedExprs(label, exprs, givens, selfContainedFirst = false) {
|
|
278354
|
+
async assertAuthorizedExprs(label, exprs, givens, selfContainedFirst = false, ambientPrefix = 0) {
|
|
278219
278355
|
if (exprs.length === 0)
|
|
278220
278356
|
return;
|
|
278221
278357
|
const deny = () => {
|
|
@@ -278225,7 +278361,7 @@ class Model {
|
|
|
278225
278361
|
deny();
|
|
278226
278362
|
let passed = false;
|
|
278227
278363
|
try {
|
|
278228
|
-
passed = await evaluateAuthorize(this.modelMaterializer, exprs, givens, this.givenDeclaredTypes(), { selfContainedFirst });
|
|
278364
|
+
passed = await evaluateAuthorize(this.modelMaterializer, exprs, givens, this.givenDeclaredTypes(), { selfContainedFirst, ambientPrefix });
|
|
278229
278365
|
} catch (err) {
|
|
278230
278366
|
logger.debug("Authorize probe failed; denying", {
|
|
278231
278367
|
sourceName: label,
|
|
@@ -278240,27 +278376,19 @@ class Model {
|
|
|
278240
278376
|
async assertAuthorizedForAllSources(runnable, givens) {
|
|
278241
278377
|
const ownSourceName = await this.resolveAuthorizeSourceFromRunnable(runnable);
|
|
278242
278378
|
await this.assertAuthorized(ownSourceName, givens);
|
|
278243
|
-
const { struct, modelDef, compositeResolvedSourceDef
|
|
278379
|
+
const { struct, modelDef, compositeResolvedSourceDef } = await this.resolveRunTargetStruct(runnable);
|
|
278244
278380
|
const seen = new Set;
|
|
278245
|
-
const
|
|
278246
|
-
if (modelDef) {
|
|
278247
|
-
const runTargetLabel = ownSourceName ?? "(run target)";
|
|
278248
|
-
for (const field of extendSources) {
|
|
278249
|
-
const { resolved, denyGate } = this.classifyJoinedField(field, runTargetLabel);
|
|
278250
|
-
if (denyGate) {
|
|
278251
|
-
joinedGates.push(denyGate);
|
|
278252
|
-
continue;
|
|
278253
|
-
}
|
|
278254
|
-
if (!resolved)
|
|
278255
|
-
continue;
|
|
278256
|
-
joinedGates.push(...this.collectAllReachableGates(resolved, modelDef, seen));
|
|
278257
|
-
}
|
|
278258
|
-
}
|
|
278381
|
+
const entryPointGates = this.collectEntryPointGates(struct, modelDef, seen, true);
|
|
278259
278382
|
if (compositeResolvedSourceDef && modelDef) {
|
|
278260
|
-
|
|
278383
|
+
entryPointGates.push(...this.collectEntryPointGates(compositeResolvedSourceDef, modelDef, seen, true));
|
|
278261
278384
|
}
|
|
278262
|
-
for (const {
|
|
278263
|
-
|
|
278385
|
+
for (const {
|
|
278386
|
+
label,
|
|
278387
|
+
exprs,
|
|
278388
|
+
selfContained,
|
|
278389
|
+
ambientPrefix
|
|
278390
|
+
} of entryPointGates) {
|
|
278391
|
+
await this.assertAuthorizedExprs(label, exprs, givens, selfContained, ambientPrefix);
|
|
278264
278392
|
}
|
|
278265
278393
|
}
|
|
278266
278394
|
async resolveRunTargetStruct(runnable) {
|
|
@@ -278271,112 +278399,120 @@ class Model {
|
|
|
278271
278399
|
return {
|
|
278272
278400
|
struct: undefined,
|
|
278273
278401
|
modelDef: undefined,
|
|
278274
|
-
compositeResolvedSourceDef: undefined
|
|
278275
|
-
extendSources: []
|
|
278402
|
+
compositeResolvedSourceDef: undefined
|
|
278276
278403
|
};
|
|
278277
278404
|
const structRef = prepared._query?.structRef;
|
|
278278
278405
|
const struct = typeof structRef === "string" ? modelDef.contents[structRef] : structRef;
|
|
278279
|
-
const extendSources = (prepared._query?.pipeline ?? []).flatMap((segment) => segment.extendSource ?? []);
|
|
278280
278406
|
return {
|
|
278281
278407
|
struct: struct && typeof struct === "object" ? struct : undefined,
|
|
278282
278408
|
modelDef,
|
|
278283
|
-
compositeResolvedSourceDef: prepared._query?.compositeResolvedSourceDef
|
|
278284
|
-
extendSources
|
|
278409
|
+
compositeResolvedSourceDef: prepared._query?.compositeResolvedSourceDef
|
|
278285
278410
|
};
|
|
278286
278411
|
} catch {
|
|
278287
278412
|
return {
|
|
278288
278413
|
struct: undefined,
|
|
278289
278414
|
modelDef: undefined,
|
|
278290
|
-
compositeResolvedSourceDef: undefined
|
|
278291
|
-
extendSources: []
|
|
278415
|
+
compositeResolvedSourceDef: undefined
|
|
278292
278416
|
};
|
|
278293
278417
|
}
|
|
278294
278418
|
}
|
|
278295
|
-
gateExprsForOwnAnnotations(struct) {
|
|
278419
|
+
gateExprsForOwnAnnotations(struct, modelDef) {
|
|
278296
278420
|
const ownNotes = (struct.annotations?.blockNotes ?? []).map((note) => note.text);
|
|
278297
278421
|
try {
|
|
278298
|
-
|
|
278299
|
-
|
|
278300
|
-
|
|
278301
|
-
|
|
278422
|
+
const own = collectAuthorizeExprs(ownNotes);
|
|
278423
|
+
if (own.length > 0) {
|
|
278424
|
+
return {
|
|
278425
|
+
exprs: [...this.fileLevelAuthorize, ...own],
|
|
278426
|
+
fromAncestor: false,
|
|
278427
|
+
ambientPrefix: this.fileLevelAuthorize.length
|
|
278428
|
+
};
|
|
278429
|
+
}
|
|
278430
|
+
const ancestor = this.ancestorGateExprs(struct, modelDef);
|
|
278431
|
+
return {
|
|
278432
|
+
exprs: [...this.fileLevelAuthorize, ...ancestor],
|
|
278433
|
+
fromAncestor: ancestor.length > 0,
|
|
278434
|
+
ambientPrefix: this.fileLevelAuthorize.length
|
|
278435
|
+
};
|
|
278302
278436
|
} catch {
|
|
278303
|
-
return ["false"];
|
|
278437
|
+
return { exprs: ["false"], fromAncestor: false, ambientPrefix: 0 };
|
|
278304
278438
|
}
|
|
278305
278439
|
}
|
|
278306
|
-
|
|
278307
|
-
|
|
278308
|
-
|
|
278309
|
-
|
|
278310
|
-
|
|
278311
|
-
|
|
278312
|
-
|
|
278313
|
-
modelPath: this.modelPath,
|
|
278314
|
-
parentSource: parentLabel,
|
|
278315
|
-
fieldName: field.name,
|
|
278316
|
-
fieldType: field.type
|
|
278317
|
-
});
|
|
278318
|
-
return {
|
|
278319
|
-
denyGate: {
|
|
278320
|
-
label: `${parentLabel} (unresolvable joined source)`,
|
|
278321
|
-
exprs: ["false"],
|
|
278322
|
-
selfContained: false
|
|
278323
|
-
}
|
|
278324
|
-
};
|
|
278440
|
+
ancestorGateExprs(struct, modelDef, seen = new Set) {
|
|
278441
|
+
let inherited = struct.annotations?.inherits;
|
|
278442
|
+
for (let depth = 0;inherited && depth < ANCESTOR_WALK_MAX_DEPTH; depth++) {
|
|
278443
|
+
const exprs2 = collectAuthorizeExprs((inherited.blockNotes ?? []).map((note) => note.text));
|
|
278444
|
+
if (exprs2.length > 0)
|
|
278445
|
+
return exprs2;
|
|
278446
|
+
inherited = inherited.inherits;
|
|
278325
278447
|
}
|
|
278326
|
-
|
|
278448
|
+
if (inherited)
|
|
278449
|
+
return ["false"];
|
|
278450
|
+
seen.add(struct);
|
|
278451
|
+
if (seen.size > ANCESTOR_WALK_MAX_DEPTH)
|
|
278452
|
+
return ["false"];
|
|
278453
|
+
const declared = this.resolveDeclaredSource(struct, modelDef);
|
|
278454
|
+
if (declared.kind === "unresolvable")
|
|
278455
|
+
return ["false"];
|
|
278456
|
+
if (declared.kind === "none" || seen.has(declared.source))
|
|
278457
|
+
return [];
|
|
278458
|
+
const exprs = collectAuthorizeExprs((declared.source.annotations?.blockNotes ?? []).map((note) => note.text));
|
|
278459
|
+
return exprs.length > 0 ? exprs : this.ancestorGateExprs(declared.source, modelDef, seen);
|
|
278327
278460
|
}
|
|
278328
|
-
|
|
278461
|
+
resolveDeclaredSource(struct, modelDef) {
|
|
278462
|
+
if (!modelDef)
|
|
278463
|
+
return { kind: "none" };
|
|
278464
|
+
let sawBrokenEntry = false;
|
|
278465
|
+
for (const id of [struct.referenceID, struct.sourceID]) {
|
|
278466
|
+
const entry = id ? modelDef.sourceRegistry?.[id]?.entry : undefined;
|
|
278467
|
+
if (!entry)
|
|
278468
|
+
continue;
|
|
278469
|
+
const declared = entry.type === "source_registry_reference" ? modelDef.contents[entry.name] : entry;
|
|
278470
|
+
if (declared === struct)
|
|
278471
|
+
continue;
|
|
278472
|
+
if (!declared || !isSourceDef2(declared)) {
|
|
278473
|
+
sawBrokenEntry = true;
|
|
278474
|
+
continue;
|
|
278475
|
+
}
|
|
278476
|
+
return { kind: "resolved", source: declared };
|
|
278477
|
+
}
|
|
278478
|
+
return sawBrokenEntry ? { kind: "unresolvable" } : { kind: "none" };
|
|
278479
|
+
}
|
|
278480
|
+
collectEntryPointGates(struct, modelDef, seen = new Set, treatAsOwnGate = false) {
|
|
278329
278481
|
if (!struct || !modelDef || seen.has(struct))
|
|
278330
278482
|
return [];
|
|
278331
278483
|
seen.add(struct);
|
|
278332
278484
|
const results = [];
|
|
278333
278485
|
const label = struct.as ?? struct.name;
|
|
278334
|
-
const
|
|
278486
|
+
const {
|
|
278487
|
+
exprs: ownExprs,
|
|
278488
|
+
fromAncestor,
|
|
278489
|
+
ambientPrefix
|
|
278490
|
+
} = this.gateExprsForOwnAnnotations(struct, modelDef);
|
|
278335
278491
|
if (ownExprs.length > 0) {
|
|
278336
278492
|
results.push({
|
|
278337
278493
|
label,
|
|
278338
278494
|
exprs: ownExprs,
|
|
278339
|
-
selfContained: !treatAsOwnGate
|
|
278495
|
+
selfContained: fromAncestor || !treatAsOwnGate,
|
|
278496
|
+
ambientPrefix
|
|
278340
278497
|
});
|
|
278341
278498
|
}
|
|
278342
|
-
for (const field of struct.fields) {
|
|
278343
|
-
const { resolved, denyGate } = this.classifyJoinedField(field, label);
|
|
278344
|
-
if (denyGate) {
|
|
278345
|
-
results.push(denyGate);
|
|
278346
|
-
continue;
|
|
278347
|
-
}
|
|
278348
|
-
if (!resolved)
|
|
278349
|
-
continue;
|
|
278350
|
-
const joinedSource = resolved;
|
|
278351
|
-
results.push(...this.collectAllReachableGates(joinedSource, modelDef, seen));
|
|
278352
|
-
if (joinedSource.type === "composite") {
|
|
278353
|
-
const members = joinedSource.sources;
|
|
278354
|
-
for (const member of members) {
|
|
278355
|
-
results.push(...this.collectAllReachableGates(member, modelDef, seen));
|
|
278356
|
-
}
|
|
278357
|
-
}
|
|
278358
|
-
}
|
|
278359
278499
|
const duck = struct;
|
|
278360
278500
|
if (duck.type === "query_source") {
|
|
278361
278501
|
const ref = duck.query?.structRef;
|
|
278362
278502
|
const base = typeof ref === "string" ? modelDef.contents[ref] : ref;
|
|
278363
278503
|
if (base && isSourceDef2(base)) {
|
|
278364
|
-
results.push(...this.
|
|
278504
|
+
results.push(...this.collectEntryPointGates(base, modelDef, seen));
|
|
278505
|
+
} else {
|
|
278506
|
+
results.push({
|
|
278507
|
+
label,
|
|
278508
|
+
exprs: ["false"],
|
|
278509
|
+
selfContained: true,
|
|
278510
|
+
ambientPrefix: 0
|
|
278511
|
+
});
|
|
278365
278512
|
}
|
|
278366
278513
|
const resolved = duck.query?.compositeResolvedSourceDef;
|
|
278367
278514
|
if (resolved) {
|
|
278368
|
-
results.push(...this.
|
|
278369
|
-
}
|
|
278370
|
-
const innerJoins = (duck.query?.pipeline ?? []).flatMap((segment) => segment.extendSource ?? []);
|
|
278371
|
-
for (const field of innerJoins) {
|
|
278372
|
-
const { resolved: innerJoinSource, denyGate: innerJoinDenyGate } = this.classifyJoinedField(field, label);
|
|
278373
|
-
if (innerJoinDenyGate) {
|
|
278374
|
-
results.push(innerJoinDenyGate);
|
|
278375
|
-
continue;
|
|
278376
|
-
}
|
|
278377
|
-
if (!innerJoinSource)
|
|
278378
|
-
continue;
|
|
278379
|
-
results.push(...this.collectAllReachableGates(innerJoinSource, modelDef, seen));
|
|
278515
|
+
results.push(...this.collectEntryPointGates(resolved, modelDef, seen));
|
|
278380
278516
|
}
|
|
278381
278517
|
}
|
|
278382
278518
|
return results;
|
|
@@ -278434,7 +278570,7 @@ class Model {
|
|
|
278434
278570
|
sources = sourceResult.sources;
|
|
278435
278571
|
filterMap = sourceResult.filterMap;
|
|
278436
278572
|
queries = Model.getQueries(modelDef);
|
|
278437
|
-
await validateAuthorizeProbes(modelMaterializer,
|
|
278573
|
+
await validateAuthorizeProbes(modelMaterializer, sourceResult.ownAuthorizeSources);
|
|
278438
278574
|
const imports = modelDef.imports || [];
|
|
278439
278575
|
const importedSourceNames = new Set;
|
|
278440
278576
|
for (const importLocation of imports) {
|
|
@@ -278830,18 +278966,33 @@ class Model {
|
|
|
278830
278966
|
if (!this.modelMaterializer || !this.modelDef || !this.modelInfo)
|
|
278831
278967
|
throw new BadRequestError("Model has no queryable entities.");
|
|
278832
278968
|
const boundary = this.assertQueryBoundaryEarly(sourceName, queryName, query);
|
|
278833
|
-
const
|
|
278969
|
+
const surfaceName = extractRunTargetSourceName(query);
|
|
278970
|
+
const earlySource = sourceName || (queryName ? this.queries?.find((q) => q.name === queryName)?.sourceName : undefined) || (surfaceName && !this.sources?.some((s) => s.name === surfaceName) ? this.queries?.find((q) => q.name === surfaceName)?.sourceName : undefined) || surfaceName;
|
|
278834
278971
|
if (earlySource) {
|
|
278835
278972
|
await this.assertAuthorized(earlySource, givens ?? {});
|
|
278836
278973
|
}
|
|
278837
278974
|
try {
|
|
278975
|
+
for (const [field, callerText] of [
|
|
278976
|
+
["query", query],
|
|
278977
|
+
["source_name", sourceName],
|
|
278978
|
+
["query_name", queryName]
|
|
278979
|
+
]) {
|
|
278980
|
+
if (!callerText)
|
|
278981
|
+
continue;
|
|
278982
|
+
try {
|
|
278983
|
+
assertNoCallerAuthorizeAnnotation(callerText);
|
|
278984
|
+
} catch (err) {
|
|
278985
|
+
recordAuthorizeGuardRejection(field);
|
|
278986
|
+
throw err;
|
|
278987
|
+
}
|
|
278988
|
+
}
|
|
278838
278989
|
let queryString;
|
|
278839
278990
|
if (!sourceName && !queryName && query) {
|
|
278840
278991
|
queryString = `
|
|
278841
278992
|
` + query;
|
|
278842
278993
|
} else if (queryName && !query) {
|
|
278843
278994
|
queryString = `
|
|
278844
|
-
run: ${sourceName ? sourceName
|
|
278995
|
+
run: ${sourceName ? `${quoteMalloyIdentifier(sourceName)} -> ` : ""}${quoteMalloyIdentifier(queryName)}`;
|
|
278845
278996
|
} else {
|
|
278846
278997
|
const endTime = performance.now();
|
|
278847
278998
|
const executionTime2 = endTime - startTime;
|
|
@@ -279017,7 +279168,8 @@ run: ${sourceName ? sourceName + "->" : ""}${queryName}`;
|
|
|
279017
279168
|
executionTime = performance.now() - startTime;
|
|
279018
279169
|
}
|
|
279019
279170
|
const wrappedResult = API.util.wrapResult(queryResults);
|
|
279020
|
-
const
|
|
279171
|
+
const serializedResult = stringifyQueryResponse(wrappedResult, queryResults.totalRows, maxBytes, "model_query");
|
|
279172
|
+
const serializedBytes = maxBytes > 0 ? Buffer.byteLength(serializedResult, "utf8") : 0;
|
|
279021
279173
|
assertWithinModelResponseLimits(queryResults.totalRows, serializedBytes, { maxRows, maxBytes }, "model_query");
|
|
279022
279174
|
this.queryExecutionHistogram.record(executionTime, {
|
|
279023
279175
|
"malloy.model.path": this.modelPath,
|
|
@@ -279032,6 +279184,7 @@ run: ${sourceName ? sourceName + "->" : ""}${queryName}`;
|
|
|
279032
279184
|
});
|
|
279033
279185
|
return {
|
|
279034
279186
|
result: wrappedResult,
|
|
279187
|
+
serializedResult,
|
|
279035
279188
|
compactResult: queryResults.data.value,
|
|
279036
279189
|
modelInfo: this.modelInfo,
|
|
279037
279190
|
dataStyles: this.dataStyles,
|
|
@@ -279169,7 +279322,7 @@ run: ${sourceName ? sourceName + "->" : ""}${queryName}`;
|
|
|
279169
279322
|
});
|
|
279170
279323
|
const query = (await runnableToExecute.getPreparedQuery())._query;
|
|
279171
279324
|
queryName = query.as || query.name;
|
|
279172
|
-
queryResult = result?._queryResult && this.modelInfo &&
|
|
279325
|
+
queryResult = result?._queryResult && this.modelInfo && stringifyQueryResponse(API.util.wrapResult(result), result.totalRows, cellMaxBytes, "notebook_cell");
|
|
279173
279326
|
if (result?._queryResult && queryResult) {
|
|
279174
279327
|
assertWithinModelResponseLimits(result.totalRows, Buffer.byteLength(queryResult, "utf8"), { maxRows: cellMaxRows, maxBytes: cellMaxBytes }, "notebook_cell");
|
|
279175
279328
|
}
|
|
@@ -279215,7 +279368,7 @@ run: ${sourceName ? sourceName + "->" : ""}${queryName}`;
|
|
|
279215
279368
|
static async getModelRuntime(packagePath, modelPath, malloyConfig, options) {
|
|
279216
279369
|
const fullModelPath = path6.join(packagePath, modelPath);
|
|
279217
279370
|
try {
|
|
279218
|
-
if (!(await
|
|
279371
|
+
if (!(await fs6.stat(fullModelPath)).isFile()) {
|
|
279219
279372
|
throw new ModelNotFoundError(`${modelPath} is not a file.`);
|
|
279220
279373
|
}
|
|
279221
279374
|
} catch {
|
|
@@ -279253,8 +279406,12 @@ run: ${sourceName ? sourceName + "->" : ""}${queryName}`;
|
|
|
279253
279406
|
return extractQueriesFromModelDef(modelDef);
|
|
279254
279407
|
}
|
|
279255
279408
|
static getSources(modelDef, givens) {
|
|
279256
|
-
const { sources, filterMap } = extractSourcesFromModelDef(modelDef, givens, (sourceName, err) => logger.warn(`Failed to parse filter annotations on source "${sourceName}"`, { error: err }));
|
|
279257
|
-
return {
|
|
279409
|
+
const { sources, filterMap, ownAuthorizeSources } = extractSourcesFromModelDef(modelDef, givens, (sourceName, err) => logger.warn(`Failed to parse filter annotations on source "${sourceName}"`, { error: err }));
|
|
279410
|
+
return {
|
|
279411
|
+
sources,
|
|
279412
|
+
filterMap,
|
|
279413
|
+
ownAuthorizeSources
|
|
279414
|
+
};
|
|
279258
279415
|
}
|
|
279259
279416
|
static async getModelMaterializer(runtime, importBaseURL, modelURL, modelPath) {
|
|
279260
279417
|
if (modelPath.endsWith(MODEL_FILE_SUFFIX)) {
|
|
@@ -279284,7 +279441,7 @@ run: ${sourceName ? sourceName + "->" : ""}${queryName}`;
|
|
|
279284
279441
|
let fileContents = undefined;
|
|
279285
279442
|
let parse = undefined;
|
|
279286
279443
|
try {
|
|
279287
|
-
fileContents = await
|
|
279444
|
+
fileContents = await fs6.readFile(modelURL, "utf8");
|
|
279288
279445
|
} catch {
|
|
279289
279446
|
throw new ModelNotFoundError("Model not found: " + modelPath);
|
|
279290
279447
|
}
|
|
@@ -279377,7 +279534,7 @@ run: ${sourceName ? sourceName + "->" : ""}${queryName}`;
|
|
|
279377
279534
|
async getFileText(packagePath) {
|
|
279378
279535
|
const fullPath = path6.join(packagePath, this.modelPath);
|
|
279379
279536
|
try {
|
|
279380
|
-
return await
|
|
279537
|
+
return await fs6.readFile(fullPath, "utf8");
|
|
279381
279538
|
} catch {
|
|
279382
279539
|
throw new ModelNotFoundError(`Model file not found: ${this.modelPath}`);
|
|
279383
279540
|
}
|
|
@@ -279979,11 +280136,11 @@ class Package {
|
|
|
279979
280136
|
if (!cleanupDirectoryOnFailure) {
|
|
279980
280137
|
logger.info(`Preserving existing package directory after failed load: ${packagePath}`);
|
|
279981
280138
|
} else {
|
|
279982
|
-
const stat6 = await
|
|
280139
|
+
const stat6 = await fs7.lstat(packagePath).catch(() => null);
|
|
279983
280140
|
if (stat6?.isSymbolicLink()) {
|
|
279984
280141
|
logger.info(`Skipping cleanup of symlinked package path on failure: ${packagePath}`);
|
|
279985
280142
|
} else {
|
|
279986
|
-
await
|
|
280143
|
+
await fs7.rm(packagePath, { recursive: true, force: true });
|
|
279987
280144
|
logger.info(`Cleaned up failed package directory: ${packagePath}`);
|
|
279988
280145
|
}
|
|
279989
280146
|
}
|
|
@@ -280057,7 +280214,7 @@ class Package {
|
|
|
280057
280214
|
renderTagWarnings.push({ model: sm.modelPath, ...w });
|
|
280058
280215
|
}
|
|
280059
280216
|
if (sm.modelPath.endsWith(MODEL_FILE_SUFFIX)) {
|
|
280060
|
-
const modelSource = await
|
|
280217
|
+
const modelSource = await fs7.readFile(path7.join(packagePath, sm.modelPath), "utf-8");
|
|
280061
280218
|
assertPersistNamesQuoted(modelSource, sm.modelPath);
|
|
280062
280219
|
}
|
|
280063
280220
|
models.set(sm.modelPath, model);
|
|
@@ -280589,7 +280746,7 @@ class Package {
|
|
|
280589
280746
|
static async validatePackageManifestExistsOrThrowError(packagePath) {
|
|
280590
280747
|
const packageConfigPath = safeJoinUnderRoot(packagePath, PACKAGE_MANIFEST_NAME);
|
|
280591
280748
|
try {
|
|
280592
|
-
await
|
|
280749
|
+
await fs7.stat(packageConfigPath);
|
|
280593
280750
|
} catch {
|
|
280594
280751
|
logger.error(`Can't find ${packageConfigPath}`);
|
|
280595
280752
|
throw new PackageNotFoundError(`Package manifest for ${packagePath} does not exist.`);
|
|
@@ -280738,7 +280895,7 @@ class Environment {
|
|
|
280738
280895
|
return;
|
|
280739
280896
|
const readmePath = path8.join(this.environmentPath, "README.md");
|
|
280740
280897
|
try {
|
|
280741
|
-
await
|
|
280898
|
+
await fs8.promises.writeFile(readmePath, readme, "utf-8");
|
|
280742
280899
|
logger.info(`Updated README.md for environment ${this.environmentName}`);
|
|
280743
280900
|
} catch (err) {
|
|
280744
280901
|
logger.error(`Failed to write README.md`, { error: err });
|
|
@@ -280772,7 +280929,7 @@ class Environment {
|
|
|
280772
280929
|
}
|
|
280773
280930
|
static async create(environmentName, environmentPath, connections, storageDestinations = []) {
|
|
280774
280931
|
assertSafeEnvironmentPath(environmentPath);
|
|
280775
|
-
if (!(await
|
|
280932
|
+
if (!(await fs8.promises.stat(environmentPath))?.isDirectory()) {
|
|
280776
280933
|
throw new EnvironmentNotFoundError(`Environment path ${environmentPath} not found`);
|
|
280777
280934
|
}
|
|
280778
280935
|
logger.info(`Creating environment with connection configuration`);
|
|
@@ -280790,7 +280947,7 @@ class Environment {
|
|
|
280790
280947
|
async reloadEnvironmentMetadata() {
|
|
280791
280948
|
let readme = "";
|
|
280792
280949
|
try {
|
|
280793
|
-
readme = (await
|
|
280950
|
+
readme = (await fs8.promises.readFile(safeJoinUnderRoot(this.environmentPath, README_NAME))).toString();
|
|
280794
280951
|
} catch {}
|
|
280795
280952
|
this.metadata = {
|
|
280796
280953
|
...this.metadata,
|
|
@@ -280803,6 +280960,12 @@ class Environment {
|
|
|
280803
280960
|
async compileSource(packageName, modelName, source, includeSql = false, givens) {
|
|
280804
280961
|
assertSafePackageName(packageName);
|
|
280805
280962
|
assertSafeRelativeModelPath(modelName);
|
|
280963
|
+
try {
|
|
280964
|
+
assertNoCallerAuthorizeAnnotation(source);
|
|
280965
|
+
} catch (err) {
|
|
280966
|
+
recordAuthorizeGuardRejection("compile_source");
|
|
280967
|
+
throw err;
|
|
280968
|
+
}
|
|
280806
280969
|
if (modelName.endsWith(NOTEBOOK_FILE_SUFFIX)) {
|
|
280807
280970
|
throw new BadRequestError(`Cannot compile against a notebook ("${modelName}"). ` + `/compile takes a .malloy model path for namespace context.`);
|
|
280808
280971
|
}
|
|
@@ -280813,7 +280976,7 @@ class Environment {
|
|
|
280813
280976
|
const virtualUri = virtualUrl.toString();
|
|
280814
280977
|
let modelContent = "";
|
|
280815
280978
|
try {
|
|
280816
|
-
modelContent = await
|
|
280979
|
+
modelContent = await fs8.promises.readFile(modelPath, "utf8");
|
|
280817
280980
|
} catch {}
|
|
280818
280981
|
const fullSource = modelContent ? `${modelContent}
|
|
280819
280982
|
${source}` : source;
|
|
@@ -280914,7 +281077,7 @@ ${source}` : source;
|
|
|
280914
281077
|
try {
|
|
280915
281078
|
const destinationRoot = storageDestinationRoot(this.environmentPath);
|
|
280916
281079
|
if (this.destinations.length > 0) {
|
|
280917
|
-
|
|
281080
|
+
fs8.mkdirSync(destinationRoot, { recursive: true });
|
|
280918
281081
|
}
|
|
280919
281082
|
this.destinationMalloyConfig = buildEnvironmentMalloyConfig(this.destinations, destinationRoot);
|
|
280920
281083
|
} catch (error) {
|
|
@@ -281034,10 +281197,10 @@ ${source}` : source;
|
|
|
281034
281197
|
return this.getOrCreatePackageMutex(packageName).runExclusive(fn);
|
|
281035
281198
|
}
|
|
281036
281199
|
allocateStagingPath(packageName) {
|
|
281037
|
-
return safeJoinUnderRoot(this.environmentPath, STAGING_DIR_NAME, `${packageName}-${
|
|
281200
|
+
return safeJoinUnderRoot(this.environmentPath, STAGING_DIR_NAME, `${packageName}-${crypto4.randomUUID()}`);
|
|
281038
281201
|
}
|
|
281039
281202
|
allocateRetiredPath(packageName) {
|
|
281040
|
-
return safeJoinUnderRoot(this.environmentPath, RETIRED_DIR_NAME, `${packageName}-${
|
|
281203
|
+
return safeJoinUnderRoot(this.environmentPath, RETIRED_DIR_NAME, `${packageName}-${crypto4.randomUUID()}`);
|
|
281041
281204
|
}
|
|
281042
281205
|
static async sweepStaleInstallDirs(environmentPath) {
|
|
281043
281206
|
assertSafeEnvironmentPath(environmentPath);
|
|
@@ -281048,7 +281211,7 @@ ${source}` : source;
|
|
|
281048
281211
|
if (path8.basename(dir) !== dirName)
|
|
281049
281212
|
continue;
|
|
281050
281213
|
try {
|
|
281051
|
-
await
|
|
281214
|
+
await fs8.promises.rm(dir, { recursive: true, force: true });
|
|
281052
281215
|
} catch (err) {
|
|
281053
281216
|
logger.warn(`Failed to sweep stale ${dirName} dir at ${dir}`, {
|
|
281054
281217
|
error: err
|
|
@@ -281149,7 +281312,7 @@ ${source}` : source;
|
|
|
281149
281312
|
async addPackage(packageName, options = {}) {
|
|
281150
281313
|
assertSafePackageName(packageName);
|
|
281151
281314
|
const packagePath = safeJoinUnderRoot(this.environmentPath, packageName);
|
|
281152
|
-
if (!await
|
|
281315
|
+
if (!await fs8.promises.access(packagePath).then(() => true).catch(() => false) || !(await fs8.promises.stat(packagePath))?.isDirectory()) {
|
|
281153
281316
|
throw new PackageNotFoundError(`Package ${packageName} not found`);
|
|
281154
281317
|
}
|
|
281155
281318
|
this.assertCanAdmitNewPackage(packageName, "add a new package", options.allowAdmission === true);
|
|
@@ -281181,7 +281344,7 @@ ${source}` : source;
|
|
|
281181
281344
|
async installPackage(packageName, downloader, validate) {
|
|
281182
281345
|
assertSafePackageName(packageName);
|
|
281183
281346
|
const stagingPath = this.allocateStagingPath(packageName);
|
|
281184
|
-
await
|
|
281347
|
+
await fs8.promises.mkdir(path8.dirname(stagingPath), { recursive: true });
|
|
281185
281348
|
logger.debug("install.phase1.download.started", {
|
|
281186
281349
|
environmentName: this.environmentName,
|
|
281187
281350
|
packageName,
|
|
@@ -281191,7 +281354,7 @@ ${source}` : source;
|
|
|
281191
281354
|
try {
|
|
281192
281355
|
await downloader(stagingPath);
|
|
281193
281356
|
} catch (err) {
|
|
281194
|
-
await
|
|
281357
|
+
await fs8.promises.rm(stagingPath, { recursive: true, force: true }).catch(() => {});
|
|
281195
281358
|
throw err;
|
|
281196
281359
|
}
|
|
281197
281360
|
logger.debug("install.phase1.download.completed", {
|
|
@@ -281207,13 +281370,13 @@ ${source}` : source;
|
|
|
281207
281370
|
const canonicalPath = safeJoinUnderRoot(this.environmentPath, packageName);
|
|
281208
281371
|
let retiredPath;
|
|
281209
281372
|
const oldPackage = this.packages.get(packageName);
|
|
281210
|
-
const oldExistsOnDisk = await
|
|
281373
|
+
const oldExistsOnDisk = await fs8.promises.access(canonicalPath).then(() => true).catch(() => false);
|
|
281211
281374
|
if (oldExistsOnDisk) {
|
|
281212
281375
|
retiredPath = this.allocateRetiredPath(packageName);
|
|
281213
|
-
await
|
|
281376
|
+
await fs8.promises.mkdir(path8.dirname(retiredPath), {
|
|
281214
281377
|
recursive: true
|
|
281215
281378
|
});
|
|
281216
|
-
await
|
|
281379
|
+
await fs8.promises.rename(canonicalPath, retiredPath);
|
|
281217
281380
|
logger.debug("install.phase2.retired_old", {
|
|
281218
281381
|
environmentName: this.environmentName,
|
|
281219
281382
|
packageName,
|
|
@@ -281222,7 +281385,7 @@ ${source}` : source;
|
|
|
281222
281385
|
}
|
|
281223
281386
|
let newPackage;
|
|
281224
281387
|
try {
|
|
281225
|
-
await
|
|
281388
|
+
await fs8.promises.rename(stagingPath, canonicalPath);
|
|
281226
281389
|
this.setPackageStatus(packageName, "loading" /* LOADING */);
|
|
281227
281390
|
newPackage = await Package.create(this.environmentName, packageName, canonicalPath, () => this.malloyConfig.malloyConfig, true);
|
|
281228
281391
|
this.attachDestinationServeConfig(newPackage);
|
|
@@ -281236,11 +281399,11 @@ ${source}` : source;
|
|
|
281236
281399
|
canonicalPath
|
|
281237
281400
|
});
|
|
281238
281401
|
} catch (err) {
|
|
281239
|
-
await
|
|
281402
|
+
await fs8.promises.rm(canonicalPath, { recursive: true, force: true }).catch(() => {});
|
|
281240
281403
|
let restored = false;
|
|
281241
281404
|
if (retiredPath) {
|
|
281242
281405
|
try {
|
|
281243
|
-
await
|
|
281406
|
+
await fs8.promises.rename(retiredPath, canonicalPath);
|
|
281244
281407
|
restored = true;
|
|
281245
281408
|
} catch (restoreErr) {
|
|
281246
281409
|
logger.error("Failed to restore retired package after install rollback", {
|
|
@@ -281250,7 +281413,7 @@ ${source}` : source;
|
|
|
281250
281413
|
});
|
|
281251
281414
|
}
|
|
281252
281415
|
}
|
|
281253
|
-
await
|
|
281416
|
+
await fs8.promises.rm(stagingPath, { recursive: true, force: true }).catch(() => {});
|
|
281254
281417
|
if (oldPackage && restored) {
|
|
281255
281418
|
this.setPackageStatus(packageName, "serving" /* SERVING */);
|
|
281256
281419
|
} else {
|
|
@@ -281284,7 +281447,7 @@ ${source}` : source;
|
|
|
281284
281447
|
packageName,
|
|
281285
281448
|
retiredPath: pathToClean
|
|
281286
281449
|
});
|
|
281287
|
-
|
|
281450
|
+
fs8.promises.rm(pathToClean, { recursive: true, force: true }).catch((err) => {
|
|
281288
281451
|
logger.warn(`Failed to clean up retired package directory ${pathToClean}`, { error: err });
|
|
281289
281452
|
});
|
|
281290
281453
|
});
|
|
@@ -281417,7 +281580,7 @@ ${source}` : source;
|
|
|
281417
281580
|
try {
|
|
281418
281581
|
let existingManifest = {};
|
|
281419
281582
|
try {
|
|
281420
|
-
const content = await
|
|
281583
|
+
const content = await fs8.promises.readFile(manifestPath, "utf-8");
|
|
281421
281584
|
existingManifest = JSON.parse(content);
|
|
281422
281585
|
} catch (_err) {
|
|
281423
281586
|
logger.warn(`Could not read manifest for ${packageName}`);
|
|
@@ -281437,7 +281600,7 @@ ${source}` : source;
|
|
|
281437
281600
|
...resolvedScope !== undefined ? { scope: resolvedScope } : {},
|
|
281438
281601
|
...materializationBlock !== undefined ? { materialization: materializationBlock } : {}
|
|
281439
281602
|
};
|
|
281440
|
-
await
|
|
281603
|
+
await fs8.promises.writeFile(manifestPath, JSON.stringify(updatedManifest, null, 2), "utf-8");
|
|
281441
281604
|
logger.info(`Updated publisher.json for ${packageName}`);
|
|
281442
281605
|
} catch (error) {
|
|
281443
281606
|
logger.error(`Failed to update publisher.json`, { error });
|
|
@@ -281560,10 +281723,10 @@ ${source}` : source;
|
|
|
281560
281723
|
const retiredPath = this.allocateRetiredPath(packageName);
|
|
281561
281724
|
let renamed = false;
|
|
281562
281725
|
try {
|
|
281563
|
-
await
|
|
281726
|
+
await fs8.promises.mkdir(path8.dirname(retiredPath), {
|
|
281564
281727
|
recursive: true
|
|
281565
281728
|
});
|
|
281566
|
-
await
|
|
281729
|
+
await fs8.promises.rename(canonicalPath, retiredPath);
|
|
281567
281730
|
renamed = true;
|
|
281568
281731
|
} catch (err) {
|
|
281569
281732
|
logger.error("Error renaming package directory to retired during unload", {
|
|
@@ -281576,7 +281739,7 @@ ${source}` : source;
|
|
|
281576
281739
|
this.packageStatuses.delete(packageName);
|
|
281577
281740
|
if (renamed) {
|
|
281578
281741
|
setImmediate(() => {
|
|
281579
|
-
|
|
281742
|
+
fs8.promises.rm(retiredPath, { recursive: true, force: true }).catch((err) => {
|
|
281580
281743
|
logger.warn(`Failed to clean up retired package directory ${retiredPath}`, { error: err });
|
|
281581
281744
|
});
|
|
281582
281745
|
});
|
|
@@ -281661,7 +281824,7 @@ ${source}` : source;
|
|
|
281661
281824
|
async deleteDuckDBConnection(connectionName) {
|
|
281662
281825
|
const duckdbPath = path8.join(this.environmentPath, `${connectionName}.duckdb`);
|
|
281663
281826
|
try {
|
|
281664
|
-
await
|
|
281827
|
+
await fs8.promises.rm(duckdbPath, { force: true });
|
|
281665
281828
|
logger.info(`Removed DuckDB connection file ${connectionName} from environment ${this.environmentName}`);
|
|
281666
281829
|
} catch (error) {
|
|
281667
281830
|
logger.error(`Failed to remove DuckDB connection file ${connectionName} from environment ${this.environmentName}`, { error });
|
|
@@ -281722,11 +281885,11 @@ function validateEnvironmentAzureUrls(environment) {
|
|
|
281722
281885
|
}
|
|
281723
281886
|
async function clearMountTarget(targetPath) {
|
|
281724
281887
|
try {
|
|
281725
|
-
const stats = await
|
|
281888
|
+
const stats = await fs9.promises.lstat(targetPath);
|
|
281726
281889
|
if (stats.isDirectory() && !stats.isSymbolicLink()) {
|
|
281727
|
-
await
|
|
281890
|
+
await fs9.promises.rm(targetPath, { recursive: true, force: true });
|
|
281728
281891
|
} else {
|
|
281729
|
-
await
|
|
281892
|
+
await fs9.promises.unlink(targetPath);
|
|
281730
281893
|
}
|
|
281731
281894
|
} catch {}
|
|
281732
281895
|
}
|
|
@@ -281978,7 +282141,7 @@ class EnvironmentStore {
|
|
|
281978
282141
|
if (existingEnvironments.length > 0) {
|
|
281979
282142
|
await Promise.all(existingEnvironments.map(async (dbEnvironment) => {
|
|
281980
282143
|
try {
|
|
281981
|
-
const environmentExists = await
|
|
282144
|
+
const environmentExists = await fs9.promises.access(dbEnvironment.path).then(() => true).catch(() => false);
|
|
281982
282145
|
const environmentConfig = environmentManifest.environments.find((p) => p.name === dbEnvironment.name);
|
|
281983
282146
|
if (!environmentExists) {
|
|
281984
282147
|
if (environmentConfig) {
|
|
@@ -282330,12 +282493,12 @@ class EnvironmentStore {
|
|
|
282330
282493
|
}
|
|
282331
282494
|
async cleanupAndCreatePublisherPath() {
|
|
282332
282495
|
const reInit = process.env.INITIALIZE_STORAGE === "true";
|
|
282333
|
-
await
|
|
282496
|
+
await fs9.promises.mkdir(this.serverRootPath, { recursive: true });
|
|
282334
282497
|
if (reInit) {
|
|
282335
282498
|
const uploadDocsPath2 = path9.join(this.serverRootPath, PUBLISHER_DATA_DIR);
|
|
282336
282499
|
logger.info(`Reinitialization mode: Cleaning up upload documents path ${uploadDocsPath2}`);
|
|
282337
282500
|
try {
|
|
282338
|
-
await
|
|
282501
|
+
await fs9.promises.rm(uploadDocsPath2, {
|
|
282339
282502
|
recursive: true,
|
|
282340
282503
|
force: true
|
|
282341
282504
|
});
|
|
@@ -282350,7 +282513,7 @@ class EnvironmentStore {
|
|
|
282350
282513
|
logger.info(`Using existing publisher path`);
|
|
282351
282514
|
}
|
|
282352
282515
|
const uploadDocsPath = path9.join(this.serverRootPath, PUBLISHER_DATA_DIR);
|
|
282353
|
-
await
|
|
282516
|
+
await fs9.promises.mkdir(uploadDocsPath, { recursive: true });
|
|
282354
282517
|
}
|
|
282355
282518
|
async listEnvironments(skipInitializationCheck = false) {
|
|
282356
282519
|
if (!skipInitializationCheck) {
|
|
@@ -282516,11 +282679,11 @@ class EnvironmentStore {
|
|
|
282516
282679
|
const startedAt = Date.now();
|
|
282517
282680
|
logger.info(`Detected zip file at "${absoluteEnvironmentPath}". Unzipping...`);
|
|
282518
282681
|
const unzippedEnvironmentPath = absoluteEnvironmentPath.replace(".zip", "");
|
|
282519
|
-
await
|
|
282682
|
+
await fs9.promises.rm(unzippedEnvironmentPath, {
|
|
282520
282683
|
recursive: true,
|
|
282521
282684
|
force: true
|
|
282522
282685
|
});
|
|
282523
|
-
await
|
|
282686
|
+
await fs9.promises.mkdir(unzippedEnvironmentPath, { recursive: true });
|
|
282524
282687
|
let entryCount = 0;
|
|
282525
282688
|
let totalUncompressedBytes = 0;
|
|
282526
282689
|
await import_extract_zip.default(absoluteEnvironmentPath, {
|
|
@@ -282570,7 +282733,7 @@ class EnvironmentStore {
|
|
|
282570
282733
|
await this.deleteEnvironmentFromDatabase(environmentName);
|
|
282571
282734
|
if (environmentPath) {
|
|
282572
282735
|
try {
|
|
282573
|
-
await
|
|
282736
|
+
await fs9.promises.rm(environmentPath, {
|
|
282574
282737
|
recursive: true,
|
|
282575
282738
|
force: true
|
|
282576
282739
|
});
|
|
@@ -282592,7 +282755,7 @@ class EnvironmentStore {
|
|
|
282592
282755
|
return { frozenConfig: false, environments: [] };
|
|
282593
282756
|
} else {
|
|
282594
282757
|
try {
|
|
282595
|
-
const entries = await
|
|
282758
|
+
const entries = await fs9.promises.readdir(serverRootPath, {
|
|
282596
282759
|
withFileTypes: true
|
|
282597
282760
|
});
|
|
282598
282761
|
const environments = [];
|
|
@@ -282625,9 +282788,9 @@ class EnvironmentStore {
|
|
|
282625
282788
|
assertSafePackageName(environment.name);
|
|
282626
282789
|
const environmentName = environment.name;
|
|
282627
282790
|
const absoluteEnvironmentPath = safeJoinUnderRoot(this.serverRootPath, PUBLISHER_DATA_DIR, environmentName);
|
|
282628
|
-
await
|
|
282791
|
+
await fs9.promises.mkdir(absoluteEnvironmentPath, { recursive: true });
|
|
282629
282792
|
if (environment.readme) {
|
|
282630
|
-
await
|
|
282793
|
+
await fs9.promises.writeFile(safeJoinUnderRoot(absoluteEnvironmentPath, "README.md"), environment.readme);
|
|
282631
282794
|
}
|
|
282632
282795
|
return absoluteEnvironmentPath;
|
|
282633
282796
|
}
|
|
@@ -282657,7 +282820,7 @@ class EnvironmentStore {
|
|
|
282657
282820
|
assertSafePackageName(environmentName);
|
|
282658
282821
|
const absoluteTargetPath = safeJoinUnderRoot(this.serverRootPath, PUBLISHER_DATA_DIR, environmentName);
|
|
282659
282822
|
const mountErrors = new Map;
|
|
282660
|
-
await
|
|
282823
|
+
await fs9.promises.mkdir(absoluteTargetPath, { recursive: true });
|
|
282661
282824
|
if (!packages || packages.length === 0) {
|
|
282662
282825
|
throw new PackageNotFoundError(`No packages found for environment ${environmentName}`);
|
|
282663
282826
|
}
|
|
@@ -282687,9 +282850,9 @@ class EnvironmentStore {
|
|
|
282687
282850
|
const totalPackages = packages.length;
|
|
282688
282851
|
let mountedCount = 0;
|
|
282689
282852
|
for (const [groupedLocation, packagesForLocation] of locationGroups) {
|
|
282690
|
-
const locationHash =
|
|
282853
|
+
const locationHash = crypto5.createHash("sha256").update(groupedLocation).digest("hex").substring(0, 16);
|
|
282691
282854
|
const tempDownloadPath = safeJoinUnderRoot(absoluteTargetPath, `.temp_${locationHash}`);
|
|
282692
|
-
await
|
|
282855
|
+
await fs9.promises.mkdir(tempDownloadPath, { recursive: true });
|
|
282693
282856
|
logger.info(`Created temporary directory: ${tempDownloadPath}`);
|
|
282694
282857
|
let downloaded = true;
|
|
282695
282858
|
try {
|
|
@@ -282724,7 +282887,7 @@ class EnvironmentStore {
|
|
|
282724
282887
|
sourcePath = safeJoinUnderRoot(tempDownloadPath, groupedLocation);
|
|
282725
282888
|
}
|
|
282726
282889
|
}
|
|
282727
|
-
const sourceExists = await
|
|
282890
|
+
const sourceExists = await fs9.promises.access(sourcePath).then(() => true).catch(() => false);
|
|
282728
282891
|
if (sourceExists) {
|
|
282729
282892
|
const isInPlace = this.inPlaceEnvs.has(environmentName) && this.isLocalPath(_package.location);
|
|
282730
282893
|
if (isInPlace) {
|
|
@@ -282732,16 +282895,16 @@ class EnvironmentStore {
|
|
|
282732
282895
|
const absoluteSourcePath = path9.resolve(sourcePath);
|
|
282733
282896
|
const linkType = process.platform === "win32" ? "junction" : "dir";
|
|
282734
282897
|
try {
|
|
282735
|
-
await
|
|
282898
|
+
await fs9.promises.symlink(absoluteSourcePath, absolutePackagePath, linkType);
|
|
282736
282899
|
logger.info(`In-place mount (watch mode): linked package "${packageDir}" -> "${absoluteSourcePath}" (${++mountedCount}/${totalPackages})`);
|
|
282737
282900
|
} catch (linkError) {
|
|
282738
282901
|
const code = linkError?.code ?? String(linkError);
|
|
282739
282902
|
logger.warn(`In-place mount failed for package "${packageDir}" (${code}); falling back to a copy. Source-edit live reload is disabled for this package.`);
|
|
282740
282903
|
await clearMountTarget(absolutePackagePath);
|
|
282741
|
-
await
|
|
282904
|
+
await fs9.promises.mkdir(absolutePackagePath, {
|
|
282742
282905
|
recursive: true
|
|
282743
282906
|
});
|
|
282744
|
-
await
|
|
282907
|
+
await fs9.promises.cp(sourcePath, absolutePackagePath, {
|
|
282745
282908
|
recursive: true
|
|
282746
282909
|
});
|
|
282747
282910
|
logger.info(`Copied package "${packageDir}" (${++mountedCount}/${totalPackages})`);
|
|
@@ -282751,20 +282914,20 @@ class EnvironmentStore {
|
|
|
282751
282914
|
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.`);
|
|
282752
282915
|
}
|
|
282753
282916
|
await clearMountTarget(absolutePackagePath);
|
|
282754
|
-
await
|
|
282917
|
+
await fs9.promises.mkdir(absolutePackagePath, {
|
|
282755
282918
|
recursive: true
|
|
282756
282919
|
});
|
|
282757
|
-
await
|
|
282920
|
+
await fs9.promises.cp(sourcePath, absolutePackagePath, {
|
|
282758
282921
|
recursive: true
|
|
282759
282922
|
});
|
|
282760
282923
|
logger.info(`Extracted package "${packageDir}" from ${groupedLocation.startsWith("https://github.com/") && _package.location.includes("/tree/") ? "GitHub subdirectory" : "shared download"} (${++mountedCount}/${totalPackages})`);
|
|
282761
282924
|
}
|
|
282762
282925
|
} else {
|
|
282763
282926
|
await clearMountTarget(absolutePackagePath);
|
|
282764
|
-
await
|
|
282927
|
+
await fs9.promises.mkdir(absolutePackagePath, {
|
|
282765
282928
|
recursive: true
|
|
282766
282929
|
});
|
|
282767
|
-
await
|
|
282930
|
+
await fs9.promises.cp(tempDownloadPath, absolutePackagePath, {
|
|
282768
282931
|
recursive: true
|
|
282769
282932
|
});
|
|
282770
282933
|
logger.info(`Copied entire download as package "${packageDir}" (${++mountedCount}/${totalPackages})`);
|
|
@@ -282777,7 +282940,7 @@ class EnvironmentStore {
|
|
|
282777
282940
|
}
|
|
282778
282941
|
}
|
|
282779
282942
|
try {
|
|
282780
|
-
await
|
|
282943
|
+
await fs9.promises.rm(tempDownloadPath, {
|
|
282781
282944
|
recursive: true,
|
|
282782
282945
|
force: true
|
|
282783
282946
|
});
|
|
@@ -282848,14 +283011,14 @@ class EnvironmentStore {
|
|
|
282848
283011
|
if (environmentPath.endsWith(".zip")) {
|
|
282849
283012
|
environmentPath = await this.unzipEnvironment(environmentPath);
|
|
282850
283013
|
}
|
|
282851
|
-
const environmentDirExists = (await
|
|
283014
|
+
const environmentDirExists = (await fs9.promises.stat(environmentPath))?.isDirectory() ?? false;
|
|
282852
283015
|
if (environmentDirExists) {
|
|
282853
|
-
await
|
|
283016
|
+
await fs9.promises.rm(absoluteTargetPath, {
|
|
282854
283017
|
recursive: true,
|
|
282855
283018
|
force: true
|
|
282856
283019
|
});
|
|
282857
|
-
await
|
|
282858
|
-
await
|
|
283020
|
+
await fs9.promises.mkdir(absoluteTargetPath, { recursive: true });
|
|
283021
|
+
await fs9.promises.cp(environmentPath, absoluteTargetPath, {
|
|
282859
283022
|
recursive: true
|
|
282860
283023
|
});
|
|
282861
283024
|
} else {
|
|
@@ -282874,11 +283037,11 @@ class EnvironmentStore {
|
|
|
282874
283037
|
throw new EnvironmentNotFoundError(`Environment ${environmentName} not found in ${gcsPath}`);
|
|
282875
283038
|
}
|
|
282876
283039
|
if (!isCompressedFile) {
|
|
282877
|
-
await
|
|
283040
|
+
await fs9.promises.rm(absoluteDirPath, {
|
|
282878
283041
|
recursive: true,
|
|
282879
283042
|
force: true
|
|
282880
283043
|
});
|
|
282881
|
-
await
|
|
283044
|
+
await fs9.promises.mkdir(absoluteDirPath, { recursive: true });
|
|
282882
283045
|
} else {
|
|
282883
283046
|
absoluteDirPath = `${absoluteDirPath}.zip`;
|
|
282884
283047
|
}
|
|
@@ -282888,10 +283051,10 @@ class EnvironmentStore {
|
|
|
282888
283051
|
if (file.name.endsWith("/")) {
|
|
282889
283052
|
return;
|
|
282890
283053
|
}
|
|
282891
|
-
await
|
|
283054
|
+
await fs9.promises.mkdir(path9.dirname(absoluteFilePath), {
|
|
282892
283055
|
recursive: true
|
|
282893
283056
|
});
|
|
282894
|
-
return
|
|
283057
|
+
return fs9.promises.writeFile(absoluteFilePath, await file.download());
|
|
282895
283058
|
}));
|
|
282896
283059
|
if (isCompressedFile) {
|
|
282897
283060
|
await this.unzipEnvironment(absoluteDirPath);
|
|
@@ -282905,7 +283068,7 @@ class EnvironmentStore {
|
|
|
282905
283068
|
const prefix = prefixParts.join("/");
|
|
282906
283069
|
if (isCompressedFile) {
|
|
282907
283070
|
const zipFilePath = `${absoluteDirPath}.zip`;
|
|
282908
|
-
await
|
|
283071
|
+
await fs9.promises.mkdir(path9.dirname(zipFilePath), {
|
|
282909
283072
|
recursive: true
|
|
282910
283073
|
});
|
|
282911
283074
|
const command = new import_client_s33.GetObjectCommand({
|
|
@@ -282916,7 +283079,7 @@ class EnvironmentStore {
|
|
|
282916
283079
|
if (!item.Body) {
|
|
282917
283080
|
throw new EnvironmentNotFoundError(`Environment ${environmentName} not found in ${s3Path}`);
|
|
282918
283081
|
}
|
|
282919
|
-
const file =
|
|
283082
|
+
const file = fs9.createWriteStream(zipFilePath);
|
|
282920
283083
|
item.Body.transformToWebStream().pipeTo(Writable.toWeb(file));
|
|
282921
283084
|
await new Promise((resolve5, reject) => {
|
|
282922
283085
|
file.on("error", reject);
|
|
@@ -282930,8 +283093,8 @@ class EnvironmentStore {
|
|
|
282930
283093
|
Bucket: bucketName,
|
|
282931
283094
|
Prefix: prefix
|
|
282932
283095
|
});
|
|
282933
|
-
await
|
|
282934
|
-
await
|
|
283096
|
+
await fs9.promises.rm(absoluteDirPath, { recursive: true, force: true });
|
|
283097
|
+
await fs9.promises.mkdir(absoluteDirPath, { recursive: true });
|
|
282935
283098
|
if (!objects.Contents || objects.Contents.length === 0) {
|
|
282936
283099
|
throw new EnvironmentNotFoundError(`Environment ${environmentName} not found in ${s3Path}`);
|
|
282937
283100
|
}
|
|
@@ -282945,7 +283108,7 @@ class EnvironmentStore {
|
|
|
282945
283108
|
return;
|
|
282946
283109
|
}
|
|
282947
283110
|
const absoluteFilePath = safeJoinUnderRoot(absoluteDirPath, relativeFilePath);
|
|
282948
|
-
await
|
|
283111
|
+
await fs9.promises.mkdir(path9.dirname(absoluteFilePath), {
|
|
282949
283112
|
recursive: true
|
|
282950
283113
|
});
|
|
282951
283114
|
const command = new import_client_s33.GetObjectCommand({
|
|
@@ -282956,7 +283119,7 @@ class EnvironmentStore {
|
|
|
282956
283119
|
if (!item.Body) {
|
|
282957
283120
|
return;
|
|
282958
283121
|
}
|
|
282959
|
-
const file =
|
|
283122
|
+
const file = fs9.createWriteStream(absoluteFilePath);
|
|
282960
283123
|
item.Body.transformToWebStream().pipeTo(Writable.toWeb(file));
|
|
282961
283124
|
await new Promise((resolve5, reject) => {
|
|
282962
283125
|
file.on("error", reject);
|
|
@@ -282973,11 +283136,11 @@ class EnvironmentStore {
|
|
|
282973
283136
|
}
|
|
282974
283137
|
const { owner, repoName, packagePath } = githubInfo;
|
|
282975
283138
|
const cleanPackagePath = (packagePath?.replace("/tree/main", "") || "").replace(/^\/+/, "");
|
|
282976
|
-
await
|
|
283139
|
+
await fs9.promises.rm(absoluteDirPath, {
|
|
282977
283140
|
recursive: true,
|
|
282978
283141
|
force: true
|
|
282979
283142
|
});
|
|
282980
|
-
await
|
|
283143
|
+
await fs9.promises.mkdir(absoluteDirPath, { recursive: true });
|
|
282981
283144
|
const repoUrl = `https://github.com/${owner}/${repoName}`;
|
|
282982
283145
|
const reporter = new CloneProgressReporter(cloneProgressLabel(`${owner}/${repoName}`, progressContext));
|
|
282983
283146
|
await new Promise((resolve5, reject) => {
|
|
@@ -283003,24 +283166,24 @@ class EnvironmentStore {
|
|
|
283003
283166
|
return;
|
|
283004
283167
|
}
|
|
283005
283168
|
const packageFullPath = safeJoinUnderRoot(absoluteDirPath, cleanPackagePath);
|
|
283006
|
-
const packageExists = await
|
|
283169
|
+
const packageExists = await fs9.promises.access(packageFullPath).then(() => true).catch(() => false);
|
|
283007
283170
|
if (!packageExists) {
|
|
283008
283171
|
throw new Error(`Package path "${cleanPackagePath}" does not exist in the cloned repository.`);
|
|
283009
283172
|
}
|
|
283010
|
-
const dirContents = await
|
|
283173
|
+
const dirContents = await fs9.promises.readdir(absoluteDirPath);
|
|
283011
283174
|
for (const entry of dirContents) {
|
|
283012
283175
|
if (entry !== cleanPackagePath.replace(/^\/+/, "").split("/")[0]) {
|
|
283013
|
-
await
|
|
283176
|
+
await fs9.promises.rm(safeJoinUnderRoot(absoluteDirPath, entry), {
|
|
283014
283177
|
recursive: true,
|
|
283015
283178
|
force: true
|
|
283016
283179
|
});
|
|
283017
283180
|
}
|
|
283018
283181
|
}
|
|
283019
|
-
const packageContents = await
|
|
283182
|
+
const packageContents = await fs9.promises.readdir(packageFullPath);
|
|
283020
283183
|
for (const entry of packageContents) {
|
|
283021
|
-
await
|
|
283184
|
+
await fs9.promises.rename(safeJoinUnderRoot(packageFullPath, entry), safeJoinUnderRoot(absoluteDirPath, entry));
|
|
283022
283185
|
}
|
|
283023
|
-
await
|
|
283186
|
+
await fs9.promises.rm(packageFullPath, { recursive: true, force: true });
|
|
283024
283187
|
}
|
|
283025
283188
|
extractErrorDataFromError(error) {
|
|
283026
283189
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -286013,6 +286176,15 @@ function classifyToolError(operation, identifier, error) {
|
|
|
286013
286176
|
suggestions: [...BACK_PRESSURE_SUGGESTIONS]
|
|
286014
286177
|
};
|
|
286015
286178
|
}
|
|
286179
|
+
if (error instanceof ResponseUnserializableError) {
|
|
286180
|
+
return {
|
|
286181
|
+
message: error.message,
|
|
286182
|
+
suggestions: [
|
|
286183
|
+
"This is not transient. The same query will fail the same way, so change the query rather than retrying it.",
|
|
286184
|
+
"Raising the byte cap will not help, because the response cannot be serialized at any cap. Shrink it instead: project fewer columns, add a LIMIT, or filter out the wide values."
|
|
286185
|
+
]
|
|
286186
|
+
};
|
|
286187
|
+
}
|
|
286016
286188
|
if (error instanceof QueryTimeoutError || error instanceof PayloadTooLargeError) {
|
|
286017
286189
|
return {
|
|
286018
286190
|
message: error.message,
|
|
@@ -286139,7 +286311,7 @@ var COMPILE_DESCRIPTION = `Compile-check Malloy source against a model and retur
|
|
|
286139
286311
|
|
|
286140
286312
|
## Parameters
|
|
286141
286313
|
- environmentName, packageName, modelPath (required): the model whose namespace the source compiles against. The source is appended to that model, so its imports, sources, and queries are in scope, and modelPath is real context, not a label.
|
|
286142
|
-
- source (required): the Malloy text to validate.
|
|
286314
|
+
- source (required): the Malloy text to validate. An \`#(authorize)\` annotation in it is rejected with a 400 — gates come only from package files; save and reload to validate one.
|
|
286143
286315
|
- includeSql (optional): also return the generated SQL when the source ends in a runnable query. The query is still not executed and no data is scanned.
|
|
286144
286316
|
|
|
286145
286317
|
## Checking part of a source
|
|
@@ -286382,31 +286554,31 @@ var executeQueryShape = {
|
|
|
286382
286554
|
packageName: exports_external.string().describe("Package containing the model. Call malloy_getContext with just environmentName to list its packages."),
|
|
286383
286555
|
modelPath: exports_external.string().describe("Path to the .malloy model file"),
|
|
286384
286556
|
query: exports_external.string().optional().describe("Ad-hoc Malloy query code"),
|
|
286385
|
-
sourceName: exports_external.string().optional().describe("Source name for a view"),
|
|
286386
|
-
queryName: exports_external.string().optional().describe("Named query or view"),
|
|
286557
|
+
sourceName: exports_external.string().optional().describe("Source name for a view. A NAME, not Malloy code: one name exactly as malloy_getContext returned it, sent bare (the server quotes it, so a hyphen or a reserved word is fine — do not add backticks yourself). Anything richer, such as a parameterized source or an inline extension, goes in query."),
|
|
286558
|
+
queryName: exports_external.string().optional().describe("Named query or view. A NAME, not Malloy code, on the same terms as sourceName: one view name as malloy_getContext returned it. A dotted path (carriers.by_name), a refinement (by_carrier + { limit: 10 }), or anything containing a newline goes in query instead."),
|
|
286387
286559
|
filterParams: exports_external.record(exports_external.union([exports_external.string(), exports_external.array(exports_external.string())])).optional().describe("Filter parameter values keyed by filter name. Used with sources that declare #(filter) annotations."),
|
|
286388
286560
|
givens: exports_external.record(exports_external.unknown()).optional().describe("Per-query given values that override model defaults. Keys are given names declared in the model's given: block.")
|
|
286389
286561
|
};
|
|
286390
286562
|
var EXECUTE_QUERY_DESCRIPTION = `Run a Malloy query against a model and return the rows. Takes either ad-hoc Malloy in query, or a named view/query via queryName (with sourceName for a view).
|
|
286391
286563
|
|
|
286392
286564
|
## Contract rules
|
|
286393
|
-
- Check _limit_hit before reporting any total, count, or "top N". True means the server's default
|
|
286565
|
+
- Check _limit_hit before reporting any total, count, or "top N". True means the server's default cap cut the result off and more rows exist, so what came back is a partial set, not the answer.
|
|
286394
286566
|
- Never sum or count the returned rows to state a total when _limit_hit or _rows_truncated is set. Aggregate in the query instead.
|
|
286395
286567
|
- _returned_rows: 0 with _rows_truncated set means one row was too large to send, NOT that nothing matched. Do not report it as an empty result.
|
|
286396
|
-
- Use source, view, and field names exactly as malloy_getContext returned them.
|
|
286568
|
+
- Use source, view, and field names exactly as malloy_getContext returned them. sourceName/queryName take one NAME each, never Malloy code — they are quoted for you, so send even a hyphenated name bare, and put anything richer (a dotted path, a refinement, a second statement) in query.
|
|
286397
286569
|
|
|
286398
286570
|
## Response
|
|
286399
|
-
A JSON object, the same shape Credible's execute_query
|
|
286400
|
-
- rows: flat objects keyed by column name
|
|
286571
|
+
A JSON object, the same shape Credible's execute_query and an in-package data app receive:
|
|
286572
|
+
- rows: flat objects keyed by column name.
|
|
286401
286573
|
- _meta: the Malloy metadata flat rows drop (schema with field types and render tags, annotations, connection_name, query_timezone).
|
|
286402
286574
|
- _query_row_limit: the cap pushed into the SQL, from the query's own limit: or the server default.
|
|
286403
286575
|
- _limit_source: "query" when the cap came from the query's own limit:/top:, "server_default" otherwise.
|
|
286404
|
-
- _limit_hit: the row count equals that cap AND the cap was the server default.
|
|
286576
|
+
- _limit_hit: the row count equals that cap AND the cap was the server default, so a query carrying its own limit:/top: never sets it and exactly that many rows is a complete answer.
|
|
286405
286577
|
- _rows_truncated / _total_rows / _returned_rows: present only when the payload cap dropped rows.
|
|
286406
286578
|
- _query_id: this query's id in the warehouse's own query history. Present only where enabled.
|
|
286407
286579
|
- warning, renderLogErrors: present only when they apply.
|
|
286408
286580
|
|
|
286409
|
-
|
|
286581
|
+
Values above 2^53 are returned as JSON strings so their digits survive.`;
|
|
286410
286582
|
function registerExecuteQueryTool(mcpServer, environmentStore) {
|
|
286411
286583
|
mcpServer.tool("malloy_executeQuery", EXECUTE_QUERY_DESCRIPTION, executeQueryShape, async (params) => {
|
|
286412
286584
|
const {
|
|
@@ -288749,7 +288921,7 @@ source: orders is duckdb.table('orders.parquet') extend {
|
|
|
288749
288921
|
\`\`\`
|
|
288750
288922
|
|
|
288751
288923
|
- **Source-level** \`#(authorize) "<expr>"\` gates that one source. **File-level** \`##(authorize) "<expr>"\` applies to every source in the file. Multiple gates combine as an OR, access is granted if any one is true, so a permissive file-level gate is a **model-wide override**, not an added restriction.
|
|
288752
|
-
- **
|
|
288924
|
+
- **Entry point only: not joined, but inherited through \`extend\`.** The gate applies to the source a query enters through. A gate on a source reached only via \`join_*\` **never fires**, at any depth, so anything ungated that joins a locked base hands the base's rows to every caller. A source that \`extend\`s a locked base and declares no gate of its own **does** carry the base's gate; declaring its own replaces it. Pair a locked base (\`#(authorize) "false"\`) with curated extension sources, using access modifiers (\`include { public: …, private: * }\`), so an extension re-exposes only a curated column surface, and keep sensitive sources out of ungated joins.
|
|
288753
288925
|
- The expression may reference only givens and literals, never a column of the gated source; the check runs against a synthetic probe row, not your data.
|
|
288754
288926
|
|
|
288755
288927
|
> **Trust caveat.** Givens are **caller-asserted**, anyone who can reach the query API can claim a favorable given, e.g. \`{"ROLE":"admin"}\`. \`#(authorize)\` is only a real boundary when it sits behind a trusted tier that sets givens from its own verified context, never directly from an untrusted caller. It is not, on its own, end-user authentication.
|
|
@@ -290105,7 +290277,7 @@ function initializeMcpServer(environmentStore) {
|
|
|
290105
290277
|
}
|
|
290106
290278
|
|
|
290107
290279
|
// src/mcp_config.ts
|
|
290108
|
-
import * as
|
|
290280
|
+
import * as fs10 from "fs";
|
|
290109
290281
|
import * as os3 from "os";
|
|
290110
290282
|
import * as path11 from "path";
|
|
290111
290283
|
init_logger();
|
|
@@ -290134,7 +290306,7 @@ function mcpEndpoint(host, port) {
|
|
|
290134
290306
|
function findGitWorkTreeRoot(dir) {
|
|
290135
290307
|
let current = path11.resolve(dir);
|
|
290136
290308
|
for (;; ) {
|
|
290137
|
-
if (
|
|
290309
|
+
if (fs10.existsSync(path11.join(current, ".git")))
|
|
290138
290310
|
return current;
|
|
290139
290311
|
const parent = path11.dirname(current);
|
|
290140
290312
|
if (parent === current)
|
|
@@ -290153,7 +290325,7 @@ function ensureMcpConfig(options) {
|
|
|
290153
290325
|
try {
|
|
290154
290326
|
return {
|
|
290155
290327
|
path: file,
|
|
290156
|
-
isSymlink:
|
|
290328
|
+
isSymlink: fs10.lstatSync(file).isSymbolicLink()
|
|
290157
290329
|
};
|
|
290158
290330
|
} catch {
|
|
290159
290331
|
return;
|
|
@@ -290172,7 +290344,7 @@ function ensureMcpConfig(options) {
|
|
|
290172
290344
|
}
|
|
290173
290345
|
const realish = (p) => {
|
|
290174
290346
|
try {
|
|
290175
|
-
return
|
|
290347
|
+
return fs10.realpathSync(p);
|
|
290176
290348
|
} catch {
|
|
290177
290349
|
return path11.resolve(p);
|
|
290178
290350
|
}
|
|
@@ -290190,7 +290362,7 @@ function ensureMcpConfig(options) {
|
|
|
290190
290362
|
action: "skipped-git",
|
|
290191
290363
|
dir,
|
|
290192
290364
|
gitRoot,
|
|
290193
|
-
rootConfig:
|
|
290365
|
+
rootConfig: fs10.existsSync(rootCandidate) ? rootCandidate : undefined,
|
|
290194
290366
|
endpoint,
|
|
290195
290367
|
staleConfig
|
|
290196
290368
|
};
|
|
@@ -290199,7 +290371,7 @@ function ensureMcpConfig(options) {
|
|
|
290199
290371
|
return { action: "exists", file, endpoint };
|
|
290200
290372
|
const body = JSON.stringify({ mcpServers: { malloy: malloyServer(endpoint) } }, null, 2) + `
|
|
290201
290373
|
`;
|
|
290202
|
-
|
|
290374
|
+
fs10.writeFileSync(file, body, { encoding: "utf8", flag: "wx" });
|
|
290203
290375
|
return { action: "created", file };
|
|
290204
290376
|
} catch (error) {
|
|
290205
290377
|
const code = error?.code;
|
|
@@ -292377,7 +292549,82 @@ function listSanitizerDrops(raw, sanitized) {
|
|
|
292377
292549
|
return drops;
|
|
292378
292550
|
}
|
|
292379
292551
|
|
|
292552
|
+
// src/spa_fallback.ts
|
|
292553
|
+
var ASSET_EXTENSIONS = new Set([
|
|
292554
|
+
"avif",
|
|
292555
|
+
"css",
|
|
292556
|
+
"csv",
|
|
292557
|
+
"gif",
|
|
292558
|
+
"htm",
|
|
292559
|
+
"html",
|
|
292560
|
+
"ico",
|
|
292561
|
+
"jpeg",
|
|
292562
|
+
"jpg",
|
|
292563
|
+
"js",
|
|
292564
|
+
"json",
|
|
292565
|
+
"map",
|
|
292566
|
+
"mjs",
|
|
292567
|
+
"parquet",
|
|
292568
|
+
"pdf",
|
|
292569
|
+
"png",
|
|
292570
|
+
"svg",
|
|
292571
|
+
"ttf",
|
|
292572
|
+
"txt",
|
|
292573
|
+
"webp",
|
|
292574
|
+
"woff",
|
|
292575
|
+
"woff2",
|
|
292576
|
+
"xlsx"
|
|
292577
|
+
]);
|
|
292578
|
+
var SPA_OWNED_SEGMENTS = new Set(["pages", "workbook"]);
|
|
292579
|
+
function extensionOf(segment) {
|
|
292580
|
+
const dot = segment.lastIndexOf(".");
|
|
292581
|
+
if (dot <= 0 || dot === segment.length - 1)
|
|
292582
|
+
return "";
|
|
292583
|
+
return segment.slice(dot + 1).toLowerCase();
|
|
292584
|
+
}
|
|
292585
|
+
function classifySpaFallback(requestPath, apiPrefix) {
|
|
292586
|
+
if (requestPath === apiPrefix || requestPath.startsWith(`${apiPrefix}/`)) {
|
|
292587
|
+
return { kind: "apiNotFound", path: requestPath };
|
|
292588
|
+
}
|
|
292589
|
+
const segments = requestPath.split("/").filter((s) => s.length > 0);
|
|
292590
|
+
const last2 = segments[segments.length - 1] ?? "";
|
|
292591
|
+
if (!ASSET_EXTENSIONS.has(extensionOf(last2)))
|
|
292592
|
+
return { kind: "spa" };
|
|
292593
|
+
if (segments.length >= 3 && SPA_OWNED_SEGMENTS.has(segments[2])) {
|
|
292594
|
+
return { kind: "spa" };
|
|
292595
|
+
}
|
|
292596
|
+
if (segments.length >= 3) {
|
|
292597
|
+
const alreadyStaticForm = segments[0] === "environments" && segments[2] === "packages";
|
|
292598
|
+
const traverses = segments.some((segment) => {
|
|
292599
|
+
let decoded;
|
|
292600
|
+
try {
|
|
292601
|
+
decoded = decodeURIComponent(segment);
|
|
292602
|
+
} catch {
|
|
292603
|
+
return true;
|
|
292604
|
+
}
|
|
292605
|
+
return decoded === "." || decoded === ".." || decoded.includes("\\");
|
|
292606
|
+
});
|
|
292607
|
+
if (!alreadyStaticForm && !traverses) {
|
|
292608
|
+
const [environmentName, packageName, ...rest] = segments;
|
|
292609
|
+
if (rest[0] === "public" && rest.length > 1)
|
|
292610
|
+
rest.shift();
|
|
292611
|
+
return {
|
|
292612
|
+
kind: "redirect",
|
|
292613
|
+
location: `/environments/${environmentName}/packages/${packageName}/${rest.join("/")}`,
|
|
292614
|
+
environmentName,
|
|
292615
|
+
packageName
|
|
292616
|
+
};
|
|
292617
|
+
}
|
|
292618
|
+
}
|
|
292619
|
+
return {
|
|
292620
|
+
kind: "assetNotFound",
|
|
292621
|
+
path: requestPath,
|
|
292622
|
+
appRouteCandidate: segments.length === 1 ? { environmentName: segments[0] } : segments.length === 2 ? { environmentName: segments[0], packageName: segments[1] } : null
|
|
292623
|
+
};
|
|
292624
|
+
}
|
|
292625
|
+
|
|
292380
292626
|
// src/server.ts
|
|
292627
|
+
assertSupportedNodeVersion();
|
|
292381
292628
|
function parseArgs() {
|
|
292382
292629
|
const args = process.argv.slice(2);
|
|
292383
292630
|
let sawServerRoot = false;
|
|
@@ -292567,6 +292814,17 @@ app.get("/sdk/publisher.js", (_req, res) => {
|
|
|
292567
292814
|
}
|
|
292568
292815
|
});
|
|
292569
292816
|
});
|
|
292817
|
+
var PACKAGE_FILE_NOT_FOUND_HTML = `<!doctype html><meta charset="utf-8">
|
|
292818
|
+
<title>Not found</title>
|
|
292819
|
+
<style>body{font:14px/1.4 -apple-system,system-ui,sans-serif;margin:40px;max-width:720px;color:#222}code{background:#f4f4f5;padding:1px 4px;border-radius:3px}</style>
|
|
292820
|
+
<h1>Not found</h1>
|
|
292821
|
+
<p>This package does not serve that file. Only files inside the package's
|
|
292822
|
+
<code>public/</code> directory are web-served, at
|
|
292823
|
+
<code>/environments/<env>/packages/<pkg>/<file></code>, where <code><file></code> is
|
|
292824
|
+
relative to <code>public/</code> and does not include it.</p>
|
|
292825
|
+
<p>Models and notebooks are not served here; they open in the web UI at
|
|
292826
|
+
<code>/<env>/<pkg>/<file>.malloy</code>. <a href="/">Publisher home</a> lists what
|
|
292827
|
+
this server has.</p>`;
|
|
292570
292828
|
async function serveFromPackage(req, res) {
|
|
292571
292829
|
const subPathRaw = req.params["0"] ?? "";
|
|
292572
292830
|
try {
|
|
@@ -292586,7 +292844,7 @@ async function serveFromPackage(req, res) {
|
|
|
292586
292844
|
realFullPath = await fsp.realpath(fullPath);
|
|
292587
292845
|
} catch {
|
|
292588
292846
|
if (!res.headersSent) {
|
|
292589
|
-
res.status(404).
|
|
292847
|
+
res.status(404).type("text/html").send(PACKAGE_FILE_NOT_FOUND_HTML);
|
|
292590
292848
|
}
|
|
292591
292849
|
return;
|
|
292592
292850
|
}
|
|
@@ -292605,7 +292863,7 @@ async function serveFromPackage(req, res) {
|
|
|
292605
292863
|
res.sendFile(realFullPath, (err) => {
|
|
292606
292864
|
if (err) {
|
|
292607
292865
|
if (!res.headersSent) {
|
|
292608
|
-
res.status(404).
|
|
292866
|
+
res.status(404).type("text/html").send(PACKAGE_FILE_NOT_FOUND_HTML);
|
|
292609
292867
|
}
|
|
292610
292868
|
}
|
|
292611
292869
|
});
|
|
@@ -292616,21 +292874,17 @@ async function serveFromPackage(req, res) {
|
|
|
292616
292874
|
}
|
|
292617
292875
|
}
|
|
292618
292876
|
}
|
|
292877
|
+
function withRequestQuery(req, target) {
|
|
292878
|
+
const hash = req.originalUrl.indexOf("#");
|
|
292879
|
+
const target_ = hash === -1 ? req.originalUrl : req.originalUrl.slice(0, hash);
|
|
292880
|
+
const marker = target_.indexOf("?");
|
|
292881
|
+
return marker === -1 ? target : target + target_.slice(marker);
|
|
292882
|
+
}
|
|
292619
292883
|
app.get("/environments/:environmentName/packages/:packageName", (req, res, next) => {
|
|
292620
292884
|
if (req.path.endsWith("/"))
|
|
292621
292885
|
return next();
|
|
292622
292886
|
const canonical = `/environments/${encodeURIComponent(req.params.environmentName)}/packages/${encodeURIComponent(req.params.packageName)}/`;
|
|
292623
|
-
|
|
292624
|
-
for (const [key, value] of Object.entries(req.query)) {
|
|
292625
|
-
if (Array.isArray(value)) {
|
|
292626
|
-
for (const v of value)
|
|
292627
|
-
query.append(key, String(v));
|
|
292628
|
-
} else if (value !== undefined) {
|
|
292629
|
-
query.append(key, String(value));
|
|
292630
|
-
}
|
|
292631
|
-
}
|
|
292632
|
-
const qs = query.toString();
|
|
292633
|
-
res.redirect(308, qs ? `${canonical}?${qs}` : canonical);
|
|
292887
|
+
res.redirect(308, withRequestQuery(req, canonical));
|
|
292634
292888
|
});
|
|
292635
292889
|
app.get("/environments/:environmentName/packages/:packageName/*", serveFromPackage);
|
|
292636
292890
|
var PAGES_DEPTH_CAP = 3;
|
|
@@ -292645,11 +292899,11 @@ function stripNonTagText(input) {
|
|
|
292645
292899
|
return current;
|
|
292646
292900
|
}
|
|
292647
292901
|
async function listPackagePages(environmentName, packageName, publicRoot) {
|
|
292648
|
-
const
|
|
292902
|
+
const fs11 = await import("fs/promises");
|
|
292649
292903
|
const out = [];
|
|
292650
292904
|
let realPublicRoot;
|
|
292651
292905
|
try {
|
|
292652
|
-
realPublicRoot = await
|
|
292906
|
+
realPublicRoot = await fs11.realpath(publicRoot);
|
|
292653
292907
|
} catch {
|
|
292654
292908
|
return out;
|
|
292655
292909
|
}
|
|
@@ -292658,7 +292912,7 @@ async function listPackagePages(environmentName, packageName, publicRoot) {
|
|
|
292658
292912
|
return;
|
|
292659
292913
|
let entries;
|
|
292660
292914
|
try {
|
|
292661
|
-
entries = await
|
|
292915
|
+
entries = await fs11.readdir(dir, { withFileTypes: true });
|
|
292662
292916
|
} catch {
|
|
292663
292917
|
return;
|
|
292664
292918
|
}
|
|
@@ -292668,7 +292922,7 @@ async function listPackagePages(environmentName, packageName, publicRoot) {
|
|
|
292668
292922
|
const full = path13.join(dir, entry.name);
|
|
292669
292923
|
let realFull;
|
|
292670
292924
|
try {
|
|
292671
|
-
realFull = await
|
|
292925
|
+
realFull = await fs11.realpath(full);
|
|
292672
292926
|
} catch {
|
|
292673
292927
|
continue;
|
|
292674
292928
|
}
|
|
@@ -292682,7 +292936,7 @@ async function listPackagePages(environmentName, packageName, publicRoot) {
|
|
|
292682
292936
|
let title = rel;
|
|
292683
292937
|
let fit;
|
|
292684
292938
|
try {
|
|
292685
|
-
const fh = await
|
|
292939
|
+
const fh = await fs11.open(full, "r");
|
|
292686
292940
|
try {
|
|
292687
292941
|
const buf = Buffer.alloc(4096);
|
|
292688
292942
|
const { bytesRead } = await fh.read(buf, 0, 4096, 0);
|
|
@@ -293371,7 +293625,62 @@ registerLegacyRoutes(app, {
|
|
|
293371
293625
|
});
|
|
293372
293626
|
if (!isDevelopment) {
|
|
293373
293627
|
const SPA_INDEX = path13.resolve(ROOT, "index.html");
|
|
293628
|
+
const escapeHtml = (value) => value.replace(/[<>&]/g, (c) => ({ "<": "<", ">": ">", "&": "&" })[c] ?? c);
|
|
293629
|
+
const decodeSegment = (segment) => {
|
|
293630
|
+
if (segment === undefined)
|
|
293631
|
+
return "";
|
|
293632
|
+
try {
|
|
293633
|
+
return decodeURIComponent(segment);
|
|
293634
|
+
} catch {
|
|
293635
|
+
return segment;
|
|
293636
|
+
}
|
|
293637
|
+
};
|
|
293374
293638
|
app.get("*", (req, res) => {
|
|
293639
|
+
let fallback = classifySpaFallback(req.path, API_PREFIX2);
|
|
293640
|
+
const loadedEnvironment = (name) => environmentStore.getLoadedEnvironments().find((environment) => environment.getEnvironmentName() === name);
|
|
293641
|
+
if (fallback.kind === "redirect") {
|
|
293642
|
+
const environment = loadedEnvironment(decodeSegment(fallback.environmentName));
|
|
293643
|
+
const packageName = decodeSegment(fallback.packageName);
|
|
293644
|
+
const known = environment?.getLoadedPackages().some((pkg) => pkg.getPackageName() === packageName);
|
|
293645
|
+
if (!known) {
|
|
293646
|
+
fallback = {
|
|
293647
|
+
kind: "assetNotFound",
|
|
293648
|
+
path: req.path,
|
|
293649
|
+
appRouteCandidate: null
|
|
293650
|
+
};
|
|
293651
|
+
}
|
|
293652
|
+
}
|
|
293653
|
+
if (fallback.kind === "assetNotFound" && fallback.appRouteCandidate) {
|
|
293654
|
+
const { environmentName, packageName } = fallback.appRouteCandidate;
|
|
293655
|
+
const environment = loadedEnvironment(decodeSegment(environmentName));
|
|
293656
|
+
const isAppRoute = environment !== undefined && (packageName === undefined || environment.getLoadedPackages().some((pkg) => pkg.getPackageName() === decodeSegment(packageName)));
|
|
293657
|
+
if (isAppRoute)
|
|
293658
|
+
fallback = { kind: "spa" };
|
|
293659
|
+
}
|
|
293660
|
+
if (fallback.kind === "redirect") {
|
|
293661
|
+
res.redirect(302, withRequestQuery(req, fallback.location));
|
|
293662
|
+
return;
|
|
293663
|
+
}
|
|
293664
|
+
if (fallback.kind === "apiNotFound") {
|
|
293665
|
+
res.status(404).json({
|
|
293666
|
+
code: 404,
|
|
293667
|
+
message: `Unknown API endpoint: ${fallback.path}. See /api-doc.yaml for the endpoints this server serves.`
|
|
293668
|
+
});
|
|
293669
|
+
return;
|
|
293670
|
+
}
|
|
293671
|
+
if (fallback.kind === "assetNotFound") {
|
|
293672
|
+
res.status(404).type("text/html").send(`<!doctype html><meta charset="utf-8">
|
|
293673
|
+
<title>Not found</title>
|
|
293674
|
+
<style>body{font:14px/1.4 -apple-system,system-ui,sans-serif;margin:40px;max-width:720px;color:#222}code{background:#f4f4f5;padding:1px 4px;border-radius:3px}</style>
|
|
293675
|
+
<h1>Not found</h1>
|
|
293676
|
+
<p>Nothing is served at <code>${escapeHtml(fallback.path)}</code>.</p>
|
|
293677
|
+
<p>A file inside a package is served from that package's <code>public/</code> directory at
|
|
293678
|
+
<code>/environments/<env>/packages/<pkg>/<file></code>, where <code><file></code> is relative to
|
|
293679
|
+
<code>public/</code> and does not include it. Models and notebooks open in the web UI at
|
|
293680
|
+
<code>/<env>/<pkg>/<file>.malloy</code> and <code>.malloynb</code>.</p>
|
|
293681
|
+
<p><a href="/">Publisher home</a> lists the environments and packages this server has.</p>`);
|
|
293682
|
+
return;
|
|
293683
|
+
}
|
|
293375
293684
|
res.sendFile(SPA_INDEX, (err) => {
|
|
293376
293685
|
if (!err)
|
|
293377
293686
|
return;
|