@malloy-publisher/server 0.9.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.docker.md +46 -5
- package/dist/app/api-doc.yaml +17 -1
- package/dist/package_load_worker.mjs +136 -52
- package/dist/server.mjs +417 -241
- package/package.json +1 -1
package/README.docker.md
CHANGED
|
@@ -80,12 +80,26 @@ Every application file is root-owned, so the server cannot modify one in place.
|
|
|
80
80
|
|
|
81
81
|
- `/publisher/`, the server root, where it creates `publisher.db`. Because it owns this directory, the server can also rename aside and replace any of its top-level entries: `package.json`, `bun.lock`, and the `packages/` and `node_modules/` directories. Such a change lasts as long as the container. Some storage drivers, Docker's default overlayfs among them, refuse to rename a directory that comes from an image layer, but that is the driver's limit, not the image's.
|
|
82
82
|
- `/publisher/publisher_data/`.
|
|
83
|
+
- `/publisher/ducklake_data/`, when a DuckLake storage destination's `bucketUrl` points there.
|
|
83
84
|
- `/home/bun/.duckdb/extensions/`, for an extension the image did not bake.
|
|
84
85
|
|
|
85
|
-
What you mount has to be writable by uid 1000 too:
|
|
86
|
+
What you mount has to be writable by uid 1000 too. Per kind of mount:
|
|
86
87
|
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
| Mount | The server | What to do |
|
|
89
|
+
| --- | --- | --- |
|
|
90
|
+
| A new named volume on `/publisher/publisher_data` or `/publisher/ducklake_data` | writes | Nothing: Docker seeds it from the image, owned by uid 1000. |
|
|
91
|
+
| A new named volume anywhere else | writes | `docker run --rm --user 0 --entrypoint chown -v <volume>:/path ms2data/malloy-publisher -R 1000:1000 /path`, once. |
|
|
92
|
+
| A volume an older, root-run image wrote to | writes | The same `chown`, once, before starting the new image. With Compose, `docker compose run --rm --no-deps --user 0 --entrypoint chown publisher -R 1000:1000 /publisher/publisher_data`. |
|
|
93
|
+
| A bind of a host directory the server writes | writes | `sudo chown -R 1000:1000 <dir>`, or keep your ownership and add an ACL, which needs no `sudo` on a directory you own: `setfacl -R -m u:1000:rwX -m d:u:1000:rwX <dir>`. |
|
|
94
|
+
| A bind of a host directory the server only reads (a package `location`, a directory of zips) | reads | Readable by others, `chmod -R o+rX <dir>`, or group-readable with `sudo chgrp -R 1000 <dir> && chmod -R g+rX <dir>`. Mount it `:ro`. |
|
|
95
|
+
| A single bound file (the config, a key file) | reads | Readable by others or by gid 1000; a `0600` file is not. See the key-file recipes below. Mount it `:ro`. |
|
|
96
|
+
| A Kubernetes PersistentVolume | writes | `fsGroup: 1000` and `fsGroupChangePolicy: OnRootMismatch` in the pod's `securityContext`. |
|
|
97
|
+
| A Kubernetes Secret or projected token | reads | `fsGroup: 1000` makes a `0600`-mounted file readable by the group. |
|
|
98
|
+
|
|
99
|
+
Before starting the server, the probe at the end of this section confirms a mount is usable as uid 1000. The detail behind each row:
|
|
100
|
+
|
|
101
|
+
- **A new named volume on `/publisher/publisher_data` or `/publisher/ducklake_data`** works as-is. Docker seeds an empty named volume from the image's directory, ownership included, and those are the two writable mount points the image prepares: `publisher_data` for packages and per-package sandboxes, `ducklake_data` for a DuckLake storage destination whose `bucketUrl` is a local path.
|
|
102
|
+
- **A new named volume anywhere else** starts owned by root, because the image has no directory there to copy ownership from. Prepare it yourself: build a derived image with `RUN mkdir -p /path && chown 1000:1000 /path` (new named volumes there are then seeded correctly), chown the volume once with `--user 0`, or bind-mount a host directory owned by uid 1000. DuckDB reports the unprepared case as `No such file or directory` (for example `Failed to create directory "/data/lake/main/daily_orders"`), not as `EACCES`. The one-time chown names the mount path twice, as the mount target and as chown's argument:
|
|
89
103
|
|
|
90
104
|
```bash
|
|
91
105
|
docker run --rm --user 0 --entrypoint chown \
|
|
@@ -110,8 +124,35 @@ What you mount has to be writable by uid 1000 too:
|
|
|
110
124
|
|
|
111
125
|
`docker volume ls` shows the volume's full name if you would rather use the `docker run` form.
|
|
112
126
|
|
|
113
|
-
- **A bind mount** keeps the host directory's ownership. On Linux, `chown -R 1000:1000` the host directory
|
|
114
|
-
|
|
127
|
+
- **A bind mount** keeps the host directory's ownership. On Linux, `sudo chown -R 1000:1000` the host directory, or keep it yours and grant uid 1000 through a POSIX ACL, which also covers files created later and, unlike `chown`, needs no `sudo` on a directory you own:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
setfacl -R -m u:1000:rwX -m d:u:1000:rwX <dir>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Docker Desktop on macOS and Windows maps ownership for you. Running the container as some other uid to match the host is not a substitute: `/home/bun` is private to uid 1000, so that uid cannot read the baked DuckDB extensions.
|
|
134
|
+
- **A Kubernetes PersistentVolume** is not seeded from the image, so even a new one on `/publisher/publisher_data` starts owned by root (an `emptyDir` is world-writable and needs nothing). Set `fsGroup: 1000` in the pod's `securityContext`, which makes the volume group-writable by gid 1000, and `fsGroupChangePolicy: OnRootMismatch` so the kubelet does not re-chown a large volume on every start. `fsGroup` is also what makes a mounted Secret key file, or a projected service-account token, readable by uid 1000 where the platform mounts them `0600`.
|
|
135
|
+
- **A read-only mount** only needs to be readable by uid 1000. That covers the config file, a package `location`, a directory of package zips (a `.zip` location is extracted into `publisher_data/`, never beside the archive), and the key file `GOOGLE_APPLICATION_CREDENTIALS` names. A key file bound from a host path that does not exist arrives as a directory, and the server says so. The usual trap is the key file itself: a `gcloud` application-default credentials file is `0600` and owned by you, so uid 1000 cannot read it through a bind on Linux, unless your own uid is 1000 (the first user on most Ubuntu installs), in which case nothing is needed. Otherwise bind a copy it can read, or grant the group. Both need root, because only root can hand a file to another uid or to a group you are not in:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
sudo install -o 1000 -g 1000 -m 0400 ~/.config/gcloud/application_default_credentials.json ./secrets/key.json
|
|
139
|
+
# or, keeping the original in place:
|
|
140
|
+
sudo chgrp 1000 key.json && chmod 0640 key.json
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
For a directory you own, `chmod -R o+rX <dir>` needs no root; the `chgrp 1000` / `g+rX` equivalent does.
|
|
144
|
+
- **Ownership is right and the server still reports `EACCES`:** on SELinux hosts (Fedora, RHEL) a bind mount needs the `:z` (shared) or `:Z` (private) option, or every access is refused whatever the owner. Under rootless Docker, Podman, or `userns-remap`, uid 1000 in the container is a subordinate uid on the host, so a host `chown 1000` names the wrong owner; use `podman unshare chown -R 1000:1000 <dir>`, or the remapped uid.
|
|
145
|
+
|
|
146
|
+
To check a mount before starting the server, run the probe as the image's user:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
docker run --rm --entrypoint sh -v <mount> ms2data/malloy-publisher \
|
|
150
|
+
-c 'id; touch <path>/.probe && rm <path>/.probe && echo writable'
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
For a read-only mount, the same with `cat <file> >/dev/null && echo readable`.
|
|
154
|
+
|
|
155
|
+
When the server cannot make a write it needs, the response names the errno (`EACCES: permission denied, mkdir '…'`) rather than answering a bare `Internal server error.`. A package that cannot be mounted at boot, or added at runtime, is listed under `loadErrors` in `GET /api/v0/status` with that message, until it is added successfully or deleted. If the server cannot start at all, for example on a read-only root filesystem or with a config file it cannot read, `/api/v0/status` stays `initializing` and `initError` says why.
|
|
115
156
|
|
|
116
157
|
If you cannot change the ownership yet, `--user 0` runs the server as root, as earlier images did. The image sets `HOME=/home/bun`, so a root run still finds the baked DuckDB extensions.
|
|
117
158
|
|
package/dist/app/api-doc.yaml
CHANGED
|
@@ -2876,11 +2876,27 @@ components:
|
|
|
2876
2876
|
environments list as intended. Absent once any environment exists, including one created
|
|
2877
2877
|
at runtime through the API, and absent when a config was found but
|
|
2878
2878
|
lists no environments.
|
|
2879
|
+
initError:
|
|
2880
|
+
type: string
|
|
2881
|
+
readOnly: true
|
|
2882
|
+
description:
|
|
2883
|
+
Present only when initialization failed, and says why. Such a
|
|
2884
|
+
server stays up but never becomes ready, so operationalState stays
|
|
2885
|
+
initializing; without this field that reads as a server still
|
|
2886
|
+
starting. Typical causes are a config file the server cannot read
|
|
2887
|
+
or parse, and a server root it cannot write (where it creates
|
|
2888
|
+
publisher.db), such as a read-only root filesystem. A package or
|
|
2889
|
+
environment that fails to load is reported under loadErrors
|
|
2890
|
+
instead. Fix the cause and restart.
|
|
2879
2891
|
loadErrors:
|
|
2880
2892
|
type: array
|
|
2881
2893
|
readOnly: true
|
|
2882
2894
|
description:
|
|
2883
|
-
Configured packages and environments that did not load, and why
|
|
2895
|
+
Configured packages and environments that did not load, and why,
|
|
2896
|
+
including a package add through the API that failed on the
|
|
2897
|
+
server's side, carrying the same message the add was answered
|
|
2898
|
+
with (an entry cleared by a later successful add of that package,
|
|
2899
|
+
or by deleting it). A
|
|
2884
2900
|
load failure is not fatal to the server, so operationalState stays
|
|
2885
2901
|
serving and the affected packages are absent from environments,
|
|
2886
2902
|
unless the entry carries stale = true, in which case the package is
|
|
@@ -13058,9 +13058,54 @@ function logInternalFailure(summary, error, level = "error") {
|
|
|
13058
13058
|
}
|
|
13059
13059
|
});
|
|
13060
13060
|
}
|
|
13061
|
-
function
|
|
13061
|
+
function filesystemAccessFailure(error) {
|
|
13062
|
+
let current = error;
|
|
13063
|
+
for (let depth = 0;depth < 8 && current instanceof Error; depth++) {
|
|
13064
|
+
const errno = current;
|
|
13065
|
+
if (typeof errno.code === "string" && errno.code in FILESYSTEM_ACCESS_DESCRIPTIONS && typeof errno.syscall === "string") {
|
|
13066
|
+
return errno;
|
|
13067
|
+
}
|
|
13068
|
+
current = errno.cause;
|
|
13069
|
+
}
|
|
13070
|
+
return;
|
|
13071
|
+
}
|
|
13072
|
+
function describeFilesystemAccessFailure(errno) {
|
|
13073
|
+
const code = errno.code ?? "";
|
|
13074
|
+
const target = errno.path ? ` '${errno.path}'` : "";
|
|
13075
|
+
return `${code}: ${FILESYSTEM_ACCESS_DESCRIPTIONS[code] ?? code}, ${errno.syscall}${target}`;
|
|
13076
|
+
}
|
|
13077
|
+
function messageWithFilesystemCause(error) {
|
|
13078
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
13079
|
+
const access = filesystemAccessFailure(error);
|
|
13080
|
+
if (!access || message.includes(access.code ?? ""))
|
|
13081
|
+
return message;
|
|
13082
|
+
return `${message}: ${describeFilesystemAccessFailure(access)}`;
|
|
13083
|
+
}
|
|
13084
|
+
function errnoWireFields(error) {
|
|
13085
|
+
const { code, syscall, path } = error;
|
|
13086
|
+
if (typeof code !== "string")
|
|
13087
|
+
return;
|
|
13088
|
+
return {
|
|
13089
|
+
code,
|
|
13090
|
+
...typeof syscall === "string" ? { syscall } : {},
|
|
13091
|
+
...typeof path === "string" ? { path } : {}
|
|
13092
|
+
};
|
|
13093
|
+
}
|
|
13094
|
+
function internalErrorToHttpError(error, { log = true } = {}) {
|
|
13095
|
+
const logInternal = (...args) => {
|
|
13096
|
+
if (log)
|
|
13097
|
+
logInternalFailure(...args);
|
|
13098
|
+
};
|
|
13099
|
+
const access = filesystemAccessFailure(error);
|
|
13100
|
+
if (access) {
|
|
13101
|
+
logInternal("Filesystem access refused", error, "warn");
|
|
13102
|
+
return httpError(500, `The server cannot access a path it needs (${describeFilesystemAccessFailure(access)}). ` + `Give the user the server runs as access to it.`);
|
|
13103
|
+
}
|
|
13062
13104
|
if (error instanceof BadRequestError) {
|
|
13063
13105
|
return httpError(400, error.message);
|
|
13106
|
+
} else if (error instanceof ServerConfigurationError) {
|
|
13107
|
+
logInternal("Server configuration error", error, "warn");
|
|
13108
|
+
return httpError(500, error.message);
|
|
13064
13109
|
} else if (error instanceof FrozenConfigError) {
|
|
13065
13110
|
return httpError(403, error.message);
|
|
13066
13111
|
} else if (error instanceof AccessDeniedError) {
|
|
@@ -13106,7 +13151,7 @@ function internalErrorToHttpError(error) {
|
|
|
13106
13151
|
if (error.callerSafe) {
|
|
13107
13152
|
return httpError(502, error.message);
|
|
13108
13153
|
}
|
|
13109
|
-
|
|
13154
|
+
logInternal("Upstream connection error", error, "warn");
|
|
13110
13155
|
return httpError(502, GENERIC_UPSTREAM_MESSAGE);
|
|
13111
13156
|
} else if (error instanceof MaterializationNotFoundError) {
|
|
13112
13157
|
return httpError(404, error.message);
|
|
@@ -13117,7 +13162,7 @@ function internalErrorToHttpError(error) {
|
|
|
13117
13162
|
} else if (error instanceof WriteConflictError) {
|
|
13118
13163
|
return httpError(409, error.message);
|
|
13119
13164
|
} else if (error instanceof WriteRolledBackError) {
|
|
13120
|
-
|
|
13165
|
+
logInternal("Dashboard write rolled back", error, "warn");
|
|
13121
13166
|
return httpError(500, error.message);
|
|
13122
13167
|
} else if (error instanceof ServiceUnavailableError) {
|
|
13123
13168
|
return httpError(503, error.message);
|
|
@@ -13128,7 +13173,7 @@ function internalErrorToHttpError(error) {
|
|
|
13128
13173
|
} else if (error instanceof NotImplementedError) {
|
|
13129
13174
|
return httpError(501, error.message);
|
|
13130
13175
|
} else {
|
|
13131
|
-
|
|
13176
|
+
logInternal("Unhandled internal error", error);
|
|
13132
13177
|
return httpError(500, GENERIC_INTERNAL_MESSAGE);
|
|
13133
13178
|
}
|
|
13134
13179
|
}
|
|
@@ -13150,10 +13195,15 @@ function toQueryTextProblem(problem) {
|
|
|
13150
13195
|
...problem.at ? { at: { range: problem.at.range } } : {}
|
|
13151
13196
|
};
|
|
13152
13197
|
}
|
|
13153
|
-
var GENERIC_INTERNAL_MESSAGE = "Internal server error.", GENERIC_UPSTREAM_MESSAGE = "Upstream connection error.", MAX_LOGGED_DETAIL_CHARS = 2000, NotImplementedError, BadRequestError, InvalidArgumentError, CompileRefusedError, EnvironmentNotFoundError, PackageNotFoundError, ModelNotFoundError, DashboardNotFoundError, ConnectionNotFoundError, TableNotFoundError, ConnectionError, DestinationNotFoundError, ConnectionAuthError, UnsupportedCatalogFormatError, ModelCompilationError, PackageManifestError, MaterializationEligibilityError, PublisherConfigError, FrozenConfigError, AccessDeniedError, QueryCompileError, NotQueryableError, OffSurfaceError, MaterializationNotFoundError, MaterializationConflictError, WriteConflictError, WriteRolledBackError, InvalidStateTransitionError, ServiceUnavailableError, PayloadTooLargeError, ResponseUnserializableError, QueryTimeoutError;
|
|
13198
|
+
var GENERIC_INTERNAL_MESSAGE = "Internal server error.", GENERIC_UPSTREAM_MESSAGE = "Upstream connection error.", MAX_LOGGED_DETAIL_CHARS = 2000, FILESYSTEM_ACCESS_DESCRIPTIONS, NotImplementedError, BadRequestError, InvalidArgumentError, CompileRefusedError, EnvironmentNotFoundError, PackageNotFoundError, ModelNotFoundError, DashboardNotFoundError, ConnectionNotFoundError, TableNotFoundError, ConnectionError, DestinationNotFoundError, ConnectionAuthError, UnsupportedCatalogFormatError, ModelCompilationError, PackageManifestError, MaterializationEligibilityError, PublisherConfigError, ServerConfigurationError, FrozenConfigError, AccessDeniedError, QueryCompileError, NotQueryableError, OffSurfaceError, MaterializationNotFoundError, MaterializationConflictError, WriteConflictError, WriteRolledBackError, InvalidStateTransitionError, ServiceUnavailableError, PayloadTooLargeError, ResponseUnserializableError, QueryTimeoutError;
|
|
13154
13199
|
var init_errors = __esm(() => {
|
|
13155
13200
|
init_constants();
|
|
13156
13201
|
init_logger();
|
|
13202
|
+
FILESYSTEM_ACCESS_DESCRIPTIONS = {
|
|
13203
|
+
EACCES: "permission denied",
|
|
13204
|
+
EPERM: "operation not permitted",
|
|
13205
|
+
EROFS: "read-only file system"
|
|
13206
|
+
};
|
|
13157
13207
|
NotImplementedError = class NotImplementedError extends Error {
|
|
13158
13208
|
constructor(message) {
|
|
13159
13209
|
super(message);
|
|
@@ -13174,8 +13224,8 @@ var init_errors = __esm(() => {
|
|
|
13174
13224
|
}
|
|
13175
13225
|
};
|
|
13176
13226
|
PackageNotFoundError = class PackageNotFoundError extends Error {
|
|
13177
|
-
constructor(message) {
|
|
13178
|
-
super(message);
|
|
13227
|
+
constructor(message, options) {
|
|
13228
|
+
super(message, options);
|
|
13179
13229
|
}
|
|
13180
13230
|
};
|
|
13181
13231
|
ModelNotFoundError = class ModelNotFoundError extends Error {
|
|
@@ -13246,6 +13296,12 @@ var init_errors = __esm(() => {
|
|
|
13246
13296
|
this.cause = cause;
|
|
13247
13297
|
}
|
|
13248
13298
|
};
|
|
13299
|
+
ServerConfigurationError = class ServerConfigurationError extends Error {
|
|
13300
|
+
constructor(message) {
|
|
13301
|
+
super(message);
|
|
13302
|
+
this.name = "ServerConfigurationError";
|
|
13303
|
+
}
|
|
13304
|
+
};
|
|
13249
13305
|
FrozenConfigError = class FrozenConfigError extends Error {
|
|
13250
13306
|
constructor(message = `Publisher config can't be updated when ${PUBLISHER_CONFIG_NAME} has { "frozenConfig": true }`) {
|
|
13251
13307
|
super(message);
|
|
@@ -13303,8 +13359,8 @@ var init_errors = __esm(() => {
|
|
|
13303
13359
|
}
|
|
13304
13360
|
};
|
|
13305
13361
|
ServiceUnavailableError = class ServiceUnavailableError extends Error {
|
|
13306
|
-
constructor(message) {
|
|
13307
|
-
super(message);
|
|
13362
|
+
constructor(message, options) {
|
|
13363
|
+
super(message, options);
|
|
13308
13364
|
}
|
|
13309
13365
|
};
|
|
13310
13366
|
PayloadTooLargeError = class PayloadTooLargeError extends Error {
|
|
@@ -13723,6 +13779,76 @@ var init_data_styles = __esm(() => {
|
|
|
13723
13779
|
init_logger();
|
|
13724
13780
|
});
|
|
13725
13781
|
|
|
13782
|
+
// src/package_load/error_wire.ts
|
|
13783
|
+
import { MalloyError as MalloyError2 } from "@malloydata/malloy";
|
|
13784
|
+
function serializeError(error) {
|
|
13785
|
+
const serialized = serializeErrorShape(error);
|
|
13786
|
+
const errno = error instanceof Error ? errnoWireFields(error) : undefined;
|
|
13787
|
+
return errno ? { ...serialized, errno } : serialized;
|
|
13788
|
+
}
|
|
13789
|
+
function serializeErrorShape(error) {
|
|
13790
|
+
if (error instanceof MalloyError2) {
|
|
13791
|
+
return {
|
|
13792
|
+
name: error.name,
|
|
13793
|
+
message: error.message,
|
|
13794
|
+
stack: error.stack,
|
|
13795
|
+
malloyProblems: error.problems,
|
|
13796
|
+
isCompilationError: true
|
|
13797
|
+
};
|
|
13798
|
+
}
|
|
13799
|
+
if (error instanceof ModelCompilationError) {
|
|
13800
|
+
return {
|
|
13801
|
+
name: error.name,
|
|
13802
|
+
message: error.message,
|
|
13803
|
+
stack: error.stack,
|
|
13804
|
+
isCompilationError: true
|
|
13805
|
+
};
|
|
13806
|
+
}
|
|
13807
|
+
if (error instanceof PackageManifestError) {
|
|
13808
|
+
return {
|
|
13809
|
+
name: error.name,
|
|
13810
|
+
message: error.message,
|
|
13811
|
+
stack: error.stack,
|
|
13812
|
+
isManifestError: true
|
|
13813
|
+
};
|
|
13814
|
+
}
|
|
13815
|
+
if (error instanceof Error) {
|
|
13816
|
+
return {
|
|
13817
|
+
name: error.name,
|
|
13818
|
+
message: error.message,
|
|
13819
|
+
stack: error.stack
|
|
13820
|
+
};
|
|
13821
|
+
}
|
|
13822
|
+
return { name: "Error", message: String(error) };
|
|
13823
|
+
}
|
|
13824
|
+
function deserializeError(serialized) {
|
|
13825
|
+
const err = new Error(serialized.message);
|
|
13826
|
+
err.name = serialized.name;
|
|
13827
|
+
if (serialized.stack)
|
|
13828
|
+
err.stack = serialized.stack;
|
|
13829
|
+
if (serialized.errno)
|
|
13830
|
+
Object.assign(err, serialized.errno);
|
|
13831
|
+
if (serialized.malloyProblems) {
|
|
13832
|
+
err.problems = serialized.malloyProblems;
|
|
13833
|
+
}
|
|
13834
|
+
if (serialized.isCompilationError) {
|
|
13835
|
+
const wrapped = new ModelCompilationError(err);
|
|
13836
|
+
if (serialized.stack)
|
|
13837
|
+
wrapped.stack = serialized.stack;
|
|
13838
|
+
return wrapped;
|
|
13839
|
+
}
|
|
13840
|
+
if (serialized.isManifestError) {
|
|
13841
|
+
const manifestError = new PackageManifestError(serialized.message);
|
|
13842
|
+
if (serialized.stack)
|
|
13843
|
+
manifestError.stack = serialized.stack;
|
|
13844
|
+
return manifestError;
|
|
13845
|
+
}
|
|
13846
|
+
return err;
|
|
13847
|
+
}
|
|
13848
|
+
var init_error_wire = __esm(() => {
|
|
13849
|
+
init_errors();
|
|
13850
|
+
});
|
|
13851
|
+
|
|
13726
13852
|
// src/service/annotations.ts
|
|
13727
13853
|
import { Annotations } from "@malloydata/malloy";
|
|
13728
13854
|
function isReservedRoute(route) {
|
|
@@ -23935,6 +24061,7 @@ init_constants();
|
|
|
23935
24061
|
init_authorize_metrics();
|
|
23936
24062
|
init_data_styles();
|
|
23937
24063
|
init_errors();
|
|
24064
|
+
init_error_wire();
|
|
23938
24065
|
init_authorize();
|
|
23939
24066
|
init_gate_classification();
|
|
23940
24067
|
init_gate_dimension();
|
|
@@ -23943,7 +24070,6 @@ import {
|
|
|
23943
24070
|
contextOverlay,
|
|
23944
24071
|
isSourceDef as isSourceDef7,
|
|
23945
24072
|
MalloyConfig,
|
|
23946
|
-
MalloyError as MalloyError2,
|
|
23947
24073
|
modelDefToModelInfo as modelDefToModelInfo2,
|
|
23948
24074
|
Runtime
|
|
23949
24075
|
} from "@malloydata/malloy";
|
|
@@ -24722,48 +24848,6 @@ async function loadPackage(job) {
|
|
|
24722
24848
|
}
|
|
24723
24849
|
};
|
|
24724
24850
|
}
|
|
24725
|
-
function serializeError(error) {
|
|
24726
|
-
if (error instanceof MalloyError2) {
|
|
24727
|
-
return {
|
|
24728
|
-
name: error.name,
|
|
24729
|
-
message: error.message,
|
|
24730
|
-
stack: error.stack,
|
|
24731
|
-
malloyProblems: error.problems,
|
|
24732
|
-
isCompilationError: true
|
|
24733
|
-
};
|
|
24734
|
-
}
|
|
24735
|
-
if (error instanceof ModelCompilationError) {
|
|
24736
|
-
return {
|
|
24737
|
-
name: error.name,
|
|
24738
|
-
message: error.message,
|
|
24739
|
-
stack: error.stack,
|
|
24740
|
-
isCompilationError: true
|
|
24741
|
-
};
|
|
24742
|
-
}
|
|
24743
|
-
if (error instanceof PackageManifestError) {
|
|
24744
|
-
return {
|
|
24745
|
-
name: error.name,
|
|
24746
|
-
message: error.message,
|
|
24747
|
-
stack: error.stack,
|
|
24748
|
-
isManifestError: true
|
|
24749
|
-
};
|
|
24750
|
-
}
|
|
24751
|
-
if (error instanceof Error) {
|
|
24752
|
-
return {
|
|
24753
|
-
name: error.name,
|
|
24754
|
-
message: error.message,
|
|
24755
|
-
stack: error.stack
|
|
24756
|
-
};
|
|
24757
|
-
}
|
|
24758
|
-
return { name: "Error", message: String(error) };
|
|
24759
|
-
}
|
|
24760
|
-
function deserializeError(serialized) {
|
|
24761
|
-
const err = new Error(serialized.message);
|
|
24762
|
-
err.name = serialized.name;
|
|
24763
|
-
if (serialized.stack)
|
|
24764
|
-
err.stack = serialized.stack;
|
|
24765
|
-
return err;
|
|
24766
|
-
}
|
|
24767
24851
|
var shuttingDown = false;
|
|
24768
24852
|
var inFlightJobs = new Set;
|
|
24769
24853
|
port.on("message", (message) => {
|