diff --git a/.changeset/common-pears-drive.md b/.changeset/common-pears-drive.md index 7f85b20b8d59..be02b434fc62 100644 --- a/.changeset/common-pears-drive.md +++ b/.changeset/common-pears-drive.md @@ -11,7 +11,6 @@ '@astrojs/mdx': major '@astrojs/vue': major 'astro': major -'@astrojs/db': major --- Upgrade to Vite v8 diff --git a/.changeset/pre.json b/.changeset/pre.json index 82aaf2ec1396..645fd5adbf18 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -6,7 +6,6 @@ "@astrojs/prism": "4.0.1", "@astrojs/rss": "4.0.17", "create-astro": "5.0.3", - "@astrojs/db": "0.20.1", "@astrojs/alpinejs": "0.5.0", "@astrojs/cloudflare": "13.1.3", "@astrojs/markdoc": "1.0.2", diff --git a/.changeset/remove-db-cli-command.md b/.changeset/remove-db-cli-command.md new file mode 100644 index 000000000000..b86b7f705025 --- /dev/null +++ b/.changeset/remove-db-cli-command.md @@ -0,0 +1,7 @@ +--- +'astro': major +--- + +Removes the `astro db`, `astro login`, `astro logout`, `astro link`, and `astro init` CLI commands. + +The `@astrojs/db` package is now deprecated. We recommend using a database client (Drizzle, Kysely, etc.) directly instead. diff --git a/.github/renovate.json5 b/.github/renovate.json5 index c8708e4e8d17..20cf1aba758b 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -146,12 +146,6 @@ //#endregion //#region Standalone packages - { - "groupName": "@astrojs/db", - "matchManagers": ["npm"], - "matchUpdateTypes": ["minor", "patch"], - "matchFileNames": ["packages/db/**"] - }, { "groupName": "create-astro", "matchManagers": ["npm"], diff --git a/.prettierignore b/.prettierignore index cca3a0e0fe66..e900ff19a901 100644 --- a/.prettierignore +++ b/.prettierignore @@ -12,9 +12,6 @@ benchmark/results/ **/.vercel **/.vscode-test -# Short-term need to format -!packages/db/test/fixtures - # Directories .github .changeset diff --git a/README.md b/README.md index 32003cf0e6f8..6a291888555a 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,6 @@ Join us on [Discord](https://astro.build/chat) to meet other maintainers. We'll | [@astrojs/sitemap](packages/integrations/sitemap) | [![@astrojs/sitemap version](https://img.shields.io/npm/v/@astrojs/sitemap.svg?label=%20)](packages/integrations/sitemap/CHANGELOG.md) | | [@astrojs/alpinejs](packages/integrations/alpinejs) | [![@astrojs/alpinejs version](https://img.shields.io/npm/v/@astrojs/alpinejs.svg?label=%20)](packages/integrations/alpinejs/CHANGELOG.md) | | [@astrojs/mdx](packages/integrations/mdx) | [![@astrojs/mdx version](https://img.shields.io/npm/v/@astrojs/mdx.svg?label=%20)](packages/integrations/mdx/CHANGELOG.md) | -| [@astrojs/db](packages/db) | [![@astrojs/db version](https://img.shields.io/npm/v/@astrojs/db.svg?label=%20)](packages/db/CHANGELOG.md) | | [@astrojs/rss](packages/astro-rss) | [![@astrojs/rss version](https://img.shields.io/npm/v/@astrojs/rss.svg?label=%20)](packages/astro-rss/CHANGELOG.md) | | [@astrojs/netlify](packages/integrations/netlify) | [![@astrojs/netlify version](https://img.shields.io/npm/v/@astrojs/netlify.svg?label=%20)](packages/integrations/netlify/CHANGELOG.md) | | [@astrojs/check](packages/language-tools/astro-check) | [![astro-check version](https://img.shields.io/npm/v/@astrojs/check.svg?label=%20)](packages/language-tools/astro-check/CHANGELOG.md) | diff --git a/biome.jsonc b/biome.jsonc index 63a65b9fdd6d..e1842a360a33 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -176,7 +176,6 @@ }, { "includes": [ - "**/packages/db/**/cli/**/*.ts", "**/benchmark/**/*.js", "**/packages/astro/src/cli/**/*.ts", "**/packages/astro/bin/**/*.mjs" diff --git a/eslint.config.js b/eslint.config.js index 32e38f649d25..a92a65d0a74e 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -140,24 +140,6 @@ const configs = [ }, }, - { - files: ['packages/db/src/runtime/**/*.ts'], - rules: { - 'no-restricted-imports': 'off', - '@typescript-eslint/no-restricted-imports': [ - 'error', - { - patterns: [ - { - group: ['../core/*'], - allowTypeImports: true, - }, - ], - }, - ], - }, - }, - { files: [ 'packages/language-tools/ts-plugin/**/*', diff --git a/knip.js b/knip.js index a42bf17cbb46..7beb577b8e76 100644 --- a/knip.js +++ b/knip.js @@ -63,9 +63,6 @@ export default { entry: [srcEntry, dtsEntry, testEntry], ignoreUnresolved: ['#prism-loadLanguages'], }, - 'packages/db': { - entry: [srcEntry, dtsEntry, testEntry, 'test/types/**/*'], - }, 'packages/integrations/*': { entry: [srcEntry, dtsEntry, testEntry], }, diff --git a/package.json b/package.json index fa640e68062b..65ff50b55aea 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,6 @@ "@flue/runtime": "^0.8.0", "@types/node": "^22.10.6", "bgproc": "^0.2.0", - "esbuild": "0.25.5", "eslint": "^10.4.0", "eslint-plugin-regexp": "^3.1.0", "knip": "5.82.1", diff --git a/packages/astro/e2e/actions-blog.test.ts b/packages/astro/e2e/actions-blog.test.ts index 5a0efc5e070d..d63c91add872 100644 --- a/packages/astro/e2e/actions-blog.test.ts +++ b/packages/astro/e2e/actions-blog.test.ts @@ -1,3 +1,4 @@ +import { rmSync } from 'node:fs'; import { expect } from '@playwright/test'; import { type DevServer, testFactory, waitForHydrate } from './test-utils.ts'; @@ -13,9 +14,9 @@ test.afterAll(async () => { await devServer.stop(); }); -test.afterEach(async ({ astro }) => { - // Force database reset between tests - await astro.editFile('./db/seed.ts', (original) => original, false); +test.afterEach(({ astro }) => { + // Reset the store between tests by deleting its data file + rmSync(new URL('src/db/temp', astro.config.root), { recursive: true, force: true }); }); test.describe('Astro Actions - Blog', () => { diff --git a/packages/astro/e2e/actions-react-19.test.ts b/packages/astro/e2e/actions-react-19.test.ts index 8a7617a024f9..6f8d499835ab 100644 --- a/packages/astro/e2e/actions-react-19.test.ts +++ b/packages/astro/e2e/actions-react-19.test.ts @@ -1,3 +1,4 @@ +import { rmSync } from 'node:fs'; import { expect } from '@playwright/test'; import { type DevServer, testFactory, waitForHydrate } from './test-utils.ts'; @@ -9,9 +10,9 @@ test.beforeAll(async ({ astro }) => { devServer = await astro.startDevServer(); }); -test.afterEach(async ({ astro }) => { - // Force database reset between tests - await astro.editFile('./db/seed.ts', (original) => original, false); +test.afterEach(({ astro }) => { + // Reset the store between tests by deleting its data file + rmSync(new URL('src/db/temp', astro.config.root), { recursive: true, force: true }); }); test.afterAll(async () => { diff --git a/packages/astro/e2e/fixtures/actions-blog/astro.config.mjs b/packages/astro/e2e/fixtures/actions-blog/astro.config.mjs index c00c4da70df2..caa1e90a6132 100644 --- a/packages/astro/e2e/fixtures/actions-blog/astro.config.mjs +++ b/packages/astro/e2e/fixtures/actions-blog/astro.config.mjs @@ -1,12 +1,11 @@ import { defineConfig } from 'astro/config'; -import db from '@astrojs/db'; import react from '@astrojs/react'; import node from '@astrojs/node'; // https://astro.build/config export default defineConfig({ site: 'https://example.com', - integrations: [db(), react()], + integrations: [react()], output: 'server', adapter: node({ mode: 'standalone', diff --git a/packages/astro/e2e/fixtures/actions-blog/db/config.ts b/packages/astro/e2e/fixtures/actions-blog/db/config.ts deleted file mode 100644 index da005471e10c..000000000000 --- a/packages/astro/e2e/fixtures/actions-blog/db/config.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { column, defineDb, defineTable } from "astro:db"; - -const Comment = defineTable({ - columns: { - postId: column.text(), - author: column.text(), - body: column.text(), - }, -}); - -const Likes = defineTable({ - columns: { - postId: column.text(), - likes: column.number(), - }, -}); - -// https://astro.build/db/config -export default defineDb({ - tables: { Comment, Likes }, -}); diff --git a/packages/astro/e2e/fixtures/actions-blog/db/seed.ts b/packages/astro/e2e/fixtures/actions-blog/db/seed.ts deleted file mode 100644 index 4e54174b1ede..000000000000 --- a/packages/astro/e2e/fixtures/actions-blog/db/seed.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { db, Likes, Comment } from "astro:db"; - -// https://astro.build/db/seed -export default async function seed() { - await db.insert(Likes).values({ - postId: "first-post", - likes: 10, - }); - - await db.insert(Comment).values({ - postId: "first-post", - author: "Alice", - body: "Great post!", - }); -} diff --git a/packages/astro/e2e/fixtures/actions-blog/package.json b/packages/astro/e2e/fixtures/actions-blog/package.json index c8aa6c1cad18..3c6895b3ca38 100644 --- a/packages/astro/e2e/fixtures/actions-blog/package.json +++ b/packages/astro/e2e/fixtures/actions-blog/package.json @@ -11,7 +11,6 @@ }, "dependencies": { "@astrojs/check": "workspace:*", - "@astrojs/db": "workspace:*", "@astrojs/node": "workspace:*", "@astrojs/react": "workspace:*", "@types/react": "^18.3.28", diff --git a/packages/astro/e2e/fixtures/actions-blog/src/actions/index.ts b/packages/astro/e2e/fixtures/actions-blog/src/actions/index.ts index b928330a4a0d..17e1f5f6e919 100644 --- a/packages/astro/e2e/fixtures/actions-blog/src/actions/index.ts +++ b/packages/astro/e2e/fixtures/actions-blog/src/actions/index.ts @@ -1,7 +1,7 @@ -import { db, Comment, Likes, eq, sql } from 'astro:db'; import { ActionError, defineAction } from 'astro:actions'; import { z } from 'astro/zod'; import { getCollection } from 'astro:content'; +import { addComment, incrementLikes } from '../db/store'; export const server = { logout: defineAction({ @@ -15,16 +15,7 @@ export const server = { handler: async ({ postId }) => { await new Promise((r) => setTimeout(r, 500)); - const result = await db - .update(Likes) - .set({ - likes: sql`${Likes.likes} + 1`, - }) - .where(eq(Likes.postId, postId)) - .returning() - .get(); - - return result?.likes; + return incrementLikes(postId); }, }), @@ -43,16 +34,7 @@ export const server = { }); } - const comment = await db - .insert(Comment) - .values({ - postId, - body, - author, - }) - .returning() - .get(); - return comment; + return addComment({ postId, author, body }); }, }), diff --git a/packages/astro/e2e/fixtures/actions-blog/src/db/store.ts b/packages/astro/e2e/fixtures/actions-blog/src/db/store.ts new file mode 100644 index 000000000000..4e37caa11144 --- /dev/null +++ b/packages/astro/e2e/fixtures/actions-blog/src/db/store.ts @@ -0,0 +1,56 @@ +// Tiny file-backed store for the demo actions. State is read from and written to a +// JSON file on disk, so it is shared across every module instance the dev server +// evaluates (the page render and the action handler run in separate module graphs), +// the same way the previous SQLite-backed store was. The e2e tests reset it between +// runs by deleting `./temp/` (see the `afterEach` in actions-blog.test.ts). +import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'; + +export interface Comment { + postId: string; + author: string; + body: string; +} + +interface Data { + likes: Record; + comments: Comment[]; +} + +const file = new URL('./temp/store.json', import.meta.url); + +function read(): Data { + if (!existsSync(file)) { + return { + likes: { 'first-post': 10 }, + comments: [{ postId: 'first-post', author: 'Alice', body: 'Great post!' }], + }; + } + return JSON.parse(readFileSync(file, 'utf-8')); +} + +function write(data: Data): void { + mkdirSync(new URL('./temp/', import.meta.url), { recursive: true }); + writeFileSync(file, JSON.stringify(data)); +} + +export function getLikes(postId: string): number { + return read().likes[postId] ?? 0; +} + +export function incrementLikes(postId: string): number { + const data = read(); + data.likes[postId] = (data.likes[postId] ?? 0) + 1; + write(data); + return data.likes[postId]; +} + +export function getComments(postId: string): Comment[] { + return read().comments.filter((comment) => comment.postId === postId); +} + +export function addComment(comment: Comment): Comment { + const data = read(); + data.comments.push(comment); + write(data); + return comment; +} diff --git a/packages/astro/e2e/fixtures/actions-blog/src/pages/blog/[...slug].astro b/packages/astro/e2e/fixtures/actions-blog/src/pages/blog/[...slug].astro index 51e94747de14..96cd90942a4a 100644 --- a/packages/astro/e2e/fixtures/actions-blog/src/pages/blog/[...slug].astro +++ b/packages/astro/e2e/fixtures/actions-blog/src/pages/blog/[...slug].astro @@ -2,7 +2,7 @@ import { type CollectionEntry, getEntry, render } from 'astro:content'; import BlogPost from '../../layouts/BlogPost.astro'; import { Logout } from '../../components/Logout'; -import { db, eq, Comment, Likes } from 'astro:db'; +import { getComments, getLikes } from '../../db/store'; import { Like } from '../../components/Like'; import { PostComment } from '../../components/PostComment'; import { actions } from 'astro:actions'; @@ -19,16 +19,16 @@ if (Astro.url.searchParams.has('like')) { const comment = Astro.getActionResult(actions.blog.comment); -const comments = await db.select().from(Comment).where(eq(Comment.postId, post.id)); +const comments = getComments(post.id); -const initialLikes = await db.select().from(Likes).where(eq(Likes.postId, post.id)).get(); +const initialLikes = getLikes(post.id); // Used to force validation errors for testing const commentPostIdOverride = Astro.url.searchParams.get('commentPostIdOverride'); --- - + diff --git a/packages/astro/e2e/fixtures/actions-react-19/astro.config.mjs b/packages/astro/e2e/fixtures/actions-react-19/astro.config.mjs index 35f7481f230e..9fc4e7f4d890 100644 --- a/packages/astro/e2e/fixtures/actions-react-19/astro.config.mjs +++ b/packages/astro/e2e/fixtures/actions-react-19/astro.config.mjs @@ -1,12 +1,11 @@ import { defineConfig } from 'astro/config'; -import db from '@astrojs/db'; import react from '@astrojs/react'; import node from '@astrojs/node'; // https://astro.build/config export default defineConfig({ site: 'https://example.com', - integrations: [db(), react()], + integrations: [react()], output: 'static', adapter: node({ mode: 'standalone', diff --git a/packages/astro/e2e/fixtures/actions-react-19/db/config.ts b/packages/astro/e2e/fixtures/actions-react-19/db/config.ts deleted file mode 100644 index da005471e10c..000000000000 --- a/packages/astro/e2e/fixtures/actions-react-19/db/config.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { column, defineDb, defineTable } from "astro:db"; - -const Comment = defineTable({ - columns: { - postId: column.text(), - author: column.text(), - body: column.text(), - }, -}); - -const Likes = defineTable({ - columns: { - postId: column.text(), - likes: column.number(), - }, -}); - -// https://astro.build/db/config -export default defineDb({ - tables: { Comment, Likes }, -}); diff --git a/packages/astro/e2e/fixtures/actions-react-19/db/seed.ts b/packages/astro/e2e/fixtures/actions-react-19/db/seed.ts deleted file mode 100644 index 4e54174b1ede..000000000000 --- a/packages/astro/e2e/fixtures/actions-react-19/db/seed.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { db, Likes, Comment } from "astro:db"; - -// https://astro.build/db/seed -export default async function seed() { - await db.insert(Likes).values({ - postId: "first-post", - likes: 10, - }); - - await db.insert(Comment).values({ - postId: "first-post", - author: "Alice", - body: "Great post!", - }); -} diff --git a/packages/astro/e2e/fixtures/actions-react-19/package.json b/packages/astro/e2e/fixtures/actions-react-19/package.json index 93d5133f0443..c67f08f2615a 100644 --- a/packages/astro/e2e/fixtures/actions-react-19/package.json +++ b/packages/astro/e2e/fixtures/actions-react-19/package.json @@ -11,7 +11,6 @@ }, "dependencies": { "@astrojs/check": "workspace:*", - "@astrojs/db": "workspace:*", "@astrojs/node": "workspace:*", "@astrojs/react": "workspace:*", "@types/react": "npm:types-react", diff --git a/packages/astro/e2e/fixtures/actions-react-19/src/actions/index.ts b/packages/astro/e2e/fixtures/actions-react-19/src/actions/index.ts index 2e4ba89dae20..677706023b83 100644 --- a/packages/astro/e2e/fixtures/actions-react-19/src/actions/index.ts +++ b/packages/astro/e2e/fixtures/actions-react-19/src/actions/index.ts @@ -1,7 +1,7 @@ -import { db, Likes, eq, sql } from 'astro:db'; import { defineAction, type SafeResult } from 'astro:actions'; import { z } from 'astro/zod'; import { getActionState } from '@astrojs/react/actions'; +import { incrementLikes, setLikes } from '../db/store'; export const server = { blog: { @@ -11,16 +11,7 @@ export const server = { handler: async ({ postId }) => { await new Promise((r) => setTimeout(r, 1000)); - const { likes } = await db - .update(Likes) - .set({ - likes: sql`likes + 1`, - }) - .where(eq(Likes.postId, postId)) - .returning() - .get(); - - return likes; + return incrementLikes(postId); }, }), likeWithActionState: defineAction({ @@ -32,16 +23,7 @@ export const server = { const state = await getActionState>(ctx); const previousLikes = state.data ?? 0; - const { likes } = await db - .update(Likes) - .set({ - likes: previousLikes + 1, - }) - .where(eq(Likes.postId, postId)) - .returning() - .get(); - - return likes; + return setLikes(postId, previousLikes + 1); }, }), }, diff --git a/packages/astro/e2e/fixtures/actions-react-19/src/db/store.ts b/packages/astro/e2e/fixtures/actions-react-19/src/db/store.ts new file mode 100644 index 000000000000..1b6147fcb126 --- /dev/null +++ b/packages/astro/e2e/fixtures/actions-react-19/src/db/store.ts @@ -0,0 +1,42 @@ +// Tiny file-backed store for the demo actions. State is read from and written to a +// JSON file on disk, so it is shared across every module instance the dev server +// evaluates (the page render and the action handler run in separate module graphs), +// the same way the previous SQLite-backed store was. The e2e tests reset it between +// runs by deleting `./temp/` (see the `afterEach` in actions-react-19.test.ts). +import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'; + +interface Data { + likes: Record; +} + +const file = new URL('./temp/store.json', import.meta.url); + +function read(): Data { + if (!existsSync(file)) { + return { likes: { 'first-post': 10 } }; + } + return JSON.parse(readFileSync(file, 'utf-8')); +} + +function write(data: Data): void { + mkdirSync(new URL('./temp/', import.meta.url), { recursive: true }); + writeFileSync(file, JSON.stringify(data)); +} + +export function getLikes(postId: string): number { + return read().likes[postId] ?? 0; +} + +export function incrementLikes(postId: string): number { + const data = read(); + data.likes[postId] = (data.likes[postId] ?? 0) + 1; + write(data); + return data.likes[postId]; +} + +export function setLikes(postId: string, value: number): number { + const data = read(); + data.likes[postId] = value; + write(data); + return value; +} diff --git a/packages/astro/e2e/fixtures/actions-react-19/src/pages/blog/[...slug].astro b/packages/astro/e2e/fixtures/actions-react-19/src/pages/blog/[...slug].astro index 59824d83efb2..c79a74e258e1 100644 --- a/packages/astro/e2e/fixtures/actions-react-19/src/pages/blog/[...slug].astro +++ b/packages/astro/e2e/fixtures/actions-react-19/src/pages/blog/[...slug].astro @@ -1,7 +1,7 @@ --- import { type CollectionEntry, getCollection, getEntry, render } from 'astro:content'; import BlogPost from '../../layouts/BlogPost.astro'; -import { db, eq, Likes } from 'astro:db'; +import { getLikes } from '../../db/store'; import { Like, LikeWithActionState } from '../../components/Like'; export const prerender = false; @@ -19,17 +19,13 @@ type Props = CollectionEntry<'blog'>; const post = await getEntry('blog', Astro.params.slug)!; const { Content } = await render(post) -const likesRes = await db.select().from(Likes).where(eq(Likes.postId, post.id)).get()!; +const likes = getLikes(post.id); ---

Like

- { - likesRes && ( - - - ) - } + +

Like with action state

diff --git a/packages/astro/src/cli/add/index.ts b/packages/astro/src/cli/add/index.ts index 2ea93a8c0e16..7f0246004184 100644 --- a/packages/astro/src/cli/add/index.ts +++ b/packages/astro/src/cli/add/index.ts @@ -63,22 +63,6 @@ export default { LIT_NPMRC: `\ # Lit libraries are required to be hoisted due to dependency issues. public-hoist-pattern[]=*lit* -`, - DB_CONFIG: `\ -import { defineDb } from 'astro:db'; - -// https://astro.build/db/config -export default defineDb({ - tables: {} -}); -`, - DB_SEED: `\ -import { db } from 'astro:db'; - -// https://astro.build/db/seed -export default async function seed() { - // TODO -} `, CLOUDFLARE_WRANGLER_CONFIG: (name: string, compatibilityDate: string) => `\ { @@ -135,7 +119,6 @@ export async function add(names: string[], { flags }: AddOptions) { ['node', 'astro add node'], ], Others: [ - ['db', 'astro add db'], ['tailwind', 'astro add tailwind'], ['mdx', 'astro add mdx'], ['markdoc', 'astro add markdoc'], @@ -270,33 +253,6 @@ export async function add(names: string[], { flags }: AddOptions) { defaultConfigContent: STUBS.SVELTE_CONFIG, }); } - if (integrations.find((integration) => integration.id === 'db')) { - if (!existsSync(new URL('./db/', root))) { - logger.info( - 'SKIP_FORMAT', - `\n ${magenta( - `Astro will scaffold ${green('./db/config.ts')}${magenta(' and ')}${green( - './db/seed.ts', - )}${magenta(' files.')}`, - )}\n`, - ); - - if (await askToContinue({ flags, logger })) { - await fs.mkdir(new URL('./db', root)); - await Promise.all([ - fs.writeFile(new URL('./db/config.ts', root), STUBS.DB_CONFIG, { encoding: 'utf-8' }), - fs.writeFile(new URL('./db/seed.ts', root), STUBS.DB_SEED, { encoding: 'utf-8' }), - ]); - } else { - logger.info( - 'SKIP_FORMAT', - `\n Astro DB requires additional configuration. Please refer to https://astro.build/db/config`, - ); - } - } else { - logger.debug('add', `Using existing db configuration`); - } - } // Some lit dependencies needs to be hoisted, so for strict package managers like pnpm, // we add an .npmrc to hoist them if ( diff --git a/packages/astro/src/cli/db/index.ts b/packages/astro/src/cli/db/index.ts deleted file mode 100644 index 8dce31cbc223..000000000000 --- a/packages/astro/src/cli/db/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -import type { Arguments } from 'yargs-parser'; -import { resolveConfig } from '../../core/config/config.js'; -import type { AstroConfig } from '../../types/public/config.js'; -import { createLoggerFromFlags, flagsToAstroInlineConfig } from '../flags.js'; -import { getPackage } from '../install-package.js'; - -type DBPackage = { - cli: (args: { flags: Arguments; config: AstroConfig }) => unknown; -}; - -export async function db({ flags }: { flags: Arguments }) { - const logger = createLoggerFromFlags(flags); - const getPackageOpts = { - skipAsk: !!flags.yes || !!flags.y, - cwd: flags.root, - }; - const dbPackage = await getPackage('@astrojs/db', logger, getPackageOpts, []); - - if (!dbPackage) { - logger.error( - 'check', - 'The `@astrojs/db` package is required for this command to work. Please manually install it in your project and try again.', - ); - return; - } - - const { cli } = dbPackage; - const inlineConfig = flagsToAstroInlineConfig(flags); - const { astroConfig } = await resolveConfig(inlineConfig, 'build'); - - await cli({ flags, config: astroConfig }); -} diff --git a/packages/astro/src/cli/help/index.ts b/packages/astro/src/cli/help/index.ts index c244df3a1e1c..37c18cd2d6c1 100644 --- a/packages/astro/src/cli/help/index.ts +++ b/packages/astro/src/cli/help/index.ts @@ -10,7 +10,6 @@ export const DEFAULT_HELP_PAYLOAD: HelpPayload = { ['build', 'Build your project and write it to disk.'], ['check', 'Check your project for errors.'], ['create-key', 'Create a cryptography key'], - ['db', 'Manage your Astro database.'], ['dev', 'Start the development server.'], ['docs', 'Open documentation in your web browser.'], ['info', 'List info about your current Astro setup.'], diff --git a/packages/astro/src/cli/index.ts b/packages/astro/src/cli/index.ts index 7d1523bb7d94..bf005a3838a2 100644 --- a/packages/astro/src/cli/index.ts +++ b/packages/astro/src/cli/index.ts @@ -9,7 +9,6 @@ type CLICommand = | 'dev' | 'build' | 'preview' - | 'db' | 'sync' | 'check' | 'info' @@ -32,12 +31,7 @@ function resolveCommand(flags: yargs.Arguments): CLICommand { 'check', 'create-key', 'docs', - 'db', 'info', - 'login', - 'logout', - 'link', - 'init', ]); if (supportedCommands.has(cmd)) { return cmd as CLICommand; @@ -222,15 +216,6 @@ async function runCommand(cmd: string, flags: yargs.Arguments) { await add(packages, { flags }); return; } - case 'db': - case 'login': - case 'logout': - case 'link': - case 'init': { - const { db } = await import('./db/index.js'); - await db({ flags }); - return; - } case 'dev': { const { dev } = await import('./dev/index.js'); const server = await dev({ flags }); diff --git a/packages/db/CHANGELOG.md b/packages/db/CHANGELOG.md deleted file mode 100644 index 41d3d9fa6349..000000000000 --- a/packages/db/CHANGELOG.md +++ /dev/null @@ -1,1002 +0,0 @@ -# @astrojs/db - -## 1.0.0-alpha.0 - -### Major Changes - -- [#15819](https://github.com/withastro/astro/pull/15819) [`cafec4e`](https://github.com/withastro/astro/commit/cafec4e23365061491103dfce2e889a15cf86f27) Thanks [@delucis](https://github.com/delucis)! - Upgrade to Vite v8 - -## 0.21.3 - -### Patch Changes - -- [#16964](https://github.com/withastro/astro/pull/16964) [`b048826`](https://github.com/withastro/astro/commit/b048826b7a0406c751073c1bd95686d9ffae8edc) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Deprecates the `@astrojs/db` integration. We no longer have the bandwidth to maintain this package, and we recommend that users directly use the database client of their choice (Drizzle, Kysely, etc.) in their Astro projects instead. - -## 0.21.2 - -### Patch Changes - -- [#16661](https://github.com/withastro/astro/pull/16661) [`03b8f7f`](https://github.com/withastro/astro/commit/03b8f7f7644cc1d9e738a8221d6bd377399538c0) Thanks [@ocavue](https://github.com/ocavue)! - Updates `typescript` to v6. No changes are needed from users. - -## 0.21.1 - -### Patch Changes - -- [#16534](https://github.com/withastro/astro/pull/16534) [`5cf6c51`](https://github.com/withastro/astro/commit/5cf6c51188b52d22f133ea9373da0080f74701f9) Thanks [@matthewp](https://github.com/matthewp)! - Fixes compatibility with Zod 4.4.0 for the `server` config property and error formatting - -## 0.21.0 - -### Minor Changes - -- [#16289](https://github.com/withastro/astro/pull/16289) [`5d580c0`](https://github.com/withastro/astro/commit/5d580c0b743f9e87befd74e45721f1b5ac9fa166) Thanks [@maxmalkin](https://github.com/maxmalkin)! - Adds a new `getDbError()` helper exported from `astro:db`. It walks the error `.cause` chain and returns the underlying `LibsqlError`, or `undefined` if the error did not originate from libSQL. This is needed because `drizzle-orm` 0.44+ wraps query errors in a `DrizzleQueryError` whose `.cause` is the real `LibsqlError`. - - #### Upgrading - - Code that reads `.code` or `.message` after catching a database error should migrate from `isDbError()` to `getDbError()`: - - ```ts - // Before - import { isDbError } from 'astro:db'; - try { - await db.insert(MyTable).values({ ... }); - } catch (e) { - if (isDbError(e)) { - console.error(e.code, e.message); - } - } - - // After - import { getDbError } from 'astro:db'; - try { - await db.insert(MyTable).values({ ... }); - } catch (e) { - const dbError = getDbError(e); - if (dbError) { - console.error(dbError.code, dbError.message); - } - } - ``` - - `isDbError()` is still exported and still returns `true` for wrapped errors, but its return type is now `boolean` instead of the `err is LibsqlError` type predicate. Code that relied on the narrowing to access `.code` or `.message` directly will now produce a TypeScript error pointing you to `getDbError()`. - -### Patch Changes - -- [#16289](https://github.com/withastro/astro/pull/16289) [`5d580c0`](https://github.com/withastro/astro/commit/5d580c0b743f9e87befd74e45721f1b5ac9fa166) Thanks [@maxmalkin](https://github.com/maxmalkin)! - Fixes a SQL injection vulnerability by updating `drizzle-orm` to `^0.45.2`, patching GHSA-gpj5-g38j-94v9 (CVE-2026-39356). - -## 0.20.1 - -### Patch Changes - -- [#15364](https://github.com/withastro/astro/pull/15364) [`948b693`](https://github.com/withastro/astro/commit/948b693e6f083df3823a0907b4afe938f059bfdb) Thanks [@VagnoDev](https://github.com/VagnoDev)! - Replace deprecated deep-diff with microdiff and resolve subdependency warnings. - -## 0.20.0 - -### Minor Changes - -- [#14445](https://github.com/withastro/astro/pull/14445) [`ecb0b98`](https://github.com/withastro/astro/commit/ecb0b98396f639d830a99ddb5895ab9223e4dc87) Thanks [@florian-lefebvre](https://github.com/florian-lefebvre)! - Astro v6.0 upgrades to Vite v7.0 as the development server and production bundler - ([v6 upgrade guidance](https://docs.astro.build/en/guides/upgrade-to/v6/#vite-70)) - -### Patch Changes - -- [#15187](https://github.com/withastro/astro/pull/15187) [`bbb5811`](https://github.com/withastro/astro/commit/bbb5811eb801a42dc091bb09ea19d6cde3033795) Thanks [@matthewp](https://github.com/matthewp)! - Update to Astro 6 beta - -- [#14956](https://github.com/withastro/astro/pull/14956) [`0ff51df`](https://github.com/withastro/astro/commit/0ff51dfa3c6c615af54228e159f324034472b1a2) Thanks [@matthewp](https://github.com/matthewp)! - Updates usage of zod to own dependency rather than relying on `astro/zod` - -- [#15373](https://github.com/withastro/astro/pull/15373) [`14252b2`](https://github.com/withastro/astro/commit/14252b22f9129f51fae9b224386ab6c4ea1b76c5) Thanks [@renovate](https://github.com/apps/renovate)! - Updates zod to v4 - -- [#14589](https://github.com/withastro/astro/pull/14589) [`7038f07`](https://github.com/withastro/astro/commit/7038f0700898a17cb87b5a2e408480c1226a47f4) Thanks [@43081j](https://github.com/43081j)! - Improves CLI styling - -## 0.19.0-beta.4 - -### Patch Changes - -- [#14589](https://github.com/withastro/astro/pull/14589) [`7038f07`](https://github.com/withastro/astro/commit/7038f0700898a17cb87b5a2e408480c1226a47f4) Thanks [@43081j](https://github.com/43081j)! - Improves CLI styling - -## 0.19.0-beta.3 - -### Patch Changes - -- [#15373](https://github.com/withastro/astro/pull/15373) [`14252b2`](https://github.com/withastro/astro/commit/14252b22f9129f51fae9b224386ab6c4ea1b76c5) Thanks [@renovate](https://github.com/apps/renovate)! - Updates zod to v4 - -## 0.19.0-beta.2 - -### Patch Changes - -- [#15187](https://github.com/withastro/astro/pull/15187) [`bbb5811`](https://github.com/withastro/astro/commit/bbb5811eb801a42dc091bb09ea19d6cde3033795) Thanks [@matthewp](https://github.com/matthewp)! - Update to Astro 6 beta - -## 0.19.0-alpha.1 - -### Patch Changes - -- [#14956](https://github.com/withastro/astro/pull/14956) [`0ff51df`](https://github.com/withastro/astro/commit/0ff51dfa3c6c615af54228e159f324034472b1a2) Thanks [@matthewp](https://github.com/matthewp)! - Updates usage of zod to own dependency rather than relying on `astro/zod` - -## 0.19.0-alpha.0 - -### Minor Changes - -- [#14445](https://github.com/withastro/astro/pull/14445) [`ecb0b98`](https://github.com/withastro/astro/commit/ecb0b98396f639d830a99ddb5895ab9223e4dc87) Thanks [@florian-lefebvre](https://github.com/florian-lefebvre)! - Astro v6.0 upgrades to Vite v7.0 as the development server and production bundler - ([v6 upgrade guidance](https://docs.astro.build/en/guides/upgrade-to/v6/#vite-70)) - -## 0.19.0 - -### Minor Changes - -- [#15069](https://github.com/withastro/astro/pull/15069) [`d14dfc2`](https://github.com/withastro/astro/commit/d14dfc2d4da71ec6958dc4b34ab04666b367352e) Thanks [@webstackdev](https://github.com/webstackdev)! - Adds a `--db-app-token` CLI flag to `astro db` commands `execute`, `push`, `query`, and `verify` - - The new Astro DB CLI flags allow you to provide a remote database app token directly instead of `ASTRO_DB_APP_TOKEN`. This ensures that no untrusted code (e.g. CI / CD workflows) has access to the secret that is only needed by the `astro db` commands. - - The following command can be used to safely push database configuration changes to your project database: - - ``` - astro db push --db-app-token - ``` - - See the [Astro DB integration documentation](https://docs.astro.build/en/guides/integrations-guide/db/#astro-db-cli-reference) for more information. - -## 0.18.3 - -### Patch Changes - -- [#14813](https://github.com/withastro/astro/pull/14813) [`e1dd377`](https://github.com/withastro/astro/commit/e1dd377398a3dcf6ba0697dc8d4bde6d77a45700) Thanks [@ematipico](https://github.com/ematipico)! - Removes `picocolors` as dependency in favor of the fork `piccolore`. - -## 0.18.2 - -### Patch Changes - -- [#14621](https://github.com/withastro/astro/pull/14621) [`e3175d9`](https://github.com/withastro/astro/commit/e3175d9ccbf070150ab2229b2564ca0b12a86c30) Thanks [@GameRoMan](https://github.com/GameRoMan)! - Updates `vite` version to fix CVE - -## 0.18.1 - -### Patch Changes - -- [#14598](https://github.com/withastro/astro/pull/14598) [`7b45c65`](https://github.com/withastro/astro/commit/7b45c65c62e37d4225fb14ea378e2301de31cbea) Thanks [@delucis](https://github.com/delucis)! - Reduces terminal text styling dependency size by switching from `kleur` to `picocolors` - -## 0.18.0 - -### Minor Changes - -- [#14204](https://github.com/withastro/astro/pull/14204) [`d71448e`](https://github.com/withastro/astro/commit/d71448efd8b6693ef5d2b071ef4dea20a289699c) Thanks [@Adammatthiesen](https://github.com/Adammatthiesen)! - Adds a new libSQL web driver to support environments that require a non-Node.js libSQL client such as Cloudflare or Deno. Also adds a new `mode` configuration option to allow you to set your client connection type: `node` (default) or `web`. - - The default db `node` driver mode is identical to the previous AstroDB functionality. No changes have been made to how AstroDB works in Node.js environments, and this is still the integration's default behavior. If you are currently using AstroDB, no changes to your project code are required and setting a `mode` is not required. - - However, if you have previously been unable to use AstroDB because you required a non-Node.js libSQL client, you can now install and configure the libSQL web driver by setting `mode: 'web'` in your `db` configuration: - - ```ts - import db from '@astrojs/db'; - import { defineConfig } from 'astro/config'; - - // https://astro.build/config - export default defineConfig({ - integrations: [db({ mode: 'web' })], - }); - ``` - - For more information, see the [`@astrojs/db` documentation](https://docs.astro.build/en/guides/integrations-guide/db/#mode). - -## 0.17.2 - -### Patch Changes - -- [#14326](https://github.com/withastro/astro/pull/14326) [`c24a8f4`](https://github.com/withastro/astro/commit/c24a8f42a17410ea78fc2d68ff0105b931a381eb) Thanks [@jsparkdev](https://github.com/jsparkdev)! - Updates `vite` version to fix CVE - -## 0.17.1 - -### Patch Changes - -- [#14207](https://github.com/withastro/astro/pull/14207) [`91283b5`](https://github.com/withastro/astro/commit/91283b5f56af8c1a976b0516948ec340cbe24e01) Thanks [@Adammatthiesen](https://github.com/Adammatthiesen)! - Fixes inferred types for Astro DB tables using `column.text` fields. - -## 0.17.0 - -### Minor Changes - -- [#14190](https://github.com/withastro/astro/pull/14190) [`438adab`](https://github.com/withastro/astro/commit/438adab4b7b24ff8614cd7244aa3a94d42f0602c) Thanks [@Adammatthiesen](https://github.com/Adammatthiesen)! - Adds support for enum support for text columns in Astro DB tables. - - ```ts - import { column, defineTable } from 'astro:db'; - - // Table definition - const UserTable = defineTable({ - columns: { - id: column.number({ primaryKey: true }), - name: column.text(), - rank: column.text({ enum: ['user', 'mod', 'admin'] }), - }, - }); - - // Resulting type definition - type UserTableInferInsert = { - id: string; - name: string; - rank: 'user' | 'mod' | 'admin'; - }; - ``` - -## 0.16.1 - -### Patch Changes - -- [#14186](https://github.com/withastro/astro/pull/14186) [`9fe883e`](https://github.com/withastro/astro/commit/9fe883ece60f11da7d63c2eef8af61923997021e) Thanks [@Adammatthiesen](https://github.com/Adammatthiesen)! - Fixes types for optional and primary key columns in Astro DB tables. - -## 0.16.0 - -### Minor Changes - -- [#13894](https://github.com/withastro/astro/pull/13894) [`b36e72f`](https://github.com/withastro/astro/commit/b36e72f11fbcc0f3d5826f2b1939084f1fb1e3a8) Thanks [@florian-lefebvre](https://github.com/florian-lefebvre)! - Removes support for Astro Studio - - Astro Studio has been [discontinued since September 2024](https://astro.build/blog/goodbye-astro-studio/). If you still haven't migrated yet to Turso, check [our guide](https://docs.astro.build/en/guides/astro-db/#migrate-from-astro-studio-to-turso). - -## 0.15.1 - -### Patch Changes - -- [#14127](https://github.com/withastro/astro/pull/14127) [`2309ada`](https://github.com/withastro/astro/commit/2309ada1c6d96c75815eda0760656147de435ba2) Thanks [@florian-lefebvre](https://github.com/florian-lefebvre)! - Upgrades zod - -## 0.15.0 - -### Minor Changes - -- [#13815](https://github.com/withastro/astro/pull/13815) [`03435f8`](https://github.com/withastro/astro/commit/03435f8269b91ce8973bc8ded8e8071481d39dda) Thanks [@jonaspm](https://github.com/jonaspm)! - Upgraded drizzle-orm to latest v0.42.0 - -## 0.14.14 - -### Patch Changes - -- [#13772](https://github.com/withastro/astro/pull/13772) [`83193d4`](https://github.com/withastro/astro/commit/83193d43cfb7fb28254f0ff3fb717a7bdd65977b) Thanks [@Adammatthiesen](https://github.com/Adammatthiesen)! - Fix options parsing for the libsql client connection to ensure that proper values are being set when adding URLSearchParams to the `ASTRO_DB_REMOTE_URL` - -- [#13783](https://github.com/withastro/astro/pull/13783) [`1609044`](https://github.com/withastro/astro/commit/1609044face6f58fff1dc82ceb14b3fd13b5ff67) Thanks [@Adammatthiesen](https://github.com/Adammatthiesen)! - Modify Database type to allow transactions to be properly typed now that Astro Studio has sunset. - -## 0.14.13 - -### Patch Changes - -- [#13731](https://github.com/withastro/astro/pull/13731) [`c3e80c2`](https://github.com/withastro/astro/commit/c3e80c25b90c803e2798b752583a8e77cdad3146) Thanks [@jsparkdev](https://github.com/jsparkdev)! - update vite to latest version for fixing CVE - -- Updated dependencies [[`c3e80c2`](https://github.com/withastro/astro/commit/c3e80c25b90c803e2798b752583a8e77cdad3146)]: - - @astrojs/studio@0.1.9 - -## 0.14.12 - -### Patch Changes - -- [#13591](https://github.com/withastro/astro/pull/13591) [`5dd2d3f`](https://github.com/withastro/astro/commit/5dd2d3fde8a138ed611dedf39ffa5dfeeed315f8) Thanks [@florian-lefebvre](https://github.com/florian-lefebvre)! - Removes unused code - -- Updated dependencies [[`5dd2d3f`](https://github.com/withastro/astro/commit/5dd2d3fde8a138ed611dedf39ffa5dfeeed315f8)]: - - @astrojs/studio@0.1.8 - -## 0.14.11 - -### Patch Changes - -- [#13596](https://github.com/withastro/astro/pull/13596) [`3752519`](https://github.com/withastro/astro/commit/375251966d1b28a570bff45ff0fe7e7d2fe46f72) Thanks [@jsparkdev](https://github.com/jsparkdev)! - update vite to latest version to fix CVE - -- [#13547](https://github.com/withastro/astro/pull/13547) [`360cb91`](https://github.com/withastro/astro/commit/360cb9199a4314f90825c5639ff4396760e9cfcc) Thanks [@jsparkdev](https://github.com/jsparkdev)! - Updates vite to the latest version - -- Updated dependencies [[`3752519`](https://github.com/withastro/astro/commit/375251966d1b28a570bff45ff0fe7e7d2fe46f72), [`360cb91`](https://github.com/withastro/astro/commit/360cb9199a4314f90825c5639ff4396760e9cfcc)]: - - @astrojs/studio@0.1.7 - -## 0.14.10 - -### Patch Changes - -- [#13526](https://github.com/withastro/astro/pull/13526) [`ff9d69e`](https://github.com/withastro/astro/commit/ff9d69e3443c80059c54f6296d19f66bb068ead3) Thanks [@jsparkdev](https://github.com/jsparkdev)! - update `vite` to the latest version - -- Updated dependencies [[`ff9d69e`](https://github.com/withastro/astro/commit/ff9d69e3443c80059c54f6296d19f66bb068ead3)]: - - @astrojs/studio@0.1.6 - -## 0.14.9 - -### Patch Changes - -- [#13505](https://github.com/withastro/astro/pull/13505) [`a98ae5b`](https://github.com/withastro/astro/commit/a98ae5b8f5c33900379012e9e253a755c0a8927e) Thanks [@ematipico](https://github.com/ematipico)! - Updates the dependency `vite` to the latest. - -- Updated dependencies [[`a98ae5b`](https://github.com/withastro/astro/commit/a98ae5b8f5c33900379012e9e253a755c0a8927e)]: - - @astrojs/studio@0.1.5 - -## 0.14.8 - -### Patch Changes - -- [#13343](https://github.com/withastro/astro/pull/13343) [`a001a75`](https://github.com/withastro/astro/commit/a001a75d6ec08378d607531dc73959bf0a9e079e) Thanks [@dreyfus92](https://github.com/dreyfus92)! - Fix Astro DB seed failing when project path contains spaces. This resolves by properly decoding URL pathnames that contain encoded spaces (%20) before passing them to Vite's ssrLoadModule. - -- Updated dependencies []: - - @astrojs/studio@0.1.4 - -## 0.14.7 - -### Patch Changes - -- [#13314](https://github.com/withastro/astro/pull/13314) [`797a948`](https://github.com/withastro/astro/commit/797a9480b23303329dd618633194cbfb3dccb459) Thanks [@jlebras](https://github.com/jlebras)! - Expose `ilike` function from `drizzle-orm` - -- Updated dependencies []: - - @astrojs/studio@0.1.4 - -## 0.14.6 - -### Patch Changes - -- [#13011](https://github.com/withastro/astro/pull/13011) [`cf30880`](https://github.com/withastro/astro/commit/cf3088060d45227dcb48e041c4ed5e0081d71398) Thanks [@ascorbic](https://github.com/ascorbic)! - Upgrades Vite - -- Updated dependencies [[`cf30880`](https://github.com/withastro/astro/commit/cf3088060d45227dcb48e041c4ed5e0081d71398)]: - - @astrojs/studio@0.1.4 - -## 0.14.5 - -### Patch Changes - -- [#12799](https://github.com/withastro/astro/pull/12799) [`739dbfb`](https://github.com/withastro/astro/commit/739dbfba4214107cf8fc40c702834dad33eed3b0) Thanks [@ascorbic](https://github.com/ascorbic)! - Upgrades Vite to pin esbuild - -- Updated dependencies [[`739dbfb`](https://github.com/withastro/astro/commit/739dbfba4214107cf8fc40c702834dad33eed3b0)]: - - @astrojs/studio@0.1.3 - -## 0.14.4 - -### Patch Changes - -- [#12416](https://github.com/withastro/astro/pull/12416) [`618de28`](https://github.com/withastro/astro/commit/618de283f57d19397246f69dd476611abd56cf13) Thanks [@abegehr](https://github.com/abegehr)! - Fixes `isDbError()` guard for `LibsqlError` - -- [#12719](https://github.com/withastro/astro/pull/12719) [`358eae8`](https://github.com/withastro/astro/commit/358eae83b7cf3d79395eea3824e321b502522547) Thanks [@ascorbic](https://github.com/ascorbic)! - Fixes the publishing of the package - -- Updated dependencies []: - - @astrojs/studio@0.1.2 - -## 0.14.1 - -### Patch Changes - -- [#12628](https://github.com/withastro/astro/pull/12628) [`348c71e`](https://github.com/withastro/astro/commit/348c71ecdc7e2a7afb169c2251692416d5e59fcb) Thanks [@ascorbic](https://github.com/ascorbic)! - Fixes a bug that caused an error to be logged about invalid entrypoints - -- Updated dependencies []: - - @astrojs/studio@0.1.2 - -## 0.14.0 - -### Minor Changes - -- [#12008](https://github.com/withastro/astro/pull/12008) [`5608338`](https://github.com/withastro/astro/commit/560833843c6d3ce2b6c6c473ec4ae70e744bf255) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Welcome to the Astro 5 beta! This release has no changes from the latest alpha of this package, but it does bring us one step closer to the final, stable release. - - Starting from this release, no breaking changes will be introduced unless absolutely necessary. - - To learn how to upgrade, check out the [Astro v5.0 upgrade guide in our beta docs site](https://5-0-0-beta.docs.astro.build/en/guides/upgrade-to/v5/). - -### Patch Changes - -- [#12073](https://github.com/withastro/astro/pull/12073) [`acf264d`](https://github.com/withastro/astro/commit/acf264d8c003718cda5a0b9ce5fb7ac1cd6641b6) Thanks [@bluwy](https://github.com/bluwy)! - Replaces `ora` with `yocto-spinner` - -- Updated dependencies [[`acf264d`](https://github.com/withastro/astro/commit/acf264d8c003718cda5a0b9ce5fb7ac1cd6641b6)]: - - @astrojs/studio@0.1.2 - -## 0.14.0-beta.2 - -### Patch Changes - -- [#12073](https://github.com/withastro/astro/pull/12073) [`acf264d`](https://github.com/withastro/astro/commit/acf264d8c003718cda5a0b9ce5fb7ac1cd6641b6) Thanks [@bluwy](https://github.com/bluwy)! - Replaces `ora` with `yocto-spinner` - -- Updated dependencies [[`acf264d`](https://github.com/withastro/astro/commit/acf264d8c003718cda5a0b9ce5fb7ac1cd6641b6)]: - - @astrojs/studio@0.1.2-beta.0 - -## 0.14.0-beta.1 - -### Minor Changes - -- [#12008](https://github.com/withastro/astro/pull/12008) [`5608338`](https://github.com/withastro/astro/commit/560833843c6d3ce2b6c6c473ec4ae70e744bf255) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Welcome to the Astro 5 beta! This release has no changes from the latest alpha of this package, but it does bring us one step closer to the final, stable release. - - Starting from this release, no breaking changes will be introduced unless absolutely necessary. - - To learn how to upgrade, check out the [Astro v5.0 upgrade guide in our beta docs site](https://5-0-0-beta.docs.astro.build/en/guides/upgrade-to/v5/). - -### Patch Changes - -- Updated dependencies []: - - @astrojs/studio@0.1.1 - -## 0.14.3 - -### Patch Changes - -- [#11435](https://github.com/withastro/astro/pull/11435) [`f32a7a8`](https://github.com/withastro/astro/commit/f32a7a83889dd6180b2e4cde9b30286ab6874e49) Thanks [@haivuw](https://github.com/haivuw)! - Fixes a bug where `astro:db:seed` couldn't access to the environment variable `ASTRO_DATABASE_FILE` - -- Updated dependencies []: - - @astrojs/studio@0.1.1 - -## 0.14.2 - -### Patch Changes - -- [#12118](https://github.com/withastro/astro/pull/12118) [`f47b347`](https://github.com/withastro/astro/commit/f47b347da899c6e1dcd0b2e7887f7fce6ec8e270) Thanks [@Namchee](https://github.com/Namchee)! - Removes the `strip-ansi` dependency in favor of the native Node API - -- [#12089](https://github.com/withastro/astro/pull/12089) [`6e06e6e`](https://github.com/withastro/astro/commit/6e06e6ed4f1c983f842527d7e3561a45a4407777) Thanks [@Fryuni](https://github.com/Fryuni)! - Fixes initial schema push for local file and in-memory libSQL DB - -- [#12089](https://github.com/withastro/astro/pull/12089) [`6e06e6e`](https://github.com/withastro/astro/commit/6e06e6ed4f1c983f842527d7e3561a45a4407777) Thanks [@Fryuni](https://github.com/Fryuni)! - Fixes relative local libSQL db URL - -- Updated dependencies []: - - @astrojs/studio@0.1.1 - -## 0.14.1 - -### Patch Changes - -- [#11894](https://github.com/withastro/astro/pull/11894) [`cc820c5`](https://github.com/withastro/astro/commit/cc820c5d5e176a8d71594d612af75e1c94b9bf02) Thanks [@Fryuni](https://github.com/Fryuni)! - Fixes mixed environment variable for app token when using DB commands with libSQL remote. - -- Updated dependencies []: - - @astrojs/studio@0.1.1 - -## 0.14.0 - -### Minor Changes - -- [#11385](https://github.com/withastro/astro/pull/11385) [`d6611e8`](https://github.com/withastro/astro/commit/d6611e8bb05e7d913aeb5e59e90906b8b919d48e) Thanks [@Fryuni](https://github.com/Fryuni)! - Adds support for connecting Astro DB to any remote LibSQL server. This allows Astro DB to be used with self-hosting and air-gapped deployments. - - To connect Astro DB to a remote LibSQL server instead of Studio, set the following environment variables: - - `ASTRO_DB_REMOTE_URL`: the connection URL to your LibSQL server - - `ASTRO_DB_APP_TOKEN`: the auth token to your LibSQL server - - Details of the LibSQL connection can be configured using the connection URL. For example, `memory:?syncUrl=libsql%3A%2F%2Fdb-server.example.com` would create an in-memory embedded replica for the LibSQL DB on `libsql://db-server.example.com`. - - For more details, please visit [the Astro DB documentation](https://docs.astro.build/en/guides/astro-db/#libsql) - -### Patch Changes - -- Updated dependencies []: - - @astrojs/studio@0.1.1 - -## 0.13.2 - -### Patch Changes - -- [#11744](https://github.com/withastro/astro/pull/11744) [`b677429`](https://github.com/withastro/astro/commit/b67742961a384c10e5cd04cf5b02d0f014ea7362) Thanks [@bluwy](https://github.com/bluwy)! - Disables the WebSocket server when creating a Vite server for loading config files - -- Updated dependencies []: - - @astrojs/studio@0.1.1 - -## 0.13.1 - -### Patch Changes - -- [#11733](https://github.com/withastro/astro/pull/11733) [`391324d`](https://github.com/withastro/astro/commit/391324df969db71d1c7ca25c2ed14c9eb6eea5ee) Thanks [@bluwy](https://github.com/bluwy)! - Reverts back to `yargs-parser` package for CLI argument parsing - -- Updated dependencies []: - - @astrojs/studio@0.1.1 - -## 0.13.0 - -### Minor Changes - -- [#11360](https://github.com/withastro/astro/pull/11360) [`a79a8b0`](https://github.com/withastro/astro/commit/a79a8b0230b06ed32ce1802f2a5f84a6cf92dbe7) Thanks [@ascorbic](https://github.com/ascorbic)! - Changes how type generation works - - The generated `.d.ts` file is now at a new location: - - ```diff - - .astro/db-types.d.ts - + .astro/integrations/astro_db/db.d.ts - ``` - - The following line can now be removed from `src/env.d.ts`: - - ```diff - - /// - ``` - -### Patch Changes - -- [#11645](https://github.com/withastro/astro/pull/11645) [`849e4c6`](https://github.com/withastro/astro/commit/849e4c6c23e61f7fa59f583419048b998bef2475) Thanks [@bluwy](https://github.com/bluwy)! - Refactors internally to use `node:util` `parseArgs` instead of `yargs-parser` - -- Updated dependencies []: - - @astrojs/studio@0.1.1 - -## 0.12.0 - -### Minor Changes - -- [#11304](https://github.com/withastro/astro/pull/11304) [`2e70741`](https://github.com/withastro/astro/commit/2e70741362afc1e7d03c8b2a9d8edb8466dfe9c3) Thanks [@Fryuni](https://github.com/Fryuni)! - Removes the `AstroDbIntegration` type - - Astro integration hooks can now be extended and as such `@astrojs/db` no longer needs to declare its own integration type. Using `AstroIntegration` will have the same type. - - If you were using the `AstroDbIntegration` type, apply this change to your integration code: - - ```diff - - import { defineDbIntegration, type AstroDbIntegration } from '@astrojs/db/utils'; - + import { defineDbIntegration } from '@astrojs/db/utils'; - import type { AstroIntegration } from 'astro'; - - - export default (): AstroDbIntegration => { - + export default (): AstroIntegration => { - return defineDbIntegration({ - name: 'your-integration', - hooks: {}, - }); - } - ``` - -### Patch Changes - -- Updated dependencies []: - - @astrojs/studio@0.1.1 - -## 0.11.7 - -### Patch Changes - -- [#11331](https://github.com/withastro/astro/pull/11331) [`f1b78a4`](https://github.com/withastro/astro/commit/f1b78a496034d53b0e9dfc276a4a1b1d691772c4) Thanks [@bluwy](https://github.com/bluwy)! - Relaxes exports condition to allow importing ESM from CJS - -- Updated dependencies [[`f1b78a4`](https://github.com/withastro/astro/commit/f1b78a496034d53b0e9dfc276a4a1b1d691772c4)]: - - @astrojs/studio@0.1.1 - -## 0.11.6 - -### Patch Changes - -- [#11262](https://github.com/withastro/astro/pull/11262) [`9b03023`](https://github.com/withastro/astro/commit/9b030239cb4db4e51a8a1da638743b60837f7e1a) Thanks [@nezouse](https://github.com/nezouse)! - Import type `Database` from correct file - -- Updated dependencies []: - - @astrojs/studio@0.1.0 - -## 0.11.5 - -### Patch Changes - -- [#11216](https://github.com/withastro/astro/pull/11216) [`29463df`](https://github.com/withastro/astro/commit/29463dff52f2e74d0d522168afe6faf70ff2fabb) Thanks [@OliverSpeir](https://github.com/OliverSpeir)! - Export type `Database` from `@astrojs/db/runtime` - -- Updated dependencies []: - - @astrojs/studio@0.1.0 - -## 0.11.4 - -### Patch Changes - -- [#11032](https://github.com/withastro/astro/pull/11032) [`b78e83f`](https://github.com/withastro/astro/commit/b78e83f448d142e83be592f6249c4822e7cd5726) Thanks [@itsMapleLeaf](https://github.com/itsMapleLeaf)! - Adds support for multiple Astro Studio workspaces (aka “Teams”) to the Astro DB CLI - - Users who are members of a team workspace in Astro Studio can now choose between those and their personal workspace when running `astro db link`. - -- [#11091](https://github.com/withastro/astro/pull/11091) [`e14ce57`](https://github.com/withastro/astro/commit/e14ce5726df73e2988fe1a39e078ef2d66d2f4a8) Thanks [@matthewp](https://github.com/matthewp)! - Fix inconsistent result type using raw SQL - -- Updated dependencies []: - - @astrojs/studio@0.1.0 - -## 0.11.3 - -### Patch Changes - -- [#11070](https://github.com/withastro/astro/pull/11070) [`1fec4a6`](https://github.com/withastro/astro/commit/1fec4a6eb986011d4d6d998410ff9b6144c28c34) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Fixes some error messages not using the proper command to login or sync the project - -- [#11037](https://github.com/withastro/astro/pull/11037) [`9332bb1`](https://github.com/withastro/astro/commit/9332bb1c1f237f5666ded09532ccd651837b94e5) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Internal refactor, this change should have no visible effect - -- Updated dependencies [[`9332bb1`](https://github.com/withastro/astro/commit/9332bb1c1f237f5666ded09532ccd651837b94e5)]: - - @astrojs/studio@0.1.0 - -## 0.11.2 - -### Patch Changes - -- [#11027](https://github.com/withastro/astro/pull/11027) [`eb1d9a4`](https://github.com/withastro/astro/commit/eb1d9a447bc73534b8dd8fa6d3dcdb265950753a) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix `isDbError()` returning `false` for remote database errors. Astro will now return a `LibsqlError` in development and production. - -## 0.11.1 - -### Patch Changes - -- [#10967](https://github.com/withastro/astro/pull/10967) [`a134318`](https://github.com/withastro/astro/commit/a1343184da2a67439de4792e9e404d17ec3943df) Thanks [@matthewp](https://github.com/matthewp)! - Convert non-ISO date to UTC time - -## 0.11.0 - -### Minor Changes - -- [#10919](https://github.com/withastro/astro/pull/10919) [`44bafa9`](https://github.com/withastro/astro/commit/44bafa989af0cc380696bb6381048fc1ee55dd5b) Thanks [@bholmesdev](https://github.com/bholmesdev)! - - Fix duplicate table recreations when you start your dev server. - - Remove eager re-seeding when updating your seed file in development. Seeding still runs on dev server startup for SQLite inspector tools. - -## 0.10.7 - -### Patch Changes - -- [#10882](https://github.com/withastro/astro/pull/10882) [`cf58d1e`](https://github.com/withastro/astro/commit/cf58d1ed56c671d0ee077dfecc286002b4bae5ed) Thanks [@delucis](https://github.com/delucis)! - Improves the typing of the `asDrizzleTable()` utility - - Fixes a type error when passing the output of `defineTable()` to the utility and returns a more detailed type inferred from the columns of the passed table config. - -- [#10918](https://github.com/withastro/astro/pull/10918) [`ca605f4`](https://github.com/withastro/astro/commit/ca605f4dd8fcd070d3d5a5ca2f7080d921801e17) Thanks [@matthewp](https://github.com/matthewp)! - Provide a better error message when app token is missing in CI - -- [#10925](https://github.com/withastro/astro/pull/10925) [`a0c77fc`](https://github.com/withastro/astro/commit/a0c77fc7164662ea62b65c51fd1bd4c2f6028bc1) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Fixes `ASTRO_DATABASE_FILE` not correctly resolving relative paths (e.g. `ASTRO_DATABASE_FILE=./api/database.db` - -## 0.10.6 - -### Patch Changes - -- [#10816](https://github.com/withastro/astro/pull/10816) [`8e6eb62`](https://github.com/withastro/astro/commit/8e6eb624aee40bac66a58169a30107f624a8c539) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Add `astro login` support from online editors like Stackblitz and GitHub Codespaces - -## 0.10.5 - -### Patch Changes - -- [#10789](https://github.com/withastro/astro/pull/10789) [`d4c91cb10924a0627a9e9a80bc549b3c82d043e6`](https://github.com/withastro/astro/commit/d4c91cb10924a0627a9e9a80bc549b3c82d043e6) Thanks [@NickDubelman](https://github.com/NickDubelman)! - Expose the Drizzle `alias` utility from `astro:db` to enable self-joins on a table. - -## 0.10.4 - -### Patch Changes - -- [#10764](https://github.com/withastro/astro/pull/10764) [`d1080ea81de0db1d1aed97a65c490766c17ab312`](https://github.com/withastro/astro/commit/d1080ea81de0db1d1aed97a65c490766c17ab312) Thanks [@delucis](https://github.com/delucis)! - Improves `package.json` metadata fields - -## 0.10.3 - -### Patch Changes - -- [#10720](https://github.com/withastro/astro/pull/10720) [`2d2ff58bb90e09248afc04cc8e2016ef983a7f07`](https://github.com/withastro/astro/commit/2d2ff58bb90e09248afc04cc8e2016ef983a7f07) Thanks [@matthewp](https://github.com/matthewp)! - Fix db seeding when srcDir is root - -## 0.10.2 - -### Patch Changes - -- [#10681](https://github.com/withastro/astro/pull/10681) [`4bf8bd3848a6f3461f0186854588a8e2f90f4dbc`](https://github.com/withastro/astro/commit/4bf8bd3848a6f3461f0186854588a8e2f90f4dbc) Thanks [@matthewp](https://github.com/matthewp)! - Prevent errors in finding workspaceId from interrupting link prompts - -- [#10600](https://github.com/withastro/astro/pull/10600) [`28e7535e5c7a8234049bd187cac88c7fabf15f9c`](https://github.com/withastro/astro/commit/28e7535e5c7a8234049bd187cac88c7fabf15f9c) Thanks [@matthewp](https://github.com/matthewp)! - Provide better messaging when renaming a table - -## 0.10.1 - -### Patch Changes - -- [#10677](https://github.com/withastro/astro/pull/10677) [`1662aa8a850ff4f860a80c2f33a8b33bcc7aee12`](https://github.com/withastro/astro/commit/1662aa8a850ff4f860a80c2f33a8b33bcc7aee12) Thanks [@matthewp](https://github.com/matthewp)! - Fix compatibility of @astrojs/db with Cloudflare - -## 0.10.0 - -### Minor Changes - -- [#10638](https://github.com/withastro/astro/pull/10638) [`f395ebcc08279515f8d53bb82edeee288d8579db`](https://github.com/withastro/astro/commit/f395ebcc08279515f8d53bb82edeee288d8579db) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Rename internal import from `runtime/config` to `runtime/virtual` - -## 0.9.11 - -### Patch Changes - -- [#10655](https://github.com/withastro/astro/pull/10655) [`b1eda3dc5c33c1c6d50d5ee8a2a08d34851dc253`](https://github.com/withastro/astro/commit/b1eda3dc5c33c1c6d50d5ee8a2a08d34851dc253) Thanks [@matthewp](https://github.com/matthewp)! - Pass through appToken on static sites with Astro DB - -## 0.9.10 - -### Patch Changes - -- [#10646](https://github.com/withastro/astro/pull/10646) [`713f99e849b26edb831ea6527b7103ad7a6b200f`](https://github.com/withastro/astro/commit/713f99e849b26edb831ea6527b7103ad7a6b200f) Thanks [@lilnasy](https://github.com/lilnasy)! - Fixes an issue astro:db could not be used on serverless platforms. - -## 0.9.9 - -### Patch Changes - -- [#10599](https://github.com/withastro/astro/pull/10599) [`5a7733dde52d439402404d5207a2b1d897c4e025`](https://github.com/withastro/astro/commit/5a7733dde52d439402404d5207a2b1d897c4e025) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Seed database on dev server startup, and log whenever the seed file is reloaded. - -- [#10636](https://github.com/withastro/astro/pull/10636) [`504d15d77291f0fe36aa9fecc22f276b734f83cb`](https://github.com/withastro/astro/commit/504d15d77291f0fe36aa9fecc22f276b734f83cb) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Detailed error messages for remote database exceptions. - -- [#10635](https://github.com/withastro/astro/pull/10635) [`17badaf55c79cec460c74f4da58bf188eedef7e3`](https://github.com/withastro/astro/commit/17badaf55c79cec460c74f4da58bf188eedef7e3) Thanks [@matthewp](https://github.com/matthewp)! - Give proper error when seed missing default export - -- [#10631](https://github.com/withastro/astro/pull/10631) [`157392ee44db08de0d3c01222644dae0a904044d`](https://github.com/withastro/astro/commit/157392ee44db08de0d3c01222644dae0a904044d) Thanks [@matthewp](https://github.com/matthewp)! - Make ASTRO_DATABASE_FILE work with file paths - -## 0.9.8 - -### Patch Changes - -- [#10589](https://github.com/withastro/astro/pull/10589) [`ed1031ba29af9a8a89ab386d772a228ba1414b4d`](https://github.com/withastro/astro/commit/ed1031ba29af9a8a89ab386d772a228ba1414b4d) Thanks [@column.text(),]()! - Update the table indexes configuration to allow generated index names. The `indexes` object syntax is now deprecated in favor of an array. - - ## Migration - - You can update your `indexes` configuration object to an array like so: - - ```diff - import { defineDb, defineTable, column } from 'astro:db'; - - const Comment = defineTable({ - columns: { - postId: column.number(), - - body: column.text(), - }, - - indexes: { - - postIdIdx: { on: 'postId' }, - - authorPostIdIdx: { on: ['author, postId'], unique: true }, - - }, - + indexes: [ - + { on: 'postId' /* 'name' is optional */ }, - + { on: ['author, postId'], unique: true }, - + ] - }) - ``` - - This example will generate indexes with the names `Comment_postId_idx` and `Comment_author_postId_idx`, respectively. You can specify a name manually by adding the `name` attribute to a given object. This name will be **global,** so ensure index names do not conflict between tables. - -## 0.9.7 - -### Patch Changes - -- [#10587](https://github.com/withastro/astro/pull/10587) [`62a1d6df6916e08cb25d51814dfad352bc4cce75`](https://github.com/withastro/astro/commit/62a1d6df6916e08cb25d51814dfad352bc4cce75) Thanks [@matthewp](https://github.com/matthewp)! - Conditionally drop table with --force-reset - -- [#10460](https://github.com/withastro/astro/pull/10460) [`713abb2998bc179443a476f6274432b2fc7d8434`](https://github.com/withastro/astro/commit/713abb2998bc179443a476f6274432b2fc7d8434) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Remove legacy Astro DB internals using the "collections" naming convention instead of "tables." - -## 0.9.6 - -### Patch Changes - -- [#10579](https://github.com/withastro/astro/pull/10579) [`f5df12cfebba1abdef50faa7a5549b545f0b3f8c`](https://github.com/withastro/astro/commit/f5df12cfebba1abdef50faa7a5549b545f0b3f8c) Thanks [@matthewp](https://github.com/matthewp)! - Provide guidance when --remote is missing - - When running the build `astro build` without the `--remote`, either require a `DATABASE_FILE` variable be defined, which means you are going expert-mode and having your own database, or error suggesting to use the `--remote` flag. - -- [#10568](https://github.com/withastro/astro/pull/10568) [`764d67fc3f399d62b6a97a2ee698dca03b9f0557`](https://github.com/withastro/astro/commit/764d67fc3f399d62b6a97a2ee698dca03b9f0557) Thanks [@matthewp](https://github.com/matthewp)! - Prevent runtime from importing core code - -## 0.9.5 - -### Patch Changes - -- [#10566](https://github.com/withastro/astro/pull/10566) [`b5a80405b93a166f6f019209152b860ffe2f73ef`](https://github.com/withastro/astro/commit/b5a80405b93a166f6f019209152b860ffe2f73ef) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix `db.run()` type signature in production. - -## 0.9.4 - -### Patch Changes - -- [#10533](https://github.com/withastro/astro/pull/10533) [`6576f5d458ee8cc872210f3a7ae629439546e361`](https://github.com/withastro/astro/commit/6576f5d458ee8cc872210f3a7ae629439546e361) Thanks [@matthewp](https://github.com/matthewp)! - Ensure ASTRO_STUDIO_APP_TOKEN is found at runtime - -## 0.9.3 - -### Patch Changes - -- [#10520](https://github.com/withastro/astro/pull/10520) [`30ce9a0c47a4653a9e9619380a6514459563cf92`](https://github.com/withastro/astro/commit/30ce9a0c47a4653a9e9619380a6514459563cf92) Thanks [@matthewp](https://github.com/matthewp)! - Fix accessing remote database URL - -## 0.9.2 - -### Patch Changes - -- [#10506](https://github.com/withastro/astro/pull/10506) [`980020c5e0935a2e0e177164d02f5e49f0a9ab4b`](https://github.com/withastro/astro/commit/980020c5e0935a2e0e177164d02f5e49f0a9ab4b) Thanks [@matthewp](https://github.com/matthewp)! - Ensure --force-reset drops previous tables - -## 0.9.1 - -### Patch Changes - -- [#10498](https://github.com/withastro/astro/pull/10498) [`f0fc78c8734b2bcf39078c782998e60b49ecc146`](https://github.com/withastro/astro/commit/f0fc78c8734b2bcf39078c782998e60b49ecc146) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Expose `isDbError()` utility to handle database exceptions when querying. - -## 0.9.0 - -### Minor Changes - -- [#10479](https://github.com/withastro/astro/pull/10479) [`ad57a02c330b544770ab853fe0521eb784421016`](https://github.com/withastro/astro/commit/ad57a02c330b544770ab853fe0521eb784421016) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Expose Drizzle aggregation helpers including `count()` from the `astro:db` module. - -### Patch Changes - -- [#10501](https://github.com/withastro/astro/pull/10501) [`48310512601e0c0b2886759e4d81b4091042eb8f`](https://github.com/withastro/astro/commit/48310512601e0c0b2886759e4d81b4091042eb8f) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Remove `db.transaction()` from type definitions until it is supported by our remote database adapter. - -- [#10497](https://github.com/withastro/astro/pull/10497) [`2fc7231df28e5a3425ee47b871ba3766e0856bd8`](https://github.com/withastro/astro/commit/2fc7231df28e5a3425ee47b871ba3766e0856bd8) Thanks [@matthewp](https://github.com/matthewp)! - Remove embedded app token from CI - -- [#10405](https://github.com/withastro/astro/pull/10405) [`2ebcf94d0af5ac789c61b4190dea0ad6a402a6ea`](https://github.com/withastro/astro/commit/2ebcf94d0af5ac789c61b4190dea0ad6a402a6ea) Thanks [@43081j](https://github.com/43081j)! - Added github-slugger as a direct dependency - -## 0.8.8 - -### Patch Changes - -- [#10477](https://github.com/withastro/astro/pull/10477) [`124cdd64f20d86f936853f3cf834fde8cd6abcb7`](https://github.com/withastro/astro/commit/124cdd64f20d86f936853f3cf834fde8cd6abcb7) Thanks [@FredKSchott](https://github.com/FredKSchott)! - Remove redundant wait time on token creation - -## 0.8.7 - -### Patch Changes - -- [#10435](https://github.com/withastro/astro/pull/10435) [`37a485b4d1d4b7e60eee2067ffd86d0eea4f03e8`](https://github.com/withastro/astro/commit/37a485b4d1d4b7e60eee2067ffd86d0eea4f03e8) Thanks [@matthewp](https://github.com/matthewp)! - Fetch new app token when previous has expired - -- [#10457](https://github.com/withastro/astro/pull/10457) [`219c49473fe44d8df2b69444b2dce0f5bc971655`](https://github.com/withastro/astro/commit/219c49473fe44d8df2b69444b2dce0f5bc971655) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix type error in db/seed.ts file before type generation is run. - -## 0.8.6 - -### Patch Changes - -- [#10439](https://github.com/withastro/astro/pull/10439) [`0989cd3284281e3e471a92ac116e14e65f59f8a5`](https://github.com/withastro/astro/commit/0989cd3284281e3e471a92ac116e14e65f59f8a5) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Add success and error logs to `astro db execute` command - -- [#10438](https://github.com/withastro/astro/pull/10438) [`5b48cc0fc8383b0659a595afd3a6ee28b28779c3`](https://github.com/withastro/astro/commit/5b48cc0fc8383b0659a595afd3a6ee28b28779c3) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Generate Astro DB types when running `astro sync`. - -## 0.8.5 - -### Patch Changes - -- [#10445](https://github.com/withastro/astro/pull/10445) [`098623c2616124bcc689e2409564dfda187f6688`](https://github.com/withastro/astro/commit/098623c2616124bcc689e2409564dfda187f6688) Thanks [@matthewp](https://github.com/matthewp)! - Prefer getting the app token from the runtime env - -- [#10441](https://github.com/withastro/astro/pull/10441) [`5166e9715a1ea18eb5c737ccf834c2ff446d253c`](https://github.com/withastro/astro/commit/5166e9715a1ea18eb5c737ccf834c2ff446d253c) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Remove duplicate astro:db log during type generation - -## 0.8.4 - -### Patch Changes - -- [#10443](https://github.com/withastro/astro/pull/10443) [`238f047b9d1ebc407f53d61ee61574b380a76ac9`](https://github.com/withastro/astro/commit/238f047b9d1ebc407f53d61ee61574b380a76ac9) Thanks [@lilnasy](https://github.com/lilnasy)! - Fixes an issue where `astro:db` could not be used in serverless environments. - -## 0.8.3 - -### Patch Changes - -- [#10431](https://github.com/withastro/astro/pull/10431) [`1076864cc4aa4b4dad570bbab9907996642cdd1f`](https://github.com/withastro/astro/commit/1076864cc4aa4b4dad570bbab9907996642cdd1f) Thanks [@FredKSchott](https://github.com/FredKSchott)! - Add wait time for the db token to propagate - -- [#10432](https://github.com/withastro/astro/pull/10432) [`4e24628aacc556515b27d0c04361df1526ae778f`](https://github.com/withastro/astro/commit/4e24628aacc556515b27d0c04361df1526ae778f) Thanks [@FredKSchott](https://github.com/FredKSchott)! - Add all regions to the link command - -## 0.8.2 - -### Patch Changes - -- [#10409](https://github.com/withastro/astro/pull/10409) [`96c8bca19aa477318b5eb48af12b260a6f173e25`](https://github.com/withastro/astro/commit/96c8bca19aa477318b5eb48af12b260a6f173e25) Thanks [@lilnasy](https://github.com/lilnasy)! - Fixes an issue where one table schema could not reference text fields of another table schema. - -- [#10428](https://github.com/withastro/astro/pull/10428) [`189ec47c1e3232d8b4db42035ddd44ea862ecfca`](https://github.com/withastro/astro/commit/189ec47c1e3232d8b4db42035ddd44ea862ecfca) Thanks [@FredKSchott](https://github.com/FredKSchott)! - Fix an issue where short-lived tokens were not being authorized - -- [#10420](https://github.com/withastro/astro/pull/10420) [`2db25c05a467f2ffd6ebff5eb82076449fa9d72f`](https://github.com/withastro/astro/commit/2db25c05a467f2ffd6ebff5eb82076449fa9d72f) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Fixes some situations where failing requests would not error properly - -## 0.8.1 - -### Patch Changes - -- [#10401](https://github.com/withastro/astro/pull/10401) [`a084d8cec66e4fb1952bd0dfe293712401f2f463`](https://github.com/withastro/astro/commit/a084d8cec66e4fb1952bd0dfe293712401f2f463) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix astro:db configuration types returning `any` - -## 0.8.0 - -### Minor Changes - -- [#10395](https://github.com/withastro/astro/pull/10395) [`a49892349ecee2b5d3184e59ac0ab54368481672`](https://github.com/withastro/astro/commit/a49892349ecee2b5d3184e59ac0ab54368481672) Thanks [@matthewp](https://github.com/matthewp)! - Sets new Astro Studio production URL - -### Patch Changes - -- [#10396](https://github.com/withastro/astro/pull/10396) [`41ca94e5136a80a58d000f3eb87029442599a4a3`](https://github.com/withastro/astro/commit/41ca94e5136a80a58d000f3eb87029442599a4a3) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Remove risk of data loss when pushing an out-of-date table schema. - -- [#10374](https://github.com/withastro/astro/pull/10374) [`f76dcb769f6869acb96b2a77898926f109f54a33`](https://github.com/withastro/astro/commit/f76dcb769f6869acb96b2a77898926f109f54a33) Thanks [@itsMapleLeaf](https://github.com/itsMapleLeaf)! - Expose DB utility types from @astrojs/db/types - -## 0.7.2 - -### Patch Changes - -- [#10391](https://github.com/withastro/astro/pull/10391) [`9667ee990ca2a02a146e442f2494981df4c88b52`](https://github.com/withastro/astro/commit/9667ee990ca2a02a146e442f2494981df4c88b52) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Remove @astrojs/runtime/config suggestion for astro:db configuration helpers. - -- [#10385](https://github.com/withastro/astro/pull/10385) [`38abae47b57af481a8dcdf2393317de6df46920a`](https://github.com/withastro/astro/commit/38abae47b57af481a8dcdf2393317de6df46920a) Thanks [@delucis](https://github.com/delucis)! - Fixes support for integrations configuring `astro:db` and for projects that use `astro:db` but do not include a seed file. - -- [#10381](https://github.com/withastro/astro/pull/10381) [`8cceab587d681d90842184904182833117687750`](https://github.com/withastro/astro/commit/8cceab587d681d90842184904182833117687750) Thanks [@delucis](https://github.com/delucis)! - Fixes builds for projects using integration seed files - -- [#10384](https://github.com/withastro/astro/pull/10384) [`cd5e8d4b9309e43f5bf884a0014b8a5769d816e0`](https://github.com/withastro/astro/commit/cd5e8d4b9309e43f5bf884a0014b8a5769d816e0) Thanks [@matthewp](https://github.com/matthewp)! - Upgrades the `@libsql/client` dependency to fix the use of `db.batch` in StackBlitz - -- [#10387](https://github.com/withastro/astro/pull/10387) [`8a23ee530cd1d7d7b4e93e9e72f4e06d1fc3d845`](https://github.com/withastro/astro/commit/8a23ee530cd1d7d7b4e93e9e72f4e06d1fc3d845) Thanks [@FredKSchott](https://github.com/FredKSchott)! - handle success=false response on api endpoints - -- [#10390](https://github.com/withastro/astro/pull/10390) [`236cdbb611587692d3c781850cb949604677ef82`](https://github.com/withastro/astro/commit/236cdbb611587692d3c781850cb949604677ef82) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Adds `--help` reference for new db and studio CLI commands - -## 0.7.1 - -### Patch Changes - -- [#10378](https://github.com/withastro/astro/pull/10378) [`41dca1e413c2f1e38f0326bd6241ccbf9b8ee0e4`](https://github.com/withastro/astro/commit/41dca1e413c2f1e38f0326bd6241ccbf9b8ee0e4) Thanks [@FredKSchott](https://github.com/FredKSchott)! - Handle new schema API response format - -## 0.7.0 - -### Minor Changes - -## 0.7.0 - -### Breaking Changes - -- The seed file now requires an `export default async function()` wrapper -- `defineDB` has been renamed to `defineDb` - -### Minor Changes - -- [#10334](https://github.com/withastro/astro/pull/10334) [`bad9b583a267e239ba52237d45a89063ea277200`](https://github.com/withastro/astro/commit/bad9b583a267e239ba52237d45a89063ea277200) Thanks [@delucis](https://github.com/delucis)! - Changes the seed file format to require exporting a default function instead of running seed code at the top level. - - To migrate a seed file, wrap your existing code in a default function export: - - ```diff - // db/seed.ts - import { db, Table } from 'astro:db'; - - + export default async function() { - await db.insert(Table).values({ foo: 'bar' }); - + } - ``` - -- [#10352](https://github.com/withastro/astro/pull/10352) [`06fe94e29de97290cb41c4f862ab88f48cda3d4a`](https://github.com/withastro/astro/commit/06fe94e29de97290cb41c4f862ab88f48cda3d4a) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Introduce `astro build --remote` to build with a remote database connection. Running `astro build` plain will use a local database file, and `--remote` will authenticate with a studio app token. - -- [#10321](https://github.com/withastro/astro/pull/10321) [`2e4958c8a75dc9836efcc7dd272fb8ed4187c000`](https://github.com/withastro/astro/commit/2e4958c8a75dc9836efcc7dd272fb8ed4187c000) Thanks [@delucis](https://github.com/delucis)! - Adds support for integrations providing `astro:db` configuration and seed files, using the new `astro:db:setup` hook. - - To get TypeScript support for the `astro:db:setup` hook, wrap your integration object in the `defineDbIntegration()` utility: - - ```js - import { defineDbIntegration } from '@astrojs/db/utils'; - - export default function MyDbIntegration() { - return defineDbIntegration({ - name: 'my-astro-db-powered-integration', - hooks: { - 'astro:db:setup': ({ extendDb }) => { - extendDb({ - configEntrypoint: '@astronaut/my-package/config', - seedEntrypoint: '@astronaut/my-package/seed', - }); - }, - }, - }); - } - ``` - - Use the `extendDb` method to register additional `astro:db` config and seed files. - - Integration config and seed files follow the same format as their user-defined equivalents. However, often while working on integrations, you may not be able to benefit from Astro’s generated table types exported from `astro:db`. For full type safety and autocompletion support, use the `asDrizzleTable()` utility to wrap your table definitions in the seed file. - - ```js - // config.ts - import { defineTable, column } from 'astro:db'; - - export const Pets = defineTable({ - columns: { - name: column.text(), - age: column.number(), - }, - }); - ``` - - ```js - // seed.ts - import { asDrizzleTable } from '@astrojs/db/utils'; - import { db } from 'astro:db'; - import { Pets } from './config'; - - export default async function () { - // Convert the Pets table into a format ready for querying. - const typeSafePets = asDrizzleTable('Pets', Pets); - - await db.insert(typeSafePets).values([ - { name: 'Palomita', age: 7 }, - { name: 'Pan', age: 3.5 }, - ]); - } - ``` - -- [#10361](https://github.com/withastro/astro/pull/10361) [`988aad6705e5ee129cf3a28da80aca4229052bb3`](https://github.com/withastro/astro/commit/988aad6705e5ee129cf3a28da80aca4229052bb3) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Add support for batch queries with `db.batch()`. This includes an internal bump to Drizzle v0.29. - -### Patch Changes - -- [#10357](https://github.com/withastro/astro/pull/10357) [`5a9dab286f3f436f3dce18f3b13a2cd9b774a8ef`](https://github.com/withastro/astro/commit/5a9dab286f3f436f3dce18f3b13a2cd9b774a8ef) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix runtime export error when building with the node adapter - -- [#10348](https://github.com/withastro/astro/pull/10348) [`9f422e9bd338c1f6deee8f727143bf801a6b1651`](https://github.com/withastro/astro/commit/9f422e9bd338c1f6deee8f727143bf801a6b1651) Thanks [@matthewp](https://github.com/matthewp)! - Rename `experimentalVersion` to `version` - -- [#10364](https://github.com/withastro/astro/pull/10364) [`3f27e096283b6b477c4a66d0a7df52feaa3f4233`](https://github.com/withastro/astro/commit/3f27e096283b6b477c4a66d0a7df52feaa3f4233) Thanks [@delucis](https://github.com/delucis)! - Renames the Astro DB `defineDB()` helper to `defineDb()` - -## 0.6.5 - -### Patch Changes - -- [#10350](https://github.com/withastro/astro/pull/10350) [`393ad9b2aa9fde45eb14b8b01ff3526063772452`](https://github.com/withastro/astro/commit/393ad9b2aa9fde45eb14b8b01ff3526063772452) Thanks [@Fryuni](https://github.com/Fryuni)! - Includes `./virtual.d.ts` file that was previously unpublished - -## 0.6.4 - -### Patch Changes - -- [#10342](https://github.com/withastro/astro/pull/10342) [`a2e9b2b936666b2a4779feb00dcb8ff0ab82c2ec`](https://github.com/withastro/astro/commit/a2e9b2b936666b2a4779feb00dcb8ff0ab82c2ec) Thanks [@matthewp](https://github.com/matthewp)! - Fixes @astrojs/db loading TS in the fixtures - -## 0.6.3 - -### Patch Changes - -- [#10340](https://github.com/withastro/astro/pull/10340) [`a60861c960bf3d24af9b2784b5b333855c968731`](https://github.com/withastro/astro/commit/a60861c960bf3d24af9b2784b5b333855c968731) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Ensure `astro:db` types exist in your `db/config.ts` before running type generation. - -## 0.6.2 - -### Patch Changes - -- [#10336](https://github.com/withastro/astro/pull/10336) [`f2e60a96754ed1d86001fe4d5d3a0c0ef657408d`](https://github.com/withastro/astro/commit/f2e60a96754ed1d86001fe4d5d3a0c0ef657408d) Thanks [@FredKSchott](https://github.com/FredKSchott)! - Add back confirmation handling on verify and push - -## 0.6.1 - -### Patch Changes - -- [#10315](https://github.com/withastro/astro/pull/10315) [`78ddfadbf9cc5a12a9bd25eab64ec8ec1bd8617d`](https://github.com/withastro/astro/commit/78ddfadbf9cc5a12a9bd25eab64ec8ec1bd8617d) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix type definitions for `astro:db` - -## 0.6.0 - -### Minor Changes - -- [#10312](https://github.com/withastro/astro/pull/10312) [`93ec9e264a1dbdff61233289418612f558508135`](https://github.com/withastro/astro/commit/93ec9e264a1dbdff61233289418612f558508135) Thanks [@FredKSchott](https://github.com/FredKSchott)! - Revamp migrations system - -### Patch Changes - -- [#10313](https://github.com/withastro/astro/pull/10313) [`cb00c8b6927242369debe92ad2bc7e791616696a`](https://github.com/withastro/astro/commit/cb00c8b6927242369debe92ad2bc7e791616696a) Thanks [@FredKSchott](https://github.com/FredKSchott)! - Fix bad package.json types - -## 0.5.0 - -### Minor Changes - -- [#10280](https://github.com/withastro/astro/pull/10280) [`3488be9b59d1cb65325b0e087c33bcd74aaa4926`](https://github.com/withastro/astro/commit/3488be9b59d1cb65325b0e087c33bcd74aaa4926) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Finalize db API to a shared db/ directory. - -## 0.4.1 - -### Patch Changes - -- [#10223](https://github.com/withastro/astro/pull/10223) [`aa45eb9fa60b254e859750d9cef671daa605b213`](https://github.com/withastro/astro/commit/aa45eb9fa60b254e859750d9cef671daa605b213) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix: use correct remote database url during production builds - -- [#10207](https://github.com/withastro/astro/pull/10207) [`5d4ff093a21c072553b2cac6c799d3efa3cb84c0`](https://github.com/withastro/astro/commit/5d4ff093a21c072553b2cac6c799d3efa3cb84c0) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Improve error messaging when seeding invalid data. - -## 0.4.0 - -### Minor Changes - -- [`f85ace2e66370e522b5a4e9b54c578a02298fe0e`](https://github.com/withastro/astro/commit/f85ace2e66370e522b5a4e9b54c578a02298fe0e) Thanks [@matthewp](https://github.com/matthewp)! - @astrojs/db prerelease diff --git a/packages/db/README.md b/packages/db/README.md deleted file mode 100644 index f09ba618be35..000000000000 --- a/packages/db/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# @astrojs/db 💿 - -> ⚠️ **This integration is deprecated** -> -> This integration is no longer maintained and will not receive updates. We recommend directly using the database client (Drizzle, Kysely, etc.) of your choice in your Astro project instead. - -## Support - -- Get help in the [Astro Discord][discord]. Post questions in our `#support` forum, or visit our dedicated `#framework` channel to discuss current development and more! - -- Check our [Astro Integration Documentation][astro-integration] for more on integrations. - -- Submit bug reports and feature requests as [GitHub issues][issues]. - -## Contributing - -This package is maintained by Astro's Core team. You're welcome to submit an issue or PR! These links will help you get started: - -- [Contributor Manual][contributing] -- [Code of Conduct][coc] -- [Community Guide][community] - -## License - -MIT - -Copyright (c) 2023–present [Astro][astro] - -[astro]: https://astro.build/ -[contributing]: https://github.com/withastro/astro/blob/main/CONTRIBUTING.md -[coc]: https://github.com/withastro/.github/blob/main/CODE_OF_CONDUCT.md -[community]: https://github.com/withastro/.github/blob/main/COMMUNITY_GUIDE.md -[discord]: https://astro.build/chat/ -[issues]: https://github.com/withastro/astro/issues -[astro-integration]: https://docs.astro.build/en/guides/integrations-guide/ diff --git a/packages/db/index.d.ts b/packages/db/index.d.ts deleted file mode 100644 index 7c0e055b2c9f..000000000000 --- a/packages/db/index.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import './virtual.js'; - -export { default, cli } from './dist/index.js'; diff --git a/packages/db/package.json b/packages/db/package.json deleted file mode 100644 index c637b9f32a9c..000000000000 --- a/packages/db/package.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "name": "@astrojs/db", - "version": "1.0.0-alpha.0", - "description": "Add libSQL support to your Astro site", - "license": "MIT", - "repository": { - "type": "git", - "url": "git+https://github.com/withastro/astro.git", - "directory": "packages/db" - }, - "bugs": "https://github.com/withastro/astro/issues", - "homepage": "https://docs.astro.build/en/guides/integrations-guide/db/", - "type": "module", - "author": "withastro", - "types": "./index.d.ts", - "main": "./dist/index.js", - "exports": { - ".": { - "types": "./index.d.ts", - "default": "./dist/index.js" - }, - "./utils": { - "types": "./dist/utils.d.ts", - "default": "./dist/utils.js" - }, - "./runtime": { - "types": "./dist/runtime/index.d.ts", - "default": "./dist/runtime/index.js" - }, - "./db-client/*": "./dist/core/db-client/*", - "./dist/runtime/virtual.js": { - "default": "./dist/runtime/virtual.js" - }, - "./types": { - "types": "./dist/core/types.d.ts", - "default": "./dist/core/types.js" - }, - "./package.json": "./package.json" - }, - "typesVersions": { - "*": { - ".": [ - "./index.d.ts" - ], - "types": [ - "./dist/types.d.ts" - ], - "utils": [ - "./dist/utils.d.ts" - ], - "runtime": [ - "./dist/runtime/index.d.ts" - ] - } - }, - "files": [ - "index.d.ts", - "virtual.d.ts", - "dist" - ], - "keywords": [ - "withastro", - "astro-integration" - ], - "scripts": { - "build": "astro-scripts build \"src/**/*.ts\" && tsc -b", - "build:ci": "astro-scripts build \"src/**/*.ts\"", - "dev": "astro-scripts dev \"src/**/*.ts\"", - "test": "pnpm run test:integration", - "test:integration": "astro-scripts test \"test/**/*.test.ts\"" - }, - "dependencies": { - "@clack/prompts": "^1.0.1", - "@libsql/client": "^0.17.0", - "drizzle-orm": "^0.45.2", - "microdiff": "^1.5.0", - "nanoid": "^5.1.6", - "piccolore": "^0.1.3", - "yargs-parser": "^22.0.0", - "zod": "^4.3.6" - }, - "devDependencies": { - "@types/yargs-parser": "^21.0.3", - "astro": "workspace:*", - "astro-scripts": "workspace:*", - "cheerio": "1.2.0", - "expect-type": "^1.3.0", - "typescript": "^6.0.3", - "vite": "^8.0.13" - } -} diff --git a/packages/db/src/core/cli/commands/execute/index.ts b/packages/db/src/core/cli/commands/execute/index.ts deleted file mode 100644 index 23a0ea265a4d..000000000000 --- a/packages/db/src/core/cli/commands/execute/index.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { existsSync } from 'node:fs'; -import type { AstroConfig } from 'astro'; -import colors from 'piccolore'; -import type { Arguments } from 'yargs-parser'; -import { getDbError } from '../../../../runtime/utils.js'; -import { - EXEC_DEFAULT_EXPORT_ERROR, - EXEC_ERROR, - FILE_NOT_FOUND_ERROR, - MISSING_EXECUTE_PATH_ERROR, -} from '../../../errors.js'; -import { - getLocalVirtualModContents, - getRemoteVirtualModContents, -} from '../../../integration/vite-plugin-db.js'; -import { bundleFile, importBundledFile } from '../../../load-file.js'; -import type { DBConfig } from '../../../types.js'; -import { getRemoteDatabaseInfo, resolveDbAppToken } from '../../../utils.js'; - -export async function cmd({ - astroConfig, - dbConfig, - flags, -}: { - astroConfig: AstroConfig; - dbConfig: DBConfig; - flags: Arguments; -}) { - const filePath = flags._[4]; - if (typeof filePath !== 'string') { - console.error(MISSING_EXECUTE_PATH_ERROR); - process.exit(1); - } - - const fileUrl = new URL(filePath, astroConfig.root); - if (!existsSync(fileUrl)) { - console.error(FILE_NOT_FOUND_ERROR(filePath)); - process.exit(1); - } - - let virtualModContents: string; - if (flags.remote) { - const dbInfo = getRemoteDatabaseInfo(); - const appToken = resolveDbAppToken(flags, dbInfo.token); - virtualModContents = getRemoteVirtualModContents({ - tables: dbConfig.tables ?? {}, - appToken, - isBuild: false, - output: 'server', - localExecution: true, - }); - } else { - virtualModContents = getLocalVirtualModContents({ - tables: dbConfig.tables ?? {}, - root: astroConfig.root, - localExecution: true, - }); - } - const { code } = await bundleFile({ virtualModContents, root: astroConfig.root, fileUrl }); - - const mod = await importBundledFile({ code, root: astroConfig.root }); - if (typeof mod.default !== 'function') { - console.error(EXEC_DEFAULT_EXPORT_ERROR(filePath)); - process.exit(1); - } - try { - await mod.default(); - console.info(`${colors.green('✔')} File run successfully.`); - } catch (e) { - const dbError = getDbError(e); - if (dbError) throw new Error(EXEC_ERROR(dbError.message)); - else throw e; - } -} diff --git a/packages/db/src/core/cli/commands/push/index.ts b/packages/db/src/core/cli/commands/push/index.ts deleted file mode 100644 index 6223394fabe1..000000000000 --- a/packages/db/src/core/cli/commands/push/index.ts +++ /dev/null @@ -1,136 +0,0 @@ -import * as clack from '@clack/prompts'; -import type { AstroConfig } from 'astro'; -import { sql } from 'drizzle-orm'; -import type { Arguments } from 'yargs-parser'; -import { MIGRATION_VERSION } from '../../../consts.js'; -import { createClient } from '../../../db-client/libsql-node.js'; -import type { DBConfig, DBSnapshot } from '../../../types.js'; -import { - getRemoteDatabaseInfo, - type RemoteDatabaseInfo, - resolveDbAppToken, -} from '../../../utils.js'; -import { - createCurrentSnapshot, - createEmptySnapshot, - formatDataLossMessage, - getMigrationQueries, - getProductionCurrentSnapshot, -} from '../../migration-queries.js'; - -export async function cmd({ - dbConfig, - flags, -}: { - astroConfig: AstroConfig; - dbConfig: DBConfig; - flags: Arguments; -}) { - const isDryRun = flags.dryRun; - const isForceReset = flags.forceReset; - const dbInfo = getRemoteDatabaseInfo(); - const appToken = resolveDbAppToken(flags, dbInfo.token); - const productionSnapshot = await getProductionCurrentSnapshot({ ...dbInfo, token: appToken }); - const currentSnapshot = createCurrentSnapshot(dbConfig); - const isFromScratch = !productionSnapshot; - const { queries: migrationQueries, confirmations } = await getMigrationQueries({ - oldSnapshot: isFromScratch ? createEmptySnapshot() : productionSnapshot, - newSnapshot: currentSnapshot, - reset: isForceReset, - }); - - // // push the database schema - if (migrationQueries.length === 0) { - console.log('Database schema is up to date.'); - } else { - console.log(`Database schema is out of date.`); - } - - if (isForceReset) { - const begin = await clack.confirm({ - message: `Reset your database? All of your data will be erased and your schema created from scratch.`, - initialValue: false, - withGuide: false, - }); - - if (begin !== true) { - console.log('Canceled.'); - process.exit(0); - } - - console.log(`Force-pushing to the database. All existing data will be erased.`); - } else if (confirmations.length > 0) { - console.log('\n' + formatDataLossMessage(confirmations) + '\n'); - throw new Error('Exiting.'); - } - - if (isDryRun) { - console.log('Statements:', JSON.stringify(migrationQueries, undefined, 2)); - } else { - console.log(`Pushing database schema updates...`); - await pushSchema({ - statements: migrationQueries, - dbInfo, - appToken, - isDryRun, - currentSnapshot: currentSnapshot, - }); - } - console.info('Push complete!'); -} - -async function pushSchema({ - statements, - dbInfo, - appToken, - isDryRun, - currentSnapshot, -}: { - statements: string[]; - dbInfo: RemoteDatabaseInfo; - appToken: string; - isDryRun: boolean; - currentSnapshot: DBSnapshot; -}) { - const requestBody: RequestBody = { - snapshot: currentSnapshot, - sql: statements, - version: MIGRATION_VERSION, - }; - if (isDryRun) { - console.info('[DRY RUN] Batch query:', JSON.stringify(requestBody, null, 2)); - return new Response(null, { status: 200 }); - } - - return pushToDb(requestBody, appToken, dbInfo.url); -} - -type RequestBody = { - snapshot: DBSnapshot; - sql: string[]; - version: string; -}; - -async function pushToDb(requestBody: RequestBody, appToken: string, remoteUrl: string) { - const client = createClient({ - token: appToken, - url: remoteUrl, - }); - - await client.run(sql`create table if not exists _astro_db_snapshot ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - version TEXT, - snapshot BLOB - );`); - - await client.transaction(async (tx) => { - for (const stmt of requestBody.sql) { - await tx.run(sql.raw(stmt)); - } - - await tx.run(sql`insert into _astro_db_snapshot (version, snapshot) values ( - ${requestBody.version}, - ${JSON.stringify(requestBody.snapshot)} - )`); - }); -} diff --git a/packages/db/src/core/cli/commands/shell/index.ts b/packages/db/src/core/cli/commands/shell/index.ts deleted file mode 100644 index d652fa017437..000000000000 --- a/packages/db/src/core/cli/commands/shell/index.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { AstroConfig } from 'astro'; -import { sql } from 'drizzle-orm'; -import type { Arguments } from 'yargs-parser'; -import { normalizeDatabaseUrl } from '../../../../runtime/index.js'; -import { DB_PATH } from '../../../consts.js'; -import { createClient as createLocalDatabaseClient } from '../../../db-client/libsql-local.js'; -import { createClient as createRemoteDatabaseClient } from '../../../db-client/libsql-node.js'; -import { SHELL_QUERY_MISSING_ERROR } from '../../../errors.js'; -import type { DBConfigInput } from '../../../types.js'; -import { getAstroEnv, getRemoteDatabaseInfo, resolveDbAppToken } from '../../../utils.js'; - -export async function cmd({ - flags, - astroConfig, -}: { - dbConfig: DBConfigInput; - astroConfig: AstroConfig; - flags: Arguments; -}) { - const query = flags.query; - if (!query) { - console.error(SHELL_QUERY_MISSING_ERROR); - process.exit(1); - } - const dbInfo = getRemoteDatabaseInfo(); - if (flags.remote) { - const appToken = resolveDbAppToken(flags, dbInfo.token); - const db = createRemoteDatabaseClient({ ...dbInfo, token: appToken }); - const result = await db.run(sql.raw(query)); - console.log(result); - } else { - const { ASTRO_DATABASE_FILE } = getAstroEnv(); - const dbUrl = normalizeDatabaseUrl( - ASTRO_DATABASE_FILE, - new URL(DB_PATH, astroConfig.root).href, - ); - const db = createLocalDatabaseClient({ url: dbUrl }); - const result = await db.run(sql.raw(query)); - console.log(result); - } -} diff --git a/packages/db/src/core/cli/commands/verify/index.ts b/packages/db/src/core/cli/commands/verify/index.ts deleted file mode 100644 index 3f876c323259..000000000000 --- a/packages/db/src/core/cli/commands/verify/index.ts +++ /dev/null @@ -1,54 +0,0 @@ -import type { AstroConfig } from 'astro'; -import type { Arguments } from 'yargs-parser'; -import type { DBConfig } from '../../../types.js'; -import { getRemoteDatabaseInfo, resolveDbAppToken } from '../../../utils.js'; -import { - createCurrentSnapshot, - createEmptySnapshot, - formatDataLossMessage, - getMigrationQueries, - getProductionCurrentSnapshot, -} from '../../migration-queries.js'; - -export async function cmd({ - dbConfig, - flags, -}: { - astroConfig: AstroConfig; - dbConfig: DBConfig; - flags: Arguments; -}) { - const isJson = flags.json; - const dbInfo = getRemoteDatabaseInfo(); - const appToken = resolveDbAppToken(flags, dbInfo.token); - const productionSnapshot = await getProductionCurrentSnapshot({ ...dbInfo, token: appToken }); - const currentSnapshot = createCurrentSnapshot(dbConfig); - const { queries: migrationQueries, confirmations } = await getMigrationQueries({ - oldSnapshot: productionSnapshot || createEmptySnapshot(), - newSnapshot: currentSnapshot, - }); - - const result = { exitCode: 0, message: '', code: '', data: undefined as unknown }; - if (migrationQueries.length === 0) { - result.code = 'MATCH'; - result.message = `Database schema is up to date.`; - } else { - result.code = 'NO_MATCH'; - result.message = `Database schema is out of date.\nRun 'astro db push' to push up your latest changes.`; - } - - if (confirmations.length > 0) { - result.code = 'DATA_LOSS'; - result.exitCode = 1; - result.data = confirmations; - result.message = formatDataLossMessage(confirmations, !isJson); - } - - if (isJson) { - console.log(JSON.stringify(result)); - } else { - console.log(result.message); - } - - process.exit(result.exitCode); -} diff --git a/packages/db/src/core/cli/index.ts b/packages/db/src/core/cli/index.ts deleted file mode 100644 index f6a68583f09c..000000000000 --- a/packages/db/src/core/cli/index.ts +++ /dev/null @@ -1,83 +0,0 @@ -import type { AstroConfig } from 'astro'; -import type { Arguments } from 'yargs-parser'; -import { resolveDbConfig } from '../load-file.js'; -import { printHelp } from './print-help.js'; - -export async function cli({ - flags, - config: astroConfig, -}: { - flags: Arguments; - config: AstroConfig; -}) { - const args = flags._ as string[]; - // Most commands are `astro db foo`, but for now login/logout - // are also handled by this package, so first check if this is a db command. - const command = args[2] === 'db' ? args[3] : args[2]; - validateDbAppTokenFlag(command, flags); - const { dbConfig } = await resolveDbConfig(astroConfig); - - switch (command) { - case 'shell': { - const { cmd } = await import('./commands/shell/index.js'); - return await cmd({ astroConfig, dbConfig, flags }); - } - case 'gen': { - console.log('"astro db gen" is no longer needed! Visit the docs for more information.'); - return; - } - case 'sync': { - console.log('"astro db sync" is no longer needed! Visit the docs for more information.'); - return; - } - case 'push': { - const { cmd } = await import('./commands/push/index.js'); - return await cmd({ astroConfig, dbConfig, flags }); - } - case 'verify': { - const { cmd } = await import('./commands/verify/index.js'); - return await cmd({ astroConfig, dbConfig, flags }); - } - case 'execute': { - const { cmd } = await import('./commands/execute/index.js'); - return await cmd({ astroConfig, dbConfig, flags }); - } - default: { - if (command != null) { - console.error(`Unknown command: ${command}`); - } - printHelp({ - commandName: 'astro db', - usage: '[command] [...flags]', - headline: ' ', - tables: { - Commands: [ - ['push', 'Push table schema updates to libSQL.'], - ['verify', 'Test schema updates with libSQL (good for CI).'], - [ - 'astro db execute ', - 'Execute a ts/js file using astro:db. Use --remote to connect to libSQL.', - ], - [ - 'astro db shell --query ', - 'Execute a SQL string. Use --remote to connect to libSQL.', - ], - ], - }, - }); - return; - } - } -} - -function validateDbAppTokenFlag(command: string | undefined, flags: Arguments) { - if (command !== 'execute' && command !== 'push' && command !== 'verify' && command !== 'shell') - return; - - const dbAppToken = (flags as Arguments & { dbAppToken?: unknown }).dbAppToken; - if (dbAppToken == null) return; - if (typeof dbAppToken !== 'string') { - console.error(`Invalid value for --db-app-token; expected a string.`); - process.exit(1); - } -} diff --git a/packages/db/src/core/cli/migration-queries.ts b/packages/db/src/core/cli/migration-queries.ts deleted file mode 100644 index e8e8b9679a69..000000000000 --- a/packages/db/src/core/cli/migration-queries.ts +++ /dev/null @@ -1,510 +0,0 @@ -import { stripVTControlCharacters } from 'node:util'; -import diff from 'microdiff'; -import { sql } from 'drizzle-orm'; -import { SQLiteAsyncDialect } from 'drizzle-orm/sqlite-core'; -import { customAlphabet } from 'nanoid'; -import color from 'piccolore'; -import { isSerializedSQL } from '../../runtime/types.js'; -import { getDbError, hasPrimaryKey } from '../../runtime/utils.js'; -import { MIGRATION_VERSION } from '../consts.js'; -import { createClient } from '../db-client/libsql-node.js'; -import { RENAME_COLUMN_ERROR, RENAME_TABLE_ERROR } from '../errors.js'; -import { - getCreateIndexQueries, - getCreateTableQuery, - getDropTableIfExistsQuery, - getModifiers, - getReferencesConfig, - hasDefault, - schemaTypeToSqlType, -} from '../queries.js'; -import { columnSchema } from '../schemas.js'; -import type { - BooleanColumn, - ColumnType, - DateColumn, - DBColumn, - DBColumns, - DBConfig, - DBSnapshot, - JsonColumn, - NumberColumn, - ResolvedDBTable, - ResolvedDBTables, - ResolvedIndexes, - TextColumn, -} from '../types.js'; -import type { RemoteDatabaseInfo } from '../utils.js'; - -const sqlite = new SQLiteAsyncDialect(); -const genTempTableName = customAlphabet('abcdefghijklmnopqrstuvwxyz', 10); - -export async function getMigrationQueries({ - oldSnapshot, - newSnapshot, - reset = false, -}: { - oldSnapshot: DBSnapshot; - newSnapshot: DBSnapshot; - reset?: boolean; -}): Promise<{ queries: string[]; confirmations: string[] }> { - const queries: string[] = []; - const confirmations: string[] = []; - - // When doing a reset, first create DROP TABLE statements, then treat everything - // else as creation. - if (reset) { - const currentSnapshot = oldSnapshot; - oldSnapshot = createEmptySnapshot(); - queries.push(...getDropTableQueriesForSnapshot(currentSnapshot)); - } - - const addedTables = getAddedTables(oldSnapshot, newSnapshot); - const droppedTables = getDroppedTables(oldSnapshot, newSnapshot); - const notDeprecatedDroppedTables = Object.fromEntries( - Object.entries(droppedTables).filter(([, table]) => !table.deprecated), - ); - if (!isEmpty(addedTables) && !isEmpty(notDeprecatedDroppedTables)) { - const oldTable = Object.keys(notDeprecatedDroppedTables)[0]; - const newTable = Object.keys(addedTables)[0]; - throw new Error(RENAME_TABLE_ERROR(oldTable, newTable)); - } - - for (const [tableName, table] of Object.entries(addedTables)) { - queries.push(getCreateTableQuery(tableName, table)); - queries.push(...getCreateIndexQueries(tableName, table)); - } - - for (const [tableName] of Object.entries(droppedTables)) { - const dropQuery = `DROP TABLE ${sqlite.escapeName(tableName)}`; - queries.push(dropQuery); - } - - for (const [tableName, newTable] of Object.entries(newSnapshot.schema)) { - const oldTable = oldSnapshot.schema[tableName]; - if (!oldTable) continue; - const addedColumns = getAdded(oldTable.columns, newTable.columns); - const droppedColumns = getDropped(oldTable.columns, newTable.columns); - const notDeprecatedDroppedColumns = Object.fromEntries( - Object.entries(droppedColumns).filter(([, col]) => !col.schema.deprecated), - ); - if (!isEmpty(addedColumns) && !isEmpty(notDeprecatedDroppedColumns)) { - throw new Error( - RENAME_COLUMN_ERROR( - `${tableName}.${Object.keys(addedColumns)[0]}`, - `${tableName}.${Object.keys(notDeprecatedDroppedColumns)[0]}`, - ), - ); - } - const result = await getTableChangeQueries({ - tableName, - oldTable, - newTable, - }); - queries.push(...result.queries); - confirmations.push(...result.confirmations); - } - return { queries, confirmations }; -} - -export async function getTableChangeQueries({ - tableName, - oldTable, - newTable, -}: { - tableName: string; - oldTable: ResolvedDBTable; - newTable: ResolvedDBTable; -}): Promise<{ queries: string[]; confirmations: string[] }> { - const queries: string[] = []; - const confirmations: string[] = []; - const updated = getUpdatedColumns(oldTable.columns, newTable.columns); - const added = getAdded(oldTable.columns, newTable.columns); - const dropped = getDropped(oldTable.columns, newTable.columns); - /** Any foreign key changes require a full table recreate */ - const hasForeignKeyChanges = - diff(oldTable.foreignKeys ?? [], newTable.foreignKeys ?? []).length > 0; - - if (!hasForeignKeyChanges && isEmpty(updated) && isEmpty(added) && isEmpty(dropped)) { - return { - queries: getChangeIndexQueries({ - tableName, - oldIndexes: oldTable.indexes, - newIndexes: newTable.indexes, - }), - confirmations, - }; - } - - if ( - !hasForeignKeyChanges && - isEmpty(updated) && - Object.values(dropped).every(canAlterTableDropColumn) && - Object.values(added).every(canAlterTableAddColumn) - ) { - queries.push( - ...getAlterTableQueries(tableName, added, dropped), - ...getChangeIndexQueries({ - tableName, - oldIndexes: oldTable.indexes, - newIndexes: newTable.indexes, - }), - ); - return { queries, confirmations }; - } - - const dataLossCheck = canRecreateTableWithoutDataLoss(added, updated); - if (dataLossCheck.dataLoss) { - const { reason, columnName } = dataLossCheck; - const reasonMsgs: Record = { - 'added-required': `You added new required column '${color.bold( - tableName + '.' + columnName, - )}' with no default value.\n This cannot be executed on an existing table.`, - 'updated-type': `Updating existing column ${color.bold( - tableName + '.' + columnName, - )} to a new type that cannot be handled automatically.`, - }; - confirmations.push(reasonMsgs[reason]); - } - - const primaryKeyExists = Object.entries(newTable.columns).find(([, column]) => - hasPrimaryKey(column), - ); - const droppedPrimaryKey = Object.entries(dropped).find(([, column]) => hasPrimaryKey(column)); - - const recreateTableQueries = getRecreateTableQueries({ - tableName, - newTable, - added, - hasDataLoss: dataLossCheck.dataLoss, - migrateHiddenPrimaryKey: !primaryKeyExists && !droppedPrimaryKey, - }); - queries.push(...recreateTableQueries, ...getCreateIndexQueries(tableName, newTable)); - return { queries, confirmations }; -} - -function getChangeIndexQueries({ - tableName, - oldIndexes = {}, - newIndexes = {}, -}: { - tableName: string; - oldIndexes?: ResolvedIndexes; - newIndexes?: ResolvedIndexes; -}) { - const added = getAdded(oldIndexes, newIndexes); - const dropped = getDropped(oldIndexes, newIndexes); - const updated = getUpdated(oldIndexes, newIndexes); - - Object.assign(dropped, updated); - Object.assign(added, updated); - - const queries: string[] = []; - for (const indexName of Object.keys(dropped)) { - const dropQuery = `DROP INDEX ${sqlite.escapeName(indexName)}`; - queries.push(dropQuery); - } - queries.push(...getCreateIndexQueries(tableName, { indexes: added })); - return queries; -} - -function getAddedTables(oldTables: DBSnapshot, newTables: DBSnapshot): ResolvedDBTables { - const added: ResolvedDBTables = {}; - for (const [key, newTable] of Object.entries(newTables.schema)) { - if (!(key in oldTables.schema)) added[key] = newTable; - } - return added; -} - -function getDroppedTables(oldTables: DBSnapshot, newTables: DBSnapshot): ResolvedDBTables { - const dropped: ResolvedDBTables = {}; - for (const [key, oldTable] of Object.entries(oldTables.schema)) { - if (!(key in newTables.schema)) dropped[key] = oldTable; - } - return dropped; -} - -/** - * Get ALTER TABLE queries to update the table schema. Assumes all added and dropped columns pass - * `canUseAlterTableAddColumn` and `canAlterTableDropColumn` checks! - */ -function getAlterTableQueries( - unescTableName: string, - added: DBColumns, - dropped: DBColumns, -): string[] { - const queries: string[] = []; - const tableName = sqlite.escapeName(unescTableName); - - for (const [unescColumnName, column] of Object.entries(added)) { - const columnName = sqlite.escapeName(unescColumnName); - const type = schemaTypeToSqlType(column.type); - const q = `ALTER TABLE ${tableName} ADD COLUMN ${columnName} ${type}${getModifiers( - columnName, - column, - )}`; - queries.push(q); - } - - for (const unescColumnName of Object.keys(dropped)) { - const columnName = sqlite.escapeName(unescColumnName); - const q = `ALTER TABLE ${tableName} DROP COLUMN ${columnName}`; - queries.push(q); - } - - return queries; -} - -function getRecreateTableQueries({ - tableName: unescTableName, - newTable, - added, - hasDataLoss, - migrateHiddenPrimaryKey, -}: { - tableName: string; - newTable: ResolvedDBTable; - added: Record; - hasDataLoss: boolean; - migrateHiddenPrimaryKey: boolean; -}): string[] { - const unescTempName = `${unescTableName}_${genTempTableName()}`; - const tempName = sqlite.escapeName(unescTempName); - const tableName = sqlite.escapeName(unescTableName); - - if (hasDataLoss) { - return [`DROP TABLE ${tableName}`, getCreateTableQuery(unescTableName, newTable)]; - } - const newColumns = [...Object.keys(newTable.columns)]; - if (migrateHiddenPrimaryKey) { - newColumns.unshift('_id'); - } - const escapedColumns = newColumns - .filter((i) => !(i in added)) - .map((c) => sqlite.escapeName(c)) - .join(', '); - - return [ - getCreateTableQuery(unescTempName, newTable), - `INSERT INTO ${tempName} (${escapedColumns}) SELECT ${escapedColumns} FROM ${tableName}`, - `DROP TABLE ${tableName}`, - `ALTER TABLE ${tempName} RENAME TO ${tableName}`, - ]; -} - -function isEmpty(obj: Record) { - return Object.keys(obj).length === 0; -} - -/** - * ADD COLUMN is preferred for O(1) table updates, but is only supported for _some_ column - * definitions. - * - * @see https://www.sqlite.org/lang_altertable.html#alter_table_add_column - */ -function canAlterTableAddColumn(column: DBColumn) { - if (column.schema.unique) return false; - if (hasRuntimeDefault(column)) return false; - if (!column.schema.optional && !hasDefault(column)) return false; - if (hasPrimaryKey(column)) return false; - if (getReferencesConfig(column)) return false; - return true; -} - -function canAlterTableDropColumn(column: DBColumn) { - if (column.schema.unique) return false; - if (hasPrimaryKey(column)) return false; - return true; -} - -type DataLossReason = 'added-required' | 'updated-type'; -type DataLossResponse = - | { dataLoss: false } - | { dataLoss: true; columnName: string; reason: DataLossReason }; - -function canRecreateTableWithoutDataLoss( - added: DBColumns, - updated: UpdatedColumns, -): DataLossResponse { - for (const [columnName, a] of Object.entries(added)) { - if (hasPrimaryKey(a) && a.type !== 'number' && !hasDefault(a)) { - return { dataLoss: true, columnName, reason: 'added-required' }; - } - if (!a.schema.optional && !hasDefault(a)) { - return { dataLoss: true, columnName, reason: 'added-required' }; - } - } - for (const [columnName, u] of Object.entries(updated)) { - if (u.old.type !== u.new.type && !canChangeTypeWithoutQuery(u.old, u.new)) { - return { dataLoss: true, columnName, reason: 'updated-type' }; - } - } - return { dataLoss: false }; -} - -function getAdded(oldObj: Record, newObj: Record) { - const added: Record = {}; - for (const [key, value] of Object.entries(newObj)) { - if (!(key in oldObj)) added[key] = value; - } - return added; -} - -function getDropped(oldObj: Record, newObj: Record) { - const dropped: Record = {}; - for (const [key, value] of Object.entries(oldObj)) { - if (!(key in newObj)) dropped[key] = value; - } - return dropped; -} - -function getUpdated>( - oldObj: Record, - newObj: Record, -) { - const updated: Record = {}; - for (const [key, value] of Object.entries(newObj)) { - const oldValue = oldObj[key]; - if (!oldValue) continue; - if (diff(oldValue, value).length > 0) updated[key] = value; - } - return updated; -} - -type UpdatedColumns = Record; - -function getUpdatedColumns(oldColumns: DBColumns, newColumns: DBColumns): UpdatedColumns { - const updated: UpdatedColumns = {}; - for (const [key, newColumn] of Object.entries(newColumns)) { - let oldColumn = oldColumns[key]; - if (!oldColumn) continue; - - if (oldColumn.type !== newColumn.type && canChangeTypeWithoutQuery(oldColumn, newColumn)) { - // If we can safely change the type without a query, - // try parsing the old schema as the new schema. - // This lets us diff the columns as if they were the same type. - const asNewColumn = columnSchema.safeParse({ - type: newColumn.type, - schema: oldColumn.schema, - }); - if (asNewColumn.success) { - oldColumn = asNewColumn.data; - } - // If parsing fails, move on to the standard diff. - } - - const diffResult = diff(oldColumn, newColumn); - - if (diffResult.length > 0) { - updated[key] = { old: oldColumn, new: newColumn }; - } - } - return updated; -} -const typeChangesWithoutQuery: Array<{ from: ColumnType; to: ColumnType }> = [ - { from: 'boolean', to: 'number' }, - { from: 'date', to: 'text' }, - { from: 'json', to: 'text' }, -]; - -function canChangeTypeWithoutQuery(oldColumn: DBColumn, newColumn: DBColumn) { - return typeChangesWithoutQuery.some( - ({ from, to }) => oldColumn.type === from && newColumn.type === to, - ); -} - -// Using `DBColumn` will not narrow `default` based on the column `type` -// Handle each column separately -type WithDefaultDefined = T & Required>; -type DBColumnWithDefault = - | WithDefaultDefined - | WithDefaultDefined - | WithDefaultDefined - | WithDefaultDefined - | WithDefaultDefined; - -function hasRuntimeDefault(column: DBColumn): column is DBColumnWithDefault { - return !!(column.schema.default && isSerializedSQL(column.schema.default)); -} - -export function getProductionCurrentSnapshot({ - url, - token, -}: RemoteDatabaseInfo): Promise { - return getDbCurrentSnapshot(token, url); -} - -async function getDbCurrentSnapshot( - appToken: string, - remoteUrl: string, -): Promise { - const client = createClient({ - token: appToken, - url: remoteUrl, - }); - - try { - const res = await client.get<{ snapshot: string }>( - // Latest snapshot - sql`select snapshot from _astro_db_snapshot order by id desc limit 1;`, - ); - - return JSON.parse(res.snapshot); - } catch (error) { - const dbError = getDbError(error); - // Don't handle errors that are not from libSQL - if ( - dbError && - // If the schema was never pushed to the database yet the table won't exist. - // Treat a missing snapshot table as an empty table. - - // When connecting to a remote database in that condition - // the query will fail with the following error code and message. - ((dbError.code === 'SQLITE_UNKNOWN' && - dbError.message === 'SQLITE_UNKNOWN: SQLite error: no such table: _astro_db_snapshot') || - // When connecting to a local or in-memory database that does not have a snapshot table yet - // the query will fail with the following error code and message. - (dbError.code === 'SQLITE_ERROR' && - dbError.message === 'SQLITE_ERROR: no such table: _astro_db_snapshot')) - ) { - return; - } - - throw error; - } -} - -function getDropTableQueriesForSnapshot(snapshot: DBSnapshot) { - const queries = []; - for (const tableName of Object.keys(snapshot.schema)) { - const dropQuery = getDropTableIfExistsQuery(tableName); - queries.unshift(dropQuery); - } - return queries; -} - -export function createCurrentSnapshot({ tables = {} }: DBConfig): DBSnapshot { - const schema = JSON.parse(JSON.stringify(tables)); - return { version: MIGRATION_VERSION, schema }; -} - -export function createEmptySnapshot(): DBSnapshot { - return { version: MIGRATION_VERSION, schema: {} }; -} - -export function formatDataLossMessage(confirmations: string[], isColor = true): string { - const messages = []; - messages.push(color.red('✖ We found some schema changes that cannot be handled automatically:')); - messages.push(``); - messages.push(...confirmations.map((m, i) => color.red(` (${i + 1}) `) + m)); - messages.push(``); - messages.push(`To resolve, revert these changes or update your schema, and re-run the command.`); - messages.push( - `You may also run 'astro db push --force-reset' to ignore all warnings and force-push your local database schema to production instead. All data will be lost and the database will be reset.`, - ); - let finalMessage = messages.join('\n'); - if (!isColor) { - finalMessage = stripVTControlCharacters(finalMessage); - } - return finalMessage; -} diff --git a/packages/db/src/core/cli/print-help.ts b/packages/db/src/core/cli/print-help.ts deleted file mode 100644 index 9f859a7c9f11..000000000000 --- a/packages/db/src/core/cli/print-help.ts +++ /dev/null @@ -1,69 +0,0 @@ -import colors from 'piccolore'; - -/** - * Uses implementation from Astro core - * @see https://github.com/withastro/astro/blob/main/packages/astro/src/core/messages.ts#L303 - */ -export function printHelp({ - commandName, - headline, - usage, - tables, - description, -}: { - commandName: string; - headline?: string; - usage?: string; - tables?: Record; - description?: string; -}) { - const linebreak = () => ''; - const title = (label: string) => ` ${colors.bgWhite(colors.black(` ${label} `))}`; - const table = (rows: [string, string][], { padding }: { padding: number }) => { - const split = process.stdout.columns < 60; - let raw = ''; - - for (const row of rows) { - if (split) { - raw += ` ${row[0]}\n `; - } else { - raw += `${`${row[0]}`.padStart(padding)}`; - } - raw += ' ' + colors.dim(row[1]) + '\n'; - } - - return raw.slice(0, -1); // remove latest \n - }; - - let message = []; - - if (headline) { - message.push( - linebreak(), - ` ${colors.bgGreen(colors.black(` ${commandName} `))} ${colors.green( - `v${process.env.PACKAGE_VERSION ?? ''}`, - )} ${headline}`, - ); - } - - if (usage) { - message.push(linebreak(), ` ${colors.green(commandName)} ${colors.bold(usage)}`); - } - - if (tables) { - function calculateTablePadding(rows: [string, string][]) { - return rows.reduce((val, [first]) => Math.max(val, first.length), 0) + 2; - } - const tableEntries = Object.entries(tables); - const padding = Math.max(...tableEntries.map(([, rows]) => calculateTablePadding(rows))); - for (const [tableTitle, tableRows] of tableEntries) { - message.push(linebreak(), title(tableTitle), table(tableRows, { padding })); - } - } - - if (description) { - message.push(linebreak(), `${description}`); - } - - console.log(message.join('\n') + '\n'); -} diff --git a/packages/db/src/core/consts.ts b/packages/db/src/core/consts.ts deleted file mode 100644 index 7cb3cf565cc2..000000000000 --- a/packages/db/src/core/consts.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { readFileSync } from 'node:fs'; - -const PACKAGE_NAME = JSON.parse( - readFileSync(new URL('../../package.json', import.meta.url), 'utf8'), -).name; - -export const RUNTIME_IMPORT = JSON.stringify(`${PACKAGE_NAME}/runtime`); - -export const RUNTIME_VIRTUAL_IMPORT = JSON.stringify(`${PACKAGE_NAME}/dist/runtime/virtual.js`); - -export const VIRTUAL_MODULE_ID = 'astro:db'; - -export const DB_PATH = '.astro/content.db'; - -export const CONFIG_FILE_NAMES = ['config.ts', 'config.js', 'config.mts', 'config.mjs']; - -export const MIGRATION_VERSION = '2024-03-12'; - -export const VIRTUAL_CLIENT_MODULE_ID = 'virtual:astro:db-client'; - -export const DB_CLIENTS = { - node: `${PACKAGE_NAME}/db-client/libsql-node.js`, - web: `${PACKAGE_NAME}/db-client/libsql-web.js`, - local: `${PACKAGE_NAME}/db-client/libsql-local.js`, -}; diff --git a/packages/db/src/core/db-client/libsql-local.ts b/packages/db/src/core/db-client/libsql-local.ts deleted file mode 100644 index 8d8f6ad3df30..000000000000 --- a/packages/db/src/core/db-client/libsql-local.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { createClient as createLibsqlClient } from '@libsql/client'; -import { drizzle as drizzleLibsql, type LibSQLDatabase } from 'drizzle-orm/libsql'; - -const isWebContainer = !!process.versions?.webcontainer; - -type LocalDbClientOptions = { - url: string; -}; - -export function createClient(options: LocalDbClientOptions): LibSQLDatabase { - const url = isWebContainer ? 'file:content.db' : options.url; - const client = createLibsqlClient({ url }); - const db = drizzleLibsql(client); - return db; -} diff --git a/packages/db/src/core/db-client/libsql-node.ts b/packages/db/src/core/db-client/libsql-node.ts deleted file mode 100644 index 1653d4047564..000000000000 --- a/packages/db/src/core/db-client/libsql-node.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { createClient as createLibsqlClient } from '@libsql/client'; -import { drizzle as drizzleLibsql } from 'drizzle-orm/libsql'; -import { parseLibSQLConfig } from './utils.js'; - -type RemoteDbClientOptions = { - token: string; - url: string; -}; - -export function createClient(opts: RemoteDbClientOptions) { - const { token, url: rawUrl } = opts; - - let parsedUrl = new URL(rawUrl); - - const options: Record = Object.fromEntries(parsedUrl.searchParams.entries()); - parsedUrl.search = ''; - - let url = parsedUrl.toString(); - if (parsedUrl.protocol === 'memory:') { - // libSQL expects a special string in place of a URL - // for in-memory DBs. - url = ':memory:'; - } else if ( - parsedUrl.protocol === 'file:' && - parsedUrl.pathname.startsWith('/') && - !rawUrl.startsWith('file:/') - ) { - // libSQL accepts relative and absolute file URLs - // for local DBs. This doesn't match the URL specification. - // Parsing `file:some.db` and `file:/some.db` should yield - // the same result, but libSQL interprets the former as - // a relative path, and the latter as an absolute path. - // This detects when such a conversion happened during parsing - // and undoes it so that the URL given to libSQL is the - // same as given by the user. - url = 'file:' + parsedUrl.pathname.substring(1); - } - - const libSQLOptions = parseLibSQLConfig(options); - - const client = createLibsqlClient({ ...libSQLOptions, url, authToken: token }); - return drizzleLibsql(client); -} diff --git a/packages/db/src/core/db-client/libsql-web.ts b/packages/db/src/core/db-client/libsql-web.ts deleted file mode 100644 index fce032f61e60..000000000000 --- a/packages/db/src/core/db-client/libsql-web.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { createClient as createLibsqlClient } from '@libsql/client/web'; -import { drizzle as drizzleLibsql } from 'drizzle-orm/libsql/web'; -import { parseLibSQLConfig } from './utils.js'; - -type RemoteDbClientOptions = { - token: string; - url: string; -}; - -export function createClient(opts: RemoteDbClientOptions) { - const { token, url: rawUrl } = opts; - - let parsedUrl = new URL(rawUrl); - - const options: Record = Object.fromEntries(parsedUrl.searchParams.entries()); - - parsedUrl.search = ''; - - let url = parsedUrl.toString(); - - const supportedProtocols = ['http:', 'https:', 'libsql:']; - - if (!supportedProtocols.includes(parsedUrl.protocol)) { - throw new Error( - `Unsupported protocol "${parsedUrl.protocol}" for libSQL web client. Supported protocols are: ${supportedProtocols.join(', ')}.`, - ); - } - - const libSQLOptions = parseLibSQLConfig(options); - - const client = createLibsqlClient({ ...libSQLOptions, url, authToken: token }); - return drizzleLibsql(client); -} diff --git a/packages/db/src/core/db-client/utils.ts b/packages/db/src/core/db-client/utils.ts deleted file mode 100644 index 7de5f5b4da90..000000000000 --- a/packages/db/src/core/db-client/utils.ts +++ /dev/null @@ -1,57 +0,0 @@ -import type { Config as LibSQLConfig } from '@libsql/client'; -import * as z from 'zod/v4'; - -const rawLibSQLOptions = z.record(z.string(), z.string()); - -const parseNumber = (value: string) => z.coerce.number().parse(value); -const parseBoolean = (value: string) => z.coerce.boolean().parse(value); - -const booleanValues = ['true', 'false']; - -// parse a value that should be a boolean, but could be a valueless variable: -// e.g. 'file://local-copy.db?readYourWrites' & 'file://local-copy.db?readYourWrites=true' should be parsed as true -const parseOptionalBoolean = (value: string) => { - if (booleanValues.includes(value)) { - return parseBoolean(value); - } - return true; // If the value is not explicitly 'true' or 'false', assume it's true (valueless variable) -}; - -const libSQLConfigTransformed = rawLibSQLOptions.transform((raw) => { - // Ensure the URL is always present - const parsed: Partial = {}; - - // Optional fields - for (const [key, value] of Object.entries(raw)) { - switch (key) { - case 'syncInterval': - case 'concurrency': - parsed[key] = parseNumber(value); - break; - case 'readYourWrites': - case 'offline': - case 'tls': - parsed[key] = parseOptionalBoolean(value); - break; - case 'authToken': - case 'encryptionKey': - case 'syncUrl': - parsed[key] = value; - break; - } - } - - // Return the parsed config - return parsed; -}); - -export const parseLibSQLConfig = (config: Record): Partial => { - try { - return libSQLConfigTransformed.parse(config); - } catch (error) { - if (error instanceof z.ZodError) { - throw new Error(`Invalid LibSQL config: ${error.issues.map((e) => e.message).join(', ')}`); - } - throw error; - } -}; diff --git a/packages/db/src/core/errors.ts b/packages/db/src/core/errors.ts deleted file mode 100644 index d99464a4f79d..000000000000 --- a/packages/db/src/core/errors.ts +++ /dev/null @@ -1,52 +0,0 @@ -import colors from 'piccolore'; - -export const MISSING_EXECUTE_PATH_ERROR = `${colors.red( - '▶ No file path provided.', -)} Provide a path by running ${colors.cyan('astro db execute ')}\n`; - -export const RENAME_TABLE_ERROR = (oldTable: string, newTable: string) => { - return ( - colors.red('\u25B6 Potential table rename detected: ' + oldTable + ' -> ' + newTable) + - ` - You cannot add and remove tables in the same schema update batch. - - 1. Use "deprecated: true" to deprecate a table before renaming. - 2. Use "--force-reset" to ignore this warning and reset the database (deleting all of your data). - - Visit https://docs.astro.build/en/guides/astro-db/#renaming-tables to learn more.` - ); -}; - -export const RENAME_COLUMN_ERROR = (oldSelector: string, newSelector: string) => { - return ( - colors.red('▶ Potential column rename detected: ' + oldSelector + ', ' + newSelector) + - `\n You cannot add and remove columns in the same table.` + - `\n To resolve, add a 'deprecated: true' flag to '${oldSelector}' instead.` - ); -}; - -export const FILE_NOT_FOUND_ERROR = (path: string) => - `${colors.red('▶ File not found:')} ${colors.bold(path)}\n`; - -export const SHELL_QUERY_MISSING_ERROR = `${colors.red( - '▶ Please provide a query to execute using the --query flag.', -)}\n`; - -export const EXEC_ERROR = (error: string) => { - return `${colors.red(`Error while executing file:`)}\n\n${error}`; -}; - -export const EXEC_DEFAULT_EXPORT_ERROR = (fileName: string) => { - return EXEC_ERROR(`Missing default function export in ${colors.bold(fileName)}`); -}; - -export const INTEGRATION_TABLE_CONFLICT_ERROR = ( - integrationName: string, - tableName: string, - isUserConflict: boolean, -) => { - return colors.red('▶ Conflicting table name in integration ' + colors.bold(integrationName)) + - isUserConflict - ? `\n A user-defined table named ${colors.bold(tableName)} already exists` - : `\n Another integration already added a table named ${colors.bold(tableName)}`; -}; diff --git a/packages/db/src/core/integration/error-map.ts b/packages/db/src/core/integration/error-map.ts deleted file mode 100644 index 6e1af1ecb213..000000000000 --- a/packages/db/src/core/integration/error-map.ts +++ /dev/null @@ -1,164 +0,0 @@ -import type { $ZodErrorMap } from 'zod/v4/core'; - -type TypeOrLiteralErrByPathEntry = { - code: 'invalid_type' | 'invalid_literal'; - received: unknown; - expected: unknown[]; - message: string | undefined; -}; - -export const errorMap: $ZodErrorMap = (issue) => { - const baseErrorPath = flattenErrorPath(issue.path ?? []); - if (issue.code === 'invalid_union') { - // Optimization: Combine type and literal errors for keys that are common across ALL union types - // Ex. a union between `{ key: z.literal('tutorial') }` and `{ key: z.literal('blog') }` will - // raise a single error when `key` does not match: - // > Did not match union. - // > key: Expected `'tutorial' | 'blog'`, received 'foo' - let typeOrLiteralErrByPath = new Map(); - for (const unionError of issue.errors.flat()) { - if (unionError.code === 'invalid_type') { - const flattenedErrorPath = flattenErrorPath(unionError.path); - if (typeOrLiteralErrByPath.has(flattenedErrorPath)) { - typeOrLiteralErrByPath.get(flattenedErrorPath)!.expected.push(unionError.expected); - } else { - typeOrLiteralErrByPath.set(flattenedErrorPath, { - code: unionError.code, - received: (unionError as any).received, - expected: [unionError.expected], - message: unionError.message, - }); - } - } - } - const messages: string[] = [prefix(baseErrorPath, 'Did not match union.')]; - const details: string[] = [...typeOrLiteralErrByPath.entries()] - // If type or literal error isn't common to ALL union types, - // filter it out. Can lead to confusing noise. - .filter(([, error]) => error.expected.length === issue.errors.flat().length) - .map(([key, error]) => - key === baseErrorPath - ? // Avoid printing the key again if it's a base error - `> ${getTypeOrLiteralMsg(error)}` - : `> ${prefix(key, getTypeOrLiteralMsg(error))}`, - ); - - if (details.length === 0) { - // For discriminated unions, show the expected discriminator options - if ('discriminator' in issue && issue.discriminator && 'options' in issue) { - const options = (issue as any).options; - if (Array.isArray(options)) { - details.push( - `> Expected \`${issue.discriminator}\` to be ${options.map((o: unknown) => `\`${stringify(o)}\``).join(' | ')}`, - ); - details.push('> Received `' + stringify(issue.input) + '`'); - } - } - } - - if (details.length === 0) { - const expectedShapes: string[] = []; - for (const unionErrors of issue.errors) { - const expectedShape: string[] = []; - for (const _issue of unionErrors) { - // If the issue is a nested union error, show the associated error message instead of the - // base error message. - if (_issue.code === 'invalid_union') { - return errorMap(_issue as any); - } - const relativePath = flattenErrorPath(_issue.path) - .replace(baseErrorPath, '') - .replace(leadingPeriod, ''); - if ('expected' in _issue && typeof _issue.expected === 'string') { - expectedShape.push( - relativePath ? `${relativePath}: ${_issue.expected}` : _issue.expected, - ); - } else if ('values' in _issue) { - expectedShape.push( - ..._issue.values.filter((v) => typeof v === 'string').map((v) => `"${v}"`), - ); - } else if (relativePath) { - expectedShape.push(relativePath); - } - } - if (expectedShape.length === 1 && !expectedShape[0]?.includes(':')) { - // In this case the expected shape is not an object, but probably a literal type, e.g. `['string']`. - expectedShapes.push(expectedShape.join('')); - } else if (expectedShape.length > 0) { - expectedShapes.push(`{ ${expectedShape.join('; ')} }`); - } - } - if (expectedShapes.length) { - details.push('> Expected type `' + expectedShapes.join(' | ') + '`'); - details.push('> Received `' + stringify(issue.input) + '`'); - } - } - - return { - message: messages.concat(details).join('\n'), - }; - } else if (issue.code === 'invalid_key') { - // Zod 4.4.0+: Record key validation failures are now structured `invalid_key` issues - // with nested `issues` array containing the actual validation errors. - const keyIssues = (issue as any).issues; - if (Array.isArray(keyIssues) && keyIssues.length > 0) { - const firstIssue = keyIssues[0]; - const msg = firstIssue.message || 'Invalid key in record'; - return { message: prefix(baseErrorPath, msg) }; - } - return { message: prefix(baseErrorPath, 'Invalid key in record') }; - } else if (issue.code === 'invalid_element') { - // Zod 4.4.0+: Map/Set element validation failures are now structured `invalid_element` issues. - const elementIssues = (issue as any).issues; - if (Array.isArray(elementIssues) && elementIssues.length > 0) { - const firstIssue = elementIssues[0]; - const msg = firstIssue.message || 'Invalid element'; - return { message: prefix(baseErrorPath, msg) }; - } - return { message: prefix(baseErrorPath, 'Invalid element') }; - } else if (issue.code === 'invalid_type') { - return { - message: prefix( - baseErrorPath, - getTypeOrLiteralMsg({ - code: issue.code, - received: typeof issue.input, - expected: [issue.expected], - message: issue.message, - }), - ), - }; - } else if (issue.message) { - return { message: prefix(baseErrorPath, issue.message) }; - } -}; - -const getTypeOrLiteralMsg = (error: TypeOrLiteralErrByPathEntry): string => { - // received could be `undefined` or the string `'undefined'` - if (typeof error.received === 'undefined' || error.received === 'undefined') - return error.message ?? 'Required'; - const expectedDeduped = new Set(error.expected); - switch (error.code) { - case 'invalid_type': - return `Expected type \`${unionExpectedVals(expectedDeduped)}\`, received \`${stringify( - error.received, - )}\``; - case 'invalid_literal': - return `Expected \`${unionExpectedVals(expectedDeduped)}\`, received \`${stringify( - error.received, - )}\``; - } -}; - -const prefix = (key: string, msg: string) => (key.length ? `**${key}**: ${msg}` : msg); - -const unionExpectedVals = (expectedVals: Set) => - [...expectedVals].map((expectedVal) => stringify(expectedVal)).join(' | '); - -const flattenErrorPath = (errorPath: (string | number | symbol)[]) => errorPath.join('.'); - -/** `JSON.stringify()` a value with spaces around object/array entries. */ -const stringify = (val: unknown) => - JSON.stringify(val, null, 1).split(newlinePlusWhitespace).join(' '); -const newlinePlusWhitespace = /\n\s*/; -const leadingPeriod = /^\./; diff --git a/packages/db/src/core/integration/file-url.ts b/packages/db/src/core/integration/file-url.ts deleted file mode 100644 index 2c91c0725537..000000000000 --- a/packages/db/src/core/integration/file-url.ts +++ /dev/null @@ -1,98 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; -import { pathToFileURL } from 'node:url'; -import type { AstroConfig, AstroIntegration } from 'astro'; -import type { VitePlugin } from '../utils.js'; - -async function copyFile(toDir: URL, fromUrl: URL, toUrl: URL) { - await fs.promises.mkdir(toDir, { recursive: true }); - await fs.promises.rename(fromUrl, toUrl); -} - -export function fileURLIntegration(): AstroIntegration { - const fileNames: string[] = []; - - function createVitePlugin(command: 'build' | 'preview' | 'dev' | 'sync'): VitePlugin { - let referenceIds: string[] = []; - return { - name: '@astrojs/db/file-url', - enforce: 'pre', - load: { - filter: { - id: /\?fileurl$/, - }, - async handler(id) { - const filePath = id.slice(0, id.indexOf('?')); - if (command === 'build') { - const data = await fs.promises.readFile(filePath); - const name = path.basename(filePath); - const referenceId = this.emitFile({ - name, - source: data, - type: 'asset', - }); - referenceIds.push(referenceId); - return `export default import.meta.ROLLUP_FILE_URL_${referenceId};`; - } - // dev mode - else { - return `export default new URL(${JSON.stringify(pathToFileURL(filePath).toString())})`; - } - }, - }, - generateBundle() { - // Save file names so we can copy them back over. - for (const referenceId of referenceIds) { - fileNames.push(this.getFileName(referenceId)); - } - // Reset `referenceIds` for later generateBundle() runs. - // Prevents lookup for ids that have already been copied. - referenceIds = []; - }, - }; - } - - let config: AstroConfig; - return { - name: '@astrojs/db/file-url', - hooks: { - 'astro:config:setup'({ updateConfig, command }) { - updateConfig({ - vite: { - plugins: [createVitePlugin(command)], - }, - }); - }, - 'astro:config:done': ({ config: _config }) => { - config = _config; - }, - async 'astro:build:done'() { - if (config.output === 'static') { - // Delete the files since they are only used for the build process. - const unlinks: Promise[] = []; - for (const fileName of fileNames) { - const url = new URL(fileName, config.outDir); - unlinks.push(fs.promises.unlink(url)); - } - await Promise.all(unlinks); - // Delete the assets directory if it is empty. - // NOTE(fks): Ignore errors here because this is expected to fail - // if the directory contains files, or if it does not exist. - // If it errors for some unknown reason, it's not a big deal. - const assetDir = new URL(config.build.assets, config.outDir); - await fs.promises.rmdir(assetDir).catch(() => []); - } else { - // Move files back over to the dist output path - const moves: Promise[] = []; - for (const fileName of fileNames) { - const fromUrl = new URL(fileName, config.build.client); - const toUrl = new URL(fileName, config.build.server); - const toDir = new URL('./', toUrl); - moves.push(copyFile(toDir, fromUrl, toUrl)); - } - await Promise.all(moves); - } - }, - }, - }; -} diff --git a/packages/db/src/core/integration/index.ts b/packages/db/src/core/integration/index.ts deleted file mode 100644 index c72914f30048..000000000000 --- a/packages/db/src/core/integration/index.ts +++ /dev/null @@ -1,271 +0,0 @@ -import { existsSync } from 'node:fs'; -import { mkdir, writeFile } from 'node:fs/promises'; -import { dirname } from 'node:path'; -import { fileURLToPath } from 'node:url'; -import type { AstroIntegration, HookParameters } from 'astro'; -import colors from 'piccolore'; -import { - createServer, - type Environment, - type HotPayload, - isRunnableDevEnvironment, - loadEnv, - mergeConfig, - type RunnableDevEnvironment, - type ViteDevServer, -} from 'vite'; -import parseArgs from 'yargs-parser'; -import * as z from 'zod/v4'; -import { AstroDbError, getDbError } from '../../runtime/utils.js'; -import { CONFIG_FILE_NAMES, DB_PATH, VIRTUAL_MODULE_ID } from '../consts.js'; -import { EXEC_DEFAULT_EXPORT_ERROR, EXEC_ERROR } from '../errors.js'; -import { resolveDbConfig } from '../load-file.js'; -import { SEED_DEV_FILE_NAME } from '../queries.js'; -import { getDbDirectoryUrl, getRemoteDatabaseInfo, type VitePlugin } from '../utils.js'; -import { fileURLIntegration } from './file-url.js'; -import { getDtsContent } from './typegen.js'; -import { - type LateSeedFiles, - type LateTables, - type SeedHandler, - vitePluginDb, -} from './vite-plugin-db.js'; -import { vitePluginDbClient } from './vite-plugin-db-client.js'; - -const astroDBConfigSchema = z - .object({ - /** - * Sets the mode of the underlying `@libsql/client` connection. - * - * In most cases, the default 'node' mode is sufficient. On platforms like Cloudflare, or Deno, you may need to set this to 'web'. - * - * @default 'node' - */ - mode: z - .union([z.literal('node'), z.literal('web')]) - .optional() - .default('node'), - }) - .optional() - .prefault({}); - -export type AstroDBConfig = z.infer; - -function astroDBIntegration(options?: AstroDBConfig): AstroIntegration { - const resolvedConfig = astroDBConfigSchema.parse(options); - let connectToRemote = false; - let configFileDependencies: string[] = []; - let root: URL; - // Used during production builds to load seed files. - let tempViteServer: ViteDevServer | undefined; - - // Make table loading "late" to pass to plugins from `config:setup`, - // but load during `config:done` to wait for integrations to settle. - let tables: LateTables = { - get() { - throw new Error('[astro:db] INTERNAL Tables not loaded yet'); - }, - }; - let seedFiles: LateSeedFiles = { - get() { - throw new Error('[astro:db] INTERNAL Seed files not loaded yet'); - }, - }; - let seedHandler: SeedHandler = { - execute: () => { - throw new Error('[astro:db] INTERNAL Seed handler not loaded yet'); - }, - inProgress: false, - }; - - let command: HookParameters<'astro:config:setup'>['command']; - let finalBuildOutput: string; - return { - name: 'astro:db', - hooks: { - 'astro:config:setup': async ({ updateConfig, config, command: _command, logger }) => { - command = _command; - root = config.root; - - if (command === 'preview') return; - - let dbPlugin: VitePlugin | undefined = undefined; - const args = parseArgs(process.argv.slice(3)); - connectToRemote = process.env.ASTRO_INTERNAL_TEST_REMOTE || args['remote']; - - const dbClientPlugin = vitePluginDbClient({ - connectToRemote, - mode: resolvedConfig.mode, - }); - - if (connectToRemote) { - dbPlugin = vitePluginDb({ - connectToRemote, - appToken: getRemoteDatabaseInfo().token, - tables, - root: config.root, - srcDir: config.srcDir, - output: config.output, - seedHandler, - }); - } else { - dbPlugin = vitePluginDb({ - connectToRemote, - tables, - seedFiles, - root: config.root, - srcDir: config.srcDir, - output: config.output, - logger, - seedHandler, - }); - } - - updateConfig({ - vite: { - assetsInclude: [DB_PATH], - plugins: [dbClientPlugin, dbPlugin], - }, - }); - }, - 'astro:config:done': async ({ config, injectTypes, buildOutput }) => { - if (command === 'preview') return; - - finalBuildOutput = buildOutput; - - // TODO: refine where we load tables - // @matthewp: may want to load tables by path at runtime - const { dbConfig, dependencies, integrationSeedPaths } = await resolveDbConfig(config); - tables.get = () => dbConfig.tables; - seedFiles.get = () => integrationSeedPaths; - configFileDependencies = dependencies; - - const localDbUrl = new URL(DB_PATH, config.root); - if (!connectToRemote && !existsSync(localDbUrl)) { - await mkdir(dirname(fileURLToPath(localDbUrl)), { recursive: true }); - await writeFile(localDbUrl, ''); - } - - injectTypes({ - filename: 'db.d.ts', - content: getDtsContent(tables.get() ?? {}), - }); - }, - 'astro:server:setup': async ({ server, logger }) => { - let environment = server.environments['ssr'] as unknown as Environment; - if (!isRunnableDevEnvironment(environment)) { - return; - } - seedHandler.execute = async (fileUrl) => { - await executeSeedFile({ fileUrl, environment }); - }; - const filesToWatch = [ - ...CONFIG_FILE_NAMES.map((c) => new URL(c, getDbDirectoryUrl(root))), - ...configFileDependencies.map((c) => new URL(c, root)), - ]; - server.watcher.on('all', (_event, relativeEntry) => { - const entry = new URL(relativeEntry, root); - if (filesToWatch.some((f) => entry.href === f.href)) { - server.restart(); - } - }); - // Wait for dev server log before showing "connected". - logger.info( - connectToRemote ? 'Connected to remote database.' : 'New local database created.', - ); - if (connectToRemote) return; - - const localSeedPaths = SEED_DEV_FILE_NAME.map( - (name) => new URL(name, getDbDirectoryUrl(root)), - ); - // Eager load astro:db module on startup - if (seedFiles.get().length || localSeedPaths.find((path) => existsSync(path))) { - await environment.runner.import(VIRTUAL_MODULE_ID).catch((e) => { - logger.error(e instanceof Error ? e.message : String(e)); - }); - } - }, - 'astro:build:start': async ({ logger }) => { - if (!connectToRemote && !databaseFileEnvDefined() && finalBuildOutput === 'server') { - const message = `Attempting to build without the --remote flag or the ASTRO_DATABASE_FILE environment variable defined. You probably want to pass --remote to astro build.`; - const hint = - 'Learn more connecting to libSQL: https://docs.astro.build/en/guides/astro-db/#connect-a-libsql-database-for-production'; - throw new AstroDbError(message, hint); - } - - logger.info( - 'database: ' + - (connectToRemote ? colors.yellow('remote') : colors.blue('local database.')), - ); - }, - 'astro:build:setup': async ({ vite }) => { - tempViteServer = await getTempViteServer(vite); - const environment = tempViteServer.environments.ssr as RunnableDevEnvironment; - seedHandler.execute = async (fileUrl) => { - await executeSeedFile({ fileUrl, environment }); - }; - }, - 'astro:build:done': async () => { - await tempViteServer?.close(); - }, - }, - }; -} - -function databaseFileEnvDefined() { - const env = loadEnv('', process.cwd()); - return env.ASTRO_DATABASE_FILE != null || process.env.ASTRO_DATABASE_FILE != null; -} - -export function integration(options?: AstroDBConfig): AstroIntegration[] { - return [astroDBIntegration(options), fileURLIntegration()]; -} - -async function executeSeedFile({ - fileUrl, - environment, -}: { - fileUrl: URL; - environment: RunnableDevEnvironment; -}) { - // Use decodeURIComponent to handle paths with spaces correctly - // This ensures that %20 in the pathname is properly handled - const pathname = decodeURIComponent(fileUrl.pathname); - const mod = await environment.runner.import(pathname); - if (typeof mod.default !== 'function') { - throw new AstroDbError(EXEC_DEFAULT_EXPORT_ERROR(fileURLToPath(fileUrl))); - } - try { - await mod.default(); - } catch (e) { - const dbError = getDbError(e); - if (dbError) { - throw new AstroDbError(EXEC_ERROR(dbError.message)); - } - throw e; - } -} - -/** - * Inspired by Astro content collection config loader. - */ -async function getTempViteServer(viteConfig: HookParameters<'astro:build:setup'>['vite']) { - const tempViteServer = await createServer( - mergeConfig(viteConfig, { - server: { middlewareMode: true, hmr: false, watch: null, ws: false }, - optimizeDeps: { noDiscovery: true }, - ssr: { external: [] }, - logLevel: 'silent', - }), - ); - - const hotSend = tempViteServer.environments.client.hot.send; - tempViteServer.environments.client.hot.send = (payload: HotPayload) => { - if (payload.type === 'error') { - throw payload.err; - } - return hotSend(payload); - }; - - return tempViteServer; -} diff --git a/packages/db/src/core/integration/typegen.ts b/packages/db/src/core/integration/typegen.ts deleted file mode 100644 index 91364b3c3dc1..000000000000 --- a/packages/db/src/core/integration/typegen.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { RUNTIME_IMPORT } from '../consts.js'; -import type { DBTable, DBTables } from '../types.js'; - -export function getDtsContent(tables: DBTables) { - const content = `// This file is generated by Astro DB -declare module 'astro:db' { -${Object.entries(tables) - .map(([name, table]) => generateTableType(name, table)) - .join('\n')} -} -`; - return content; -} - -function generateTableType(name: string, table: DBTable): string { - const sanitizedColumnsList = Object.entries(table.columns) - // Filter out deprecated columns from the typegen, so that they don't - // appear as queryable fields in the generated types / your codebase. - .filter(([, val]) => !val.schema.deprecated); - const sanitizedColumns = Object.fromEntries(sanitizedColumnsList); - let tableType = ` export const ${name}: import(${RUNTIME_IMPORT}).Table< - ${JSON.stringify(name)}, - ${JSON.stringify(sanitizedColumns)} - >;`; - return tableType; -} diff --git a/packages/db/src/core/integration/vite-plugin-db-client.ts b/packages/db/src/core/integration/vite-plugin-db-client.ts deleted file mode 100644 index 928346fd3f44..000000000000 --- a/packages/db/src/core/integration/vite-plugin-db-client.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { DB_CLIENTS, VIRTUAL_CLIENT_MODULE_ID } from '../consts.js'; -import type { VitePlugin } from '../utils.js'; - -type VitePluginDBClientParams = { - connectToRemote: boolean; - mode: 'node' | 'web'; -}; - -function getRemoteClientModule(mode: 'node' | 'web') { - switch (mode) { - case 'web': - return `export { createClient } from '${DB_CLIENTS.web}';`; - case 'node': - default: - return `export { createClient } from '${DB_CLIENTS.node}';`; - } -} - -function getLocalClientModule(mode: 'node' | 'web') { - switch (mode) { - case 'node': - case 'web': - default: - return `export { createClient } from '${DB_CLIENTS.local}';`; - } -} - -const resolved = '\0' + VIRTUAL_CLIENT_MODULE_ID; - -export function vitePluginDbClient(params: VitePluginDBClientParams): VitePlugin { - return { - name: 'virtual:astro:db-client', - enforce: 'pre', - resolveId: { - filter: { - id: new RegExp(`^${VIRTUAL_CLIENT_MODULE_ID}$`), - }, - handler() { - return resolved; - }, - }, - load: { - filter: { - id: new RegExp(`^${resolved}$`), - }, - handler() { - switch (params.connectToRemote) { - case true: - return getRemoteClientModule(params.mode); - case false: - default: - // Local client is always available, even if not used. - return getLocalClientModule(params.mode); - } - }, - }, - }; -} diff --git a/packages/db/src/core/integration/vite-plugin-db.ts b/packages/db/src/core/integration/vite-plugin-db.ts deleted file mode 100644 index 03c2d0ee4f55..000000000000 --- a/packages/db/src/core/integration/vite-plugin-db.ts +++ /dev/null @@ -1,288 +0,0 @@ -import { existsSync } from 'node:fs'; -import { fileURLToPath } from 'node:url'; -import type { AstroConfig, AstroIntegrationLogger } from 'astro'; -import { type SQL, sql } from 'drizzle-orm'; -import { SQLiteAsyncDialect } from 'drizzle-orm/sqlite-core'; -import { normalizeDatabaseUrl } from '../../runtime/index.js'; -import { - DB_CLIENTS, - DB_PATH, - RUNTIME_IMPORT, - RUNTIME_VIRTUAL_IMPORT, - VIRTUAL_CLIENT_MODULE_ID, - VIRTUAL_MODULE_ID, -} from '../consts.js'; -import { createClient } from '../db-client/libsql-local.js'; -import { getResolvedFileUrl } from '../load-file.js'; -import { getCreateIndexQueries, getCreateTableQuery, SEED_DEV_FILE_NAME } from '../queries.js'; -import type { DBTables } from '../types.js'; -import { - getAstroEnv, - getDbDirectoryUrl, - getRemoteDatabaseInfo, - type VitePlugin, -} from '../utils.js'; - -const resolved = { - module: '\0' + VIRTUAL_MODULE_ID, - importedFromSeedFile: '\0' + VIRTUAL_MODULE_ID + ':seed', -}; - -export type LateTables = { - get: () => DBTables; -}; -export type LateSeedFiles = { - get: () => Array; -}; -export type SeedHandler = { - inProgress: boolean; - execute: (fileUrl: URL) => Promise; -}; - -type VitePluginDBParams = - | { - connectToRemote: false; - tables: LateTables; - seedFiles: LateSeedFiles; - srcDir: URL; - root: URL; - logger?: AstroIntegrationLogger; - output: AstroConfig['output']; - seedHandler: SeedHandler; - } - | { - connectToRemote: true; - tables: LateTables; - appToken: string; - srcDir: URL; - root: URL; - output: AstroConfig['output']; - seedHandler: SeedHandler; - }; - -export function vitePluginDb(params: VitePluginDBParams): VitePlugin { - let command: 'build' | 'serve' = 'build'; - return { - name: 'astro:db', - enforce: 'pre', - configResolved(resolvedConfig) { - command = resolvedConfig.command; - }, - resolveId: { - filter: { - id: new RegExp(`^${VIRTUAL_MODULE_ID}$`), - }, - handler() { - if (params.seedHandler.inProgress) { - return resolved.importedFromSeedFile; - } - return resolved.module; - }, - }, - load: { - filter: { - id: new RegExp(`^(${resolved.module}|${resolved.importedFromSeedFile})$`), - }, - async handler(id) { - if (params.connectToRemote) { - return getRemoteVirtualModContents({ - appToken: params.appToken, - tables: params.tables.get(), - isBuild: command === 'build', - output: params.output, - localExecution: false, - }); - } - - // When seeding, we resolved to a different virtual module. - // this prevents an infinite loop attempting to rerun seed files. - // Short circuit with the module contents in this case. - if (id === resolved.importedFromSeedFile) { - return getLocalVirtualModContents({ - root: params.root, - tables: params.tables.get(), - localExecution: false, - }); - } - - await recreateTables(params); - const seedFiles = getResolvedSeedFiles(params); - for await (const seedFile of seedFiles) { - // Use `addWatchFile()` to invalidate the `astro:db` module - // when a seed file changes. - this.addWatchFile(fileURLToPath(seedFile)); - if (existsSync(seedFile)) { - params.seedHandler.inProgress = true; - await params.seedHandler.execute(seedFile); - } - } - if (params.seedHandler.inProgress) { - (params.logger ?? console).info('Seeded database.'); - params.seedHandler.inProgress = false; - } - return getLocalVirtualModContents({ - root: params.root, - tables: params.tables.get(), - localExecution: false, - }); - }, - }, - }; -} - -export function getConfigVirtualModContents() { - return `export * from ${RUNTIME_VIRTUAL_IMPORT}`; -} - -/** - * Get the module import for the DB client. - * This is used to pick which module to import based on whether - * the DB client is being used by the CLI, or in the Astro runtime. - * - * This is important for the `astro db execute` command to work correctly. - * - * @param localExecution - Whether the DB client is being used in a local execution context (e.g. CLI commands). - * @returns The module import string for the DB client. - */ -function getDBModule(localExecution: boolean) { - return localExecution - ? `import { createClient } from '${DB_CLIENTS.node}';` - : `import { createClient } from '${VIRTUAL_CLIENT_MODULE_ID}';`; -} - -export function getLocalVirtualModContents({ - tables, - root, - localExecution, -}: { - tables: DBTables; - root: URL; - /** - * Used for the execute command to import the client directly. - * In other cases, we use the runtime only vite virtual module. - * - * This is used to ensure that the client is imported correctly - * when executing commands like `astro db execute`. - */ - localExecution: boolean; -}) { - const { ASTRO_DATABASE_FILE } = getAstroEnv(); - const dbUrl = new URL(DB_PATH, root); - - // If this is for the execute command, we need to import the client directly instead of using the runtime only virtual module. - const clientImport = getDBModule(localExecution); - - return ` -import { asDrizzleTable, normalizeDatabaseUrl } from ${RUNTIME_IMPORT}; - -${clientImport} - -const dbUrl = normalizeDatabaseUrl(${JSON.stringify(ASTRO_DATABASE_FILE)}, ${JSON.stringify(dbUrl)}); -export const db = createClient({ url: dbUrl }); - -export * from ${RUNTIME_VIRTUAL_IMPORT}; - -${getStringifiedTableExports(tables)}`; -} - -export function getRemoteVirtualModContents({ - tables, - appToken, - isBuild, - output, - localExecution, -}: { - tables: DBTables; - appToken: string; - isBuild: boolean; - output: AstroConfig['output']; - /** - * Used for the execute command to import the client directly. - * In other cases, we use the runtime only vite virtual module. - * - * This is used to ensure that the client is imported correctly - * when executing commands like `astro db execute`. - */ - localExecution: boolean; -}) { - const dbInfo = getRemoteDatabaseInfo(); - - function appTokenArg() { - if (isBuild) { - if (output === 'server') { - // In production build, always read the runtime environment variable. - return `process.env.ASTRO_DB_APP_TOKEN`; - } else { - // Static mode or prerendering needs the local app token. - return `process.env.ASTRO_DB_APP_TOKEN ?? ${JSON.stringify(appToken)}`; - } - } else { - return JSON.stringify(appToken); - } - } - - function dbUrlArg() { - const dbStr = JSON.stringify(dbInfo.url); - - if (isBuild) { - // Allow overriding, mostly for testing - return `import.meta.env.ASTRO_DB_REMOTE_URL ?? ${dbStr}`; - } else { - return dbStr; - } - } - - // If this is for the execute command, we need to import the client directly instead of using the runtime only virtual module. - const clientImport = getDBModule(localExecution); - - return ` -import {asDrizzleTable} from ${RUNTIME_IMPORT}; - -${clientImport} - -export const db = await createClient({ - url: ${dbUrlArg()}, - token: ${appTokenArg()}, -}); - -export * from ${RUNTIME_VIRTUAL_IMPORT}; - -${getStringifiedTableExports(tables)} - `; -} - -function getStringifiedTableExports(tables: DBTables) { - return Object.entries(tables) - .map( - ([name, table]) => - `export const ${name} = asDrizzleTable(${JSON.stringify(name)}, ${JSON.stringify( - table, - )}, false)`, - ) - .join('\n'); -} - -const sqlite = new SQLiteAsyncDialect(); - -async function recreateTables({ tables, root }: { tables: LateTables; root: URL }) { - const { ASTRO_DATABASE_FILE } = getAstroEnv(); - const dbUrl = normalizeDatabaseUrl(ASTRO_DATABASE_FILE, new URL(DB_PATH, root).href); - const db = createClient({ url: dbUrl }); - const setupQueries: SQL[] = []; - for (const [name, table] of Object.entries(tables.get() ?? {})) { - const dropQuery = sql.raw(`DROP TABLE IF EXISTS ${sqlite.escapeName(name)}`); - const createQuery = sql.raw(getCreateTableQuery(name, table)); - const indexQueries = getCreateIndexQueries(name, table); - setupQueries.push(dropQuery, createQuery, ...indexQueries.map((s) => sql.raw(s))); - } - await db.batch([ - db.run(sql`pragma defer_foreign_keys=true;`), - ...setupQueries.map((q) => db.run(q)), - ]); -} - -function getResolvedSeedFiles({ root, seedFiles }: { root: URL; seedFiles: LateSeedFiles }) { - const localSeedFiles = SEED_DEV_FILE_NAME.map((name) => new URL(name, getDbDirectoryUrl(root))); - const integrationSeedFiles = seedFiles.get().map((s) => getResolvedFileUrl(root, s)); - return [...integrationSeedFiles, ...localSeedFiles]; -} diff --git a/packages/db/src/core/load-file.ts b/packages/db/src/core/load-file.ts deleted file mode 100644 index a8a9f40a4f79..000000000000 --- a/packages/db/src/core/load-file.ts +++ /dev/null @@ -1,204 +0,0 @@ -import { existsSync } from 'node:fs'; -import { unlink, writeFile } from 'node:fs/promises'; -import { createRequire } from 'node:module'; -import { fileURLToPath, pathToFileURL } from 'node:url'; -import type { AstroConfig } from 'astro'; -import { build as esbuild } from 'esbuild'; -import { CONFIG_FILE_NAMES, VIRTUAL_MODULE_ID } from './consts.js'; -import { INTEGRATION_TABLE_CONFLICT_ERROR } from './errors.js'; -import { errorMap } from './integration/error-map.js'; -import { getConfigVirtualModContents } from './integration/vite-plugin-db.js'; -import { dbConfigSchema } from './schemas.js'; -import './types.js'; -import { getAstroEnv, getDbDirectoryUrl } from './utils.js'; - -/** - * Load a user’s `astro:db` configuration file and additional configuration files provided by integrations. - */ -export async function resolveDbConfig({ - root, - integrations, -}: Pick) { - const { mod, dependencies } = await loadUserConfigFile(root); - const userDbConfig = dbConfigSchema.parse(mod?.default ?? {}, { error: errorMap }); - /** Resolved `astro:db` config including tables provided by integrations. */ - const dbConfig = { tables: userDbConfig.tables ?? {} }; - - // Collect additional config and seed files from integrations. - const integrationDbConfigPaths: Array<{ name: string; configEntrypoint: string | URL }> = []; - const integrationSeedPaths: Array = []; - for (const integration of integrations) { - const { name, hooks } = integration; - if (hooks['astro:db:setup']) { - hooks['astro:db:setup']({ - extendDb({ configEntrypoint, seedEntrypoint }) { - if (configEntrypoint) { - integrationDbConfigPaths.push({ name, configEntrypoint }); - } - if (seedEntrypoint) { - integrationSeedPaths.push(seedEntrypoint); - } - }, - }); - } - } - for (const { name, configEntrypoint } of integrationDbConfigPaths) { - // TODO: config file dependencies are not tracked for integrations for now. - const loadedConfig = await loadIntegrationConfigFile(root, configEntrypoint); - const integrationDbConfig = dbConfigSchema.parse(loadedConfig.mod?.default ?? {}, { - error: errorMap, - }); - for (const key in integrationDbConfig.tables) { - if (key in dbConfig.tables) { - const isUserConflict = key in (userDbConfig.tables ?? {}); - throw new Error(INTEGRATION_TABLE_CONFLICT_ERROR(name, key, isUserConflict)); - } else { - dbConfig.tables[key] = integrationDbConfig.tables[key]; - } - } - } - - return { - /** Resolved `astro:db` config, including tables added by integrations. */ - dbConfig, - /** Dependencies imported into the user config file. */ - dependencies, - /** Additional `astro:db` seed file paths provided by integrations. */ - integrationSeedPaths, - }; -} - -async function loadUserConfigFile( - root: URL, -): Promise<{ mod: { default?: unknown } | undefined; dependencies: string[] }> { - let configFileUrl: URL | undefined; - for (const fileName of CONFIG_FILE_NAMES) { - const fileUrl = new URL(fileName, getDbDirectoryUrl(root)); - if (existsSync(fileUrl)) { - configFileUrl = fileUrl; - } - } - return await loadAndBundleDbConfigFile({ root, fileUrl: configFileUrl }); -} - -export function getResolvedFileUrl(root: URL, filePathOrUrl: string | URL): URL { - if (typeof filePathOrUrl === 'string') { - const { resolve } = createRequire(root); - const resolvedFilePath = resolve(filePathOrUrl); - return pathToFileURL(resolvedFilePath); - } - return filePathOrUrl; -} - -async function loadIntegrationConfigFile(root: URL, filePathOrUrl: string | URL) { - const fileUrl = getResolvedFileUrl(root, filePathOrUrl); - return await loadAndBundleDbConfigFile({ root, fileUrl }); -} - -async function loadAndBundleDbConfigFile({ - root, - fileUrl, -}: { - root: URL; - fileUrl: URL | undefined; -}): Promise<{ mod: { default?: unknown } | undefined; dependencies: string[] }> { - if (!fileUrl) { - return { mod: undefined, dependencies: [] }; - } - const { code, dependencies } = await bundleFile({ - virtualModContents: getConfigVirtualModContents(), - root, - fileUrl, - }); - return { - mod: await importBundledFile({ code, root }), - dependencies, - }; -} - -/** - * Bundle arbitrary `mjs` or `ts` file. - * Simplified fork from Vite's `bundleConfigFile` function. - * - * @see https://github.com/vitejs/vite/blob/main/packages/vite/src/node/config.ts#L961 - */ -export async function bundleFile({ - fileUrl, - root, - virtualModContents, -}: { - fileUrl: URL; - root: URL; - virtualModContents: string; -}) { - const { ASTRO_DATABASE_FILE } = getAstroEnv(); - const result = await esbuild({ - absWorkingDir: process.cwd(), - entryPoints: [fileURLToPath(fileUrl)], - outfile: 'out.js', - packages: 'external', - write: false, - target: ['node16'], - platform: 'node', - bundle: true, - format: 'esm', - sourcemap: 'inline', - metafile: true, - define: { - 'import.meta.env.ASTRO_DATABASE_FILE': JSON.stringify(ASTRO_DATABASE_FILE ?? ''), - }, - plugins: [ - { - name: 'resolve-astro-db', - setup(build) { - build.onResolve({ filter: /^astro:db$/ }, ({ path }) => { - return { path, namespace: VIRTUAL_MODULE_ID }; - }); - build.onLoad({ namespace: VIRTUAL_MODULE_ID, filter: /.*/ }, () => { - return { - contents: virtualModContents, - // Needed to resolve runtime dependencies - resolveDir: fileURLToPath(root), - }; - }); - }, - }, - ], - }); - - const file = result.outputFiles[0]; - if (!file) { - throw new Error(`Unexpected: no output file`); - } - - return { - code: file.text, - dependencies: Object.keys(result.metafile.inputs), - }; -} - -/** - * Forked from Vite config loader, replacing CJS-based path concat with ESM only - * - * @see https://github.com/vitejs/vite/blob/main/packages/vite/src/node/config.ts#L1074 - */ -export async function importBundledFile({ - code, - root, -}: { - code: string; - root: URL; -}): Promise<{ default?: unknown }> { - // Write it to disk, load it with native Node ESM, then delete the file. - const tmpFileUrl = new URL(`./db.timestamp-${Date.now()}.mjs`, root); - await writeFile(tmpFileUrl, code, { encoding: 'utf8' }); - try { - return await import(/* @vite-ignore */ tmpFileUrl.toString()); - } finally { - try { - await unlink(tmpFileUrl); - } catch { - // already removed if this function is called twice simultaneously - } - } -} diff --git a/packages/db/src/core/queries.ts b/packages/db/src/core/queries.ts deleted file mode 100644 index 1ac9e827a8f8..000000000000 --- a/packages/db/src/core/queries.ts +++ /dev/null @@ -1,206 +0,0 @@ -import type { SQL } from 'drizzle-orm'; -import { SQLiteAsyncDialect } from 'drizzle-orm/sqlite-core'; -import colors from 'piccolore'; -import { - FOREIGN_KEY_DNE_ERROR, - FOREIGN_KEY_REFERENCES_EMPTY_ERROR, - FOREIGN_KEY_REFERENCES_LENGTH_ERROR, - REFERENCE_DNE_ERROR, -} from '../runtime/errors.js'; -import { isSerializedSQL } from '../runtime/types.js'; -import { hasPrimaryKey } from '../runtime/utils.js'; -import type { - BooleanColumn, - ColumnType, - DateColumn, - DBColumn, - DBTable, - JsonColumn, - NumberColumn, - TextColumn, -} from './types.js'; - -const sqlite = new SQLiteAsyncDialect(); - -export const SEED_DEV_FILE_NAME = ['seed.ts', 'seed.js', 'seed.mjs', 'seed.mts']; - -export function getDropTableIfExistsQuery(tableName: string) { - return `DROP TABLE IF EXISTS ${sqlite.escapeName(tableName)}`; -} - -export function getCreateTableQuery(tableName: string, table: DBTable) { - let query = `CREATE TABLE ${sqlite.escapeName(tableName)} (`; - - const colQueries = []; - const colHasPrimaryKey = Object.entries(table.columns).find(([, column]) => - hasPrimaryKey(column), - ); - if (!colHasPrimaryKey) { - colQueries.push('_id INTEGER PRIMARY KEY'); - } - for (const [columnName, column] of Object.entries(table.columns)) { - const colQuery = `${sqlite.escapeName(columnName)} ${schemaTypeToSqlType( - column.type, - )}${getModifiers(columnName, column)}`; - colQueries.push(colQuery); - } - - colQueries.push(...getCreateForeignKeyQueries(tableName, table)); - - query += colQueries.join(', ') + ')'; - return query; -} - -export function getCreateIndexQueries(tableName: string, table: Pick) { - let queries: string[] = []; - for (const [indexName, indexProps] of Object.entries(table.indexes ?? {})) { - const onColNames = asArray(indexProps.on); - const onCols = onColNames.map((colName) => sqlite.escapeName(colName)); - - const unique = indexProps.unique ? 'UNIQUE ' : ''; - const indexQuery = `CREATE ${unique}INDEX ${sqlite.escapeName( - indexName, - )} ON ${sqlite.escapeName(tableName)} (${onCols.join(', ')})`; - queries.push(indexQuery); - } - return queries; -} - -function getCreateForeignKeyQueries(tableName: string, table: DBTable) { - let queries: string[] = []; - for (const foreignKey of table.foreignKeys ?? []) { - const columns = asArray(foreignKey.columns); - const references = asArray(foreignKey.references); - - if (columns.length !== references.length) { - throw new Error(FOREIGN_KEY_REFERENCES_LENGTH_ERROR(tableName)); - } - const firstReference = references[0]; - if (!firstReference) { - throw new Error(FOREIGN_KEY_REFERENCES_EMPTY_ERROR(tableName)); - } - const referencedTable = firstReference.schema.collection; - if (!referencedTable) { - throw new Error(FOREIGN_KEY_DNE_ERROR(tableName)); - } - const query = `FOREIGN KEY (${columns - .map((f) => sqlite.escapeName(f)) - .join(', ')}) REFERENCES ${sqlite.escapeName(referencedTable)}(${references - .map((r) => sqlite.escapeName(r.schema.name!)) - .join(', ')})`; - queries.push(query); - } - return queries; -} - -function asArray(value: T | T[]) { - return Array.isArray(value) ? value : [value]; -} - -export function schemaTypeToSqlType(type: ColumnType): 'text' | 'integer' { - switch (type) { - case 'date': - case 'text': - case 'json': - return 'text'; - case 'number': - case 'boolean': - return 'integer'; - } -} - -export function getModifiers(columnName: string, column: DBColumn) { - let modifiers = ''; - if (hasPrimaryKey(column)) { - return ' PRIMARY KEY'; - } - if (!column.schema.optional) { - modifiers += ' NOT NULL'; - } - if (column.schema.unique) { - modifiers += ' UNIQUE'; - } - if (hasDefault(column)) { - modifiers += ` DEFAULT ${getDefaultValueSql(columnName, column)}`; - } - const references = getReferencesConfig(column); - if (references) { - const { collection: tableName, name } = references.schema; - if (!tableName || !name) { - throw new Error(REFERENCE_DNE_ERROR(columnName)); - } - - modifiers += ` REFERENCES ${sqlite.escapeName(tableName)} (${sqlite.escapeName(name)})`; - } - return modifiers; -} - -export function getReferencesConfig(column: DBColumn) { - const canHaveReferences = column.type === 'number' || column.type === 'text'; - if (!canHaveReferences) return undefined; - return column.schema.references; -} - -// Using `DBColumn` will not narrow `default` based on the column `type` -// Handle each column separately -type WithDefaultDefined = T & { - schema: Required>; -}; -type DBColumnWithDefault = - | WithDefaultDefined - | WithDefaultDefined - | WithDefaultDefined - | WithDefaultDefined - | WithDefaultDefined; - -// Type narrowing the default fails on union types, so use a type guard -export function hasDefault(column: DBColumn): column is DBColumnWithDefault { - if (column.schema.default !== undefined) { - return true; - } - if (hasPrimaryKey(column) && column.type === 'number') { - return true; - } - return false; -} - -function toDefault(def: T | SQL): string { - const type = typeof def; - if (type === 'string') { - return sqlite.escapeString(def as string); - } else if (type === 'boolean') { - return def ? 'TRUE' : 'FALSE'; - } else { - return def + ''; - } -} - -function getDefaultValueSql(columnName: string, column: DBColumnWithDefault): string { - if (isSerializedSQL(column.schema.default)) { - return column.schema.default.sql; - } - - switch (column.type) { - case 'boolean': - case 'number': - case 'text': - case 'date': - return toDefault(column.schema.default); - case 'json': { - let stringified = ''; - try { - stringified = JSON.stringify(column.schema.default); - } catch { - // biome-ignore lint/suspicious/noConsole: allowed - console.log( - `Invalid default value for column ${colors.bold( - columnName, - )}. Defaults must be valid JSON when using the \`json()\` type.`, - ); - process.exit(0); - } - - return sqlite.escapeString(stringified); - } - } -} diff --git a/packages/db/src/core/schemas.ts b/packages/db/src/core/schemas.ts deleted file mode 100644 index cdaa7d5fa24f..000000000000 --- a/packages/db/src/core/schemas.ts +++ /dev/null @@ -1,248 +0,0 @@ -import { SQL } from 'drizzle-orm'; -import { SQLiteAsyncDialect } from 'drizzle-orm/sqlite-core'; -import * as z from 'zod/v4'; -import { SERIALIZED_SQL_KEY, type SerializedSQL } from '../runtime/types.js'; -import { errorMap } from './integration/error-map.js'; -import type { NumberColumn, TextColumn } from './types.js'; -import { mapObject } from './utils.js'; - -export type MaybeArray = T | T[]; - -// Transform to serializable object for migration files -const sqlite = new SQLiteAsyncDialect(); - -const sqlSchema = z.instanceof(SQL).transform( - (sqlObj): SerializedSQL => ({ - [SERIALIZED_SQL_KEY]: true, - sql: sqlite.sqlToQuery(sqlObj).sql, - }), -); - -const baseColumnSchema = z.object({ - label: z.string().optional(), - optional: z.boolean().optional().default(false), - unique: z.boolean().optional().default(false), - deprecated: z.boolean().optional().default(false), - - // Defined when `defineDb()` is called to resolve `references` - name: z.string().optional(), - // TODO: Update to `table`. Will need migration file version change - collection: z.string().optional(), -}); - -export const booleanColumnSchema = z.object({ - type: z.literal('boolean'), - schema: baseColumnSchema.extend({ - default: z.union([z.boolean(), sqlSchema]).optional(), - }), -}); - -const numberColumnBaseSchema = baseColumnSchema.omit({ optional: true }).and( - z.union([ - z.object({ - primaryKey: z.literal(false).optional().default(false), - optional: baseColumnSchema.shape.optional, - default: z.union([z.number(), sqlSchema]).optional(), - }), - z.object({ - // `integer primary key` uses ROWID as the default value. - // `optional` and `default` do not have an effect, - // so disable these config options for primary keys. - primaryKey: z.literal(true), - optional: z.literal(false).optional(), - default: z.literal(undefined).optional(), - }), - ]), -); - -export const numberColumnOptsSchema: z.ZodType< - z.infer & { - // ReferenceableColumn creates a circular type. Define ZodType to resolve. - references?: NumberColumn; - }, - z.input & { - references?: () => z.input; - } -> = numberColumnBaseSchema.and( - z.object({ - references: z - .function({ output: z.lazy(() => numberColumnSchema) }) - .optional() - .transform((fn) => fn?.()), - }), -); - -export const numberColumnSchema = z.object({ - type: z.literal('number'), - schema: numberColumnOptsSchema, -}); - -const textColumnBaseSchema = baseColumnSchema - .omit({ optional: true }) - .extend({ - default: z.union([z.string(), sqlSchema]).optional(), - multiline: z.boolean().optional(), - enum: z.tuple([z.string()]).rest(z.string()).optional(), // At least one value required, - }) - .and( - z.union([ - z.object({ - primaryKey: z.literal(false).optional().default(false), - optional: baseColumnSchema.shape.optional, - }), - z.object({ - // text primary key allows NULL values. - // NULL values bypass unique checks, which could - // lead to duplicate URLs per record. - // disable `optional` for primary keys. - primaryKey: z.literal(true), - optional: z.literal(false).optional(), - }), - ]), - ); - -export const textColumnOptsSchema: z.ZodType< - z.infer & { - // ReferenceableColumn creates a circular type. Define ZodType to resolve. - references?: TextColumn; - }, - z.input & { - references?: () => z.input; - } -> = textColumnBaseSchema.and( - z.object({ - references: z - .function({ output: z.lazy(() => textColumnSchema) }) - .optional() - .transform((fn) => fn?.()), - }), -); - -export const textColumnSchema = z.object({ - type: z.literal('text'), - schema: textColumnOptsSchema, -}); - -export const dateColumnSchema = z.object({ - type: z.literal('date'), - schema: baseColumnSchema.extend({ - default: z - .union([ - sqlSchema, - // transform to ISO string for serialization - z.date().transform((d) => d.toISOString()), - ]) - .optional(), - }), -}); - -export const jsonColumnSchema = z.object({ - type: z.literal('json'), - schema: baseColumnSchema.extend({ - default: z.unknown().optional(), - }), -}); - -export const columnSchema = z.discriminatedUnion('type', [ - booleanColumnSchema, - numberColumnSchema, - textColumnSchema, - dateColumnSchema, - jsonColumnSchema, -]); -export const referenceableColumnSchema = z.union([textColumnSchema, numberColumnSchema]); - -export const columnsSchema = z.record(z.string(), columnSchema); - -type ForeignKeysInput = { - columns: MaybeArray; - references: () => MaybeArray, 'references'>>; -}; - -type ForeignKeysOutput = Omit & { - // reference fn called in `transform`. Ensures output is JSON serializable. - references: MaybeArray, 'references'>>; -}; - -const foreignKeysSchema: z.ZodType = z.object({ - columns: z.string().or(z.array(z.string())), - references: z - .function({ - output: z.lazy(() => referenceableColumnSchema.or(z.array(referenceableColumnSchema))), - }) - .transform((fn) => fn()), -}); - -export const resolvedIndexSchema = z.object({ - on: z.string().or(z.array(z.string())), - unique: z.boolean().optional(), -}); -/** @deprecated */ -const legacyIndexesSchema = z.record(z.string(), resolvedIndexSchema); - -export const indexSchema = z.object({ - on: z.string().or(z.array(z.string())), - unique: z.boolean().optional(), - name: z.string().optional(), -}); -const indexesSchema = z.array(indexSchema); - -export const tableSchema = z.object({ - columns: columnsSchema, - indexes: indexesSchema.or(legacyIndexesSchema).optional(), - foreignKeys: z.array(foreignKeysSchema).optional(), - deprecated: z.boolean().optional().default(false), -}); - -export const tablesSchema = z.preprocess( - (rawTables) => { - // Use `z.any()` to avoid breaking object references - const tables = z.record(z.string(), z.any()).parse(rawTables, { error: errorMap }); - for (const [tableName, table] of Object.entries(tables)) { - // Append table and column names to columns. - // Used to track table info for references. - table.getName = () => tableName; - const { columns } = z - .object({ columns: z.record(z.string(), z.any()) }) - .parse(table, { error: errorMap }); - for (const [columnName, column] of Object.entries(columns)) { - column.schema.name = columnName; - column.schema.collection = tableName; - } - } - return rawTables; - }, - z.record(z.string(), tableSchema), -); - -export const dbConfigSchema = z - .object({ - tables: tablesSchema.optional(), - }) - .transform(({ tables = {}, ...config }) => { - return { - ...config, - tables: mapObject(tables, (tableName, table) => { - const { indexes = {} } = table; - if (!Array.isArray(indexes)) { - return { ...table, indexes }; - } - const resolvedIndexes: Record> = {}; - for (const index of indexes) { - if (index.name) { - const { name, ...rest } = index; - resolvedIndexes[index.name] = rest; - continue; - } - // Sort index columns to ensure consistent index names - const indexOn = Array.isArray(index.on) ? index.on.sort().join('_') : index.on; - const name = tableName + '_' + indexOn + '_idx'; - resolvedIndexes[name] = index; - } - return { - ...table, - indexes: resolvedIndexes, - }; - }), - }; - }); diff --git a/packages/db/src/core/types.ts b/packages/db/src/core/types.ts deleted file mode 100644 index 7637bcdb1f1e..000000000000 --- a/packages/db/src/core/types.ts +++ /dev/null @@ -1,102 +0,0 @@ -import type * as z from 'zod/v4'; -import type { - booleanColumnSchema, - columnSchema, - columnsSchema, - dateColumnSchema, - dbConfigSchema, - indexSchema, - jsonColumnSchema, - MaybeArray, - numberColumnOptsSchema, - numberColumnSchema, - referenceableColumnSchema, - resolvedIndexSchema, - tableSchema, - textColumnOptsSchema, - textColumnSchema, -} from './schemas.js'; - -export type ResolvedIndexes = z.output['tables'][string]['indexes']; -export type BooleanColumn = z.infer; -export type BooleanColumnInput = z.input; -export type NumberColumn = z.infer; -export type NumberColumnInput = z.input; -export type TextColumn = z.infer; -export type TextColumnInput = z.input; -export type DateColumn = z.infer; -export type DateColumnInput = z.input; -export type JsonColumn = z.infer; -export type JsonColumnInput = z.input; - -export type ColumnType = - | BooleanColumn['type'] - | NumberColumn['type'] - | TextColumn['type'] - | DateColumn['type'] - | JsonColumn['type']; - -export type DBColumn = z.infer; -export type DBColumnInput = - | DateColumnInput - | BooleanColumnInput - | NumberColumnInput - | TextColumnInput - | JsonColumnInput; -export type DBColumns = z.infer; -export type DBTable = z.infer; -export type DBTables = Record; -export type ResolvedDBTables = z.output['tables']; -export type ResolvedDBTable = z.output['tables'][string]; -export type DBSnapshot = { - schema: Record; - version: string; -}; - -export type DBConfigInput = z.input; -export type DBConfig = z.infer; - -export type ColumnsConfig = z.input['columns']; -export type OutputColumnsConfig = z.output['columns']; - -export interface TableConfig - // use `extends` to ensure types line up with zod, - // only adding generics for type completions. - extends Pick, 'columns' | 'indexes' | 'foreignKeys'> { - columns: TColumns; - foreignKeys?: Array<{ - columns: MaybeArray>; - references: () => MaybeArray>; - }>; - indexes?: Array> | Record>; - deprecated?: boolean; -} - -interface IndexConfig extends z.input { - on: MaybeArray>; -} - -/** @deprecated */ -interface LegacyIndexConfig - extends z.input { - on: MaybeArray>; -} - -// We cannot use `Omit`, -// since Omit collapses our union type on primary key. -export type NumberColumnOpts = z.input; -export type TextColumnOpts = z.input; - -declare global { - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace Astro { - export interface IntegrationHooks { - 'astro:db:setup'?: (options: { - extendDb: (options: { - configEntrypoint?: URL | string; - seedEntrypoint?: URL | string; - }) => void; - }) => void | Promise; - } - } -} diff --git a/packages/db/src/core/utils.ts b/packages/db/src/core/utils.ts deleted file mode 100644 index b6019e38ff13..000000000000 --- a/packages/db/src/core/utils.ts +++ /dev/null @@ -1,61 +0,0 @@ -import type { AstroConfig, AstroIntegration } from 'astro'; -import { loadEnv } from 'vite'; -import type { Arguments } from 'yargs-parser'; -import './types.js'; - -export type VitePlugin = Required['plugins'][number]; - -export function getAstroEnv(envMode = ''): Record<`ASTRO_${string}`, string> { - const env = loadEnv(envMode, process.cwd(), 'ASTRO_'); - return env; -} - -export type RemoteDatabaseInfo = { - url: string; - token: string; -}; - -export function getRemoteDatabaseInfo(): RemoteDatabaseInfo { - const astroEnv = getAstroEnv(); - - return { - url: astroEnv.ASTRO_DB_REMOTE_URL, - token: astroEnv.ASTRO_DB_APP_TOKEN, - }; -} - -export function resolveDbAppToken(flags: Arguments, envToken: string): string; -export function resolveDbAppToken( - flags: Arguments, - envToken: string | undefined, -): string | undefined; -export function resolveDbAppToken( - flags: Arguments, - envToken: string | undefined, -): string | undefined { - const dbAppToken = (flags as Arguments & { dbAppToken?: unknown }).dbAppToken; - if (typeof dbAppToken === 'string') return dbAppToken; - - return envToken; -} - -export function getDbDirectoryUrl(root: URL | string) { - return new URL('db/', root); -} - -export function defineDbIntegration(integration: AstroIntegration): AstroIntegration { - return integration; -} - -/** - * Map an object's values to a new set of values - * while preserving types. - */ -export function mapObject( - item: Record, - callback: (key: string, value: T) => U, -): Record { - return Object.fromEntries( - Object.entries(item).map(([key, value]) => [key, callback(key, value)]), - ); -} diff --git a/packages/db/src/db-client.d.ts b/packages/db/src/db-client.d.ts deleted file mode 100644 index 9f2d5e9e6f88..000000000000 --- a/packages/db/src/db-client.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -declare module 'virtual:astro:db-client' { - export const createClient: typeof import('./core/db-client/libsql-node.ts').createRemoteLibSQLClient; -} diff --git a/packages/db/src/index.ts b/packages/db/src/index.ts deleted file mode 100644 index d96fd260932a..000000000000 --- a/packages/db/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { cli } from './core/cli/index.js'; -export { type AstroDBConfig, integration as default } from './core/integration/index.js'; -export type { TableConfig } from './core/types.js'; diff --git a/packages/db/src/runtime/errors.ts b/packages/db/src/runtime/errors.ts deleted file mode 100644 index 0e7d24f16da2..000000000000 --- a/packages/db/src/runtime/errors.ts +++ /dev/null @@ -1,25 +0,0 @@ -import colors from 'piccolore'; - -export const FOREIGN_KEY_DNE_ERROR = (tableName: string) => { - return `Table ${colors.bold( - tableName, - )} references a table that does not exist. Did you apply the referenced table to the \`tables\` object in your db config?`; -}; - -export const FOREIGN_KEY_REFERENCES_LENGTH_ERROR = (tableName: string) => { - return `Foreign key on ${colors.bold( - tableName, - )} is misconfigured. \`columns\` and \`references\` must be the same length.`; -}; - -export const FOREIGN_KEY_REFERENCES_EMPTY_ERROR = (tableName: string) => { - return `Foreign key on ${colors.bold( - tableName, - )} is misconfigured. \`references\` array cannot be empty.`; -}; - -export const REFERENCE_DNE_ERROR = (columnName: string) => { - return `Column ${colors.bold( - columnName, - )} references a table that does not exist. Did you apply the referenced table to the \`tables\` object in your db config?`; -}; diff --git a/packages/db/src/runtime/index.ts b/packages/db/src/runtime/index.ts deleted file mode 100644 index dca3cacef069..000000000000 --- a/packages/db/src/runtime/index.ts +++ /dev/null @@ -1,153 +0,0 @@ -import { type ColumnBuilderBaseConfig, type ColumnDataType, sql } from 'drizzle-orm'; -import type { LibSQLDatabase } from 'drizzle-orm/libsql'; -import { - customType, - type IndexBuilder, - index, - integer, - type SQLiteColumnBuilderBase, - sqliteTable, - text, -} from 'drizzle-orm/sqlite-core'; -import type { DBColumn, DBTable } from '../core/types.js'; -import { isSerializedSQL, type SerializedSQL } from './types.js'; -import { hasPrimaryKey, pathToFileURL } from './utils.js'; -export type Database = LibSQLDatabase; -export type { Table } from './types.js'; -export { hasPrimaryKey } from './utils.js'; - -// Taken from: -// https://stackoverflow.com/questions/52869695/check-if-a-date-string-is-in-iso-and-utc-format -const isISODateString = (str: string) => /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/.test(str); - -const dateType = customType<{ data: Date; driverData: string }>({ - dataType() { - return 'text'; - }, - toDriver(value) { - return value.toISOString(); - }, - fromDriver(value) { - if (!isISODateString(value)) { - // values saved using CURRENT_TIMESTAMP are not valid ISO strings - // but *are* in UTC, so append the UTC zone. - value += 'Z'; - } - return new Date(value); - }, -}); - -const jsonType = customType<{ data: unknown; driverData: string }>({ - dataType() { - return 'text'; - }, - toDriver(value) { - return JSON.stringify(value); - }, - fromDriver(value) { - return JSON.parse(value); - }, -}); - -type D1ColumnBuilder = SQLiteColumnBuilderBase< - ColumnBuilderBaseConfig & { data: unknown } ->; - -export function asDrizzleTable(name: string, table: DBTable) { - const columns: Record = {}; - if (!Object.entries(table.columns).some(([, column]) => hasPrimaryKey(column))) { - columns['_id'] = integer('_id').primaryKey(); - } - for (const [columnName, column] of Object.entries(table.columns)) { - columns[columnName] = columnMapper(columnName, column); - } - const drizzleTable = sqliteTable(name, columns, (ormTable) => { - const indexes: Array = []; - for (const [indexName, indexProps] of Object.entries(table.indexes ?? {})) { - const onColNames = Array.isArray(indexProps.on) ? indexProps.on : [indexProps.on]; - const onCols = onColNames.map((colName) => ormTable[colName]); - if (!atLeastOne(onCols)) continue; - - indexes.push(index(indexName).on(...onCols)); - } - return indexes; - }); - return drizzleTable; -} - -function atLeastOne(arr: T[]): arr is [T, ...T[]] { - return arr.length > 0; -} - -function columnMapper(columnName: string, column: DBColumn) { - let c: ReturnType< - | typeof text - | typeof integer - | typeof jsonType - | typeof dateType - | typeof integer - >; - - switch (column.type) { - case 'text': { - c = text(columnName, { enum: column.schema.enum }); - // Duplicate default logic across cases to preserve type inference. - // No clean generic for every column builder. - if (column.schema.default !== undefined) - c = c.default(handleSerializedSQL(column.schema.default)); - if (column.schema.primaryKey === true) c = c.primaryKey(); - break; - } - case 'number': { - c = integer(columnName); - if (column.schema.default !== undefined) - c = c.default(handleSerializedSQL(column.schema.default)); - if (column.schema.primaryKey === true) c = c.primaryKey(); - break; - } - case 'boolean': { - c = integer(columnName, { mode: 'boolean' }); - if (column.schema.default !== undefined) - c = c.default(handleSerializedSQL(column.schema.default)); - break; - } - case 'json': - c = jsonType(columnName); - if (column.schema.default !== undefined) c = c.default(column.schema.default); - break; - case 'date': { - c = dateType(columnName); - if (column.schema.default !== undefined) { - const def = handleSerializedSQL(column.schema.default); - c = c.default(typeof def === 'string' ? new Date(def) : def); - } - break; - } - } - - if (!column.schema.optional) c = c.notNull(); - if (column.schema.unique) c = c.unique(); - return c; -} - -function handleSerializedSQL(def: T | SerializedSQL) { - if (isSerializedSQL(def)) { - return sql.raw(def.sql); - } - return def; -} - -export function normalizeDatabaseUrl(envDbUrl: string | undefined, defaultDbUrl: string): string { - if (envDbUrl) { - // This could be a file URL, or more likely a root-relative file path. - // Convert it to a file URL. - if (envDbUrl.startsWith('file://')) { - return envDbUrl; - } - - return new URL(envDbUrl, pathToFileURL(process.cwd()) + '/').toString(); - } else { - // This is going to be a file URL always, - return defaultDbUrl; - } -} diff --git a/packages/db/src/runtime/types.ts b/packages/db/src/runtime/types.ts deleted file mode 100644 index d2148cdc2cb1..000000000000 --- a/packages/db/src/runtime/types.ts +++ /dev/null @@ -1,140 +0,0 @@ -import type { ColumnBaseConfig, ColumnDataType } from 'drizzle-orm'; -import type { SQLiteColumn, SQLiteTableWithColumns } from 'drizzle-orm/sqlite-core'; -import type { ColumnsConfig, DBColumn, OutputColumnsConfig } from '../core/types.js'; - -type GeneratedConfig = Pick< - ColumnBaseConfig, - 'name' | 'tableName' | 'notNull' | 'hasDefault' | 'hasRuntimeDefault' | 'isPrimaryKey' ->; - -type AstroText< - T extends GeneratedConfig<'string'>, - E extends readonly [string, ...string[]] | string, -> = SQLiteColumn< - T & { - data: E extends readonly (infer U)[] ? U : string; - dataType: 'string'; - columnType: 'SQLiteText'; - driverParam: string; - enumValues: E extends [string, ...string[]] ? E : never; - baseColumn: never; - isAutoincrement: boolean; - identity: undefined; - generated: undefined; - } ->; - -type AstroDate> = SQLiteColumn< - T & { - data: Date; - dataType: 'custom'; - columnType: 'SQLiteCustomColumn'; - driverParam: string; - enumValues: never; - baseColumn: never; - isAutoincrement: boolean; - identity: undefined; - generated: undefined; - } ->; - -type AstroBoolean> = SQLiteColumn< - T & { - data: boolean; - dataType: 'boolean'; - columnType: 'SQLiteBoolean'; - driverParam: number; - enumValues: never; - baseColumn: never; - isAutoincrement: boolean; - identity: undefined; - generated: undefined; - } ->; - -type AstroNumber> = SQLiteColumn< - T & { - data: number; - dataType: 'number'; - columnType: 'SQLiteInteger'; - driverParam: number; - enumValues: never; - baseColumn: never; - isAutoincrement: boolean; - identity: undefined; - generated: undefined; - } ->; - -type AstroJson> = SQLiteColumn< - T & { - data: unknown; - dataType: 'custom'; - columnType: 'SQLiteCustomColumn'; - driverParam: string; - enumValues: never; - baseColumn: never; - isAutoincrement: boolean; - identity: undefined; - generated: undefined; - } ->; - -type Column< - T extends DBColumn['type'], - E extends readonly [string, ...string[]] | string, - S extends GeneratedConfig, -> = T extends 'boolean' - ? AstroBoolean - : T extends 'number' - ? AstroNumber - : T extends 'text' - ? AstroText - : T extends 'date' - ? AstroDate - : T extends 'json' - ? AstroJson - : never; - -export type Table< - TTableName extends string, - TColumns extends OutputColumnsConfig | ColumnsConfig, -> = SQLiteTableWithColumns<{ - name: TTableName; - schema: undefined; - dialect: 'sqlite'; - columns: { - [K in Extract]: Column< - TColumns[K]['type'], - TColumns[K]['schema'] extends { enum: infer E } - ? E extends readonly [string, ...string[]] - ? E - : string - : string, - { - tableName: TTableName; - name: K; - isPrimaryKey: TColumns[K]['schema'] extends { primaryKey: true } ? true : false; - hasDefault: TColumns[K]['schema'] extends { default: NonNullable } - ? true - : TColumns[K]['schema'] extends { primaryKey: true } - ? true - : false; - hasRuntimeDefault: TColumns[K]['schema'] extends { default: NonNullable } - ? true - : false; - notNull: TColumns[K]['schema']['optional'] extends true ? false : true; - } - >; - }; -}>; - -export const SERIALIZED_SQL_KEY = '__serializedSQL'; -export type SerializedSQL = { - [SERIALIZED_SQL_KEY]: true; - sql: string; -}; - -export function isSerializedSQL(value: any): value is SerializedSQL { - return typeof value === 'object' && value !== null && SERIALIZED_SQL_KEY in value; -} diff --git a/packages/db/src/runtime/utils.ts b/packages/db/src/runtime/utils.ts deleted file mode 100644 index 2675ed5bbad6..000000000000 --- a/packages/db/src/runtime/utils.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { LibsqlError } from '@libsql/client'; -import { AstroError } from 'astro/errors'; -import type { DBColumn } from '../core/types.js'; - -export function hasPrimaryKey(column: DBColumn) { - return 'primaryKey' in column.schema && !!column.schema.primaryKey; -} - -const isWindows = process?.platform === 'win32'; - -export class AstroDbError extends AstroError { - name = 'Astro DB Error'; -} - -// Walks the .cause chain to find the underlying LibsqlError, unwrapping drizzle-orm's -// DrizzleQueryError (introduced in 0.44). Returns the LibsqlError directly so callers -// can read .code and .message without caring whether the outer error was wrapped. -// Prefer this over isDbError when accessing libSQL-specific properties; on a wrapped -// error the outer object has a "Failed query: ..." message and no .code field. -export function getDbError(err: unknown): LibsqlError | undefined { - if (err instanceof LibsqlError) return err; - if (err instanceof Error && (err as any).libsqlError === true) return err as LibsqlError; - if (err instanceof Error && err.cause != null && err.cause !== err) { - return getDbError(err.cause); - } - return undefined; -} - -// Reports whether a caught error was (directly or transitively) caused by libSQL. -// NOTE: this returns a plain boolean rather than a `err is LibsqlError` type predicate -// because drizzle-orm 0.44+ wraps query errors in a DrizzleQueryError whose .cause is -// the real LibsqlError; narrowing `err` to LibsqlError would be a lie at runtime and -// would silently give `undefined` for .code and the wrong .message on wrapped errors. -// Use getDbError() to obtain the unwrapped LibsqlError for property access. -export function isDbError(err: unknown): boolean { - return getDbError(err) !== undefined; -} - -function slash(path: string) { - const isExtendedLengthPath = path.startsWith('\\\\?\\'); - - if (isExtendedLengthPath) { - return path; - } - - return path.replace(/\\/g, '/'); -} - -export function pathToFileURL(path: string): URL { - if (isWindows) { - let slashed = slash(path); - // Windows like C:/foo/bar - if (!slashed.startsWith('/')) { - slashed = '/' + slashed; - } - return new URL('file://' + slashed); - } - - // Unix is easy - return new URL('file://' + path); -} diff --git a/packages/db/src/runtime/virtual.ts b/packages/db/src/runtime/virtual.ts deleted file mode 100644 index 0608686c1c44..000000000000 --- a/packages/db/src/runtime/virtual.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { sql as _sql } from 'drizzle-orm'; -import type { - BooleanColumnInput, - ColumnsConfig, - DateColumnInput, - DBConfigInput, - JsonColumnInput, - NumberColumnOpts, - TableConfig, - TextColumnOpts, -} from '../core/types.js'; - -function createColumn>(type: S, schema: T) { - return { - type, - /** - * @internal - */ - schema, - }; -} - -export const column = { - number: (opts: T = {} as T) => { - return createColumn('number', opts) satisfies { type: 'number' }; - }, - boolean: (opts: T = {} as T) => { - return createColumn('boolean', opts) satisfies { type: 'boolean' }; - }, - text: < - T extends TextColumnOpts, - const E extends T['enum'] extends readonly [string, ...string[]] - ? Omit & T['enum'] - : T, - >( - opts: E = {} as E, - ) => { - return createColumn('text', opts) satisfies { type: 'text' }; - }, - date(opts: T = {} as T) { - return createColumn('date', opts) satisfies { type: 'date' }; - }, - json(opts: T = {} as T) { - return createColumn('json', opts) satisfies { type: 'json' }; - }, -}; - -export function defineTable(userConfig: TableConfig) { - return userConfig; -} - -export function defineDb(userConfig: DBConfigInput) { - return userConfig; -} - -// Exports a few common expressions -export const NOW = _sql`CURRENT_TIMESTAMP`; -export const TRUE = _sql`TRUE`; -export const FALSE = _sql`FALSE`; - -export { - and, - asc, - avg, - avgDistinct, - between, - count, - countDistinct, - desc, - eq, - exists, - gt, - gte, - ilike, - inArray, - isNotNull, - isNull, - like, - lt, - lte, - max, - min, - ne, - not, - notBetween, - notExists, - notIlike, - notInArray, - or, - sql, - sum, - sumDistinct, -} from 'drizzle-orm'; - -export { alias } from 'drizzle-orm/sqlite-core'; -export { getDbError, isDbError } from './utils.js'; diff --git a/packages/db/src/utils.ts b/packages/db/src/utils.ts deleted file mode 100644 index 0e4c97ead777..000000000000 --- a/packages/db/src/utils.ts +++ /dev/null @@ -1,15 +0,0 @@ -export { defineDbIntegration } from './core/utils.js'; - -import { tableSchema } from './core/schemas.js'; -import type { ColumnsConfig, TableConfig } from './core/types.js'; -import { asDrizzleTable as internal_asDrizzleTable, type Table } from './runtime/index.js'; - -export function asDrizzleTable< - TableName extends string = string, - TColumns extends ColumnsConfig = ColumnsConfig, ->(name: TableName, tableConfig: TableConfig) { - return internal_asDrizzleTable(name, tableSchema.parse(tableConfig)) as Table< - TableName, - TColumns - >; -} diff --git a/packages/db/test/basics.test.ts b/packages/db/test/basics.test.ts deleted file mode 100644 index 8dfb9e7f157e..000000000000 --- a/packages/db/test/basics.test.ts +++ /dev/null @@ -1,235 +0,0 @@ -import assert from 'node:assert/strict'; -import { after, before, describe, it } from 'node:test'; -import { load as cheerioLoad } from 'cheerio'; -import testAdapter from 'astro/_internal/test/test-adapter'; -import { - clearEnvironment, - type DevServer, - type Fixture, - loadFixture, - type RemoteDbServer, - setupRemoteDb, -} from './test-utils.ts'; -import { resolveDbAppToken } from '../dist/core/utils.js'; - -describe('astro:db', () => { - let fixture: Fixture; - before(async () => { - fixture = await loadFixture({ - root: new URL('./fixtures/basics/', import.meta.url), - output: 'server', - adapter: testAdapter(), - }); - }); - - describe.skip('development', () => { - let devServer: DevServer; - - before(async () => { - clearEnvironment(); - devServer = await fixture.startDevServer(); - }); - - after(async () => { - await devServer.stop(); - }); - - it('Prints the list of authors', async () => { - const html = await fixture.fetch('/').then((res) => res.text()); - const $ = cheerioLoad(html); - - const ul = $('.authors-list'); - assert.equal(ul.children().length, 5); - assert.match(ul.children().eq(0).text(), /Ben/); - }); - - it('Allows expression defaults for date columns', async () => { - const html = await fixture.fetch('/').then((res) => res.text()); - const $ = cheerioLoad(html); - - const themeAdded = $($('.themes-list .theme-added')[0]).text(); - assert.equal(Number.isNaN(new Date(themeAdded).getTime()), false); - }); - - it('Defaults can be overridden for dates', async () => { - const html = await fixture.fetch('/').then((res) => res.text()); - const $ = cheerioLoad(html); - - const themeAdded = $($('.themes-list .theme-added')[1]).text(); - assert.equal(Number.isNaN(new Date(themeAdded).getTime()), false); - }); - - it('Allows expression defaults for text columns', async () => { - const html = await fixture.fetch('/').then((res) => res.text()); - const $ = cheerioLoad(html); - - const themeOwner = $($('.themes-list .theme-owner')[0]).text(); - assert.equal(themeOwner, ''); - }); - - it('Allows expression defaults for boolean columns', async () => { - const html = await fixture.fetch('/').then((res) => res.text()); - const $ = cheerioLoad(html); - - const themeDark = $($('.themes-list .theme-dark')[0]).text(); - assert.match(themeDark, /dark mode/); - }); - - it('text fields can be used as references', async () => { - const html = await fixture.fetch('/login').then((res) => res.text()); - const $ = cheerioLoad(html); - - assert.match($('.session-id').text(), /12345/); - assert.match($('.username').text(), /Mario/); - }); - - it('Prints authors from raw sql call', async () => { - const json = await fixture.fetch('run.json').then((res) => res.json()); - assert.deepEqual(json, { - columns: ['_id', 'name', 'age2'], - columnTypes: ['INTEGER', 'TEXT', 'INTEGER'], - rows: [ - [1, 'Ben', null], - [2, 'Nate', null], - [3, 'Erika', null], - [4, 'Bjorn', null], - [5, 'Sarah', null], - ], - rowsAffected: 0, - lastInsertRowid: null, - }); - }); - }); - - describe('development --remote', () => { - let devServer: DevServer; - let remoteDbServer: RemoteDbServer; - - before(async () => { - clearEnvironment(); - remoteDbServer = await setupRemoteDb(fixture.config); - devServer = await fixture.startDevServer(); - }); - - after(async () => { - await devServer?.stop(); - await remoteDbServer?.stop(); - }); - - it('Prints the list of authors', async () => { - const html = await fixture.fetch('/').then((res) => res.text()); - const $ = cheerioLoad(html); - - const ul = $('.authors-list'); - assert.equal(ul.children().length, 5); - assert.match(ul.children().eq(0).text(), /Ben/); - }); - - it('Allows expression defaults for date columns', async () => { - const html = await fixture.fetch('/').then((res) => res.text()); - const $ = cheerioLoad(html); - - const themeAdded = $($('.themes-list .theme-added')[0]).text(); - assert.equal(Number.isNaN(new Date(themeAdded).getTime()), false); - }); - - it('Defaults can be overridden for dates', async () => { - const html = await fixture.fetch('/').then((res) => res.text()); - const $ = cheerioLoad(html); - - const themeAdded = $($('.themes-list .theme-added')[1]).text(); - assert.equal(Number.isNaN(new Date(themeAdded).getTime()), false); - }); - - it('Allows expression defaults for text columns', async () => { - const html = await fixture.fetch('/').then((res) => res.text()); - const $ = cheerioLoad(html); - - const themeOwner = $($('.themes-list .theme-owner')[0]).text(); - assert.equal(themeOwner, ''); - }); - - it('Allows expression defaults for boolean columns', async () => { - const html = await fixture.fetch('/').then((res) => res.text()); - const $ = cheerioLoad(html); - - const themeDark = $($('.themes-list .theme-dark')[0]).text(); - assert.match(themeDark, /dark mode/); - }); - - it('text fields can be used as references', async () => { - const html = await fixture.fetch('/login').then((res) => res.text()); - const $ = cheerioLoad(html); - - assert.match($('.session-id').text(), /12345/); - assert.match($('.username').text(), /Mario/); - }); - - it('Prints authors from raw sql call', async () => { - const json = await fixture.fetch('run.json').then((res) => res.json()); - assert.deepEqual(json, { - columns: ['_id', 'name', 'age2'], - columnTypes: ['INTEGER', 'TEXT', 'INTEGER'], - rows: [ - [1, 'Ben', null], - [2, 'Nate', null], - [3, 'Erika', null], - [4, 'Bjorn', null], - [5, 'Sarah', null], - ], - rowsAffected: 0, - lastInsertRowid: null, - }); - }); - }); - - describe('build --remote', () => { - let remoteDbServer: RemoteDbServer; - - before(async () => { - clearEnvironment(); - remoteDbServer = await setupRemoteDb(fixture.config); - await fixture.build(); - }); - - after(async () => { - await remoteDbServer?.stop(); - }); - - it('Can render page', async () => { - const app = await fixture.loadTestAdapterApp(); - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerioLoad(html); - - const ul = $('.authors-list'); - assert.equal(ul.children().length, 5); - }); - }); - - describe('cli --db-app-token', () => { - it('Seeds remote database with --db-app-token flag set and without ASTRO_DB_APP_TOKEN env being set', async () => { - clearEnvironment(); - assert.equal(process.env.ASTRO_DB_APP_TOKEN, undefined); - - const remoteDbServer = await setupRemoteDb(fixture.config, { useDbAppTokenFlag: true }); - try { - assert.equal(process.env.ASTRO_DB_APP_TOKEN, undefined); - } finally { - await remoteDbServer.stop(); - } - assert.equal(process.env.ASTRO_DB_APP_TOKEN, undefined); - }); - }); - - describe('Precedence for --db-app-token and ASTRO_DB_APP_TOKEN handled correctly', () => { - it('prefers --db-app-token over `ASTRO_DB_APP_TOKEN`', () => { - assert.equal(resolveDbAppToken({ _: [], dbAppToken: 'from-flag' }, 'from-env'), 'from-flag'); - }); - - it('falls back to ASTRO_DB_APP_TOKEN if no flags set', () => { - assert.equal(resolveDbAppToken({ _: [] }, 'from-env'), 'from-env'); - }); - }); -}); diff --git a/packages/db/test/db-in-src.test.ts b/packages/db/test/db-in-src.test.ts deleted file mode 100644 index 50ad8bc1270c..000000000000 --- a/packages/db/test/db-in-src.test.ts +++ /dev/null @@ -1,38 +0,0 @@ -import assert from 'node:assert/strict'; -import { after, before, describe, it } from 'node:test'; -import { load as cheerioLoad } from 'cheerio'; -import testAdapter from 'astro/_internal/test/test-adapter'; -import { type DevServer, type Fixture, loadFixture } from './test-utils.ts'; - -describe('astro:db', () => { - let fixture: Fixture; - before(async () => { - fixture = await loadFixture({ - root: new URL('./fixtures/db-in-src/', import.meta.url), - output: 'server', - srcDir: '.', - adapter: testAdapter(), - }); - }); - - describe('development: db/ folder inside srcDir', () => { - let devServer: DevServer; - - before(async () => { - devServer = await fixture.startDevServer(); - }); - - after(async () => { - await devServer.stop(); - }); - - it('Prints the list of authors', async () => { - const html = await fixture.fetch('/').then((res) => res.text()); - const $ = cheerioLoad(html); - - const ul = $('.users-list'); - assert.equal(ul.children().length, 1); - assert.match($('.users-list li').text(), /Mario/); - }); - }); -}); diff --git a/packages/db/test/error-handling.test.ts b/packages/db/test/error-handling.test.ts deleted file mode 100644 index b9f7c9672c71..000000000000 --- a/packages/db/test/error-handling.test.ts +++ /dev/null @@ -1,68 +0,0 @@ -import assert from 'node:assert/strict'; -import { after, before, describe, it } from 'node:test'; -import { type Fixture, loadFixture, type RemoteDbServer, setupRemoteDb } from './test-utils.ts'; -import { cli } from '../dist/core/cli/index.js'; - -const foreignKeyConstraintError = 'LibsqlError: SQLITE_CONSTRAINT: FOREIGN KEY constraint failed'; - -describe('astro:db - error handling', () => { - let fixture: Fixture; - before(async () => { - fixture = await loadFixture({ - root: new URL('./fixtures/error-handling/', import.meta.url), - }); - }); - - it('Errors on invalid --db-app-token input', async () => { - const originalExit = process.exit; - const originalError = console.error; - const errorMessages: string[] = []; - console.error = (...args: unknown[]) => { - errorMessages.push(args.map(String).join(' ')); - }; - process.exit = ((code?: number) => { - throw new Error(`EXIT_${code}`); - }) as typeof process.exit; - - try { - await cli({ - config: fixture.config, - flags: { - _: ['', 'astro', 'db', 'verify'], - dbAppToken: true, - }, - }); - assert.fail('Expected command to exit'); - } catch (err) { - assert.match(String(err), /EXIT_1/); - assert.ok( - errorMessages.some((m) => m.includes('Invalid value for --db-app-token')), - `Expected error output to mention invalid --db-app-token, got: ${errorMessages.join('\n')}`, - ); - } finally { - process.exit = originalExit; - console.error = originalError; - } - }); - - describe('build --remote', () => { - let remoteDbServer: RemoteDbServer; - - before(async () => { - remoteDbServer = await setupRemoteDb(fixture.config); - await fixture.build(); - }); - - after(async () => { - await remoteDbServer?.stop(); - }); - - it('Raises foreign key constraint LibsqlError', async () => { - const json = await fixture.readFile('/foreign-key-constraint.json'); - assert.deepEqual(JSON.parse(json), { - message: foreignKeyConstraintError, - code: 'SQLITE_CONSTRAINT', - }); - }); - }); -}); diff --git a/packages/db/test/fixtures/basics/astro.config.ts b/packages/db/test/fixtures/basics/astro.config.ts deleted file mode 100644 index 983a6947d115..000000000000 --- a/packages/db/test/fixtures/basics/astro.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import db from '@astrojs/db'; -import { defineConfig } from 'astro/config'; - -// https://astro.build/config -export default defineConfig({ - integrations: [db()], - devToolbar: { - enabled: false, - }, -}); diff --git a/packages/db/test/fixtures/basics/db/config.ts b/packages/db/test/fixtures/basics/db/config.ts deleted file mode 100644 index 010ed3a1863d..000000000000 --- a/packages/db/test/fixtures/basics/db/config.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { column, defineDb, defineTable } from 'astro:db'; -import { Themes } from './theme'; - -const Author = defineTable({ - columns: { - name: column.text(), - age2: column.number({ optional: true }), - }, -}); - -const User = defineTable({ - columns: { - id: column.text({ primaryKey: true, optional: false }), - username: column.text({ optional: false, unique: true }), - password: column.text({ optional: false }), - }, -}); - -const Session = defineTable({ - columns: { - id: column.text({ primaryKey: true, optional: false }), - expiresAt: column.number({ optional: false, name: 'expires_at' }), - userId: column.text({ optional: false, references: () => User.columns.id, name: 'user_id' }), - }, -}); - -export default defineDb({ - tables: { Author, Themes, User, Session }, -}); diff --git a/packages/db/test/fixtures/basics/db/seed.ts b/packages/db/test/fixtures/basics/db/seed.ts deleted file mode 100644 index 9a1ef4322e04..000000000000 --- a/packages/db/test/fixtures/basics/db/seed.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Author, Session, User, db } from 'astro:db'; -import { asDrizzleTable } from '@astrojs/db/utils'; -import { Themes as ThemesConfig } from './theme'; - -const Themes = asDrizzleTable('Themes', ThemesConfig); -export default async function () { - await db.batch([ - db - .insert(Themes) - .values([{ name: 'dracula' }, { name: 'monokai', added: new Date() }]) - .returning({ name: Themes.name }), - db - .insert(Author) - .values([ - { name: 'Ben' }, - { name: 'Nate' }, - { name: 'Erika' }, - { name: 'Bjorn' }, - { name: 'Sarah' }, - ]), - db.insert(User).values([{ id: 'mario', username: 'Mario', password: 'itsame' }]), - db.insert(Session).values([{ id: '12345', expiresAt: new Date().valueOf(), userId: 'mario' }]), - ]); -} diff --git a/packages/db/test/fixtures/basics/db/theme.ts b/packages/db/test/fixtures/basics/db/theme.ts deleted file mode 100644 index 015dcc588066..000000000000 --- a/packages/db/test/fixtures/basics/db/theme.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { NOW, column, defineTable, sql } from 'astro:db'; - -export const Themes = defineTable({ - columns: { - name: column.text(), - added: column.date({ - default: sql`CURRENT_TIMESTAMP`, - }), - updated: column.date({ - default: NOW, - }), - isDark: column.boolean({ default: sql`TRUE`, deprecated: true }), - owner: column.text({ optional: true, default: sql`NULL` }), - }, -}); diff --git a/packages/db/test/fixtures/basics/package.json b/packages/db/test/fixtures/basics/package.json deleted file mode 100644 index af7cbe229800..000000000000 --- a/packages/db/test/fixtures/basics/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "@test/db-aliases", - "version": "0.0.0", - "private": true, - "scripts": { - "dev": "astro dev", - "build": "astro build", - "preview": "astro preview" - }, - "dependencies": { - "@astrojs/db": "workspace:*", - "astro": "workspace:*" - } -} diff --git a/packages/db/test/fixtures/basics/src/pages/index.astro b/packages/db/test/fixtures/basics/src/pages/index.astro deleted file mode 100644 index 2be0c4b2385a..000000000000 --- a/packages/db/test/fixtures/basics/src/pages/index.astro +++ /dev/null @@ -1,27 +0,0 @@ ---- -/// -import { Author, Themes, db } from 'astro:db'; - -const authors = await db.select().from(Author); -const themes = await db.select().from(Themes); ---- - -

Authors

-
    - {authors.map((author) =>
  • {author.name}
  • )} -
- -

Themes

-
    - { - themes.map((theme) => ( -
  • -
    {theme.name}
    -
    {theme.added}
    -
    {theme.updated}
    -
    {theme.isDark ? 'dark' : 'light'} mode
    -
    {theme.owner}
    -
  • - )) - } -
diff --git a/packages/db/test/fixtures/basics/src/pages/login.astro b/packages/db/test/fixtures/basics/src/pages/login.astro deleted file mode 100644 index 4551fc48325f..000000000000 --- a/packages/db/test/fixtures/basics/src/pages/login.astro +++ /dev/null @@ -1,18 +0,0 @@ ---- -import { Session, User, db, eq } from 'astro:db'; - -const users = await db.select().from(User); -const sessions = await db.select().from(Session).innerJoin(User, eq(Session.userId, User.id)); ---- - -

Sessions

-
    - { - sessions.map(({ Session, User }) => ( -
  • -
    {Session.id}
    -
    {User.username}
    -
  • - )) - } -
diff --git a/packages/db/test/fixtures/basics/src/pages/run.json.ts b/packages/db/test/fixtures/basics/src/pages/run.json.ts deleted file mode 100644 index a86619314414..000000000000 --- a/packages/db/test/fixtures/basics/src/pages/run.json.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { db, sql } from 'astro:db'; -/// -import type { APIRoute } from 'astro'; - -export const GET: APIRoute = async () => { - const authors = await db.run(sql`SELECT * FROM Author`); - return new Response(JSON.stringify(authors), { - headers: { - 'content-type': 'application/json', - }, - }); -}; diff --git a/packages/db/test/fixtures/db-in-src/astro.config.ts b/packages/db/test/fixtures/db-in-src/astro.config.ts deleted file mode 100644 index 983a6947d115..000000000000 --- a/packages/db/test/fixtures/db-in-src/astro.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import db from '@astrojs/db'; -import { defineConfig } from 'astro/config'; - -// https://astro.build/config -export default defineConfig({ - integrations: [db()], - devToolbar: { - enabled: false, - }, -}); diff --git a/packages/db/test/fixtures/db-in-src/db/config.ts b/packages/db/test/fixtures/db-in-src/db/config.ts deleted file mode 100644 index 44c15abe7567..000000000000 --- a/packages/db/test/fixtures/db-in-src/db/config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { column, defineDb, defineTable } from 'astro:db'; - -const User = defineTable({ - columns: { - id: column.text({ primaryKey: true, optional: false }), - username: column.text({ optional: false, unique: true }), - password: column.text({ optional: false }), - }, -}); - -export default defineDb({ - tables: { User }, -}); diff --git a/packages/db/test/fixtures/db-in-src/db/seed.ts b/packages/db/test/fixtures/db-in-src/db/seed.ts deleted file mode 100644 index a84e6345498e..000000000000 --- a/packages/db/test/fixtures/db-in-src/db/seed.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { User, db } from 'astro:db'; -import { asDrizzleTable } from '@astrojs/db/utils'; - -export default async function () { - await db.batch([ - db.insert(User).values([{ id: 'mario', username: 'Mario', password: 'itsame' }]), - ]); -} diff --git a/packages/db/test/fixtures/db-in-src/package.json b/packages/db/test/fixtures/db-in-src/package.json deleted file mode 100644 index a1580d1cb1cf..000000000000 --- a/packages/db/test/fixtures/db-in-src/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "@test/db-db-in-src", - "version": "0.0.0", - "private": true, - "scripts": { - "dev": "astro dev", - "build": "astro build", - "preview": "astro preview" - }, - "dependencies": { - "@astrojs/db": "workspace:*", - "astro": "workspace:*" - } -} diff --git a/packages/db/test/fixtures/db-in-src/pages/index.astro b/packages/db/test/fixtures/db-in-src/pages/index.astro deleted file mode 100644 index 4b79dba2c859..000000000000 --- a/packages/db/test/fixtures/db-in-src/pages/index.astro +++ /dev/null @@ -1,11 +0,0 @@ ---- -/// -import { User, db } from 'astro:db'; - -const users = await db.select().from(User); ---- - -

Users

-
    - {users.map((user) =>
  • {user.username}
  • )} -
diff --git a/packages/db/test/fixtures/error-handling/astro.config.ts b/packages/db/test/fixtures/error-handling/astro.config.ts deleted file mode 100644 index 983a6947d115..000000000000 --- a/packages/db/test/fixtures/error-handling/astro.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import db from '@astrojs/db'; -import { defineConfig } from 'astro/config'; - -// https://astro.build/config -export default defineConfig({ - integrations: [db()], - devToolbar: { - enabled: false, - }, -}); diff --git a/packages/db/test/fixtures/error-handling/db/config.ts b/packages/db/test/fixtures/error-handling/db/config.ts deleted file mode 100644 index bd4d6edaf425..000000000000 --- a/packages/db/test/fixtures/error-handling/db/config.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { column, defineDb, defineTable } from 'astro:db'; - -const Recipe = defineTable({ - columns: { - id: column.number({ primaryKey: true }), - title: column.text(), - description: column.text(), - }, -}); - -const Ingredient = defineTable({ - columns: { - id: column.number({ primaryKey: true }), - name: column.text(), - quantity: column.number(), - recipeId: column.number(), - }, - indexes: { - recipeIdx: { on: 'recipeId' }, - }, - foreignKeys: [{ columns: 'recipeId', references: () => [Recipe.columns.id] }], -}); - -export default defineDb({ - tables: { Recipe, Ingredient }, -}); diff --git a/packages/db/test/fixtures/error-handling/db/seed.ts b/packages/db/test/fixtures/error-handling/db/seed.ts deleted file mode 100644 index 1ca219f15bf8..000000000000 --- a/packages/db/test/fixtures/error-handling/db/seed.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { Ingredient, Recipe, db } from 'astro:db'; - -export default async function () { - const pancakes = await db - .insert(Recipe) - .values({ - title: 'Pancakes', - description: 'A delicious breakfast', - }) - .returning() - .get(); - - await db.insert(Ingredient).values([ - { - name: 'Flour', - quantity: 1, - recipeId: pancakes.id, - }, - { - name: 'Eggs', - quantity: 2, - recipeId: pancakes.id, - }, - { - name: 'Milk', - quantity: 1, - recipeId: pancakes.id, - }, - ]); - - const pizza = await db - .insert(Recipe) - .values({ - title: 'Pizza', - description: 'A delicious dinner', - }) - .returning() - .get(); - - await db.insert(Ingredient).values([ - { - name: 'Flour', - quantity: 1, - recipeId: pizza.id, - }, - { - name: 'Eggs', - quantity: 2, - recipeId: pizza.id, - }, - { - name: 'Milk', - quantity: 1, - recipeId: pizza.id, - }, - { - name: 'Tomato Sauce', - quantity: 1, - recipeId: pizza.id, - }, - ]); -} diff --git a/packages/db/test/fixtures/error-handling/package.json b/packages/db/test/fixtures/error-handling/package.json deleted file mode 100644 index e0839956bcd9..000000000000 --- a/packages/db/test/fixtures/error-handling/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "@test/error-handling", - "version": "0.0.0", - "private": true, - "scripts": { - "dev": "astro dev", - "build": "astro build", - "preview": "astro preview" - }, - "dependencies": { - "@astrojs/db": "workspace:*", - "astro": "workspace:*" - } -} diff --git a/packages/db/test/fixtures/error-handling/src/pages/foreign-key-constraint.json.ts b/packages/db/test/fixtures/error-handling/src/pages/foreign-key-constraint.json.ts deleted file mode 100644 index 4807c40829ad..000000000000 --- a/packages/db/test/fixtures/error-handling/src/pages/foreign-key-constraint.json.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Ingredient, db, getDbError } from 'astro:db'; -import type { APIRoute } from 'astro'; - -export const GET: APIRoute = async () => { - try { - await db.insert(Ingredient).values({ - name: 'Flour', - quantity: 1, - // Trigger foreign key constraint error - recipeId: 42, - }); - } catch (e) { - const dbError = getDbError(e); - if (dbError) { - return new Response( - JSON.stringify({ message: `LibsqlError: ${dbError.message}`, code: dbError.code }), - ); - } - } - return new Response(JSON.stringify({ message: 'Did not raise expected exception' })); -}; diff --git a/packages/db/test/fixtures/integration-only/astro.config.mjs b/packages/db/test/fixtures/integration-only/astro.config.mjs deleted file mode 100644 index 23f52739e531..000000000000 --- a/packages/db/test/fixtures/integration-only/astro.config.mjs +++ /dev/null @@ -1,8 +0,0 @@ -import db from '@astrojs/db'; -import { defineConfig } from 'astro/config'; -import testIntegration from './integration'; - -// https://astro.build/config -export default defineConfig({ - integrations: [db(), testIntegration()], -}); diff --git a/packages/db/test/fixtures/integration-only/integration/config.ts b/packages/db/test/fixtures/integration-only/integration/config.ts deleted file mode 100644 index 71490be95727..000000000000 --- a/packages/db/test/fixtures/integration-only/integration/config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defineDb } from 'astro:db'; -import { menu } from './shared'; - -export default defineDb({ - tables: { - menu, - }, -}); diff --git a/packages/db/test/fixtures/integration-only/integration/index.ts b/packages/db/test/fixtures/integration-only/integration/index.ts deleted file mode 100644 index b249cc253853..000000000000 --- a/packages/db/test/fixtures/integration-only/integration/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { defineDbIntegration } from '@astrojs/db/utils'; - -export default function testIntegration() { - return defineDbIntegration({ - name: 'db-test-integration', - hooks: { - 'astro:db:setup'({ extendDb }) { - extendDb({ - configEntrypoint: './integration/config.ts', - seedEntrypoint: './integration/seed.ts', - }); - }, - }, - }); -} diff --git a/packages/db/test/fixtures/integration-only/integration/seed.ts b/packages/db/test/fixtures/integration-only/integration/seed.ts deleted file mode 100644 index ed2b2e2ebf2b..000000000000 --- a/packages/db/test/fixtures/integration-only/integration/seed.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { db } from 'astro:db'; -import { asDrizzleTable } from '@astrojs/db/utils'; -import { menu } from './shared'; - -export default async function () { - const table = asDrizzleTable('menu', menu); - - await db.insert(table).values([ - { name: 'Pancakes', price: 9.5, type: 'Breakfast' }, - { name: 'French Toast', price: 11.25, type: 'Breakfast' }, - { name: 'Coffee', price: 3, type: 'Beverages' }, - { name: 'Cappuccino', price: 4.5, type: 'Beverages' }, - ]); -} diff --git a/packages/db/test/fixtures/integration-only/integration/shared.ts b/packages/db/test/fixtures/integration-only/integration/shared.ts deleted file mode 100644 index d46ae65a6536..000000000000 --- a/packages/db/test/fixtures/integration-only/integration/shared.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { column, defineTable } from 'astro:db'; - -export const menu = defineTable({ - columns: { - name: column.text(), - type: column.text(), - price: column.number(), - }, -}); diff --git a/packages/db/test/fixtures/integration-only/package.json b/packages/db/test/fixtures/integration-only/package.json deleted file mode 100644 index 4229f710ae96..000000000000 --- a/packages/db/test/fixtures/integration-only/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "@test/db-integration-only", - "version": "0.0.0", - "private": true, - "scripts": { - "dev": "astro dev", - "build": "astro build", - "preview": "astro preview" - }, - "dependencies": { - "@astrojs/db": "workspace:*", - "astro": "workspace:*" - } -} diff --git a/packages/db/test/fixtures/integration-only/src/pages/index.astro b/packages/db/test/fixtures/integration-only/src/pages/index.astro deleted file mode 100644 index 7b204e124f13..000000000000 --- a/packages/db/test/fixtures/integration-only/src/pages/index.astro +++ /dev/null @@ -1,11 +0,0 @@ ---- -/// -import { db, menu } from 'astro:db'; - -const menuItems = await db.select().from(menu); ---- - -

Menu

- diff --git a/packages/db/test/fixtures/integrations/astro.config.mjs b/packages/db/test/fixtures/integrations/astro.config.mjs deleted file mode 100644 index 23f52739e531..000000000000 --- a/packages/db/test/fixtures/integrations/astro.config.mjs +++ /dev/null @@ -1,8 +0,0 @@ -import db from '@astrojs/db'; -import { defineConfig } from 'astro/config'; -import testIntegration from './integration'; - -// https://astro.build/config -export default defineConfig({ - integrations: [db(), testIntegration()], -}); diff --git a/packages/db/test/fixtures/integrations/db/config.ts b/packages/db/test/fixtures/integrations/db/config.ts deleted file mode 100644 index b8110406ab69..000000000000 --- a/packages/db/test/fixtures/integrations/db/config.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { column, defineDb, defineTable } from 'astro:db'; - -const Author = defineTable({ - columns: { - name: column.text(), - age2: column.number({ optional: true }), - }, -}); - -export default defineDb({ - tables: { Author }, -}); diff --git a/packages/db/test/fixtures/integrations/db/seed.ts b/packages/db/test/fixtures/integrations/db/seed.ts deleted file mode 100644 index 56ffb5668245..000000000000 --- a/packages/db/test/fixtures/integrations/db/seed.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Author, db } from 'astro:db'; - -export default async () => { - await db - .insert(Author) - .values([ - { name: 'Ben' }, - { name: 'Nate' }, - { name: 'Erika' }, - { name: 'Bjorn' }, - { name: 'Sarah' }, - ]); -}; diff --git a/packages/db/test/fixtures/integrations/integration/config.ts b/packages/db/test/fixtures/integrations/integration/config.ts deleted file mode 100644 index 71490be95727..000000000000 --- a/packages/db/test/fixtures/integrations/integration/config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defineDb } from 'astro:db'; -import { menu } from './shared'; - -export default defineDb({ - tables: { - menu, - }, -}); diff --git a/packages/db/test/fixtures/integrations/integration/index.ts b/packages/db/test/fixtures/integrations/integration/index.ts deleted file mode 100644 index b249cc253853..000000000000 --- a/packages/db/test/fixtures/integrations/integration/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { defineDbIntegration } from '@astrojs/db/utils'; - -export default function testIntegration() { - return defineDbIntegration({ - name: 'db-test-integration', - hooks: { - 'astro:db:setup'({ extendDb }) { - extendDb({ - configEntrypoint: './integration/config.ts', - seedEntrypoint: './integration/seed.ts', - }); - }, - }, - }); -} diff --git a/packages/db/test/fixtures/integrations/integration/seed.ts b/packages/db/test/fixtures/integrations/integration/seed.ts deleted file mode 100644 index ed2b2e2ebf2b..000000000000 --- a/packages/db/test/fixtures/integrations/integration/seed.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { db } from 'astro:db'; -import { asDrizzleTable } from '@astrojs/db/utils'; -import { menu } from './shared'; - -export default async function () { - const table = asDrizzleTable('menu', menu); - - await db.insert(table).values([ - { name: 'Pancakes', price: 9.5, type: 'Breakfast' }, - { name: 'French Toast', price: 11.25, type: 'Breakfast' }, - { name: 'Coffee', price: 3, type: 'Beverages' }, - { name: 'Cappuccino', price: 4.5, type: 'Beverages' }, - ]); -} diff --git a/packages/db/test/fixtures/integrations/integration/shared.ts b/packages/db/test/fixtures/integrations/integration/shared.ts deleted file mode 100644 index d46ae65a6536..000000000000 --- a/packages/db/test/fixtures/integrations/integration/shared.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { column, defineTable } from 'astro:db'; - -export const menu = defineTable({ - columns: { - name: column.text(), - type: column.text(), - price: column.number(), - }, -}); diff --git a/packages/db/test/fixtures/integrations/package.json b/packages/db/test/fixtures/integrations/package.json deleted file mode 100644 index 1bb17a8c78ec..000000000000 --- a/packages/db/test/fixtures/integrations/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "@test/db-integration", - "version": "0.0.0", - "private": true, - "scripts": { - "dev": "astro dev", - "build": "astro build", - "preview": "astro preview" - }, - "dependencies": { - "@astrojs/db": "workspace:*", - "astro": "workspace:*" - } -} diff --git a/packages/db/test/fixtures/integrations/src/pages/index.astro b/packages/db/test/fixtures/integrations/src/pages/index.astro deleted file mode 100644 index 3e9c30ef7112..000000000000 --- a/packages/db/test/fixtures/integrations/src/pages/index.astro +++ /dev/null @@ -1,17 +0,0 @@ ---- -/// -import { Author, db, menu } from 'astro:db'; - -const authors = await db.select().from(Author); -const menuItems = await db.select().from(menu); ---- - -

Authors

-
    - {authors.map((author) =>
  • {author.name}
  • )} -
- -

Menu

- diff --git a/packages/db/test/fixtures/libsql-remote/astro.config.ts b/packages/db/test/fixtures/libsql-remote/astro.config.ts deleted file mode 100644 index 983a6947d115..000000000000 --- a/packages/db/test/fixtures/libsql-remote/astro.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import db from '@astrojs/db'; -import { defineConfig } from 'astro/config'; - -// https://astro.build/config -export default defineConfig({ - integrations: [db()], - devToolbar: { - enabled: false, - }, -}); diff --git a/packages/db/test/fixtures/libsql-remote/db/config.ts b/packages/db/test/fixtures/libsql-remote/db/config.ts deleted file mode 100644 index 44c15abe7567..000000000000 --- a/packages/db/test/fixtures/libsql-remote/db/config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { column, defineDb, defineTable } from 'astro:db'; - -const User = defineTable({ - columns: { - id: column.text({ primaryKey: true, optional: false }), - username: column.text({ optional: false, unique: true }), - password: column.text({ optional: false }), - }, -}); - -export default defineDb({ - tables: { User }, -}); diff --git a/packages/db/test/fixtures/libsql-remote/db/seed.ts b/packages/db/test/fixtures/libsql-remote/db/seed.ts deleted file mode 100644 index 7d9aa329253f..000000000000 --- a/packages/db/test/fixtures/libsql-remote/db/seed.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { User, db } from 'astro:db'; - -export default async function () { - await db.batch([ - db.insert(User).values([{ id: 'mario', username: 'Mario', password: 'itsame' }]), - ]); -} diff --git a/packages/db/test/fixtures/libsql-remote/package.json b/packages/db/test/fixtures/libsql-remote/package.json deleted file mode 100644 index 2970a62d534a..000000000000 --- a/packages/db/test/fixtures/libsql-remote/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "@test/db-libsql-remote", - "version": "0.0.0", - "private": true, - "scripts": { - "dev": "astro dev", - "build": "astro build", - "preview": "astro preview" - }, - "dependencies": { - "@astrojs/db": "workspace:*", - "astro": "workspace:*" - } -} diff --git a/packages/db/test/fixtures/libsql-remote/src/pages/index.astro b/packages/db/test/fixtures/libsql-remote/src/pages/index.astro deleted file mode 100644 index f36d44bd4eb3..000000000000 --- a/packages/db/test/fixtures/libsql-remote/src/pages/index.astro +++ /dev/null @@ -1,11 +0,0 @@ ---- -/// -import { User, db } from 'astro:db'; - -const users = await db.select().from(User); ---- - -

Users

-
    - {users.map((user) =>
  • {user.name}
  • )} -
diff --git a/packages/db/test/fixtures/libsql-remote/temp/.gitignore b/packages/db/test/fixtures/libsql-remote/temp/.gitignore deleted file mode 100644 index 3997beadf829..000000000000 --- a/packages/db/test/fixtures/libsql-remote/temp/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.db \ No newline at end of file diff --git a/packages/db/test/fixtures/libsql-remote/temp/.gitkeep b/packages/db/test/fixtures/libsql-remote/temp/.gitkeep deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/packages/db/test/fixtures/local-prod/astro.config.ts b/packages/db/test/fixtures/local-prod/astro.config.ts deleted file mode 100644 index 983a6947d115..000000000000 --- a/packages/db/test/fixtures/local-prod/astro.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import db from '@astrojs/db'; -import { defineConfig } from 'astro/config'; - -// https://astro.build/config -export default defineConfig({ - integrations: [db()], - devToolbar: { - enabled: false, - }, -}); diff --git a/packages/db/test/fixtures/local-prod/db/config.ts b/packages/db/test/fixtures/local-prod/db/config.ts deleted file mode 100644 index 44c15abe7567..000000000000 --- a/packages/db/test/fixtures/local-prod/db/config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { column, defineDb, defineTable } from 'astro:db'; - -const User = defineTable({ - columns: { - id: column.text({ primaryKey: true, optional: false }), - username: column.text({ optional: false, unique: true }), - password: column.text({ optional: false }), - }, -}); - -export default defineDb({ - tables: { User }, -}); diff --git a/packages/db/test/fixtures/local-prod/db/seed.ts b/packages/db/test/fixtures/local-prod/db/seed.ts deleted file mode 100644 index a84e6345498e..000000000000 --- a/packages/db/test/fixtures/local-prod/db/seed.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { User, db } from 'astro:db'; -import { asDrizzleTable } from '@astrojs/db/utils'; - -export default async function () { - await db.batch([ - db.insert(User).values([{ id: 'mario', username: 'Mario', password: 'itsame' }]), - ]); -} diff --git a/packages/db/test/fixtures/local-prod/package.json b/packages/db/test/fixtures/local-prod/package.json deleted file mode 100644 index 2d11d53479bf..000000000000 --- a/packages/db/test/fixtures/local-prod/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "@test/db-local-prod", - "version": "0.0.0", - "private": true, - "scripts": { - "dev": "astro dev", - "build": "astro build", - "preview": "astro preview" - }, - "dependencies": { - "@astrojs/db": "workspace:*", - "astro": "workspace:*" - } -} diff --git a/packages/db/test/fixtures/local-prod/src/pages/index.astro b/packages/db/test/fixtures/local-prod/src/pages/index.astro deleted file mode 100644 index f36d44bd4eb3..000000000000 --- a/packages/db/test/fixtures/local-prod/src/pages/index.astro +++ /dev/null @@ -1,11 +0,0 @@ ---- -/// -import { User, db } from 'astro:db'; - -const users = await db.select().from(User); ---- - -

Users

-
    - {users.map((user) =>
  • {user.name}
  • )} -
diff --git a/packages/db/test/fixtures/no-apptoken/astro.config.ts b/packages/db/test/fixtures/no-apptoken/astro.config.ts deleted file mode 100644 index 983a6947d115..000000000000 --- a/packages/db/test/fixtures/no-apptoken/astro.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import db from '@astrojs/db'; -import { defineConfig } from 'astro/config'; - -// https://astro.build/config -export default defineConfig({ - integrations: [db()], - devToolbar: { - enabled: false, - }, -}); diff --git a/packages/db/test/fixtures/no-apptoken/db/config.ts b/packages/db/test/fixtures/no-apptoken/db/config.ts deleted file mode 100644 index 44c15abe7567..000000000000 --- a/packages/db/test/fixtures/no-apptoken/db/config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { column, defineDb, defineTable } from 'astro:db'; - -const User = defineTable({ - columns: { - id: column.text({ primaryKey: true, optional: false }), - username: column.text({ optional: false, unique: true }), - password: column.text({ optional: false }), - }, -}); - -export default defineDb({ - tables: { User }, -}); diff --git a/packages/db/test/fixtures/no-apptoken/db/seed.ts b/packages/db/test/fixtures/no-apptoken/db/seed.ts deleted file mode 100644 index ea9b101e1c22..000000000000 --- a/packages/db/test/fixtures/no-apptoken/db/seed.ts +++ /dev/null @@ -1 +0,0 @@ -export default function () {} diff --git a/packages/db/test/fixtures/no-apptoken/package.json b/packages/db/test/fixtures/no-apptoken/package.json deleted file mode 100644 index a7e17d1af0b2..000000000000 --- a/packages/db/test/fixtures/no-apptoken/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "@test/db-no-apptoken", - "version": "0.0.0", - "private": true, - "scripts": { - "dev": "astro dev", - "build": "astro build", - "preview": "astro preview" - }, - "dependencies": { - "@astrojs/db": "workspace:*", - "astro": "workspace:*" - } -} diff --git a/packages/db/test/fixtures/no-apptoken/src/pages/index.astro b/packages/db/test/fixtures/no-apptoken/src/pages/index.astro deleted file mode 100644 index 477e18fa3306..000000000000 --- a/packages/db/test/fixtures/no-apptoken/src/pages/index.astro +++ /dev/null @@ -1,16 +0,0 @@ ---- -/// -import { User, db } from 'astro:db'; - -// Just for the side-effect of running all the code -await db.select().from(User); ---- - - - - Testing - - -

Testing

- - diff --git a/packages/db/test/fixtures/no-seed/astro.config.ts b/packages/db/test/fixtures/no-seed/astro.config.ts deleted file mode 100644 index 5ff1200e2418..000000000000 --- a/packages/db/test/fixtures/no-seed/astro.config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import db from '@astrojs/db'; -import { defineConfig } from 'astro/config'; - -// https://astro.build/config -export default defineConfig({ - integrations: [db()], -}); diff --git a/packages/db/test/fixtures/no-seed/db/config.ts b/packages/db/test/fixtures/no-seed/db/config.ts deleted file mode 100644 index b8110406ab69..000000000000 --- a/packages/db/test/fixtures/no-seed/db/config.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { column, defineDb, defineTable } from 'astro:db'; - -const Author = defineTable({ - columns: { - name: column.text(), - age2: column.number({ optional: true }), - }, -}); - -export default defineDb({ - tables: { Author }, -}); diff --git a/packages/db/test/fixtures/no-seed/package.json b/packages/db/test/fixtures/no-seed/package.json deleted file mode 100644 index 66a192697826..000000000000 --- a/packages/db/test/fixtures/no-seed/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "@test/db-no-seed", - "version": "0.0.0", - "private": true, - "scripts": { - "dev": "astro dev", - "build": "astro build", - "preview": "astro preview" - }, - "dependencies": { - "@astrojs/db": "workspace:*", - "astro": "workspace:*" - } -} diff --git a/packages/db/test/fixtures/no-seed/src/pages/index.astro b/packages/db/test/fixtures/no-seed/src/pages/index.astro deleted file mode 100644 index bacd873e1332..000000000000 --- a/packages/db/test/fixtures/no-seed/src/pages/index.astro +++ /dev/null @@ -1,21 +0,0 @@ ---- -/// -import { Author, db } from 'astro:db'; - -await db - .insert(Author) - .values([ - { name: 'Ben' }, - { name: 'Nate' }, - { name: 'Erika' }, - { name: 'Bjorn' }, - { name: 'Sarah' }, - ]); - -const authors = await db.select().from(Author); ---- - -

Authors

-
    - {authors.map((author) =>
  • {author.name}
  • )} -
diff --git a/packages/db/test/fixtures/recipes/astro.config.ts b/packages/db/test/fixtures/recipes/astro.config.ts deleted file mode 100644 index bd6088769ffa..000000000000 --- a/packages/db/test/fixtures/recipes/astro.config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import astroDb from '@astrojs/db'; -import { defineConfig } from 'astro/config'; - -export default defineConfig({ - integrations: [astroDb()], -}); diff --git a/packages/db/test/fixtures/recipes/db/config.ts b/packages/db/test/fixtures/recipes/db/config.ts deleted file mode 100644 index bd4d6edaf425..000000000000 --- a/packages/db/test/fixtures/recipes/db/config.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { column, defineDb, defineTable } from 'astro:db'; - -const Recipe = defineTable({ - columns: { - id: column.number({ primaryKey: true }), - title: column.text(), - description: column.text(), - }, -}); - -const Ingredient = defineTable({ - columns: { - id: column.number({ primaryKey: true }), - name: column.text(), - quantity: column.number(), - recipeId: column.number(), - }, - indexes: { - recipeIdx: { on: 'recipeId' }, - }, - foreignKeys: [{ columns: 'recipeId', references: () => [Recipe.columns.id] }], -}); - -export default defineDb({ - tables: { Recipe, Ingredient }, -}); diff --git a/packages/db/test/fixtures/recipes/db/seed.ts b/packages/db/test/fixtures/recipes/db/seed.ts deleted file mode 100644 index 1ca219f15bf8..000000000000 --- a/packages/db/test/fixtures/recipes/db/seed.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { Ingredient, Recipe, db } from 'astro:db'; - -export default async function () { - const pancakes = await db - .insert(Recipe) - .values({ - title: 'Pancakes', - description: 'A delicious breakfast', - }) - .returning() - .get(); - - await db.insert(Ingredient).values([ - { - name: 'Flour', - quantity: 1, - recipeId: pancakes.id, - }, - { - name: 'Eggs', - quantity: 2, - recipeId: pancakes.id, - }, - { - name: 'Milk', - quantity: 1, - recipeId: pancakes.id, - }, - ]); - - const pizza = await db - .insert(Recipe) - .values({ - title: 'Pizza', - description: 'A delicious dinner', - }) - .returning() - .get(); - - await db.insert(Ingredient).values([ - { - name: 'Flour', - quantity: 1, - recipeId: pizza.id, - }, - { - name: 'Eggs', - quantity: 2, - recipeId: pizza.id, - }, - { - name: 'Milk', - quantity: 1, - recipeId: pizza.id, - }, - { - name: 'Tomato Sauce', - quantity: 1, - recipeId: pizza.id, - }, - ]); -} diff --git a/packages/db/test/fixtures/recipes/package.json b/packages/db/test/fixtures/recipes/package.json deleted file mode 100644 index cd1e83c02d03..000000000000 --- a/packages/db/test/fixtures/recipes/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "@test/recipes", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "ISC", - "dependencies": { - "@astrojs/db": "workspace:*", - "astro": "workspace:*" - } -} diff --git a/packages/db/test/fixtures/recipes/src/pages/index.astro b/packages/db/test/fixtures/recipes/src/pages/index.astro deleted file mode 100644 index 9fd2dac41915..000000000000 --- a/packages/db/test/fixtures/recipes/src/pages/index.astro +++ /dev/null @@ -1,25 +0,0 @@ ---- -/// -import { Ingredient, Recipe, db, eq } from 'astro:db'; - -const ingredientsByRecipe = await db - .select({ - name: Ingredient.name, - recipeName: Recipe.title, - }) - .from(Ingredient) - .innerJoin(Recipe, eq(Ingredient.recipeId, Recipe.id)); - -console.log(ingredientsByRecipe); ---- - -

Shopping list

-
    - { - ingredientsByRecipe.map(({ name, recipeName }) => ( -
  • - {name} ({recipeName}) -
  • - )) - } -
diff --git a/packages/db/test/fixtures/static-remote/astro.config.ts b/packages/db/test/fixtures/static-remote/astro.config.ts deleted file mode 100644 index bd6088769ffa..000000000000 --- a/packages/db/test/fixtures/static-remote/astro.config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import astroDb from '@astrojs/db'; -import { defineConfig } from 'astro/config'; - -export default defineConfig({ - integrations: [astroDb()], -}); diff --git a/packages/db/test/fixtures/static-remote/db/config.ts b/packages/db/test/fixtures/static-remote/db/config.ts deleted file mode 100644 index 8df4674d8f97..000000000000 --- a/packages/db/test/fixtures/static-remote/db/config.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { column, defineDb, defineTable } from 'astro:db'; - -const User = defineTable({ - columns: { - id: column.number({ primaryKey: true }), - name: column.text(), - }, -}); - -export default defineDb({ - tables: { User }, -}); diff --git a/packages/db/test/fixtures/static-remote/db/seed.ts b/packages/db/test/fixtures/static-remote/db/seed.ts deleted file mode 100644 index 2c86f02a1004..000000000000 --- a/packages/db/test/fixtures/static-remote/db/seed.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { User, db } from 'astro:db'; - -export default async function () { - await db.insert(User).values([ - { - name: 'Houston', - }, - ]); -} diff --git a/packages/db/test/fixtures/static-remote/package.json b/packages/db/test/fixtures/static-remote/package.json deleted file mode 100644 index aa2c9c23cb83..000000000000 --- a/packages/db/test/fixtures/static-remote/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "@test/db-static-remote", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "ISC", - "dependencies": { - "@astrojs/db": "workspace:*", - "astro": "workspace:*" - } -} diff --git a/packages/db/test/fixtures/static-remote/src/pages/index.astro b/packages/db/test/fixtures/static-remote/src/pages/index.astro deleted file mode 100644 index 849e65d18fd7..000000000000 --- a/packages/db/test/fixtures/static-remote/src/pages/index.astro +++ /dev/null @@ -1,19 +0,0 @@ ---- -import { User, db } from 'astro:db'; - -const users = await db.select().from(User); ---- - - - - Testing - - -

Testing

- -

Users

-
    - {users.map((user) =>
  • {user.name}
  • )} -
- - diff --git a/packages/db/test/fixtures/static-remote/src/pages/run.astro b/packages/db/test/fixtures/static-remote/src/pages/run.astro deleted file mode 100644 index 2f2ac1ccef1a..000000000000 --- a/packages/db/test/fixtures/static-remote/src/pages/run.astro +++ /dev/null @@ -1,17 +0,0 @@ ---- -import { User, db, sql } from 'astro:db'; - -const results = await db.run(sql`SELECT 1 as value`); -const row = results.rows[0]; ---- - - - - Testing - - -

Testing

- - {row.value} - - diff --git a/packages/db/test/integration-only.test.ts b/packages/db/test/integration-only.test.ts deleted file mode 100644 index a1ead146a2eb..000000000000 --- a/packages/db/test/integration-only.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import assert from 'node:assert/strict'; -import { before, describe, it } from 'node:test'; -import { load as cheerioLoad } from 'cheerio'; -import { type Fixture, loadFixture } from './test-utils.ts'; - -describe('astro:db with only integrations, no user db config', () => { - let fixture: Fixture; - before(async () => { - fixture = await loadFixture({ - root: new URL('./fixtures/integration-only/', import.meta.url), - }); - }); - - describe('build', () => { - before(async () => { - await fixture.build(); - }); - - it('Prints the list of menu items from integration-defined table', async () => { - const html = await fixture.readFile('/index.html'); - const $ = cheerioLoad(html); - - const ul = $('ul.menu'); - assert.equal(ul.children().length, 4); - assert.match(ul.children().eq(0).text(), /Pancakes/); - }); - }); -}); diff --git a/packages/db/test/integrations.test.ts b/packages/db/test/integrations.test.ts deleted file mode 100644 index 5ff232c8919e..000000000000 --- a/packages/db/test/integrations.test.ts +++ /dev/null @@ -1,37 +0,0 @@ -import assert from 'node:assert/strict'; -import { before, describe, it } from 'node:test'; -import { load as cheerioLoad } from 'cheerio'; -import { type Fixture, loadFixture } from './test-utils.ts'; - -describe('astro:db with integrations', () => { - let fixture: Fixture; - before(async () => { - fixture = await loadFixture({ - root: new URL('./fixtures/integrations/', import.meta.url), - }); - }); - - describe('build', () => { - before(async () => { - await fixture.build(); - }); - - it('Prints the list of authors from user-defined table', async () => { - const html = await fixture.readFile('/index.html'); - const $ = cheerioLoad(html); - - const ul = $('.authors-list'); - assert.equal(ul.children().length, 5); - assert.match(ul.children().eq(0).text(), /Ben/); - }); - - it('Prints the list of menu items from integration-defined table', async () => { - const html = await fixture.readFile('/index.html'); - const $ = cheerioLoad(html); - - const ul = $('ul.menu'); - assert.equal(ul.children().length, 4); - assert.match(ul.children().eq(0).text(), /Pancakes/); - }); - }); -}); diff --git a/packages/db/test/libsql-remote.test.ts b/packages/db/test/libsql-remote.test.ts deleted file mode 100644 index 17bf08a9a890..000000000000 --- a/packages/db/test/libsql-remote.test.ts +++ /dev/null @@ -1,85 +0,0 @@ -import assert from 'node:assert/strict'; -import { rm } from 'node:fs/promises'; -import { relative } from 'node:path'; -import { after, before, describe, it } from 'node:test'; -import { fileURLToPath } from 'node:url'; -import testAdapter from 'astro/_internal/test/test-adapter'; -import { clearEnvironment, type Fixture, initializeRemoteDb, loadFixture } from './test-utils.ts'; - -describe('astro:db local database', () => { - describe('build --remote with local libSQL file (absolute path)', () => { - let fixture: Fixture; - before(async () => { - clearEnvironment(); - - const absoluteFileUrl = new URL('./fixtures/libsql-remote/temp/absolute.db', import.meta.url); - // Remove the file if it exists to avoid conflict between test runs - await rm(absoluteFileUrl, { force: true }); - - process.env.ASTRO_INTERNAL_TEST_REMOTE = 'true'; - process.env.ASTRO_DB_REMOTE_URL = absoluteFileUrl.toString(); - - const root = new URL('./fixtures/libsql-remote/', import.meta.url); - fixture = await loadFixture({ - root, - outDir: fileURLToPath(new URL('./dist/absolute/', root)), - output: 'server', - adapter: testAdapter(), - }); - - await fixture.build(); - await initializeRemoteDb(fixture.config); - }); - - after(async () => { - delete process.env.ASTRO_INTERNAL_TEST_REMOTE; - delete process.env.ASTRO_DB_REMOTE_URL; - }); - - it('Can render page', async () => { - const app = await fixture.loadTestAdapterApp(); - const request = new Request('http://example.com/'); - const response = await app.render(request); - assert.equal(response.status, 200); - }); - }); - - describe('build --remote with local libSQL file (relative path)', () => { - let fixture: Fixture; - before(async () => { - clearEnvironment(); - - const absoluteFileUrl = new URL('./fixtures/libsql-remote/temp/relative.db', import.meta.url); - const prodDbPath = relative(process.cwd(), fileURLToPath(absoluteFileUrl)); - - // Remove the file if it exists to avoid conflict between test runs - await rm(prodDbPath, { force: true }); - - process.env.ASTRO_INTERNAL_TEST_REMOTE = 'true'; - process.env.ASTRO_DB_REMOTE_URL = `file:${prodDbPath}`; - - const root = new URL('./fixtures/libsql-remote/', import.meta.url); - fixture = await loadFixture({ - root, - outDir: fileURLToPath(new URL('./dist/relative/', root)), - output: 'server', - adapter: testAdapter(), - }); - - await fixture.build(); - await initializeRemoteDb(fixture.config); - }); - - after(async () => { - delete process.env.ASTRO_INTERNAL_TEST_REMOTE; - delete process.env.ASTRO_DB_REMOTE_URL; - }); - - it('Can render page', async () => { - const app = await fixture.loadTestAdapterApp(); - const request = new Request('http://example.com/'); - const response = await app.render(request); - assert.equal(response.status, 200); - }); - }); -}); diff --git a/packages/db/test/local-prod.test.ts b/packages/db/test/local-prod.test.ts deleted file mode 100644 index e4d989e4e514..000000000000 --- a/packages/db/test/local-prod.test.ts +++ /dev/null @@ -1,105 +0,0 @@ -import assert from 'node:assert/strict'; -import { relative } from 'node:path'; -import { after, before, describe, it } from 'node:test'; -import { fileURLToPath } from 'node:url'; -import testAdapter from 'astro/_internal/test/test-adapter'; -import { type Fixture, loadFixture } from './test-utils.ts'; - -describe('astro:db local database', () => { - describe('build (not remote) with DATABASE_FILE env (file URL)', () => { - let fixture: Fixture; - const prodDbPath = new URL('./fixtures/basics/dist/astro.db', import.meta.url).toString(); - before(async () => { - process.env.ASTRO_DATABASE_FILE = prodDbPath; - const root = new URL('./fixtures/local-prod/', import.meta.url); - fixture = await loadFixture({ - root, - outDir: fileURLToPath(new URL('./dist/file-url/', root)), - output: 'server', - adapter: testAdapter(), - }); - await fixture.build(); - }); - - after(async () => { - delete process.env.ASTRO_DATABASE_FILE; - }); - - it('Can render page', async () => { - const app = await fixture.loadTestAdapterApp(); - const request = new Request('http://example.com/'); - const response = await app.render(request); - assert.equal(response.status, 200); - }); - }); - - describe('build (not remote) with DATABASE_FILE env (relative file path)', () => { - let fixture: Fixture; - const absoluteFileUrl = new URL('./fixtures/basics/dist/astro.db', import.meta.url); - const prodDbPath = relative(process.cwd(), fileURLToPath(absoluteFileUrl)); - - before(async () => { - process.env.ASTRO_DATABASE_FILE = prodDbPath; - const root = new URL('./fixtures/local-prod/', import.meta.url); - fixture = await loadFixture({ - root, - outDir: fileURLToPath(new URL('./dist/relative/', root)), - output: 'server', - adapter: testAdapter(), - }); - await fixture.build(); - }); - - after(async () => { - delete process.env.ASTRO_DATABASE_FILE; - }); - - it('Can render page', async () => { - const app = await fixture.loadTestAdapterApp(); - const request = new Request('http://example.com/'); - const response = await app.render(request); - assert.equal(response.status, 200); - }); - }); - - describe('build (not remote)', () => { - it('should throw during the build for server output', async () => { - delete process.env.ASTRO_DATABASE_FILE; - const root = new URL('./fixtures/local-prod/', import.meta.url); - const fixture = await loadFixture({ - root, - outDir: fileURLToPath(new URL('./dist/not-remote/', root)), - output: 'server', - adapter: testAdapter(), - }); - let buildError: unknown = null; - try { - await fixture.build(); - } catch (err) { - buildError = err; - } - - assert.equal(buildError instanceof Error, true); - }); - - it('should throw during the build for hybrid output', async () => { - let root = new URL('./fixtures/local-prod/', import.meta.url); - const fixture2 = await loadFixture({ - root, - outDir: fileURLToPath(new URL('./dist/hybrid-output/', root)), - output: 'static', - adapter: testAdapter(), - }); - - delete process.env.ASTRO_DATABASE_FILE; - let buildError: unknown = null; - try { - await fixture2.build(); - } catch (err) { - buildError = err; - } - - assert.equal(buildError instanceof Error, true); - }); - }); -}); diff --git a/packages/db/test/no-seed.test.ts b/packages/db/test/no-seed.test.ts deleted file mode 100644 index 20121111be2b..000000000000 --- a/packages/db/test/no-seed.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import assert from 'node:assert/strict'; -import { before, describe, it } from 'node:test'; -import { load as cheerioLoad } from 'cheerio'; -import { type Fixture, loadFixture } from './test-utils.ts'; - -describe('astro:db with no seed file', () => { - let fixture: Fixture; - before(async () => { - fixture = await loadFixture({ - root: new URL('./fixtures/no-seed/', import.meta.url), - }); - }); - - describe('build', () => { - before(async () => { - await fixture.build(); - }); - - it('Prints the list of authors', async () => { - const html = await fixture.readFile('/index.html'); - const $ = cheerioLoad(html); - - const ul = $('.authors-list'); - assert.equal(ul.children().length, 5); - assert.match(ul.children().eq(0).text(), /Ben/); - }); - }); -}); diff --git a/packages/db/test/ssr-no-apptoken.test.ts b/packages/db/test/ssr-no-apptoken.test.ts deleted file mode 100644 index 5e140f3193ec..000000000000 --- a/packages/db/test/ssr-no-apptoken.test.ts +++ /dev/null @@ -1,36 +0,0 @@ -import assert from 'node:assert/strict'; -import { after, before, describe, it } from 'node:test'; -import testAdapter from 'astro/_internal/test/test-adapter'; -import { type Fixture, loadFixture, type RemoteDbServer, setupRemoteDb } from './test-utils.ts'; - -describe('missing app token', () => { - let fixture: Fixture; - let remoteDbServer: RemoteDbServer; - before(async () => { - fixture = await loadFixture({ - root: new URL('./fixtures/no-apptoken/', import.meta.url), - output: 'server', - adapter: testAdapter(), - }); - - remoteDbServer = await setupRemoteDb(fixture.config); - await fixture.build(); - // Ensure there's no token at runtime - delete process.env.ASTRO_DB_APP_TOKEN; - }); - - after(async () => { - await remoteDbServer?.stop(); - }); - - it('Errors as runtime', async () => { - const app = await fixture.loadTestAdapterApp(); - const request = new Request('http://example.com/'); - const response = await app.render(request); - try { - await response.text(); - } catch { - assert.equal(response.status, 501); - } - }); -}); diff --git a/packages/db/test/static-remote.test.ts b/packages/db/test/static-remote.test.ts deleted file mode 100644 index 90d387e973e7..000000000000 --- a/packages/db/test/static-remote.test.ts +++ /dev/null @@ -1,75 +0,0 @@ -import assert from 'node:assert/strict'; -import { after, before, describe, it } from 'node:test'; -import { load as cheerioLoad } from 'cheerio'; -import { - clearEnvironment, - type Fixture, - loadFixture, - type RemoteDbServer, - setupRemoteDb, -} from './test-utils.ts'; - -describe('astro:db', () => { - let fixture: Fixture; - before(async () => { - fixture = await loadFixture({ - root: new URL('./fixtures/static-remote/', import.meta.url), - output: 'static', - }); - }); - - describe('static build --remote', () => { - let remoteDbServer: RemoteDbServer; - - before(async () => { - remoteDbServer = await setupRemoteDb(fixture.config); - await fixture.build(); - }); - - after(async () => { - await remoteDbServer?.stop(); - }); - - it('Can render page', async () => { - const html = await fixture.readFile('/index.html'); - const $ = cheerioLoad(html); - - assert.equal($('li').length, 1); - }); - - it('Returns correct shape from db.run()', async () => { - const html = await fixture.readFile('/run/index.html'); - const $ = cheerioLoad(html); - - assert.match($('#row').text(), /1/); - }); - }); - - describe('static build --remote with custom LibSQL', () => { - let remoteDbServer: RemoteDbServer | undefined; - - before(async () => { - clearEnvironment(); - process.env.ASTRO_DB_REMOTE_URL = `memory:`; - await fixture.build(); - }); - - after(async () => { - await remoteDbServer?.stop(); - }); - - it('Can render page', async () => { - const html = await fixture.readFile('/index.html'); - const $ = cheerioLoad(html); - - assert.equal($('li').length, 1); - }); - - it('Returns correct shape from db.run()', async () => { - const html = await fixture.readFile('/run/index.html'); - const $ = cheerioLoad(html); - - assert.match($('#row').text(), /1/); - }); - }); -}); diff --git a/packages/db/test/test-utils.ts b/packages/db/test/test-utils.ts deleted file mode 100644 index 0c799077a48a..000000000000 --- a/packages/db/test/test-utils.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { mkdir, unlink } from 'node:fs/promises'; -import type { AstroConfig } from 'astro'; -import { createClient } from '@libsql/client'; -import { cli } from '../dist/core/cli/index.js'; -import { resolveDbConfig } from '../dist/core/load-file.js'; -import { getCreateIndexQueries, getCreateTableQuery } from '../dist/core/queries.js'; -import type { DBTable, ResolvedDBTable } from '../dist/core/types.js'; - -export { - loadFixture, - type DevServer, - type Fixture, -} from 'astro/_internal/test/test-utils'; - -const isWindows = process.platform === 'win32'; - -export type RemoteDbServer = { stop: () => Promise }; - -export async function setupRemoteDb( - astroConfig: AstroConfig, - options: { useDbAppTokenFlag?: boolean } = {}, -): Promise { - const url = isWindows - ? new URL(`./.astro/${Date.now()}.db`, astroConfig.root) - : new URL(`./${Date.now()}.db`, astroConfig.root); - const token = 'foo'; - process.env.ASTRO_DB_REMOTE_URL = url.toString(); - if (!options.useDbAppTokenFlag) { - process.env.ASTRO_DB_APP_TOKEN = token; - } - process.env.ASTRO_INTERNAL_TEST_REMOTE = 'true'; - - if (isWindows) { - await mkdir(new URL('.', url), { recursive: true }); - } - - const dbClient = createClient({ - url: url.toString(), - authToken: token, - }); - - const { dbConfig } = await resolveDbConfig(astroConfig); - const setupQueries: string[] = []; - for (const [name, table] of Object.entries(dbConfig?.tables ?? {})) { - const createQuery = getCreateTableQuery(name, table); - const indexQueries = getCreateIndexQueries(name, table); - setupQueries.push(createQuery, ...indexQueries); - } - - for (const sql of setupQueries) { - await dbClient.execute({ - sql, - args: [], - }); - } - - await cli({ - config: astroConfig, - flags: { - _: ['', 'astro', 'db', 'execute', 'db/seed.ts'], - remote: true, - ...(options.useDbAppTokenFlag ? { dbAppToken: token } : {}), - }, - }); - - return { - async stop() { - delete process.env.ASTRO_DB_REMOTE_URL; - delete process.env.ASTRO_DB_APP_TOKEN; - delete process.env.ASTRO_INTERNAL_TEST_REMOTE; - dbClient.close(); - if (!isWindows) { - await unlink(url); - } - }, - }; -} - -export async function initializeRemoteDb(astroConfig: AstroConfig) { - await cli({ - config: astroConfig, - flags: { - _: ['', 'astro', 'db', 'push'], - remote: true, - }, - }); - await cli({ - config: astroConfig, - flags: { - _: ['', 'astro', 'db', 'execute', 'db/seed.ts'], - remote: true, - }, - }); -} - -/** - * Clears the environment variables related to Astro DB. - */ -export function clearEnvironment() { - const keys = Array.from(Object.keys(process.env)); - for (const key of keys) { - if (key.startsWith('ASTRO_DB_')) { - delete process.env[key]; - } - } -} - -export function asResolved(table: DBTable): ResolvedDBTable { - return table as ResolvedDBTable; -} diff --git a/packages/db/test/types/table.ts b/packages/db/test/types/table.ts deleted file mode 100644 index 8ed12c1bda03..000000000000 --- a/packages/db/test/types/table.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { describe, it } from 'node:test'; -import { expectTypeOf } from 'expect-type'; -import { asDrizzleTable } from '../../dist/utils.js'; -import { column, defineTable } from './virtual.js'; - -describe('Table Type Tests', () => { - it('basic table', async () => { - const testTable = defineTable({ - columns: { - id: column.number({ primaryKey: true }), - name: column.text(), - createdAt: column.date(), - }, - }); - - const tsTestTable = asDrizzleTable('testTable', testTable); - - expectTypeOf(tsTestTable.$inferInsert).toEqualTypeOf<{ - name: string; - createdAt: Date; - id?: number | undefined; - }>(); - - expectTypeOf(tsTestTable.$inferSelect).toEqualTypeOf<{ - id: number; - name: string; - createdAt: Date; - }>(); - }); - - it('table with optional column', async () => { - const optionalTable = defineTable({ - columns: { - id: column.number({ primaryKey: true }), - name: column.text(), - description: column.text({ optional: true }), - }, - }); - - const tsOptionalTable = asDrizzleTable('optionalTable', optionalTable); - - expectTypeOf(tsOptionalTable.$inferInsert).toEqualTypeOf<{ - name: string; - id?: number | undefined; - description?: string | null | undefined; - }>(); - - expectTypeOf(tsOptionalTable.$inferSelect).toEqualTypeOf<{ - id: number; - name: string; - description: string | null; - }>(); - }); - - it('table with enum column', async () => { - const enumTable = defineTable({ - columns: { - id: column.number({ primaryKey: true }), - name: column.text(), - status: column.text({ enum: ['active', 'inactive'] }), - }, - }); - - const tsEnumTable = asDrizzleTable('enumTable', enumTable); - - expectTypeOf(tsEnumTable.$inferInsert).toEqualTypeOf<{ - name: string; - id?: number | undefined; - status: 'active' | 'inactive'; - }>(); - - expectTypeOf(tsEnumTable.$inferSelect).toEqualTypeOf<{ - id: number; - name: string; - status: 'active' | 'inactive'; - }>(); - }); - - it('table with optional enum column', async () => { - const enumTable = defineTable({ - columns: { - id: column.number({ primaryKey: true }), - name: column.text(), - status: column.text({ enum: ['active', 'inactive'], optional: true }), - }, - }); - - const tsEnumTable = asDrizzleTable('enumTable', enumTable); - - expectTypeOf(tsEnumTable.$inferInsert).toEqualTypeOf<{ - name: string; - id?: number | undefined; - status?: 'active' | 'inactive' | null | undefined; - }>(); - - expectTypeOf(tsEnumTable.$inferSelect).toEqualTypeOf<{ - id: number; - name: string; - status: 'active' | 'inactive' | null; - }>(); - }); -}); diff --git a/packages/db/test/types/virtual.ts b/packages/db/test/types/virtual.ts deleted file mode 100644 index d6070993be8b..000000000000 --- a/packages/db/test/types/virtual.ts +++ /dev/null @@ -1 +0,0 @@ -export { column, defineTable, NOW } from '../../dist/runtime/virtual.js'; diff --git a/packages/db/test/unit/column-queries.test.ts b/packages/db/test/unit/column-queries.test.ts deleted file mode 100644 index 2d72366e2f82..000000000000 --- a/packages/db/test/unit/column-queries.test.ts +++ /dev/null @@ -1,515 +0,0 @@ -import assert from 'node:assert/strict'; -import { describe, it } from 'node:test'; -import { - getMigrationQueries, - getTableChangeQueries, -} from '../../dist/core/cli/migration-queries.js'; -import { MIGRATION_VERSION } from '../../dist/core/consts.js'; -import { tableSchema } from '../../dist/core/schemas.js'; -import type { - DateColumn, - DBTable, - NumberColumn, - ResolvedDBTable, - TextColumn, -} from '../../dist/core/types.js'; -import { column, defineTable, NOW } from './virtual.ts'; -import { asResolved } from '../test-utils.ts'; - -const TABLE_NAME = 'Users'; - -// `parse` to resolve schema transformations -// ex. convert column.date() to ISO strings -const userInitial = tableSchema.parse( - defineTable({ - columns: { - name: column.text(), - age: column.number(), - email: column.text({ unique: true }), - mi: column.text({ optional: true }), - }, - }), -); - -function userChangeQueries(oldTable: DBTable, newTable: DBTable) { - return getTableChangeQueries({ - tableName: TABLE_NAME, - oldTable: asResolved(oldTable), - newTable: asResolved(newTable), - }); -} - -function configChangeQueries( - oldTables: Record, - newTables: Record, -) { - return getMigrationQueries({ - oldSnapshot: { - schema: oldTables, - version: MIGRATION_VERSION, - }, - newSnapshot: { - schema: newTables, - version: MIGRATION_VERSION, - }, - }); -} - -describe('column queries', () => { - describe('getMigrationQueries', () => { - it('should be empty when tables are the same', async () => { - const oldTables = { [TABLE_NAME]: asResolved(userInitial) }; - const newTables = { [TABLE_NAME]: asResolved(userInitial) }; - const { queries } = await configChangeQueries(oldTables, newTables); - assert.deepEqual(queries, []); - }); - - it('should create table for new tables', async () => { - const oldTables = {}; - const newTables = { [TABLE_NAME]: asResolved(userInitial) }; - const { queries } = await configChangeQueries(oldTables, newTables); - assert.deepEqual(queries, [ - `CREATE TABLE "${TABLE_NAME}" (_id INTEGER PRIMARY KEY, "name" text NOT NULL, "age" integer NOT NULL, "email" text NOT NULL UNIQUE, "mi" text)`, - ]); - }); - - it('should drop table for removed tables', async () => { - const oldTables = { [TABLE_NAME]: asResolved(userInitial) }; - const newTables = {}; - const { queries } = await configChangeQueries(oldTables, newTables); - assert.deepEqual(queries, [`DROP TABLE "${TABLE_NAME}"`]); - }); - - it('should error if possible table rename is detected', async () => { - const rename = 'Peeps'; - const oldTables = { [TABLE_NAME]: asResolved(userInitial) }; - const newTables = { [rename]: asResolved(userInitial) }; - let error: string | null = null; - try { - await configChangeQueries(oldTables, newTables); - } catch (e) { - error = (e as Error).message; - } - assert.match(error!, /Potential table rename detected/); - }); - - it('should error if possible column rename is detected', async () => { - const blogInitial = tableSchema.parse({ - columns: { - title: column.text(), - }, - }); - const blogFinal = tableSchema.parse({ - columns: { - title2: column.text(), - }, - }); - let error: string | null = null; - try { - await configChangeQueries( - { [TABLE_NAME]: asResolved(blogInitial) }, - { [TABLE_NAME]: asResolved(blogFinal) }, - ); - } catch (e) { - error = (e as Error).message; - } - assert.match(error!, /Potential column rename detected/); - }); - }); - - describe('getTableChangeQueries', () => { - it('should be empty when tables are the same', async () => { - const { queries } = await userChangeQueries(userInitial, userInitial); - assert.deepEqual(queries, []); - }); - - it('should return warning if column type change introduces data loss', async () => { - const blogInitial = tableSchema.parse({ - ...userInitial, - columns: { - date: column.text(), - }, - }); - const blogFinal = tableSchema.parse({ - ...userInitial, - columns: { - date: column.date(), - }, - }); - const { queries, confirmations } = await userChangeQueries(blogInitial, blogFinal); - assert.deepEqual(queries, [ - 'DROP TABLE "Users"', - 'CREATE TABLE "Users" (_id INTEGER PRIMARY KEY, "date" text NOT NULL)', - ]); - assert.equal(confirmations.length, 1); - }); - - it('should return warning if new required column added', async () => { - const blogInitial = tableSchema.parse({ - ...userInitial, - columns: {}, - }); - const blogFinal = tableSchema.parse({ - ...userInitial, - columns: { - date: column.date({ optional: false }), - }, - }); - const { queries, confirmations } = await userChangeQueries(blogInitial, blogFinal); - assert.deepEqual(queries, [ - 'DROP TABLE "Users"', - 'CREATE TABLE "Users" (_id INTEGER PRIMARY KEY, "date" text NOT NULL)', - ]); - assert.equal(confirmations.length, 1); - }); - - it('should return warning if non-number primary key with no default added', async () => { - const blogInitial = tableSchema.parse({ - ...userInitial, - columns: {}, - }); - const blogFinal = tableSchema.parse({ - ...userInitial, - columns: { - id: column.text({ primaryKey: true }), - }, - }); - const { queries, confirmations } = await userChangeQueries(blogInitial, blogFinal); - assert.deepEqual(queries, [ - 'DROP TABLE "Users"', - 'CREATE TABLE "Users" ("id" text PRIMARY KEY)', - ]); - assert.equal(confirmations.length, 1); - }); - - it('should be empty when type updated to same underlying SQL type', async () => { - const blogInitial = tableSchema.parse({ - ...userInitial, - columns: { - title: column.text(), - draft: column.boolean(), - }, - }); - const blogFinal = tableSchema.parse({ - ...userInitial, - columns: { - ...blogInitial.columns, - draft: column.number(), - }, - }); - const { queries } = await userChangeQueries(blogInitial, blogFinal); - assert.deepEqual(queries, []); - }); - - it('should respect user primary key without adding a hidden id', async () => { - const user = tableSchema.parse({ - ...userInitial, - columns: { - ...userInitial.columns, - id: column.number({ primaryKey: true }), - }, - }); - - const userFinal = tableSchema.parse({ - ...user, - columns: { - ...user.columns, - name: column.text({ unique: true, optional: true }), - }, - }); - - const { queries } = await userChangeQueries(user, userFinal); - assert.equal(queries[0] !== undefined, true); - const tempTableName = getTempTableName(queries[0]); - - assert.deepEqual(queries, [ - `CREATE TABLE \"${tempTableName}\" (\"name\" text UNIQUE, \"age\" integer NOT NULL, \"email\" text NOT NULL UNIQUE, \"mi\" text, \"id\" integer PRIMARY KEY)`, - `INSERT INTO \"${tempTableName}\" (\"name\", \"age\", \"email\", \"mi\", \"id\") SELECT \"name\", \"age\", \"email\", \"mi\", \"id\" FROM \"Users\"`, - 'DROP TABLE "Users"', - `ALTER TABLE "${tempTableName}" RENAME TO "Users"`, - ]); - }); - - describe('Lossy table recreate', () => { - it('when changing a column type', async () => { - const userFinal = { - ...userInitial, - columns: { - ...userInitial.columns, - age: column.text() as TextColumn, - }, - }; - - const { queries } = await userChangeQueries(userInitial, userFinal); - - assert.deepEqual(queries, [ - 'DROP TABLE "Users"', - `CREATE TABLE "Users" (_id INTEGER PRIMARY KEY, "name" text NOT NULL, "age" text NOT NULL, "email" text NOT NULL UNIQUE, "mi" text)`, - ]); - }); - - it('when adding a required column without a default', async () => { - const userFinal = { - ...userInitial, - columns: { - ...userInitial.columns, - phoneNumber: column.text() as TextColumn, - }, - }; - - const { queries } = await userChangeQueries(userInitial, userFinal); - - assert.deepEqual(queries, [ - 'DROP TABLE "Users"', - `CREATE TABLE "Users" (_id INTEGER PRIMARY KEY, "name" text NOT NULL, "age" integer NOT NULL, "email" text NOT NULL UNIQUE, "mi" text, "phoneNumber" text NOT NULL)`, - ]); - }); - }); - - describe('Lossless table recreate', () => { - it('when adding a primary key', async () => { - const userFinal = { - ...userInitial, - columns: { - ...userInitial.columns, - id: column.number({ primaryKey: true }) as NumberColumn, - }, - }; - - const { queries } = await userChangeQueries(userInitial, userFinal); - assert.equal(queries[0] !== undefined, true); - - const tempTableName = getTempTableName(queries[0]); - assert.deepEqual(queries, [ - `CREATE TABLE \"${tempTableName}\" (\"name\" text NOT NULL, \"age\" integer NOT NULL, \"email\" text NOT NULL UNIQUE, \"mi\" text, \"id\" integer PRIMARY KEY)`, - `INSERT INTO \"${tempTableName}\" (\"name\", \"age\", \"email\", \"mi\") SELECT \"name\", \"age\", \"email\", \"mi\" FROM \"Users\"`, - 'DROP TABLE "Users"', - `ALTER TABLE \"${tempTableName}\" RENAME TO \"Users\"`, - ]); - }); - - it('when dropping a primary key', async () => { - const user = { - ...userInitial, - columns: { - ...userInitial.columns, - id: column.number({ primaryKey: true }) as NumberColumn, - }, - }; - - const { queries } = await userChangeQueries(user, userInitial); - assert.equal(queries[0] !== undefined, true); - - const tempTableName = getTempTableName(queries[0]); - assert.deepEqual(queries, [ - `CREATE TABLE \"${tempTableName}\" (_id INTEGER PRIMARY KEY, \"name\" text NOT NULL, \"age\" integer NOT NULL, \"email\" text NOT NULL UNIQUE, \"mi\" text)`, - `INSERT INTO \"${tempTableName}\" (\"name\", \"age\", \"email\", \"mi\") SELECT \"name\", \"age\", \"email\", \"mi\" FROM \"Users\"`, - 'DROP TABLE "Users"', - `ALTER TABLE \"${tempTableName}\" RENAME TO \"Users\"`, - ]); - }); - - it('when adding an optional unique column', async () => { - const userFinal = { - ...userInitial, - columns: { - ...userInitial.columns, - phoneNumber: column.text({ unique: true, optional: true }) as TextColumn, - }, - }; - - const { queries } = await userChangeQueries(userInitial, userFinal); - assert.equal(queries.length, 4); - - const tempTableName = getTempTableName(queries[0]); - assert.equal(typeof tempTableName, 'string'); - assert.deepEqual(queries, [ - `CREATE TABLE "${tempTableName}" (_id INTEGER PRIMARY KEY, "name" text NOT NULL, "age" integer NOT NULL, "email" text NOT NULL UNIQUE, "mi" text, "phoneNumber" text UNIQUE)`, - `INSERT INTO "${tempTableName}" ("_id", "name", "age", "email", "mi") SELECT "_id", "name", "age", "email", "mi" FROM "Users"`, - 'DROP TABLE "Users"', - `ALTER TABLE "${tempTableName}" RENAME TO "Users"`, - ]); - }); - - it('when dropping unique column', async () => { - const userFinal = { - ...userInitial, - columns: { - ...userInitial.columns, - }, - }; - delete userFinal.columns.email; - - const { queries } = await userChangeQueries(userInitial, userFinal); - assert.equal(queries.length, 4); - assert.equal(queries.length, 4); - - const tempTableName = getTempTableName(queries[0]); - assert.equal(typeof tempTableName, 'string'); - assert.deepEqual(queries, [ - `CREATE TABLE "${tempTableName}" (_id INTEGER PRIMARY KEY, "name" text NOT NULL, "age" integer NOT NULL, "mi" text)`, - `INSERT INTO "${tempTableName}" ("_id", "name", "age", "mi") SELECT "_id", "name", "age", "mi" FROM "Users"`, - 'DROP TABLE "Users"', - `ALTER TABLE "${tempTableName}" RENAME TO "Users"`, - ]); - }); - - it('when updating to a runtime default', async () => { - const initial = tableSchema.parse({ - ...userInitial, - columns: { - ...userInitial.columns, - age: column.date(), - }, - }); - - const userFinal = tableSchema.parse({ - ...initial, - columns: { - ...initial.columns, - age: column.date({ default: NOW }), - }, - }); - - const { queries } = await userChangeQueries(initial, userFinal); - assert.equal(queries.length, 4); - - const tempTableName = getTempTableName(queries[0]); - assert.equal(typeof tempTableName, 'string'); - assert.deepEqual(queries, [ - `CREATE TABLE "${tempTableName}" (_id INTEGER PRIMARY KEY, "name" text NOT NULL, "age" text NOT NULL DEFAULT CURRENT_TIMESTAMP, "email" text NOT NULL UNIQUE, "mi" text)`, - `INSERT INTO "${tempTableName}" ("_id", "name", "age", "email", "mi") SELECT "_id", "name", "age", "email", "mi" FROM "Users"`, - 'DROP TABLE "Users"', - `ALTER TABLE "${tempTableName}" RENAME TO "Users"`, - ]); - }); - - it('when adding a column with a runtime default', async () => { - const userFinal = tableSchema.parse({ - ...userInitial, - columns: { - ...userInitial.columns, - birthday: column.date({ default: NOW }), - }, - }); - - const { queries } = await userChangeQueries(userInitial, userFinal); - assert.equal(queries.length, 4); - - const tempTableName = getTempTableName(queries[0]); - assert.equal(typeof tempTableName, 'string'); - assert.deepEqual(queries, [ - `CREATE TABLE "${tempTableName}" (_id INTEGER PRIMARY KEY, "name" text NOT NULL, "age" integer NOT NULL, "email" text NOT NULL UNIQUE, "mi" text, "birthday" text NOT NULL DEFAULT CURRENT_TIMESTAMP)`, - `INSERT INTO "${tempTableName}" ("_id", "name", "age", "email", "mi") SELECT "_id", "name", "age", "email", "mi" FROM "Users"`, - 'DROP TABLE "Users"', - `ALTER TABLE "${tempTableName}" RENAME TO "Users"`, - ]); - }); - - /** - * REASON: to follow the "expand" and "contract" migration model, - * you'll need to update the schema from NOT NULL to NULL. - * It's up to the user to ensure all data follows the new schema! - * - * @see https://planetscale.com/blog/safely-making-database-schema-changes#backwards-compatible-changes - */ - it('when changing a column to required', async () => { - const userFinal = { - ...userInitial, - columns: { - ...userInitial.columns, - mi: column.text() as TextColumn, - }, - }; - - const { queries } = await userChangeQueries(userInitial, userFinal); - - assert.equal(queries.length, 4); - - const tempTableName = getTempTableName(queries[0]); - assert.equal(typeof tempTableName, 'string'); - assert.deepEqual(queries, [ - `CREATE TABLE "${tempTableName}" (_id INTEGER PRIMARY KEY, "name" text NOT NULL, "age" integer NOT NULL, "email" text NOT NULL UNIQUE, "mi" text NOT NULL)`, - `INSERT INTO "${tempTableName}" ("_id", "name", "age", "email", "mi") SELECT "_id", "name", "age", "email", "mi" FROM "Users"`, - 'DROP TABLE "Users"', - `ALTER TABLE "${tempTableName}" RENAME TO "Users"`, - ]); - }); - - it('when changing a column to unique', async () => { - const userFinal = { - ...userInitial, - columns: { - ...userInitial.columns, - age: column.number({ unique: true }) as NumberColumn, - }, - }; - - const { queries } = await userChangeQueries(userInitial, userFinal); - assert.equal(queries.length, 4); - - const tempTableName = getTempTableName(queries[0]); - assert.equal(typeof tempTableName, 'string'); - assert.deepEqual(queries, [ - `CREATE TABLE "${tempTableName}" (_id INTEGER PRIMARY KEY, "name" text NOT NULL, "age" integer NOT NULL UNIQUE, "email" text NOT NULL UNIQUE, "mi" text)`, - `INSERT INTO "${tempTableName}" ("_id", "name", "age", "email", "mi") SELECT "_id", "name", "age", "email", "mi" FROM "Users"`, - 'DROP TABLE "Users"', - `ALTER TABLE "${tempTableName}" RENAME TO "Users"`, - ]); - }); - }); - - describe('ALTER ADD COLUMN', () => { - it('when adding an optional column', async () => { - const userFinal = { - ...userInitial, - columns: { - ...userInitial.columns, - birthday: column.date({ optional: true }) as DateColumn, - }, - }; - - const { queries } = await userChangeQueries(userInitial, userFinal); - assert.deepEqual(queries, ['ALTER TABLE "Users" ADD COLUMN "birthday" text']); - }); - - it('when adding a required column with default', async () => { - const defaultDate = new Date('2023-01-01'); - const userFinal = tableSchema.parse({ - ...userInitial, - columns: { - ...userInitial.columns, - birthday: column.date({ default: new Date('2023-01-01') }), - }, - }); - - const { queries } = await userChangeQueries(userInitial, userFinal); - assert.deepEqual(queries, [ - `ALTER TABLE "Users" ADD COLUMN "birthday" text NOT NULL DEFAULT '${defaultDate.toISOString()}'`, - ]); - }); - }); - - describe('ALTER DROP COLUMN', () => { - it('when removing optional or required columns', async () => { - const userFinal = { - ...userInitial, - columns: { - name: userInitial.columns.name, - email: userInitial.columns.email, - }, - }; - - const { queries } = await userChangeQueries(userInitial, userFinal); - assert.deepEqual(queries, [ - 'ALTER TABLE "Users" DROP COLUMN "age"', - 'ALTER TABLE "Users" DROP COLUMN "mi"', - ]); - }); - }); - }); -}); - -function getTempTableName(query: string) { - return /Users_[a-z\d]+/.exec(query)?.[0]; -} diff --git a/packages/db/test/unit/db-client.test.ts b/packages/db/test/unit/db-client.test.ts deleted file mode 100644 index c1c27ce97a91..000000000000 --- a/packages/db/test/unit/db-client.test.ts +++ /dev/null @@ -1,60 +0,0 @@ -import assert from 'node:assert'; -import test, { describe } from 'node:test'; -import { parseLibSQLConfig } from '../../dist/core/db-client/utils.js'; - -describe('db client config', () => { - test('parse config options from URL (docs example url)', () => { - const remoteURLToParse = new URL( - 'file://local-copy.db?encryptionKey=your-encryption-key&syncInterval=60&syncUrl=libsql%3A%2F%2Fyour.server.io', - ); - const options = Object.fromEntries(remoteURLToParse.searchParams.entries()); - - const config = parseLibSQLConfig(options); - - assert.deepEqual(config, { - encryptionKey: 'your-encryption-key', - syncInterval: 60, - syncUrl: 'libsql://your.server.io', - }); - }); - - test('parse config options from URL (test booleans without value)', () => { - const remoteURLToParse = new URL('file://local-copy.db?readYourWrites&offline&tls'); - const options = Object.fromEntries(remoteURLToParse.searchParams.entries()); - - const config = parseLibSQLConfig(options); - - assert.deepEqual(config, { - readYourWrites: true, - offline: true, - tls: true, - }); - }); - - test('parse config options from URL (test booleans with value)', () => { - const remoteURLToParse = new URL( - 'file://local-copy.db?readYourWrites=true&offline=true&tls=true', - ); - const options = Object.fromEntries(remoteURLToParse.searchParams.entries()); - - const config = parseLibSQLConfig(options); - - assert.deepEqual(config, { - readYourWrites: true, - offline: true, - tls: true, - }); - }); - - test('parse config options from URL (test numbers)', () => { - const remoteURLToParse = new URL('file://local-copy.db?syncInterval=60&concurrency=2'); - const options = Object.fromEntries(remoteURLToParse.searchParams.entries()); - - const config = parseLibSQLConfig(options); - - assert.deepEqual(config, { - syncInterval: 60, - concurrency: 2, - }); - }); -}); diff --git a/packages/db/test/unit/index-queries.test.ts b/packages/db/test/unit/index-queries.test.ts deleted file mode 100644 index eb8de4c4afa2..000000000000 --- a/packages/db/test/unit/index-queries.test.ts +++ /dev/null @@ -1,280 +0,0 @@ -import assert from 'node:assert/strict'; -import { describe, it } from 'node:test'; -import { getTableChangeQueries } from '../../dist/core/cli/migration-queries.js'; -import { dbConfigSchema, tableSchema } from '../../dist/core/schemas.js'; -import type { DBTable } from '../../dist/core/types.js'; -import { column } from './virtual.ts'; -import { asResolved } from '../test-utils.ts'; - -const userInitial = tableSchema.parse({ - columns: { - name: column.text(), - age: column.number(), - email: column.text({ unique: true }), - mi: column.text({ optional: true }), - }, - indexes: {}, - writable: false, -}); - -describe('index queries', () => { - it('generates index names by table and combined column names', async () => { - // Use dbConfigSchema.parse to resolve generated idx names - const dbConfig = dbConfigSchema.parse({ - tables: { - oldTable: userInitial, - newTable: { - ...userInitial, - indexes: [ - { on: ['name', 'age'], unique: false }, - { on: ['email'], unique: true }, - ], - }, - }, - }); - - const { queries } = await getTableChangeQueries({ - tableName: 'user', - oldTable: dbConfig.tables.oldTable, - newTable: dbConfig.tables.newTable, - }); - - assert.deepEqual(queries, [ - 'CREATE INDEX "newTable_age_name_idx" ON "user" ("age", "name")', - 'CREATE UNIQUE INDEX "newTable_email_idx" ON "user" ("email")', - ]); - }); - - it('generates index names with consistent column ordering', async () => { - const initial = dbConfigSchema.parse({ - tables: { - user: { - ...userInitial, - indexes: [ - { on: ['email'], unique: true }, - { on: ['name', 'age'], unique: false }, - ], - }, - }, - }); - - const final = dbConfigSchema.parse({ - tables: { - user: { - ...userInitial, - indexes: [ - // flip columns - { on: ['age', 'name'], unique: false }, - // flip index order - { on: ['email'], unique: true }, - ], - }, - }, - }); - - const { queries } = await getTableChangeQueries({ - tableName: 'user', - oldTable: initial.tables.user, - newTable: final.tables.user, - }); - - assert.equal(queries.length, 0); - }); - - it('does not trigger queries when changing from legacy to new format', async () => { - const initial = dbConfigSchema.parse({ - tables: { - user: { - ...userInitial, - indexes: { - emailIdx: { on: ['email'], unique: true }, - nameAgeIdx: { on: ['name', 'age'], unique: false }, - }, - }, - }, - }); - - const final = dbConfigSchema.parse({ - tables: { - user: { - ...userInitial, - indexes: [ - { on: ['email'], unique: true, name: 'emailIdx' }, - { on: ['name', 'age'], unique: false, name: 'nameAgeIdx' }, - ], - }, - }, - }); - - const { queries } = await getTableChangeQueries({ - tableName: 'user', - oldTable: initial.tables.user, - newTable: final.tables.user, - }); - - assert.equal(queries.length, 0); - }); - - it('adds indexes', async () => { - const dbConfig = dbConfigSchema.parse({ - tables: { - oldTable: userInitial, - newTable: { - ...userInitial, - indexes: [ - { on: ['name'], unique: false, name: 'nameIdx' }, - { on: ['email'], unique: true, name: 'emailIdx' }, - ], - }, - }, - }); - - const { queries } = await getTableChangeQueries({ - tableName: 'user', - oldTable: dbConfig.tables.oldTable, - newTable: dbConfig.tables.newTable, - }); - - assert.deepEqual(queries, [ - 'CREATE INDEX "nameIdx" ON "user" ("name")', - 'CREATE UNIQUE INDEX "emailIdx" ON "user" ("email")', - ]); - }); - - it('drops indexes', async () => { - const dbConfig = dbConfigSchema.parse({ - tables: { - oldTable: { - ...userInitial, - indexes: [ - { on: ['name'], unique: false, name: 'nameIdx' }, - { on: ['email'], unique: true, name: 'emailIdx' }, - ], - }, - newTable: { - ...userInitial, - indexes: {}, - }, - }, - }); - - const { queries } = await getTableChangeQueries({ - tableName: 'user', - oldTable: dbConfig.tables.oldTable, - newTable: dbConfig.tables.newTable, - }); - - assert.deepEqual(queries, ['DROP INDEX "nameIdx"', 'DROP INDEX "emailIdx"']); - }); - - it('drops and recreates modified indexes', async () => { - const dbConfig = dbConfigSchema.parse({ - tables: { - oldTable: { - ...userInitial, - indexes: [ - { unique: false, on: ['name'], name: 'nameIdx' }, - { unique: true, on: ['email'], name: 'emailIdx' }, - ], - }, - newTable: { - ...userInitial, - indexes: [ - { unique: true, on: ['name'], name: 'nameIdx' }, - { on: ['email'], name: 'emailIdx' }, - ], - }, - }, - }); - - const { queries } = await getTableChangeQueries({ - tableName: 'user', - oldTable: dbConfig.tables.oldTable, - newTable: dbConfig.tables.newTable, - }); - - assert.deepEqual(queries, [ - 'DROP INDEX "nameIdx"', - 'DROP INDEX "emailIdx"', - 'CREATE UNIQUE INDEX "nameIdx" ON "user" ("name")', - 'CREATE INDEX "emailIdx" ON "user" ("email")', - ]); - }); - - describe('legacy object config', () => { - it('adds indexes', async () => { - const userFinal: DBTable = { - ...userInitial, - indexes: { - nameIdx: { on: ['name'], unique: false }, - emailIdx: { on: ['email'], unique: true }, - }, - }; - - const { queries } = await getTableChangeQueries({ - tableName: 'user', - oldTable: asResolved(userInitial), - newTable: asResolved(userFinal), - }); - - assert.deepEqual(queries, [ - 'CREATE INDEX "nameIdx" ON "user" ("name")', - 'CREATE UNIQUE INDEX "emailIdx" ON "user" ("email")', - ]); - }); - - it('drops indexes', async () => { - const initial: DBTable = { - ...userInitial, - indexes: { - nameIdx: { on: ['name'], unique: false }, - emailIdx: { on: ['email'], unique: true }, - }, - }; - - const final: DBTable = { - ...userInitial, - indexes: {}, - }; - - const { queries } = await getTableChangeQueries({ - tableName: 'user', - oldTable: asResolved(initial), - newTable: asResolved(final), - }); - - assert.deepEqual(queries, ['DROP INDEX "nameIdx"', 'DROP INDEX "emailIdx"']); - }); - - it('drops and recreates modified indexes', async () => { - const initial: DBTable = { - ...userInitial, - indexes: { - nameIdx: { on: ['name'], unique: false }, - emailIdx: { on: ['email'], unique: true }, - }, - }; - - const final: DBTable = { - ...userInitial, - indexes: { - nameIdx: { on: ['name'], unique: true }, - emailIdx: { on: ['email'] }, - }, - }; - - const { queries } = await getTableChangeQueries({ - tableName: 'user', - oldTable: asResolved(initial), - newTable: asResolved(final), - }); - - assert.deepEqual(queries, [ - 'DROP INDEX "nameIdx"', - 'DROP INDEX "emailIdx"', - 'CREATE UNIQUE INDEX "nameIdx" ON "user" ("name")', - 'CREATE INDEX "emailIdx" ON "user" ("email")', - ]); - }); - }); -}); diff --git a/packages/db/test/unit/reference-queries.test.ts b/packages/db/test/unit/reference-queries.test.ts deleted file mode 100644 index cb3361c43802..000000000000 --- a/packages/db/test/unit/reference-queries.test.ts +++ /dev/null @@ -1,171 +0,0 @@ -import assert from 'node:assert/strict'; -import { describe, it } from 'node:test'; -import { getTableChangeQueries } from '../../dist/core/cli/migration-queries.js'; -import { tablesSchema } from '../../dist/core/schemas.js'; -import type { DBTable, TableConfig } from '../../dist/core/types.js'; -import { column, defineTable } from './virtual.ts'; -import { asResolved } from '../test-utils.ts'; - -const BaseUser = defineTable({ - columns: { - id: column.number({ primaryKey: true }), - name: column.text(), - age: column.number(), - email: column.text({ unique: true }), - mi: column.text({ optional: true }), - }, -}); - -const BaseSentBox = defineTable({ - columns: { - to: column.number(), - toName: column.text(), - subject: column.text(), - body: column.text(), - }, -}); - -function resolveReferences( - { - User = BaseUser, - SentBox = BaseSentBox, - }: { - User?: TableConfig; - SentBox?: TableConfig; - } = { - User: BaseUser, - SentBox: BaseSentBox, - }, -) { - return tablesSchema.parse({ User, SentBox }); -} - -function userChangeQueries(oldTable: DBTable, newTable: DBTable) { - return getTableChangeQueries({ - tableName: 'User', - oldTable: asResolved(oldTable), - newTable: asResolved(newTable), - }); -} - -describe('reference queries', () => { - it('adds references with lossless table recreate', async () => { - const { SentBox: Initial } = resolveReferences(); - const { SentBox: Final } = resolveReferences({ - SentBox: defineTable({ - columns: { - ...BaseSentBox.columns, - to: column.number({ references: () => BaseUser.columns.id }), - }, - }), - }); - - const { queries } = await userChangeQueries(Initial, Final); - - assert.equal(queries[0] !== undefined, true); - const tempTableName = getTempTableName(queries[0]); - assert.notEqual(typeof tempTableName, 'undefined'); - - assert.deepEqual(queries, [ - `CREATE TABLE \"${tempTableName}\" (_id INTEGER PRIMARY KEY, \"to\" integer NOT NULL REFERENCES \"User\" (\"id\"), \"toName\" text NOT NULL, \"subject\" text NOT NULL, \"body\" text NOT NULL)`, - `INSERT INTO \"${tempTableName}\" (\"_id\", \"to\", \"toName\", \"subject\", \"body\") SELECT \"_id\", \"to\", \"toName\", \"subject\", \"body\" FROM \"User\"`, - 'DROP TABLE "User"', - `ALTER TABLE \"${tempTableName}\" RENAME TO \"User\"`, - ]); - }); - - it('removes references with lossless table recreate', async () => { - const { SentBox: Initial } = resolveReferences({ - SentBox: defineTable({ - columns: { - ...BaseSentBox.columns, - to: column.number({ references: () => BaseUser.columns.id }), - }, - }), - }); - const { SentBox: Final } = resolveReferences(); - - const { queries } = await userChangeQueries(Initial, Final); - - assert.equal(queries[0] !== undefined, true); - const tempTableName = getTempTableName(queries[0]); - assert.notEqual(typeof tempTableName, 'undefined'); - - assert.deepEqual(queries, [ - `CREATE TABLE \"${tempTableName}\" (_id INTEGER PRIMARY KEY, \"to\" integer NOT NULL, \"toName\" text NOT NULL, \"subject\" text NOT NULL, \"body\" text NOT NULL)`, - `INSERT INTO \"${tempTableName}\" (\"_id\", \"to\", \"toName\", \"subject\", \"body\") SELECT \"_id\", \"to\", \"toName\", \"subject\", \"body\" FROM \"User\"`, - 'DROP TABLE "User"', - `ALTER TABLE \"${tempTableName}\" RENAME TO \"User\"`, - ]); - }); - - it('does not use ADD COLUMN when adding optional column with reference', async () => { - const { SentBox: Initial } = resolveReferences(); - const { SentBox: Final } = resolveReferences({ - SentBox: defineTable({ - columns: { - ...BaseSentBox.columns, - from: column.number({ references: () => BaseUser.columns.id, optional: true }), - }, - }), - }); - - const { queries } = await userChangeQueries(Initial, Final); - assert.equal(queries[0] !== undefined, true); - const tempTableName = getTempTableName(queries[0]); - - assert.deepEqual(queries, [ - `CREATE TABLE \"${tempTableName}\" (_id INTEGER PRIMARY KEY, \"to\" integer NOT NULL, \"toName\" text NOT NULL, \"subject\" text NOT NULL, \"body\" text NOT NULL, \"from\" integer REFERENCES \"User\" (\"id\"))`, - `INSERT INTO \"${tempTableName}\" (\"_id\", \"to\", \"toName\", \"subject\", \"body\") SELECT \"_id\", \"to\", \"toName\", \"subject\", \"body\" FROM \"User\"`, - 'DROP TABLE "User"', - `ALTER TABLE \"${tempTableName}\" RENAME TO \"User\"`, - ]); - }); - - it('adds and updates foreign key with lossless table recreate', async () => { - const { SentBox: InitialWithoutFK } = resolveReferences(); - const { SentBox: InitialWithDifferentFK } = resolveReferences({ - SentBox: defineTable({ - ...BaseSentBox, - foreignKeys: [{ columns: ['to'], references: () => [BaseUser.columns.id] }], - }), - }); - const { SentBox: Final } = resolveReferences({ - SentBox: defineTable({ - ...BaseSentBox, - foreignKeys: [ - { - columns: ['to', 'toName'], - references: () => [BaseUser.columns.id, BaseUser.columns.name], - }, - ], - }), - }); - - const expected = (tempTableName: string | undefined) => [ - `CREATE TABLE \"${tempTableName}\" (_id INTEGER PRIMARY KEY, \"to\" integer NOT NULL, \"toName\" text NOT NULL, \"subject\" text NOT NULL, \"body\" text NOT NULL, FOREIGN KEY (\"to\", \"toName\") REFERENCES \"User\"(\"id\", \"name\"))`, - `INSERT INTO \"${tempTableName}\" (\"_id\", \"to\", \"toName\", \"subject\", \"body\") SELECT \"_id\", \"to\", \"toName\", \"subject\", \"body\" FROM \"User\"`, - 'DROP TABLE "User"', - `ALTER TABLE \"${tempTableName}\" RENAME TO \"User\"`, - ]; - - const addedForeignKey = await userChangeQueries(InitialWithoutFK, Final); - const updatedForeignKey = await userChangeQueries(InitialWithDifferentFK, Final); - - assert.notEqual(typeof addedForeignKey.queries[0], 'undefined'); - assert.notEqual(typeof updatedForeignKey.queries[0], 'undefined'); - assert.deepEqual( - addedForeignKey.queries, - expected(getTempTableName(addedForeignKey.queries[0])), - ); - - assert.deepEqual( - updatedForeignKey.queries, - expected(getTempTableName(updatedForeignKey.queries[0])), - ); - }); -}); - -function getTempTableName(query: string) { - return /User_[a-z\d]+/.exec(query)?.[0]; -} diff --git a/packages/db/test/unit/remote-info.test.ts b/packages/db/test/unit/remote-info.test.ts deleted file mode 100644 index 55b5babd3a7e..000000000000 --- a/packages/db/test/unit/remote-info.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -import assert from 'node:assert'; -import test, { beforeEach, describe } from 'node:test'; -import { getRemoteDatabaseInfo } from '../../dist/core/utils.js'; -import { clearEnvironment } from '../test-utils.ts'; - -describe('RemoteDatabaseInfo', () => { - beforeEach(() => { - clearEnvironment(); - }); - - test('default remote info', () => { - const dbInfo = getRemoteDatabaseInfo(); - - assert.deepEqual(dbInfo, { - url: undefined, - token: undefined, - }); - }); - - test('configured libSQL remote', () => { - process.env.ASTRO_DB_REMOTE_URL = 'libsql://libsql.self.hosted'; - process.env.ASTRO_DB_APP_TOKEN = 'foo'; - const dbInfo = getRemoteDatabaseInfo(); - - assert.deepEqual(dbInfo, { - url: 'libsql://libsql.self.hosted', - token: 'foo', - }); - }); -}); diff --git a/packages/db/test/unit/reset-queries.test.ts b/packages/db/test/unit/reset-queries.test.ts deleted file mode 100644 index 08e38f658385..000000000000 --- a/packages/db/test/unit/reset-queries.test.ts +++ /dev/null @@ -1,56 +0,0 @@ -import assert from 'node:assert/strict'; -import { describe, it } from 'node:test'; -import { getMigrationQueries } from '../../dist/core/cli/migration-queries.js'; -import { MIGRATION_VERSION } from '../../dist/core/consts.js'; -import { tableSchema } from '../../dist/core/schemas.js'; -import type { ResolvedDBTable } from '../../dist/core/types.js'; -import { column, defineTable } from './virtual.ts'; -import { asResolved } from '../test-utils.ts'; - -const TABLE_NAME = 'Users'; - -// `parse` to resolve schema transformations -// ex. convert column.date() to ISO strings -const userInitial = tableSchema.parse( - defineTable({ - columns: { - name: column.text(), - age: column.number(), - email: column.text({ unique: true }), - mi: column.text({ optional: true }), - }, - }), -); - -describe('force reset', () => { - describe('getMigrationQueries', () => { - it('should drop table and create new version', async () => { - const oldTables = { [TABLE_NAME]: asResolved(userInitial) }; - const newTables = { [TABLE_NAME]: asResolved(userInitial) }; - const { queries } = await getMigrationQueries({ - oldSnapshot: { schema: oldTables, version: MIGRATION_VERSION }, - newSnapshot: { schema: newTables, version: MIGRATION_VERSION }, - reset: true, - }); - - assert.deepEqual(queries, [ - `DROP TABLE IF EXISTS "${TABLE_NAME}"`, - `CREATE TABLE "${TABLE_NAME}" (_id INTEGER PRIMARY KEY, "name" text NOT NULL, "age" integer NOT NULL, "email" text NOT NULL UNIQUE, "mi" text)`, - ]); - }); - - it('should not drop table when previous snapshot did not have it', async () => { - const oldTables: Record = {}; - const newTables = { [TABLE_NAME]: asResolved(userInitial) }; - const { queries } = await getMigrationQueries({ - oldSnapshot: { schema: oldTables, version: MIGRATION_VERSION }, - newSnapshot: { schema: newTables, version: MIGRATION_VERSION }, - reset: true, - }); - - assert.deepEqual(queries, [ - `CREATE TABLE "${TABLE_NAME}" (_id INTEGER PRIMARY KEY, "name" text NOT NULL, "age" integer NOT NULL, "email" text NOT NULL UNIQUE, "mi" text)`, - ]); - }); - }); -}); diff --git a/packages/db/test/unit/virtual.ts b/packages/db/test/unit/virtual.ts deleted file mode 100644 index d6070993be8b..000000000000 --- a/packages/db/test/unit/virtual.ts +++ /dev/null @@ -1 +0,0 @@ -export { column, defineTable, NOW } from '../../dist/runtime/virtual.js'; diff --git a/packages/db/tsconfig.build.json b/packages/db/tsconfig.build.json deleted file mode 100644 index 6fc16b22308a..000000000000 --- a/packages/db/tsconfig.build.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "../../configs/tsconfig.build.json", - "references": [{ "path": "../astro/tsconfig.json" }] -} diff --git a/packages/db/tsconfig.json b/packages/db/tsconfig.json deleted file mode 100644 index 64908093d2fe..000000000000 --- a/packages/db/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "extends": "../../configs/tsconfig.base.json", - "files": [], - "references": [{ "path": "./tsconfig.build.json" }, { "path": "./tsconfig.test.json" }] -} diff --git a/packages/db/tsconfig.test.json b/packages/db/tsconfig.test.json deleted file mode 100644 index 9ca68b5a3d26..000000000000 --- a/packages/db/tsconfig.test.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "../../configs/tsconfig.test.json", - "references": [{ "path": "./tsconfig.build.json" }] -} diff --git a/packages/db/virtual.d.ts b/packages/db/virtual.d.ts deleted file mode 100644 index ea1f3e44d1d8..000000000000 --- a/packages/db/virtual.d.ts +++ /dev/null @@ -1,48 +0,0 @@ -declare module 'astro:db' { - type RuntimeConfig = typeof import('./dist/runtime/virtual.js'); - - export const db: import('./dist/runtime/index.js').Database; - export const dbUrl: string; - - export const sql: RuntimeConfig['sql']; - export const NOW: RuntimeConfig['NOW']; - export const TRUE: RuntimeConfig['TRUE']; - export const FALSE: RuntimeConfig['FALSE']; - export const column: RuntimeConfig['column']; - export const defineDb: RuntimeConfig['defineDb']; - export const defineTable: RuntimeConfig['defineTable']; - export const isDbError: RuntimeConfig['isDbError']; - export const getDbError: RuntimeConfig['getDbError']; - - export const eq: RuntimeConfig['eq']; - export const gt: RuntimeConfig['gt']; - export const gte: RuntimeConfig['gte']; - export const lt: RuntimeConfig['lt']; - export const lte: RuntimeConfig['lte']; - export const ne: RuntimeConfig['ne']; - export const isNull: RuntimeConfig['isNull']; - export const isNotNull: RuntimeConfig['isNotNull']; - export const inArray: RuntimeConfig['inArray']; - export const notInArray: RuntimeConfig['notInArray']; - export const exists: RuntimeConfig['exists']; - export const notExists: RuntimeConfig['notExists']; - export const between: RuntimeConfig['between']; - export const notBetween: RuntimeConfig['notBetween']; - export const like: RuntimeConfig['like']; - export const ilike: RuntimeConfig['ilike']; - export const notIlike: RuntimeConfig['notIlike']; - export const not: RuntimeConfig['not']; - export const asc: RuntimeConfig['asc']; - export const desc: RuntimeConfig['desc']; - export const and: RuntimeConfig['and']; - export const or: RuntimeConfig['or']; - export const count: RuntimeConfig['count']; - export const countDistinct: RuntimeConfig['countDistinct']; - export const avg: RuntimeConfig['avg']; - export const avgDistinct: RuntimeConfig['avgDistinct']; - export const sum: RuntimeConfig['sum']; - export const sumDistinct: RuntimeConfig['sumDistinct']; - export const max: RuntimeConfig['max']; - export const min: RuntimeConfig['min']; - export const alias: RuntimeConfig['alias']; -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2f0b9a24f1c1..9734f368142b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,7 +33,7 @@ importers: version: 2.29.8(@types/node@22.19.19) '@flue/cli': specifier: ^0.8.0 - version: 0.8.1(@cloudflare/workers-types@4.20260527.1)(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(@types/node@22.19.19)(esbuild@0.25.5)(jiti@2.6.1)(sass@1.98.0)(tsx@4.22.3)(typebox@1.1.38)(typescript@6.0.3)(wrangler@4.95.0)(yaml@2.9.0)(zod-to-json-schema@3.25.2)(zod@4.3.6) + version: 0.8.1(@cloudflare/workers-types@4.20260527.1)(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(@types/node@22.19.19)(esbuild@0.28.0)(jiti@2.6.1)(sass@1.98.0)(tsx@4.22.3)(typebox@1.1.38)(typescript@6.0.3)(wrangler@4.95.0)(yaml@2.9.0)(zod-to-json-schema@3.25.2)(zod@4.3.6) '@flue/runtime': specifier: ^0.8.0 version: 0.8.1(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(typebox@1.1.38)(typescript@6.0.3)(zod-to-json-schema@3.25.2)(zod@4.3.6) @@ -43,9 +43,6 @@ importers: bgproc: specifier: ^0.2.0 version: 0.2.0 - esbuild: - specifier: 0.25.5 - version: 0.25.5 eslint: specifier: ^10.4.0 version: 10.4.0(jiti@2.6.1) @@ -840,9 +837,6 @@ importers: '@astrojs/check': specifier: workspace:* version: link:../../../../language-tools/astro-check - '@astrojs/db': - specifier: workspace:* - version: link:../../../../db '@astrojs/node': specifier: workspace:* version: link:../../../../integrations/node @@ -873,9 +867,6 @@ importers: '@astrojs/check': specifier: workspace:* version: link:../../../../language-tools/astro-check - '@astrojs/db': - specifier: workspace:* - version: link:../../../../db '@astrojs/node': specifier: workspace:* version: link:../../../../integrations/node @@ -4138,154 +4129,6 @@ importers: packages/create-astro/test/fixtures/not-empty: {} - packages/db: - dependencies: - '@clack/prompts': - specifier: ^1.0.1 - version: 1.1.0 - '@libsql/client': - specifier: ^0.17.0 - version: 0.17.0 - drizzle-orm: - specifier: ^0.45.2 - version: 0.45.2(@cloudflare/workers-types@4.20260527.1)(@electric-sql/pglite@0.3.16)(@libsql/client@0.17.0)(@opentelemetry/api@1.9.0)(sql.js@1.14.1) - microdiff: - specifier: ^1.5.0 - version: 1.5.0 - nanoid: - specifier: ^5.1.6 - version: 5.1.9 - piccolore: - specifier: ^0.1.3 - version: 0.1.3 - yargs-parser: - specifier: ^22.0.0 - version: 22.0.0 - zod: - specifier: ^4.3.6 - version: 4.3.6 - devDependencies: - '@types/yargs-parser': - specifier: ^21.0.3 - version: 21.0.3 - astro: - specifier: workspace:* - version: link:../astro - astro-scripts: - specifier: workspace:* - version: link:../../scripts - cheerio: - specifier: 1.2.0 - version: 1.2.0 - expect-type: - specifier: ^1.3.0 - version: 1.3.0 - typescript: - specifier: ^6.0.3 - version: 6.0.3 - vite: - specifier: ^8.0.13 - version: 8.0.14(@types/node@22.19.19)(esbuild@0.28.0)(jiti@2.6.1)(sass@1.98.0)(tsx@4.22.3)(yaml@2.9.0) - - packages/db/test/fixtures/basics: - dependencies: - '@astrojs/db': - specifier: workspace:* - version: link:../../.. - astro: - specifier: workspace:* - version: link:../../../../astro - - packages/db/test/fixtures/db-in-src: - dependencies: - '@astrojs/db': - specifier: workspace:* - version: link:../../.. - astro: - specifier: workspace:* - version: link:../../../../astro - - packages/db/test/fixtures/error-handling: - dependencies: - '@astrojs/db': - specifier: workspace:* - version: link:../../.. - astro: - specifier: workspace:* - version: link:../../../../astro - - packages/db/test/fixtures/integration-only: - dependencies: - '@astrojs/db': - specifier: workspace:* - version: link:../../.. - astro: - specifier: workspace:* - version: link:../../../../astro - - packages/db/test/fixtures/integrations: - dependencies: - '@astrojs/db': - specifier: workspace:* - version: link:../../.. - astro: - specifier: workspace:* - version: link:../../../../astro - - packages/db/test/fixtures/libsql-remote: - dependencies: - '@astrojs/db': - specifier: workspace:* - version: link:../../.. - astro: - specifier: workspace:* - version: link:../../../../astro - - packages/db/test/fixtures/local-prod: - dependencies: - '@astrojs/db': - specifier: workspace:* - version: link:../../.. - astro: - specifier: workspace:* - version: link:../../../../astro - - packages/db/test/fixtures/no-apptoken: - dependencies: - '@astrojs/db': - specifier: workspace:* - version: link:../../.. - astro: - specifier: workspace:* - version: link:../../../../astro - - packages/db/test/fixtures/no-seed: - dependencies: - '@astrojs/db': - specifier: workspace:* - version: link:../../.. - astro: - specifier: workspace:* - version: link:../../../../astro - - packages/db/test/fixtures/recipes: - dependencies: - '@astrojs/db': - specifier: workspace:* - version: link:../../.. - astro: - specifier: workspace:* - version: link:../../../../astro - - packages/db/test/fixtures/static-remote: - dependencies: - '@astrojs/db': - specifier: workspace:* - version: link:../../.. - astro: - specifier: workspace:* - version: link:../../../../astro - packages/integrations/alpinejs: devDependencies: '@playwright/test': @@ -7900,12 +7743,6 @@ packages: resolution: {integrity: sha512-cxgkB66RQB95H3X27jlnxCRNTmPuSTgmBAq6/4n2Dtv4hsk4yz8FadA1ggmd0uZzvKqWD6CR+WFgTjhDqg7eyw==} engines: {node: '>=18.0.0'} - '@esbuild/aix-ppc64@0.25.5': - resolution: {integrity: sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - '@esbuild/aix-ppc64@0.27.3': resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} engines: {node: '>=18'} @@ -7924,12 +7761,6 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.25.5': - resolution: {integrity: sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - '@esbuild/android-arm64@0.27.3': resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} engines: {node: '>=18'} @@ -7948,12 +7779,6 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.25.5': - resolution: {integrity: sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - '@esbuild/android-arm@0.27.3': resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} engines: {node: '>=18'} @@ -7972,12 +7797,6 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.25.5': - resolution: {integrity: sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - '@esbuild/android-x64@0.27.3': resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} engines: {node: '>=18'} @@ -7996,12 +7815,6 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.25.5': - resolution: {integrity: sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - '@esbuild/darwin-arm64@0.27.3': resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} engines: {node: '>=18'} @@ -8020,12 +7833,6 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.25.5': - resolution: {integrity: sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - '@esbuild/darwin-x64@0.27.3': resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} engines: {node: '>=18'} @@ -8044,12 +7851,6 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.25.5': - resolution: {integrity: sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - '@esbuild/freebsd-arm64@0.27.3': resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} engines: {node: '>=18'} @@ -8068,12 +7869,6 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.5': - resolution: {integrity: sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - '@esbuild/freebsd-x64@0.27.3': resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} engines: {node: '>=18'} @@ -8092,12 +7887,6 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.25.5': - resolution: {integrity: sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - '@esbuild/linux-arm64@0.27.3': resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} engines: {node: '>=18'} @@ -8116,12 +7905,6 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.25.5': - resolution: {integrity: sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - '@esbuild/linux-arm@0.27.3': resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} engines: {node: '>=18'} @@ -8140,12 +7923,6 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.25.5': - resolution: {integrity: sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - '@esbuild/linux-ia32@0.27.3': resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} engines: {node: '>=18'} @@ -8164,12 +7941,6 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.25.5': - resolution: {integrity: sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - '@esbuild/linux-loong64@0.27.3': resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} engines: {node: '>=18'} @@ -8188,12 +7959,6 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.25.5': - resolution: {integrity: sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - '@esbuild/linux-mips64el@0.27.3': resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} engines: {node: '>=18'} @@ -8212,12 +7977,6 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.25.5': - resolution: {integrity: sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - '@esbuild/linux-ppc64@0.27.3': resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} engines: {node: '>=18'} @@ -8236,12 +7995,6 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.25.5': - resolution: {integrity: sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - '@esbuild/linux-riscv64@0.27.3': resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} engines: {node: '>=18'} @@ -8260,12 +8013,6 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.25.5': - resolution: {integrity: sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - '@esbuild/linux-s390x@0.27.3': resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} engines: {node: '>=18'} @@ -8284,12 +8031,6 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.25.5': - resolution: {integrity: sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - '@esbuild/linux-x64@0.27.3': resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} engines: {node: '>=18'} @@ -8302,12 +8043,6 @@ packages: cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.5': - resolution: {integrity: sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - '@esbuild/netbsd-arm64@0.27.3': resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} engines: {node: '>=18'} @@ -8326,12 +8061,6 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.5': - resolution: {integrity: sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - '@esbuild/netbsd-x64@0.27.3': resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} engines: {node: '>=18'} @@ -8344,12 +8073,6 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.5': - resolution: {integrity: sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - '@esbuild/openbsd-arm64@0.27.3': resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} engines: {node: '>=18'} @@ -8368,12 +8091,6 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.5': - resolution: {integrity: sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - '@esbuild/openbsd-x64@0.27.3': resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} engines: {node: '>=18'} @@ -8404,12 +8121,6 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.25.5': - resolution: {integrity: sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - '@esbuild/sunos-x64@0.27.3': resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} engines: {node: '>=18'} @@ -8428,12 +8139,6 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.25.5': - resolution: {integrity: sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - '@esbuild/win32-arm64@0.27.3': resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} engines: {node: '>=18'} @@ -8452,12 +8157,6 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.25.5': - resolution: {integrity: sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - '@esbuild/win32-ia32@0.27.3': resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} engines: {node: '>=18'} @@ -8476,12 +8175,6 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.25.5': - resolution: {integrity: sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - '@esbuild/win32-x64@0.27.3': resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} engines: {node: '>=18'} @@ -8846,63 +8539,6 @@ packages: resolution: {integrity: sha512-n5JEf16Wr4mdkRMZ8wMP/wN9/sHmTjRPbouXjJH371mZ2LEGDl72t8tEsMRNFerQN/QJtivOxqK1frdGa4QK5Q==} engines: {node: '>=10'} - '@libsql/client@0.17.0': - resolution: {integrity: sha512-TLjSU9Otdpq0SpKHl1tD1Nc9MKhrsZbCFGot3EbCxRa8m1E5R1mMwoOjKMMM31IyF7fr+hPNHLpYfwbMKNusmg==} - - '@libsql/core@0.17.0': - resolution: {integrity: sha512-hnZRnJHiS+nrhHKLGYPoJbc78FE903MSDrFJTbftxo+e52X+E0Y0fHOCVYsKWcg6XgB7BbJYUrz/xEkVTSaipw==} - - '@libsql/darwin-arm64@0.5.22': - resolution: {integrity: sha512-4B8ZlX3nIDPndfct7GNe0nI3Yw6ibocEicWdC4fvQbSs/jdq/RC2oCsoJxJ4NzXkvktX70C1J4FcmmoBy069UA==} - cpu: [arm64] - os: [darwin] - - '@libsql/darwin-x64@0.5.22': - resolution: {integrity: sha512-ny2HYWt6lFSIdNFzUFIJ04uiW6finXfMNJ7wypkAD8Pqdm6nAByO+Fdqu8t7sD0sqJGeUCiOg480icjyQ2/8VA==} - cpu: [x64] - os: [darwin] - - '@libsql/hrana-client@0.9.0': - resolution: {integrity: sha512-pxQ1986AuWfPX4oXzBvLwBnfgKDE5OMhAdR/5cZmRaB4Ygz5MecQybvwZupnRz341r2CtFmbk/BhSu7k2Lm+Jw==} - - '@libsql/isomorphic-ws@0.1.5': - resolution: {integrity: sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg==} - - '@libsql/linux-arm-gnueabihf@0.5.22': - resolution: {integrity: sha512-3Uo3SoDPJe/zBnyZKosziRGtszXaEtv57raWrZIahtQDsjxBVjuzYQinCm9LRCJCUT5t2r5Z5nLDPJi2CwZVoA==} - cpu: [arm] - os: [linux] - - '@libsql/linux-arm-musleabihf@0.5.22': - resolution: {integrity: sha512-LCsXh07jvSojTNJptT9CowOzwITznD+YFGGW+1XxUr7fS+7/ydUrpDfsMX7UqTqjm7xG17eq86VkWJgHJfvpNg==} - cpu: [arm] - os: [linux] - - '@libsql/linux-arm64-gnu@0.5.22': - resolution: {integrity: sha512-KSdnOMy88c9mpOFKUEzPskSaF3VLflfSUCBwas/pn1/sV3pEhtMF6H8VUCd2rsedwoukeeCSEONqX7LLnQwRMA==} - cpu: [arm64] - os: [linux] - - '@libsql/linux-arm64-musl@0.5.22': - resolution: {integrity: sha512-mCHSMAsDTLK5YH//lcV3eFEgiR23Ym0U9oEvgZA0667gqRZg/2px+7LshDvErEKv2XZ8ixzw3p1IrBzLQHGSsw==} - cpu: [arm64] - os: [linux] - - '@libsql/linux-x64-gnu@0.5.22': - resolution: {integrity: sha512-kNBHaIkSg78Y4BqAdgjcR2mBilZXs4HYkAmi58J+4GRwDQZh5fIUWbnQvB9f95DkWUIGVeenqLRFY2pcTmlsew==} - cpu: [x64] - os: [linux] - - '@libsql/linux-x64-musl@0.5.22': - resolution: {integrity: sha512-UZ4Xdxm4pu3pQXjvfJiyCzZop/9j/eA2JjmhMaAhe3EVLH2g11Fy4fwyUp9sT1QJYR1kpc2JLuybPM0kuXv/Tg==} - cpu: [x64] - os: [linux] - - '@libsql/win32-x64-msvc@0.5.22': - resolution: {integrity: sha512-Fj0j8RnBpo43tVZUVoNK6BV/9AtDUM5S7DF3LB4qTYg1LMSZqi3yeCneUTLJD6XomQJlZzbI4mst89yspVSAnA==} - cpu: [x64] - os: [win32] - '@lukeed/ms@2.0.2': resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} engines: {node: '>=8'} @@ -8971,9 +8607,6 @@ packages: '@emnapi/core': ^1.7.1 '@emnapi/runtime': ^1.7.1 - '@neon-rs/load@0.0.4': - resolution: {integrity: sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw==} - '@netlify/ai@0.4.1': resolution: {integrity: sha512-ETLtV/9taYrcGhszwO+BLFgFJJ2MCnJp8BwxfwV6Z/+z3SsaUG4ExC8x4xzNCdB2GPWxXrXkvR2LFNsPFSLcRA==} engines: {node: '>=20.6.1'} @@ -10364,9 +9997,6 @@ packages: '@types/vscode@1.109.0': resolution: {integrity: sha512-0Pf95rnwEIwDbmXGC08r0B4TQhAbsHQ5UyTIgVgoieDe4cOnf92usuR5dEczb6bTKEp7ziZH4TV1TRGPPCExtw==} - '@types/ws@8.18.1': - resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} - '@types/xml2js@0.4.14': resolution: {integrity: sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ==} @@ -11476,9 +11106,6 @@ packages: cross-argv@2.0.0: resolution: {integrity: sha512-YIaY9TR5Nxeb8SMdtrU8asWVM4jqJDNDYlKV21LxtYcfNJhp1kEsgSa6qXwXgzN0WQWGODps0+TlGp2xQSHwOg==} - cross-fetch@4.1.0: - resolution: {integrity: sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==} - cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -11652,10 +11279,6 @@ packages: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} - detect-libc@2.0.2: - resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} - engines: {node: '>=8'} - detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} @@ -11760,98 +11383,6 @@ packages: resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} engines: {node: '>=10'} - drizzle-orm@0.45.2: - resolution: {integrity: sha512-kY0BSaTNYWnoDMVoyY8uxmyHjpJW1geOmBMdSSicKo9CIIWkSxMIj2rkeSR51b8KAPB7m+qysjuHme5nKP+E5Q==} - peerDependencies: - '@aws-sdk/client-rds-data': '>=3' - '@cloudflare/workers-types': '>=4' - '@electric-sql/pglite': '>=0.2.0' - '@libsql/client': '>=0.10.0' - '@libsql/client-wasm': '>=0.10.0' - '@neondatabase/serverless': '>=0.10.0' - '@op-engineering/op-sqlite': '>=2' - '@opentelemetry/api': ^1.4.1 - '@planetscale/database': '>=1.13' - '@prisma/client': '*' - '@tidbcloud/serverless': '*' - '@types/better-sqlite3': '*' - '@types/pg': '*' - '@types/sql.js': '*' - '@upstash/redis': '>=1.34.7' - '@vercel/postgres': '>=0.8.0' - '@xata.io/client': '*' - better-sqlite3: '>=7' - bun-types: '*' - expo-sqlite: '>=14.0.0' - gel: '>=2' - knex: '*' - kysely: '*' - mysql2: '>=2' - pg: '>=8' - postgres: '>=3' - prisma: '*' - sql.js: '>=1' - sqlite3: '>=5' - peerDependenciesMeta: - '@aws-sdk/client-rds-data': - optional: true - '@cloudflare/workers-types': - optional: true - '@electric-sql/pglite': - optional: true - '@libsql/client': - optional: true - '@libsql/client-wasm': - optional: true - '@neondatabase/serverless': - optional: true - '@op-engineering/op-sqlite': - optional: true - '@opentelemetry/api': - optional: true - '@planetscale/database': - optional: true - '@prisma/client': - optional: true - '@tidbcloud/serverless': - optional: true - '@types/better-sqlite3': - optional: true - '@types/pg': - optional: true - '@types/sql.js': - optional: true - '@upstash/redis': - optional: true - '@vercel/postgres': - optional: true - '@xata.io/client': - optional: true - better-sqlite3: - optional: true - bun-types: - optional: true - expo-sqlite: - optional: true - gel: - optional: true - knex: - optional: true - kysely: - optional: true - mysql2: - optional: true - pg: - optional: true - postgres: - optional: true - prisma: - optional: true - sql.js: - optional: true - sqlite3: - optional: true - dset@3.1.4: resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==} engines: {node: '>=4'} @@ -11980,11 +11511,6 @@ packages: engines: {node: '>=12'} hasBin: true - esbuild@0.25.5: - resolution: {integrity: sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==} - engines: {node: '>=18'} - hasBin: true - esbuild@0.27.3: resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} engines: {node: '>=18'} @@ -12972,9 +12498,6 @@ packages: jpeg-js@0.4.4: resolution: {integrity: sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==} - js-base64@3.7.8: - resolution: {integrity: sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==} - js-image-generator@1.0.4: resolution: {integrity: sha512-ckb7kyVojGAnArouVR+5lBIuwU1fcrn7E/YYSd0FK7oIngAkMmRvHASLro9Zt5SQdWToaI66NybG+OGxPw/HlQ==} @@ -13117,11 +12640,6 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - libsql@0.5.22: - resolution: {integrity: sha512-NscWthMQt7fpU8lqd7LXMvT9pi+KhhmTHAJWUB/Lj6MWa0MKFv0F2V4C6WKKpjCVZl0VwcDz4nOI3CyaT1DDiA==} - cpu: [x64, arm64, wasm32, arm] - os: [darwin, linux, win32] - lie@3.3.0: resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} @@ -13490,9 +13008,6 @@ packages: mhchemparser@4.2.1: resolution: {integrity: sha512-kYmyrCirqJf3zZ9t/0wGgRZ4/ZJw//VwaRVGA75C4nhE60vtnIzhl9J9ndkX/h6hxSN7pjg/cE0VxbnNM+bnDQ==} - microdiff@1.5.0: - resolution: {integrity: sha512-Drq+/THMvDdzRYrK0oxJmOKiC24ayUV8ahrt8l3oRK51PWt6gdtrIGrlIH3pT/lFh1z93FbAcidtsHcWbnRz8Q==} - micromark-core-commonmark@2.0.3: resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} @@ -13730,11 +13245,6 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - nanoid@5.1.9: - resolution: {integrity: sha512-ZUvP7KeBLe3OZ1ypw6dI/TzYJuvHP77IM4Ry73waSQTLn8/g8rpdjfyVAh7t1/+FjBtG4lCP42MEbDxOsRpBMw==} - engines: {node: ^18 || >=20} - hasBin: true - nanostores@1.1.1: resolution: {integrity: sha512-EYJqS25r2iBeTtGQCHidXl1VfZ1jXM7Q04zXJOrMlxVVmD0ptxJaNux92n1mJ7c5lN3zTq12MhH/8x59nP+qmg==} engines: {node: ^20.0.0 || >=22.0.0} @@ -14480,9 +13990,6 @@ packages: resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} engines: {node: '>=0.4.0'} - promise-limit@2.7.0: - resolution: {integrity: sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw==} - property-information@7.1.0: resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} @@ -17272,20 +16779,6 @@ snapshots: optionalDependencies: workerd: 1.20260526.1 - '@cloudflare/vite-plugin@1.39.0(@cloudflare/workers-types@4.20260527.1)(vite@8.0.14)': - dependencies: - '@cloudflare/unenv-preset': 2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260526.1) - miniflare: 4.20260526.0 - unenv: 2.0.0-rc.24 - vite: 8.0.14(@types/node@22.19.19)(esbuild@0.25.5)(jiti@2.6.1)(sass@1.98.0)(tsx@4.22.3)(yaml@2.9.0) - wrangler: 4.95.0(@cloudflare/workers-types@4.20260527.1) - ws: 8.20.1 - transitivePeerDependencies: - - '@cloudflare/workers-types' - - bufferutil - - utf-8-validate - - workerd - '@cloudflare/vite-plugin@1.39.0(@cloudflare/workers-types@4.20260527.1)(vite@8.0.14)(workerd@1.20260526.1)': dependencies: '@cloudflare/unenv-preset': 2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260526.1) @@ -17771,9 +17264,6 @@ snapshots: '@whatwg-node/promise-helpers': 1.3.2 tslib: 2.8.1 - '@esbuild/aix-ppc64@0.25.5': - optional: true - '@esbuild/aix-ppc64@0.27.3': optional: true @@ -17783,9 +17273,6 @@ snapshots: '@esbuild/android-arm64@0.17.19': optional: true - '@esbuild/android-arm64@0.25.5': - optional: true - '@esbuild/android-arm64@0.27.3': optional: true @@ -17795,9 +17282,6 @@ snapshots: '@esbuild/android-arm@0.17.19': optional: true - '@esbuild/android-arm@0.25.5': - optional: true - '@esbuild/android-arm@0.27.3': optional: true @@ -17807,9 +17291,6 @@ snapshots: '@esbuild/android-x64@0.17.19': optional: true - '@esbuild/android-x64@0.25.5': - optional: true - '@esbuild/android-x64@0.27.3': optional: true @@ -17819,9 +17300,6 @@ snapshots: '@esbuild/darwin-arm64@0.17.19': optional: true - '@esbuild/darwin-arm64@0.25.5': - optional: true - '@esbuild/darwin-arm64@0.27.3': optional: true @@ -17831,9 +17309,6 @@ snapshots: '@esbuild/darwin-x64@0.17.19': optional: true - '@esbuild/darwin-x64@0.25.5': - optional: true - '@esbuild/darwin-x64@0.27.3': optional: true @@ -17843,9 +17318,6 @@ snapshots: '@esbuild/freebsd-arm64@0.17.19': optional: true - '@esbuild/freebsd-arm64@0.25.5': - optional: true - '@esbuild/freebsd-arm64@0.27.3': optional: true @@ -17855,9 +17327,6 @@ snapshots: '@esbuild/freebsd-x64@0.17.19': optional: true - '@esbuild/freebsd-x64@0.25.5': - optional: true - '@esbuild/freebsd-x64@0.27.3': optional: true @@ -17867,9 +17336,6 @@ snapshots: '@esbuild/linux-arm64@0.17.19': optional: true - '@esbuild/linux-arm64@0.25.5': - optional: true - '@esbuild/linux-arm64@0.27.3': optional: true @@ -17879,9 +17345,6 @@ snapshots: '@esbuild/linux-arm@0.17.19': optional: true - '@esbuild/linux-arm@0.25.5': - optional: true - '@esbuild/linux-arm@0.27.3': optional: true @@ -17891,9 +17354,6 @@ snapshots: '@esbuild/linux-ia32@0.17.19': optional: true - '@esbuild/linux-ia32@0.25.5': - optional: true - '@esbuild/linux-ia32@0.27.3': optional: true @@ -17903,9 +17363,6 @@ snapshots: '@esbuild/linux-loong64@0.17.19': optional: true - '@esbuild/linux-loong64@0.25.5': - optional: true - '@esbuild/linux-loong64@0.27.3': optional: true @@ -17915,9 +17372,6 @@ snapshots: '@esbuild/linux-mips64el@0.17.19': optional: true - '@esbuild/linux-mips64el@0.25.5': - optional: true - '@esbuild/linux-mips64el@0.27.3': optional: true @@ -17927,9 +17381,6 @@ snapshots: '@esbuild/linux-ppc64@0.17.19': optional: true - '@esbuild/linux-ppc64@0.25.5': - optional: true - '@esbuild/linux-ppc64@0.27.3': optional: true @@ -17939,9 +17390,6 @@ snapshots: '@esbuild/linux-riscv64@0.17.19': optional: true - '@esbuild/linux-riscv64@0.25.5': - optional: true - '@esbuild/linux-riscv64@0.27.3': optional: true @@ -17951,9 +17399,6 @@ snapshots: '@esbuild/linux-s390x@0.17.19': optional: true - '@esbuild/linux-s390x@0.25.5': - optional: true - '@esbuild/linux-s390x@0.27.3': optional: true @@ -17963,18 +17408,12 @@ snapshots: '@esbuild/linux-x64@0.17.19': optional: true - '@esbuild/linux-x64@0.25.5': - optional: true - '@esbuild/linux-x64@0.27.3': optional: true '@esbuild/linux-x64@0.28.0': optional: true - '@esbuild/netbsd-arm64@0.25.5': - optional: true - '@esbuild/netbsd-arm64@0.27.3': optional: true @@ -17984,18 +17423,12 @@ snapshots: '@esbuild/netbsd-x64@0.17.19': optional: true - '@esbuild/netbsd-x64@0.25.5': - optional: true - '@esbuild/netbsd-x64@0.27.3': optional: true '@esbuild/netbsd-x64@0.28.0': optional: true - '@esbuild/openbsd-arm64@0.25.5': - optional: true - '@esbuild/openbsd-arm64@0.27.3': optional: true @@ -18005,9 +17438,6 @@ snapshots: '@esbuild/openbsd-x64@0.17.19': optional: true - '@esbuild/openbsd-x64@0.25.5': - optional: true - '@esbuild/openbsd-x64@0.27.3': optional: true @@ -18023,9 +17453,6 @@ snapshots: '@esbuild/sunos-x64@0.17.19': optional: true - '@esbuild/sunos-x64@0.25.5': - optional: true - '@esbuild/sunos-x64@0.27.3': optional: true @@ -18035,9 +17462,6 @@ snapshots: '@esbuild/win32-arm64@0.17.19': optional: true - '@esbuild/win32-arm64@0.25.5': - optional: true - '@esbuild/win32-arm64@0.27.3': optional: true @@ -18047,9 +17471,6 @@ snapshots: '@esbuild/win32-ia32@0.17.19': optional: true - '@esbuild/win32-ia32@0.25.5': - optional: true - '@esbuild/win32-ia32@0.27.3': optional: true @@ -18059,9 +17480,6 @@ snapshots: '@esbuild/win32-x64@0.17.19': optional: true - '@esbuild/win32-x64@0.25.5': - optional: true - '@esbuild/win32-x64@0.27.3': optional: true @@ -18150,14 +17568,14 @@ snapshots: fastq: 1.20.1 glob: 13.0.3 - '@flue/cli@0.8.1(@cloudflare/workers-types@4.20260527.1)(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(@types/node@22.19.19)(esbuild@0.25.5)(jiti@2.6.1)(sass@1.98.0)(tsx@4.22.3)(typebox@1.1.38)(typescript@6.0.3)(wrangler@4.95.0)(yaml@2.9.0)(zod-to-json-schema@3.25.2)(zod@4.3.6)': + '@flue/cli@0.8.1(@cloudflare/workers-types@4.20260527.1)(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(@types/node@22.19.19)(esbuild@0.28.0)(jiti@2.6.1)(sass@1.98.0)(tsx@4.22.3)(typebox@1.1.38)(typescript@6.0.3)(wrangler@4.95.0)(yaml@2.9.0)(zod-to-json-schema@3.25.2)(zod@4.3.6)': dependencies: - '@cloudflare/vite-plugin': 1.39.0(@cloudflare/workers-types@4.20260527.1)(vite@8.0.14) + '@cloudflare/vite-plugin': 1.39.0(@cloudflare/workers-types@4.20260527.1)(vite@8.0.14)(workerd@1.20260526.1) '@flue/runtime': 0.8.1(@standard-schema/spec@1.1.0)(@types/json-schema@7.0.15)(typebox@1.1.38)(typescript@6.0.3)(zod-to-json-schema@3.25.2)(zod@4.3.6) '@vercel/detect-agent': 1.2.3 package-up: 5.0.0 valibot: 1.2.0(typescript@6.0.3) - vite: 8.0.14(@types/node@22.19.19)(esbuild@0.25.5)(jiti@2.6.1)(sass@1.98.0)(tsx@4.22.3)(yaml@2.9.0) + vite: 8.0.14(@types/node@22.19.19)(esbuild@0.28.0)(jiti@2.6.1)(sass@1.98.0)(tsx@4.22.3)(yaml@2.9.0) optionalDependencies: wrangler: 4.95.0(@cloudflare/workers-types@4.20260527.1) transitivePeerDependencies: @@ -18436,68 +17854,6 @@ snapshots: '@jsdevtools/rehype-toc@3.0.2': {} - '@libsql/client@0.17.0': - dependencies: - '@libsql/core': 0.17.0 - '@libsql/hrana-client': 0.9.0 - js-base64: 3.7.8 - libsql: 0.5.22 - promise-limit: 2.7.0 - transitivePeerDependencies: - - bufferutil - - encoding - - utf-8-validate - - '@libsql/core@0.17.0': - dependencies: - js-base64: 3.7.8 - - '@libsql/darwin-arm64@0.5.22': - optional: true - - '@libsql/darwin-x64@0.5.22': - optional: true - - '@libsql/hrana-client@0.9.0': - dependencies: - '@libsql/isomorphic-ws': 0.1.5 - cross-fetch: 4.1.0 - js-base64: 3.7.8 - node-fetch: 3.3.2 - transitivePeerDependencies: - - bufferutil - - encoding - - utf-8-validate - - '@libsql/isomorphic-ws@0.1.5': - dependencies: - '@types/ws': 8.18.1 - ws: 8.20.1 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - '@libsql/linux-arm-gnueabihf@0.5.22': - optional: true - - '@libsql/linux-arm-musleabihf@0.5.22': - optional: true - - '@libsql/linux-arm64-gnu@0.5.22': - optional: true - - '@libsql/linux-arm64-musl@0.5.22': - optional: true - - '@libsql/linux-x64-gnu@0.5.22': - optional: true - - '@libsql/linux-x64-musl@0.5.22': - optional: true - - '@libsql/win32-x64-msvc@0.5.22': - optional: true - '@lukeed/ms@2.0.2': {} '@manypkg/find-root@1.1.0': @@ -18635,8 +17991,6 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true - '@neon-rs/load@0.0.4': {} - '@netlify/ai@0.4.1': dependencies: '@netlify/api': 14.0.18 @@ -20053,10 +19407,6 @@ snapshots: '@types/vscode@1.109.0': {} - '@types/ws@8.18.1': - dependencies: - '@types/node': 22.19.19 - '@types/xml2js@0.4.14': dependencies: '@types/node': 22.19.19 @@ -21401,12 +20751,6 @@ snapshots: cross-argv@2.0.0: {} - cross-fetch@4.1.0: - dependencies: - node-fetch: 2.7.0 - transitivePeerDependencies: - - encoding - cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -21549,8 +20893,6 @@ snapshots: detect-indent@6.1.0: {} - detect-libc@2.0.2: {} - detect-libc@2.1.2: {} detective-amd@6.0.1: @@ -21657,14 +20999,6 @@ snapshots: dotenv@8.6.0: {} - drizzle-orm@0.45.2(@cloudflare/workers-types@4.20260527.1)(@electric-sql/pglite@0.3.16)(@libsql/client@0.17.0)(@opentelemetry/api@1.9.0)(sql.js@1.14.1): - optionalDependencies: - '@cloudflare/workers-types': 4.20260527.1 - '@electric-sql/pglite': 0.3.16 - '@libsql/client': 0.17.0 - '@opentelemetry/api': 1.9.0 - sql.js: 1.14.1 - dset@3.1.4: {} dunder-proto@1.0.1: @@ -21805,34 +21139,6 @@ snapshots: '@esbuild/win32-ia32': 0.17.19 '@esbuild/win32-x64': 0.17.19 - esbuild@0.25.5: - optionalDependencies: - '@esbuild/aix-ppc64': 0.25.5 - '@esbuild/android-arm': 0.25.5 - '@esbuild/android-arm64': 0.25.5 - '@esbuild/android-x64': 0.25.5 - '@esbuild/darwin-arm64': 0.25.5 - '@esbuild/darwin-x64': 0.25.5 - '@esbuild/freebsd-arm64': 0.25.5 - '@esbuild/freebsd-x64': 0.25.5 - '@esbuild/linux-arm': 0.25.5 - '@esbuild/linux-arm64': 0.25.5 - '@esbuild/linux-ia32': 0.25.5 - '@esbuild/linux-loong64': 0.25.5 - '@esbuild/linux-mips64el': 0.25.5 - '@esbuild/linux-ppc64': 0.25.5 - '@esbuild/linux-riscv64': 0.25.5 - '@esbuild/linux-s390x': 0.25.5 - '@esbuild/linux-x64': 0.25.5 - '@esbuild/netbsd-arm64': 0.25.5 - '@esbuild/netbsd-x64': 0.25.5 - '@esbuild/openbsd-arm64': 0.25.5 - '@esbuild/openbsd-x64': 0.25.5 - '@esbuild/sunos-x64': 0.25.5 - '@esbuild/win32-arm64': 0.25.5 - '@esbuild/win32-ia32': 0.25.5 - '@esbuild/win32-x64': 0.25.5 - esbuild@0.27.3: optionalDependencies: '@esbuild/aix-ppc64': 0.27.3 @@ -23054,8 +22360,6 @@ snapshots: jpeg-js@0.4.4: {} - js-base64@3.7.8: {} - js-image-generator@1.0.4: dependencies: jpeg-js: 0.4.4 @@ -23233,21 +22537,6 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - libsql@0.5.22: - dependencies: - '@neon-rs/load': 0.0.4 - detect-libc: 2.0.2 - optionalDependencies: - '@libsql/darwin-arm64': 0.5.22 - '@libsql/darwin-x64': 0.5.22 - '@libsql/linux-arm-gnueabihf': 0.5.22 - '@libsql/linux-arm-musleabihf': 0.5.22 - '@libsql/linux-arm64-gnu': 0.5.22 - '@libsql/linux-arm64-musl': 0.5.22 - '@libsql/linux-x64-gnu': 0.5.22 - '@libsql/linux-x64-musl': 0.5.22 - '@libsql/win32-x64-msvc': 0.5.22 - lie@3.3.0: dependencies: immediate: 3.0.6 @@ -23721,8 +23010,6 @@ snapshots: mhchemparser@4.2.1: {} - microdiff@1.5.0: {} - micromark-core-commonmark@2.0.3: dependencies: decode-named-character-reference: 1.3.0 @@ -24122,8 +23409,6 @@ snapshots: nanoid@3.3.12: {} - nanoid@5.1.9: {} - nanostores@1.1.1: {} napi-build-utils@2.0.0: @@ -24936,8 +24221,6 @@ snapshots: progress@2.0.3: {} - promise-limit@2.7.0: {} - property-information@7.1.0: {} protobufjs@7.5.6: @@ -26555,22 +25838,6 @@ snapshots: tsx: 4.22.3 yaml: 2.9.0 - vite@8.0.14(@types/node@22.19.19)(esbuild@0.25.5)(jiti@2.6.1)(sass@1.98.0)(tsx@4.22.3)(yaml@2.9.0): - dependencies: - lightningcss: 1.32.0 - picomatch: 4.0.4 - postcss: 8.5.15 - rolldown: 1.0.2 - tinyglobby: 0.2.16 - optionalDependencies: - '@types/node': 22.19.19 - esbuild: 0.25.5 - fsevents: 2.3.3 - jiti: 2.6.1 - sass: 1.98.0 - tsx: 4.22.3 - yaml: 2.9.0 - vite@8.0.14(@types/node@22.19.19)(esbuild@0.28.0)(jiti@2.6.1)(sass@1.98.0)(tsx@4.22.3)(yaml@2.9.0): dependencies: lightningcss: 1.32.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index a20ae6d98e30..9a3744b5ff4d 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -31,10 +31,6 @@ overrides: # pnpm to only keep one installation of `vite@7.3.2` with `@types/node@22`. '@types/node@22': '^22.19.0' -publicHoistPattern: - # `astro sync` could try to import `@astrojs/db` but could fail due to linked dependencies in the monorepo. - # We hoist it here so that it can easily resolve `@astrojs/db` without hardcoded handling. - - '@astrojs/db' # Wait until three days after release to install new versions of packages minimumReleaseAge: 4320 minimumReleaseAgeExclude: diff --git a/tsconfig.json b/tsconfig.json index d8424352c109..44521fd6d60a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -32,7 +32,6 @@ { "path": "./packages/integrations/vercel/tsconfig.json" }, { "path": "./packages/integrations/vue/tsconfig.json" }, { "path": "./packages/create-astro/tsconfig.json" }, - { "path": "./packages/db/tsconfig.json" }, { "path": "./packages/upgrade/tsconfig.json" }, { "path": "./packages/language-tools/astro-check/tsconfig.json" }, { "path": "./packages/language-tools/language-server/tsconfig.json" },