@malloy-publisher/server 0.0.203 → 0.0.204
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 +17 -0
- package/dist/app/assets/{EnvironmentPage-BVQ7glKP.js → EnvironmentPage-CX06cjOF.js} +1 -1
- package/dist/app/assets/HomePage-CNFt_eUU.js +1 -0
- package/dist/app/assets/{MainPage-bYOWcgDP.js → MainPage-nUJ9YatG.js} +1 -1
- package/dist/app/assets/{PackagePage-N1ZBNJul.js → MaterializationsPage-B5goxVXW.js} +1 -1
- package/dist/app/assets/{ModelPage-DT0gjNy1.js → ModelPage-Ba7Xh4lL.js} +1 -1
- package/dist/app/assets/PackagePage-BaEVdEAG.js +1 -0
- package/dist/app/assets/{RouteError-_J-EBz7W.js → RouteError-BShQjZio.js} +1 -1
- package/dist/app/assets/{WorkbookPage-Bjs9Nm-_.js → WorkbookPage-CBn6ZjJW.js} +1 -1
- package/dist/app/assets/{core-BPLlx5VM.es-C2ARtwWI.js → core-DECXYL4E.es-OaRfXwuQ.js} +1 -1
- package/dist/app/assets/{index-CqUWJELr.js → index-BLfPC1gy.js} +2 -2
- package/dist/app/assets/index-DqiJ0bWp.js +455 -0
- package/dist/app/assets/index-Dy3YhAZQ.js +1812 -0
- package/dist/app/assets/index.umd-DAN9K8yC.js +2469 -0
- package/dist/app/index.html +1 -1
- package/dist/package_load_worker.mjs +392 -67
- package/dist/server.mjs +415 -152
- package/package.json +11 -11
- package/src/ducklake_version.spec.ts +43 -0
- package/src/ducklake_version.ts +26 -0
- package/src/errors.ts +18 -1
- package/src/package_load/package_load_pool.ts +0 -5
- package/src/package_load/package_load_worker.ts +41 -99
- package/src/package_load/protocol.ts +1 -7
- package/src/service/annotations.spec.ts +118 -0
- package/src/service/annotations.ts +91 -0
- package/src/service/authorize.spec.ts +132 -0
- package/src/service/authorize.ts +241 -0
- package/src/service/authorize_integration.spec.ts +838 -0
- package/src/service/connection.ts +1 -1
- package/src/service/environment.ts +4 -4
- package/src/service/filter.spec.ts +14 -3
- package/src/service/filter.ts +5 -1
- package/src/service/filter_bypass.spec.ts +418 -0
- package/src/service/given.ts +37 -12
- package/src/service/givens_integration.spec.ts +34 -7
- package/src/service/materialization_service.ts +25 -20
- package/src/service/materialized_table_gc.spec.ts +6 -5
- package/src/service/materialized_table_gc.ts +2 -50
- package/src/service/model.spec.ts +203 -8
- package/src/service/model.ts +305 -155
- package/src/service/package_worker_path.spec.ts +113 -0
- package/src/service/quoting.ts +0 -20
- package/src/service/restricted_mode.spec.ts +299 -0
- package/src/service/source_extraction.ts +226 -0
- package/src/storage/StorageManager.ts +73 -0
- package/dist/app/assets/HomePage-D9drXoZX.js +0 -1
- package/dist/app/assets/index-BeNwIeYQ.js +0 -454
- package/dist/app/assets/index-Dx7qi2LO.js +0 -1803
- package/dist/app/assets/index.umd-BXm2lnUO.js +0 -1145
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { Mutex } from "async-mutex";
|
|
2
2
|
import * as crypto from "crypto";
|
|
3
|
+
import {
|
|
4
|
+
isCatalogVersionSupported,
|
|
5
|
+
SUPPORTED_CATALOG_VERSIONS,
|
|
6
|
+
} from "../ducklake_version";
|
|
3
7
|
import { ConnectionAuthError } from "../errors";
|
|
4
8
|
import { logger } from "../logger";
|
|
5
9
|
import {
|
|
@@ -64,6 +68,53 @@ function catalogNameForConfig(c: DuckLakeManifestConfig): string {
|
|
|
64
68
|
return `manifest_lake_${hash}`;
|
|
65
69
|
}
|
|
66
70
|
|
|
71
|
+
// Read the catalog's recorded DuckLake format version from its
|
|
72
|
+
// `ducklake_metadata` table via a plain postgres ATTACH (does NOT invoke
|
|
73
|
+
// the DuckLake extension on the catalog). Returns the version string on
|
|
74
|
+
// success, or `undefined` on any failure (missing table, query timeout,
|
|
75
|
+
// connect failure) so the main ATTACH path stays the source of truth for
|
|
76
|
+
// unrelated errors. Only meaningful for postgres-backed catalogs; the
|
|
77
|
+
// caller must guard with `isPostgres`.
|
|
78
|
+
async function readDuckLakeCatalogVersion(
|
|
79
|
+
connection: DuckDBConnection,
|
|
80
|
+
catalogUrl: string,
|
|
81
|
+
catalogName: string,
|
|
82
|
+
): Promise<string | undefined> {
|
|
83
|
+
if (!catalogUrl.startsWith("postgres:")) {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
const pgConnString = catalogUrl.slice("postgres:".length);
|
|
87
|
+
const tempDb = `${catalogName}_preflight`;
|
|
88
|
+
const escaped = escapeSQL(pgConnString);
|
|
89
|
+
try {
|
|
90
|
+
await connection.run(
|
|
91
|
+
`ATTACH '${escaped}' AS ${tempDb} (TYPE postgres, READ_ONLY);`,
|
|
92
|
+
);
|
|
93
|
+
const rows = await connection.all<{ value: string }>(
|
|
94
|
+
`SELECT value FROM ${tempDb}.ducklake_metadata WHERE key = 'version' LIMIT 1;`,
|
|
95
|
+
);
|
|
96
|
+
const value = rows[0]?.value;
|
|
97
|
+
return typeof value === "string" ? value : undefined;
|
|
98
|
+
} catch (error) {
|
|
99
|
+
logger.warn(
|
|
100
|
+
"DuckLake catalog version preflight failed; falling back to ATTACH",
|
|
101
|
+
{
|
|
102
|
+
catalogName,
|
|
103
|
+
error: redactPgSecrets(
|
|
104
|
+
error instanceof Error ? error.message : String(error),
|
|
105
|
+
),
|
|
106
|
+
},
|
|
107
|
+
);
|
|
108
|
+
return undefined;
|
|
109
|
+
} finally {
|
|
110
|
+
try {
|
|
111
|
+
await connection.run(`DETACH ${tempDb};`);
|
|
112
|
+
} catch {
|
|
113
|
+
// ATTACH may have failed, so DETACH may have nothing to do.
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
67
118
|
/**
|
|
68
119
|
* Manages the storage backend (DuckDB, Postgres, etc.) and per-environment
|
|
69
120
|
* manifest stores. Environments without `materializationStorage` config use
|
|
@@ -222,6 +273,28 @@ export class StorageManager {
|
|
|
222
273
|
await connection.run("INSTALL httpfs; LOAD httpfs;");
|
|
223
274
|
}
|
|
224
275
|
|
|
276
|
+
// Preflight: read the catalog's recorded format version via the
|
|
277
|
+
// postgres extension (not DuckLake) and fail fast with a non-retryable
|
|
278
|
+
// 422 if the baked DuckLake extension can't read it. Without this,
|
|
279
|
+
// an unsupported catalog would surface as a generic DuckDB error
|
|
280
|
+
// from the ATTACH below, which retry loops misclassify as transient.
|
|
281
|
+
if (isPostgres) {
|
|
282
|
+
const catalogVersion = await readDuckLakeCatalogVersion(
|
|
283
|
+
connection,
|
|
284
|
+
catalogUrl,
|
|
285
|
+
catalogName,
|
|
286
|
+
);
|
|
287
|
+
if (catalogVersion && !isCatalogVersionSupported(catalogVersion)) {
|
|
288
|
+
const supportedMax =
|
|
289
|
+
SUPPORTED_CATALOG_VERSIONS[
|
|
290
|
+
SUPPORTED_CATALOG_VERSIONS.length - 1
|
|
291
|
+
];
|
|
292
|
+
throw new ConnectionAuthError(
|
|
293
|
+
`DuckLake catalog version ${catalogVersion} is newer than this Publisher's extension supports (max ${supportedMax}). Upgrade the Publisher image or downgrade the catalog.`,
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
225
298
|
let attachCmd = `ATTACH 'ducklake:${escapedCatalogUrl}' AS ${catalogName}`;
|
|
226
299
|
const attachOpts: string[] = [
|
|
227
300
|
`DATA_PATH '${escapedDataPath}'`,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{T as t,j as o,A as a}from"./index-BeNwIeYQ.js";function s(){const n=t();return o.jsx(a,{onClickEnvironment:n})}export{s as default};
|