Skip to content

Commit

Permalink
better config; manifest.extensions now lists individual extensions on…
Browse files Browse the repository at this point in the history
…ce only, with one reference per platform
  • Loading branch information
Fil committed Oct 21, 2024
1 parent 4f58100 commit a8cfdcd
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 36 deletions.
5 changes: 2 additions & 3 deletions src/client/stdlib/duckdb.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ const candidates = {
})
};
const bundle = await duckdb.selectBundle(candidates);
const activeBundle = manifest.bundles.find((key) => bundle.mainModule === candidates[key].mainModule);
const extensions = manifest.extensions.filter(([, {bundle}]) => bundle === activeBundle);
const activePlatform = manifest.bundles.find((key) => bundle.mainModule === candidates[key].mainModule);

const logger = new duckdb.ConsoleLogger(duckdb.LogLevel.WARNING);

Expand Down Expand Up @@ -196,7 +195,7 @@ async function registerExtensions(db, {load}) {
const connection = await db.connect();
try {
await Promise.all(
extensions.map(([name, {ref, load: l}]) =>
manifest.extensions.map(([name, {[activePlatform]: ref, load: l}]) =>
connection
.query(`INSTALL ${name} FROM '${import.meta.resolve(`../..${ref}`)}'`)
.then(() => (load ? load.includes(name) : l) && connection.query(`LOAD ${name}`))
Expand Down
47 changes: 30 additions & 17 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,8 @@ export interface SearchConfigSpec {
}

export interface DuckDBConfig {
install: string[];
load: string[];
source: {[name: string]: string};
bundles: string[];
extensions: {[name: string]: {install?: false; load: boolean; source: string}};
}

export interface Config {
Expand Down Expand Up @@ -500,23 +498,38 @@ export function stringOrNull(spec: unknown): string | null {
return spec == null || spec === false ? null : String(spec);
}

function duckDBExtensionSource(source?: string): string {
return source === undefined || source === "core"
? "https://extensions.duckdb.org"
: source === "community"
? "https://community-extensions.duckdb.org"
: (source = String(source)).startsWith("https://")
? source
: (() => {
throw new Error(`Unsupported DuckDB extension source ${source}`);
})();
}

function normalizeDuckDB(spec: unknown): DuckDBConfig {
const install = spec?.["install"] ?? ["json", "parquet"];
const load = spec?.["load"] ?? [];
const source = new Map(Object.entries(spec?.["source"] ?? {}));
const extensions = spec?.["extensions"] ?? {json: {load: false}, parquet: {load: false}};
return {
bundles: ["eh", "mvp"],
install,
load: load.filter((name: string) => install.includes(name)),
source: Object.fromEntries(
install.map((name: string) => {
let href = source.get(name) ?? "core";
if (href === "core") href = "https://extensions.duckdb.org";
else if (href === "community") href = "https://community-extensions.duckdb.org";
if (!href?.["startsWith"]?.("https://"))
throw new Error(`unknown source for duckdb extension ${name}: ${href}`);
return [name, href];
})
extensions: Object.fromEntries(
Array.from(Object.entries(extensions), ([key, config]) => {
return [
key,
!config
? null
: config === true
? {load: true, source: duckDBExtensionSource()}
: config === false
? {install: false}
: {
source: duckDBExtensionSource(config["source"]),
load: config["load"] === undefined ? true : Boolean(config["load"])
}
];
}).filter(([, config]) => config !== null)
)
};
}
38 changes: 25 additions & 13 deletions src/duckdb.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {existsSync} from "node:fs";
import {mkdir, writeFile} from "node:fs/promises";
import {dirname, join} from "node:path/posix";
import {cross} from "d3-array";
import type {DuckDBConfig} from "./config.js";
import {faint} from "./tty.js";

Expand All @@ -10,25 +9,38 @@ const downloadRequests = new Map<string, Promise<string>>();
export const DUCKDBWASMVERSION = "1.29.0";
export const DUCKDBVERSION = "1.1.1";

async function getDuckDBExtension(root, platform, source, name, aliases) {
let ext = await resolveDuckDBExtension(root, platform, source, name);
if (aliases?.has(ext)) ext = aliases.get(ext)!;
return dirname(dirname(dirname(ext)));
}

export async function getDuckDBManifest(
duckdb: DuckDBConfig,
{root, aliases}: {root: string; aliases?: Map<string, string>}
) {
return {
bundles: duckdb.bundles,
extensions: await Promise.all(
cross(duckdb.bundles, duckdb.install).map(async ([p, name]) => {
let ext = await resolveDuckDBExtension(root, p, duckdb.source[name], name);
if (aliases?.has(ext)) ext = aliases.get(ext)!;
return [
name,
{
ref: dirname(dirname(dirname(ext))),
load: duckdb.load.includes(name),
bundle: p
}
];
})
Array.from(Object.entries(duckdb.extensions), ([name, {install, load, source}]) =>
(async () => {
return [
name,
{
install,
load,
...Object.fromEntries(
await Promise.all(
duckdb.bundles.map(async (platform) => [
platform,
await getDuckDBExtension(root, platform, source, name, aliases)
])
)
)
}
];
})()
)
)
};
}
Expand Down
6 changes: 3 additions & 3 deletions src/libraries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ export function getImplicitDownloads(imports: Iterable<string>, duckdb?: DuckDBC
implicits.add("npm:@duckdb/duckdb-wasm/dist/duckdb-eh.wasm");
implicits.add("npm:@duckdb/duckdb-wasm/dist/duckdb-browser-eh.worker.js");
if (!duckdb) throw new Error("Implementation error: missing duckdb configuration");
for (const p of duckdb.bundles) {
for (const name of duckdb.install) {
implicits.add(`duckdb:${p},${name},${duckdb.source[name]}`);
for (const [name, {source}] of Object.entries(duckdb.extensions)) {
for (const platform of duckdb.bundles) {
implicits.add(`duckdb:${platform},${name},${source}`);
}
}
}
Expand Down

0 comments on commit a8cfdcd

Please sign in to comment.