@observablehq/notebook-kit 1.0.1 → 1.1.0-rc.2

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.
Files changed (50) hide show
  1. package/dist/bin/build.js +7 -0
  2. package/dist/bin/download.js +15 -19
  3. package/dist/package.json +24 -1
  4. package/dist/src/databases/duckdb.d.ts +2 -0
  5. package/dist/src/databases/duckdb.js +67 -0
  6. package/dist/src/databases/index.d.ts +36 -0
  7. package/dist/src/databases/index.js +15 -0
  8. package/dist/src/databases/options.d.ts +3 -0
  9. package/dist/src/databases/options.js +6 -0
  10. package/dist/src/databases/postgres.d.ts +2 -0
  11. package/dist/src/databases/postgres.js +95 -0
  12. package/dist/src/databases/snowflake.d.ts +2 -0
  13. package/dist/src/databases/snowflake.js +102 -0
  14. package/dist/src/javascript/imports/npm.js +2 -0
  15. package/dist/src/javascript/observable.js +24 -3
  16. package/dist/src/javascript/template.d.ts +3 -0
  17. package/dist/src/javascript/template.js +17 -1
  18. package/dist/src/javascript/transpile.d.ts +4 -2
  19. package/dist/src/javascript/transpile.js +30 -11
  20. package/dist/src/javascript/transpile.test.js +16 -0
  21. package/dist/src/lib/error.d.ts +6 -0
  22. package/dist/src/lib/error.js +6 -0
  23. package/dist/src/lib/notebook.d.ts +11 -1
  24. package/dist/src/lib/notebook.js +10 -3
  25. package/dist/src/lib/notebook.test.js +10 -2
  26. package/dist/src/lib/serialize.d.ts +3 -1
  27. package/dist/src/lib/serialize.js +13 -4
  28. package/dist/src/lib/serialize.test.js +10 -3
  29. package/dist/src/runtime/define.d.ts +2 -2
  30. package/dist/src/runtime/define.js +2 -2
  31. package/dist/src/runtime/display.d.ts +2 -0
  32. package/dist/src/runtime/display.js +5 -1
  33. package/dist/src/runtime/index.d.ts +100 -1
  34. package/dist/src/runtime/index.js +29 -3
  35. package/dist/src/runtime/stdlib/databaseClient.d.ts +46 -0
  36. package/dist/src/runtime/stdlib/databaseClient.js +80 -0
  37. package/dist/src/runtime/stdlib/duckdb.js +4 -4
  38. package/dist/src/runtime/stdlib/fileAttachment.d.ts +38 -11
  39. package/dist/src/runtime/stdlib/fileAttachment.js +21 -10
  40. package/dist/src/runtime/stdlib/generators/input.d.ts +1 -1
  41. package/dist/src/runtime/stdlib/index.d.ts +43 -6
  42. package/dist/src/runtime/stdlib/index.js +5 -5
  43. package/dist/src/styles/global.css +1 -1
  44. package/dist/src/templates/default.html +18 -18
  45. package/dist/src/vite/config.js +5 -2
  46. package/dist/src/vite/observable.d.ts +25 -6
  47. package/dist/src/vite/observable.js +58 -15
  48. package/package.json +24 -1
  49. package/dist/src/runtime/stdlib/sql.d.ts +0 -5
  50. package/dist/src/runtime/stdlib/sql.js +0 -5
@@ -1,8 +1,7 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  const files = new Map();
3
- export function FileAttachment(name, base = document.baseURI) {
4
- if (new.target !== undefined)
5
- throw new TypeError("FileAttachment is not a constructor");
3
+ // TODO Enforce that files have been registered; throw error if not found.
4
+ export const FileAttachment = (name, base = document.baseURI) => {
6
5
  const href = new URL(name, base).href;
7
6
  let file = files.get(href);
8
7
  if (!file) {
@@ -10,8 +9,20 @@ export function FileAttachment(name, base = document.baseURI) {
10
9
  files.set(href, file);
11
10
  }
12
11
  return file;
12
+ };
13
+ export function registerFile(name, info, base = location.href) {
14
+ const href = new URL(name, base).href;
15
+ if (info == null) {
16
+ files.delete(href);
17
+ }
18
+ else {
19
+ const { path, mimeType, lastModified, size } = info;
20
+ const file = new FileAttachmentImpl(new URL(path, base).href, name.split("/").pop(), mimeType, lastModified, size);
21
+ files.set(href, file);
22
+ return file;
23
+ }
13
24
  }
14
- async function remote_fetch(file) {
25
+ async function fetchFile(file) {
15
26
  const response = await fetch(file.href);
16
27
  if (!response.ok)
17
28
  throw new Error(`Unable to load file: ${file.name}`);
@@ -54,21 +65,21 @@ export class AbstractFile {
54
65
  return this.href;
55
66
  }
56
67
  async blob() {
57
- return (await remote_fetch(this)).blob();
68
+ return (await fetchFile(this)).blob();
58
69
  }
59
70
  async arrayBuffer() {
60
- return (await remote_fetch(this)).arrayBuffer();
71
+ return (await fetchFile(this)).arrayBuffer();
61
72
  }
62
73
  async text(encoding) {
63
74
  return encoding === undefined
64
- ? (await remote_fetch(this)).text()
75
+ ? (await fetchFile(this)).text()
65
76
  : new TextDecoder(encoding).decode(await this.arrayBuffer());
66
77
  }
67
78
  async json() {
68
- return (await remote_fetch(this)).json();
79
+ return (await fetchFile(this)).json();
69
80
  }
70
81
  async stream() {
71
- return (await remote_fetch(this)).body;
82
+ return (await fetchFile(this)).body;
72
83
  }
73
84
  async dsv({ delimiter = ",", array = false, typed = false } = {}) {
74
85
  const [text, d3] = await Promise.all([this.text(), import("npm:d3-dsv")]);
@@ -95,7 +106,7 @@ export class AbstractFile {
95
106
  });
96
107
  }
97
108
  async arrow() {
98
- const [Arrow, response] = await Promise.all([import("npm:apache-arrow"), remote_fetch(this)]);
109
+ const [Arrow, response] = await Promise.all([import("npm:apache-arrow"), fetchFile(this)]);
99
110
  return Arrow.tableFromIPC(response);
100
111
  }
101
112
  async arquero(options) {
@@ -1 +1 @@
1
- export declare function input(element: Element): AsyncGenerator<string | number | boolean | string[] | Date | File | FileList | null, void, unknown>;
1
+ export declare function input(element: Element): AsyncGenerator<string | number | boolean | string[] | Date | FileList | File | null, void, unknown>;
@@ -1,10 +1,10 @@
1
- import { Mutable } from "./mutable.js";
2
- import * as Generators from "./generators/index.js";
3
- import { FileAttachment } from "./fileAttachment.js";
1
+ import { DatabaseClient } from "./databaseClient.js";
4
2
  import * as DOM from "./dom/index.js";
3
+ import { FileAttachment } from "./fileAttachment.js";
4
+ import * as Generators from "./generators/index.js";
5
+ import { Mutable } from "./mutable.js";
5
6
  import { Observer } from "./observer.js";
6
7
  import { require } from "./require.js";
7
- import { __sql } from "./sql.js";
8
8
  export declare const root: HTMLElement;
9
9
  export declare const library: {
10
10
  aapl: () => Promise<any>;
@@ -46,11 +46,48 @@ export declare const library: {
46
46
  vl: () => Promise<any>;
47
47
  now: () => AsyncGenerator<number, void, unknown>;
48
48
  width: () => AsyncGenerator<number, void, unknown>;
49
- FileAttachment: () => typeof FileAttachment;
49
+ DatabaseClient: () => {
50
+ (name: string, options?: import("./databaseClient.js").QueryOptionsSpec): DatabaseClient;
51
+ hash: (strings: string[], ...params: unknown[]) => Promise<string>;
52
+ revive: ({ rows, schema, date, ...meta }: import("../../databases/index.js").SerializableQueryResult) => import("./databaseClient.js").QueryResult;
53
+ prototype: {
54
+ readonly name: string;
55
+ readonly options: import("./databaseClient.js").QueryOptions;
56
+ sql(strings: string[], ...params: import("./databaseClient.js").QueryParam[]): Promise<import("./databaseClient.js").QueryResult>;
57
+ };
58
+ };
59
+ FileAttachment: () => {
60
+ (name: string, base?: string): FileAttachment;
61
+ prototype: {
62
+ href: string;
63
+ name: string;
64
+ mimeType: string;
65
+ lastModified: number | undefined;
66
+ size: number | undefined;
67
+ url(): Promise<string>;
68
+ blob(): Promise<Blob>;
69
+ arrayBuffer(): Promise<ArrayBuffer>;
70
+ text(encoding?: string): Promise<string>;
71
+ json(): Promise<any>;
72
+ stream(): Promise<ReadableStream<Uint8Array<ArrayBufferLike>>>;
73
+ dsv({ delimiter, array, typed }?: {
74
+ delimiter?: string | undefined;
75
+ array?: boolean | undefined;
76
+ typed?: boolean | undefined;
77
+ }): Promise<import("./fileAttachment.js").DsvResult>;
78
+ csv(options?: Omit<import("./fileAttachment.js").DsvOptions, "delimiter">): Promise<import("./fileAttachment.js").DsvResult>;
79
+ tsv(options?: Omit<import("./fileAttachment.js").DsvOptions, "delimiter">): Promise<import("./fileAttachment.js").DsvResult>;
80
+ image(props?: Partial<HTMLImageElement>): Promise<HTMLImageElement>;
81
+ arrow(): Promise<any>;
82
+ arquero(options?: any): Promise<any>;
83
+ parquet(): Promise<any>;
84
+ xml(mimeType?: DOMParserSupportedType): Promise<Document>;
85
+ html(): Promise<Document>;
86
+ };
87
+ };
50
88
  Generators: () => typeof Generators;
51
89
  Mutable: () => typeof Mutable;
52
90
  DOM: () => typeof DOM;
53
91
  require: () => typeof require;
54
- __sql: () => typeof __sql;
55
92
  __ojs_observer: () => () => Observer;
56
93
  };
@@ -1,22 +1,22 @@
1
- import { Mutable } from "./mutable.js";
2
- import * as Generators from "./generators/index.js";
3
- import { FileAttachment } from "./fileAttachment.js";
1
+ import { DatabaseClient } from "./databaseClient.js";
4
2
  import * as DOM from "./dom/index.js";
3
+ import { FileAttachment } from "./fileAttachment.js";
4
+ import * as Generators from "./generators/index.js";
5
+ import { Mutable } from "./mutable.js";
5
6
  import { Observer } from "./observer.js";
6
7
  import * as recommendedLibraries from "./recommendedLibraries.js";
7
8
  import { require } from "./require.js";
8
9
  import * as sampleDatasets from "./sampleDatasets.js";
9
- import { __sql } from "./sql.js";
10
10
  export const root = document.querySelector("main") ?? document.body;
11
11
  export const library = {
12
12
  now: () => Generators.now(),
13
13
  width: () => Generators.width(root),
14
+ DatabaseClient: () => DatabaseClient,
14
15
  FileAttachment: () => FileAttachment,
15
16
  Generators: () => Generators,
16
17
  Mutable: () => Mutable,
17
18
  DOM: () => DOM, // deprecated!
18
19
  require: () => require, // deprecated!
19
- __sql: () => __sql,
20
20
  __ojs_observer: () => () => new Observer(),
21
21
  ...recommendedLibraries,
22
22
  ...sampleDatasets
@@ -17,7 +17,7 @@ html {
17
17
  -moz-osx-font-smoothing: grayscale;
18
18
  background: var(--theme-background);
19
19
  color: var(--theme-foreground);
20
- margin-top: 16px;
20
+ margin: 16px 0;
21
21
  padding: 16px 24px;
22
22
  }
23
23
 
@@ -5,24 +5,24 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <style type="text/css">
7
7
  @import url("observable:styles/index.css");
8
- @import "@fontsource/spline-sans-mono/400.css";
9
- @import "@fontsource/spline-sans-mono/600.css";
10
- @import "@fontsource/spline-sans-mono/700.css";
11
- @import "@fontsource/spline-sans-mono/400-italic.css";
12
- @import "@fontsource/spline-sans-mono/600-italic.css";
13
- @import "@fontsource/spline-sans-mono/700-italic.css";
14
- @import "@fontsource/source-serif-4/400.css";
15
- @import "@fontsource/source-serif-4/700.css";
16
- @import "@fontsource/source-serif-4/400-italic.css";
17
- @import "@fontsource/source-serif-4/700-italic.css";
18
- @import "@fontsource/inter/400.css";
19
- @import "@fontsource/inter/500.css";
20
- @import "@fontsource/inter/600.css";
21
- @import "@fontsource/inter/700.css";
22
- @import "@fontsource/inter/400-italic.css";
23
- @import "@fontsource/inter/500-italic.css";
24
- @import "@fontsource/inter/600-italic.css";
25
- @import "@fontsource/inter/700-italic.css";
8
+ @import url("@fontsource/spline-sans-mono/400.css");
9
+ @import url("@fontsource/spline-sans-mono/600.css");
10
+ @import url("@fontsource/spline-sans-mono/700.css");
11
+ @import url("@fontsource/spline-sans-mono/400-italic.css");
12
+ @import url("@fontsource/spline-sans-mono/600-italic.css");
13
+ @import url("@fontsource/spline-sans-mono/700-italic.css");
14
+ @import url("@fontsource/source-serif-4/400.css");
15
+ @import url("@fontsource/source-serif-4/700.css");
16
+ @import url("@fontsource/source-serif-4/400-italic.css");
17
+ @import url("@fontsource/source-serif-4/700-italic.css");
18
+ @import url("@fontsource/inter/400.css");
19
+ @import url("@fontsource/inter/500.css");
20
+ @import url("@fontsource/inter/600.css");
21
+ @import url("@fontsource/inter/700.css");
22
+ @import url("@fontsource/inter/400-italic.css");
23
+ @import url("@fontsource/inter/500-italic.css");
24
+ @import url("@fontsource/inter/600-italic.css");
25
+ @import url("@fontsource/inter/700-italic.css");
26
26
  </style>
27
27
  </head>
28
28
  <body>
@@ -1,10 +1,12 @@
1
1
  import { dirname, resolve } from "node:path";
2
2
  import { fileURLToPath } from "node:url";
3
+ import { resolveNpmImport } from "../javascript/imports/npm.js";
3
4
  const __filename = fileURLToPath(import.meta.url);
4
5
  const __dirname = dirname(__filename);
5
6
  export function config() {
6
7
  return {
7
8
  base: "./",
9
+ appType: "mpa", // return 404 for missing pages
8
10
  esbuild: {
9
11
  supported: {
10
12
  "top-level-await": true
@@ -13,8 +15,9 @@ export function config() {
13
15
  resolve: {
14
16
  alias: [
15
17
  {
16
- find: /^npm:(.*)$/,
17
- replacement: "https://cdn.jsdelivr.net/npm/$1/+esm"
18
+ find: /^(npm:.*)$/,
19
+ replacement: "$1",
20
+ customResolver: resolveNpmImport
18
21
  },
19
22
  {
20
23
  find: /^jsr:(.*)$/,
@@ -1,12 +1,31 @@
1
- import type { PluginOption } from "vite";
1
+ import type { PluginOption, IndexHtmlTransformContext } from "vite";
2
+ import type { Notebook } from "../lib/notebook.js";
3
+ /**
4
+ * A function which performs a per-page transformation of the template HTML.
5
+ *
6
+ * @param source The source of the template (typically HTML).
7
+ * @param context The Vite plugin context.
8
+ * @returns The transformed template source HTML.
9
+ */
10
+ export type TemplateTransform = (source: string, context: IndexHtmlTransformContext) => string | Promise<string>;
11
+ /**
12
+ * A function which transforms the parsed notebook.
13
+ *
14
+ * @param notebook The current (parsed) notebook.
15
+ * @param context The Vite plugin context.
16
+ * @returns The transformed notebook.
17
+ */
18
+ export type NotebookTransform = (notebook: Notebook, context: IndexHtmlTransformContext) => Notebook | Promise<Notebook>;
2
19
  export interface ObservableOptions {
3
- /** The global window, for the default parser and serializer implementations. */
4
- window?: Pick<typeof globalThis, "DOMParser" | "XMLSerializer">;
20
+ /** The global window, for the default parser implementations. */
21
+ window?: Pick<typeof globalThis, "DOMParser">;
5
22
  /** The parser implementation; defaults to `new window.DOMParser()`. */
6
23
  parser?: DOMParser;
7
- /** The serializer implementation; defaults to `new window.XMLSerializer()`. */
8
- serializer?: XMLSerializer;
9
24
  /** The path to the page template; defaults to the default template. */
10
25
  template?: string;
26
+ /** An optional function which transforms the template HTML for the current page. */
27
+ transformTemplate?: TemplateTransform;
28
+ /** An optional function which transforms the notebook for the current page. */
29
+ transformNotebook?: NotebookTransform;
11
30
  }
12
- export declare function observable({ window, parser, serializer, template }?: ObservableOptions): PluginOption;
31
+ export declare function observable({ window, parser, template, transformTemplate, transformNotebook }?: ObservableOptions): PluginOption;
@@ -1,16 +1,20 @@
1
- import { existsSync } from "node:fs";
2
- import { readFile } from "node:fs/promises";
1
+ import { createReadStream, existsSync } from "node:fs";
2
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
3
+ import { json } from "node:stream/consumers";
3
4
  import { dirname, join, resolve } from "node:path";
4
5
  import { fileURLToPath } from "node:url";
5
6
  import { JSDOM } from "jsdom";
7
+ import { getDatabase, isDefaultDatabase } from "../databases/index.js";
8
+ import { isEnoent } from "../lib/error.js";
6
9
  import { deserialize } from "../lib/serialize.js";
7
10
  import { Sourcemap } from "../javascript/sourcemap.js";
8
11
  import { transpile } from "../javascript/transpile.js";
9
12
  import { parseTemplate } from "../javascript/template.js";
10
13
  import { collectAssets } from "../runtime/stdlib/assets.js";
14
+ import { DatabaseClient } from "../runtime/stdlib/databaseClient.js";
11
15
  import { highlight } from "../runtime/stdlib/highlight.js";
12
16
  import { MarkdownRenderer } from "../runtime/stdlib/md.js";
13
- export function observable({ window = new JSDOM().window, parser = new window.DOMParser(), serializer = new window.XMLSerializer(), template = fileURLToPath(import.meta.resolve("../templates/default.html")) } = {}) {
17
+ export function observable({ window = new JSDOM().window, parser = new window.DOMParser(), template = fileURLToPath(import.meta.resolve("../templates/default.html")), transformTemplate = (template) => template, transformNotebook = (notebook) => notebook } = {}) {
14
18
  return {
15
19
  name: "observable",
16
20
  buildStart() {
@@ -24,9 +28,9 @@ export function observable({ window = new JSDOM().window, parser = new window.DO
24
28
  transformIndexHtml: {
25
29
  order: "pre",
26
30
  async handler(input, context) {
27
- const notebook = deserialize(input, { parser });
28
- const tsource = await readFile(template, "utf-8");
29
- const document = parser.parseFromString(tsource, "text/html");
31
+ const notebook = await transformNotebook(deserialize(input, { parser }), context);
32
+ const templateHtml = await transformTemplate(await readFile(template, "utf-8"), context);
33
+ const document = parser.parseFromString(templateHtml, "text/html");
30
34
  const statics = new Set();
31
35
  const assets = new Set();
32
36
  const md = MarkdownRenderer({ document });
@@ -41,26 +45,64 @@ export function observable({ window = new JSDOM().window, parser = new window.DO
41
45
  let cells = document.querySelector("main");
42
46
  cells ?? (cells = document.body.appendChild(document.createElement("main")));
43
47
  for (const cell of notebook.cells) {
44
- const { id, mode, pinned, value } = cell;
48
+ const { id, mode, pinned, hidden, value } = cell;
45
49
  const contents = document.createDocumentFragment();
46
50
  const div = contents.appendChild(document.createElement("div"));
47
51
  div.id = `cell-${id}`;
48
52
  div.className = "observablehq observablehq--cell";
49
- if (mode === "md") {
53
+ if (mode === "md" && !hidden) {
50
54
  const template = parseTemplate(value);
51
- if (!template.expressions.length)
55
+ if (!template.expressions.length && !cell.output)
52
56
  statics.add(cell);
53
57
  const content = md([stripExpressions(template, value)]);
54
58
  const codes = content.querySelectorAll("code[class^=language-]");
55
59
  await Promise.all(Array.from(codes, highlight));
56
60
  div.appendChild(content);
57
61
  }
58
- else if (mode === "html") {
62
+ else if (mode === "html" && !hidden) {
59
63
  const template = parseTemplate(value);
60
- if (!template.expressions.length)
64
+ if (!template.expressions.length && !cell.output)
61
65
  statics.add(cell);
62
66
  div.innerHTML = stripExpressions(template, value);
63
67
  }
68
+ else if (mode === "sql" && cell.database && !cell.database.startsWith("var:")) {
69
+ const template = parseTemplate(value);
70
+ if (!template.expressions.length) {
71
+ const dir = dirname(context.filename);
72
+ const cacheDir = join(dir, ".observable", "cache");
73
+ const hash = await DatabaseClient.hash.call(null, [value]);
74
+ const cacheName = `${cell.database}-${hash}.json`;
75
+ const cachePath = join(cacheDir, cacheName);
76
+ if (!existsSync(cachePath)) {
77
+ let config;
78
+ try {
79
+ const configPath = join(dir, ".observable", "databases.json");
80
+ const configStream = createReadStream(configPath, "utf-8");
81
+ const configs = (await json(configStream));
82
+ config = configs[cell.database];
83
+ }
84
+ catch (error) {
85
+ if (!isEnoent(error))
86
+ throw error;
87
+ }
88
+ if (isDefaultDatabase(cell.database))
89
+ config ?? (config = { type: cell.database });
90
+ if (!config)
91
+ throw new Error(`database not found: ${cell.database}`);
92
+ try {
93
+ const database = await getDatabase(config, { cwd: dir });
94
+ const results = await database.call(null, [value]);
95
+ await mkdir(cacheDir, { recursive: true });
96
+ await writeFile(cachePath, JSON.stringify(results));
97
+ }
98
+ catch (error) {
99
+ console.error(error);
100
+ }
101
+ }
102
+ cell.mode = "js";
103
+ cell.value = `FileAttachment(${JSON.stringify(`.observable/cache/${cacheName}`)}).json().then(DatabaseClient.revive)${hidden ? "" : `.then(Inputs.table)${cell.output ? ".then(view)" : ""}`}`;
104
+ }
105
+ }
64
106
  collectAssets(assets, div);
65
107
  if (pinned) {
66
108
  const pre = contents.appendChild(document.createElement("pre"));
@@ -73,15 +115,16 @@ export function observable({ window = new JSDOM().window, parser = new window.DO
73
115
  }
74
116
  // Don’t error if assets are missing (matching Vite’s behavior).
75
117
  filterMissingAssets(assets, dirname(context.filename));
76
- const output = serializer.serializeToString(document);
118
+ const output = document.documentElement.outerHTML;
77
119
  const i = output.indexOf("</body>");
78
120
  if (!(i >= 0))
79
121
  throw new Error("body not found");
80
- return (output.slice(0, i) +
122
+ return (`<!doctype html>` +
123
+ output.slice(0, i) +
81
124
  `<style type="text/css">
82
125
  @import url("observable:styles/theme-${notebook.theme}.css");
83
126
  </style><script type="module">
84
- import {define} from "observable:runtime/define";${Array.from(assets)
127
+ import {define} from "observable:runtime";${Array.from(assets)
85
128
  .map((asset, i) => `
86
129
  import asset${i + 1} from ${JSON.stringify(`${asset}?url`)};`)
87
130
  .join("")}${assets.size > 0
@@ -96,7 +139,7 @@ ${Array.from(assets)
96
139
  ${notebook.cells
97
140
  .filter((cell) => !statics.has(cell))
98
141
  .map((cell) => {
99
- const transpiled = transpile(cell.value, cell.mode, { resolveFiles: true });
142
+ const transpiled = transpile(cell, { resolveFiles: true });
100
143
  return `
101
144
  define(
102
145
  {
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/observablehq/notebook-kit.git"
7
7
  },
8
- "version": "1.0.1",
8
+ "version": "1.1.0-rc.2",
9
9
  "type": "module",
10
10
  "scripts": {
11
11
  "test": "vitest",
@@ -27,6 +27,10 @@
27
27
  "types": "./dist/src/index.d.ts",
28
28
  "import": "./dist/src/index.js"
29
29
  },
30
+ "./databases": {
31
+ "types": "./dist/src/databases/index.d.ts",
32
+ "import": "./dist/src/databases/index.js"
33
+ },
30
34
  "./runtime": {
31
35
  "types": "./dist/src/runtime/index.d.ts",
32
36
  "import": "./dist/src/runtime/index.js"
@@ -59,15 +63,34 @@
59
63
  "vite": "^7.0.0"
60
64
  },
61
65
  "devDependencies": {
66
+ "@duckdb/node-api": "^1.3.2-alpha.26",
62
67
  "@eslint/js": "^9.29.0",
63
68
  "@types/jsdom": "^21.1.7",
64
69
  "@types/markdown-it": "^14.1.2",
65
70
  "eslint": "^9.29.0",
66
71
  "globals": "^16.2.0",
67
72
  "htl": "^0.3.1",
73
+ "postgres": "^3.4.7",
74
+ "snowflake-sdk": "^2.1.3",
68
75
  "tsx": "^4.20.3",
69
76
  "typescript": "^5.8.3",
70
77
  "typescript-eslint": "^8.35.0",
71
78
  "vitest": "^3.2.4"
79
+ },
80
+ "peerDependencies": {
81
+ "@duckdb/node-api": "^1.3.2-alpha.26",
82
+ "postgres": "^3.4.7",
83
+ "snowflake-sdk": "^2.1.3"
84
+ },
85
+ "peerDependenciesMeta": {
86
+ "@duckdb/node-api": {
87
+ "optional": true
88
+ },
89
+ "postgres": {
90
+ "optional": true
91
+ },
92
+ "snowflake-sdk": {
93
+ "optional": true
94
+ }
72
95
  }
73
96
  }
@@ -1,5 +0,0 @@
1
- type Template = (template: TemplateStringsArray, ...values: unknown[]) => Promise<unknown>;
2
- export declare function __sql(db: {
3
- sql: Template;
4
- }, render: (data: unknown) => unknown): Template;
5
- export {};
@@ -1,5 +0,0 @@
1
- export function __sql(db, render) {
2
- return (template, ...values) => {
3
- return db.sql.call(db, template, ...values).then(render);
4
- };
5
- }