@astrojs/db 0.13.2 → 0.14.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_internal/core/utils.d.ts +7 -1
- package/dist/core/cli/commands/execute/index.js +2 -2
- package/dist/core/cli/commands/link/index.js +0 -1
- package/dist/core/cli/commands/push/index.d.ts +1 -1
- package/dist/core/cli/commands/push/index.js +39 -6
- package/dist/core/cli/commands/shell/index.js +9 -5
- package/dist/core/cli/commands/verify/index.js +7 -3
- package/dist/core/cli/migration-queries.d.ts +4 -2
- package/dist/core/cli/migration-queries.js +26 -7
- package/dist/core/cli/print-help.js +1 -1
- package/dist/core/integration/index.js +14 -15
- package/dist/core/integration/vite-plugin-db.js +20 -8
- package/dist/core/load-file.js +1 -0
- package/dist/core/queries.js +0 -1
- package/dist/core/utils.d.ts +7 -1
- package/dist/core/utils.js +32 -5
- package/dist/runtime/db-client.d.ts +11 -3
- package/dist/runtime/db-client.js +20 -4
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +0 -1
- package/package.json +5 -5
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
import { type ManagedAppToken } from '@astrojs/studio';
|
|
1
2
|
import type { AstroConfig, AstroIntegration } from 'astro';
|
|
2
3
|
import './types.js';
|
|
3
4
|
export type VitePlugin = Required<AstroConfig['vite']>['plugins'][number];
|
|
4
5
|
export declare function getAstroEnv(envMode?: string): Record<`ASTRO_${string}`, string>;
|
|
5
|
-
export
|
|
6
|
+
export type RemoteDatabaseInfo = {
|
|
7
|
+
type: 'libsql' | 'studio';
|
|
8
|
+
url: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function getRemoteDatabaseInfo(): RemoteDatabaseInfo;
|
|
11
|
+
export declare function getManagedRemoteToken(token?: string, dbInfo?: RemoteDatabaseInfo): Promise<ManagedAppToken>;
|
|
6
12
|
export declare function getDbDirectoryUrl(root: URL | string): URL;
|
|
7
13
|
export declare function defineDbIntegration(integration: AstroIntegration): AstroIntegration;
|
|
8
14
|
export type Result<T> = {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
-
import { getManagedAppTokenOrExit } from "@astrojs/studio";
|
|
3
2
|
import { LibsqlError } from "@libsql/client";
|
|
4
3
|
import { green } from "kleur/colors";
|
|
5
4
|
import {
|
|
@@ -13,6 +12,7 @@ import {
|
|
|
13
12
|
getStudioVirtualModContents
|
|
14
13
|
} from "../../../integration/vite-plugin-db.js";
|
|
15
14
|
import { bundleFile, importBundledFile } from "../../../load-file.js";
|
|
15
|
+
import { getManagedRemoteToken } from "../../../utils.js";
|
|
16
16
|
async function cmd({
|
|
17
17
|
astroConfig,
|
|
18
18
|
dbConfig,
|
|
@@ -30,7 +30,7 @@ async function cmd({
|
|
|
30
30
|
}
|
|
31
31
|
let virtualModContents;
|
|
32
32
|
if (flags.remote) {
|
|
33
|
-
const appToken = await
|
|
33
|
+
const appToken = await getManagedRemoteToken(flags.token);
|
|
34
34
|
virtualModContents = getStudioVirtualModContents({
|
|
35
35
|
tables: dbConfig.tables ?? {},
|
|
36
36
|
appToken: appToken.token,
|
|
@@ -12,7 +12,6 @@ import { bgRed, cyan } from "kleur/colors";
|
|
|
12
12
|
import ora from "ora";
|
|
13
13
|
import prompts from "prompts";
|
|
14
14
|
import { safeFetch } from "../../../../runtime/utils.js";
|
|
15
|
-
import {} from "../../../utils.js";
|
|
16
15
|
async function cmd() {
|
|
17
16
|
const sessionToken = await getSessionIdFromFile();
|
|
18
17
|
if (!sessionToken) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AstroConfig } from 'astro';
|
|
2
2
|
import type { Arguments } from 'yargs-parser';
|
|
3
|
-
import {
|
|
3
|
+
import type { DBConfig } from '../../../types.js';
|
|
4
4
|
export declare function cmd({ dbConfig, flags, }: {
|
|
5
5
|
astroConfig: AstroConfig;
|
|
6
6
|
dbConfig: DBConfig;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { sql } from "drizzle-orm";
|
|
2
2
|
import prompts from "prompts";
|
|
3
|
+
import { createRemoteDatabaseClient } from "../../../../runtime/index.js";
|
|
3
4
|
import { safeFetch } from "../../../../runtime/utils.js";
|
|
4
5
|
import { MIGRATION_VERSION } from "../../../consts.js";
|
|
5
|
-
import {
|
|
6
|
-
|
|
6
|
+
import {
|
|
7
|
+
getManagedRemoteToken,
|
|
8
|
+
getRemoteDatabaseInfo
|
|
9
|
+
} from "../../../utils.js";
|
|
7
10
|
import {
|
|
8
11
|
createCurrentSnapshot,
|
|
9
12
|
createEmptySnapshot,
|
|
@@ -17,8 +20,12 @@ async function cmd({
|
|
|
17
20
|
}) {
|
|
18
21
|
const isDryRun = flags.dryRun;
|
|
19
22
|
const isForceReset = flags.forceReset;
|
|
20
|
-
const
|
|
21
|
-
const
|
|
23
|
+
const dbInfo = getRemoteDatabaseInfo();
|
|
24
|
+
const appToken = await getManagedRemoteToken(flags.token, dbInfo);
|
|
25
|
+
const productionSnapshot = await getProductionCurrentSnapshot({
|
|
26
|
+
dbInfo,
|
|
27
|
+
appToken: appToken.token
|
|
28
|
+
});
|
|
22
29
|
const currentSnapshot = createCurrentSnapshot(dbConfig);
|
|
23
30
|
const isFromScratch = !productionSnapshot;
|
|
24
31
|
const { queries: migrationQueries, confirmations } = await getMigrationQueries({
|
|
@@ -53,6 +60,7 @@ async function cmd({
|
|
|
53
60
|
console.log(`Pushing database schema updates...`);
|
|
54
61
|
await pushSchema({
|
|
55
62
|
statements: migrationQueries,
|
|
63
|
+
dbInfo,
|
|
56
64
|
appToken: appToken.token,
|
|
57
65
|
isDryRun,
|
|
58
66
|
currentSnapshot
|
|
@@ -63,6 +71,7 @@ async function cmd({
|
|
|
63
71
|
}
|
|
64
72
|
async function pushSchema({
|
|
65
73
|
statements,
|
|
74
|
+
dbInfo,
|
|
66
75
|
appToken,
|
|
67
76
|
isDryRun,
|
|
68
77
|
currentSnapshot
|
|
@@ -76,7 +85,31 @@ async function pushSchema({
|
|
|
76
85
|
console.info("[DRY RUN] Batch query:", JSON.stringify(requestBody, null, 2));
|
|
77
86
|
return new Response(null, { status: 200 });
|
|
78
87
|
}
|
|
79
|
-
|
|
88
|
+
return dbInfo.type === "studio" ? pushToStudio(requestBody, appToken, dbInfo.url) : pushToDb(requestBody, appToken, dbInfo.url);
|
|
89
|
+
}
|
|
90
|
+
async function pushToDb(requestBody, appToken, remoteUrl) {
|
|
91
|
+
const client = createRemoteDatabaseClient({
|
|
92
|
+
dbType: "libsql",
|
|
93
|
+
appToken,
|
|
94
|
+
remoteUrl
|
|
95
|
+
});
|
|
96
|
+
await client.run(sql`create table if not exists _astro_db_snapshot (
|
|
97
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
98
|
+
version TEXT,
|
|
99
|
+
snapshot BLOB
|
|
100
|
+
);`);
|
|
101
|
+
await client.transaction(async (tx) => {
|
|
102
|
+
for (const stmt of requestBody.sql) {
|
|
103
|
+
await tx.run(sql.raw(stmt));
|
|
104
|
+
}
|
|
105
|
+
await tx.run(sql`insert into _astro_db_snapshot (version, snapshot) values (
|
|
106
|
+
${requestBody.version},
|
|
107
|
+
${JSON.stringify(requestBody.snapshot)}
|
|
108
|
+
)`);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
async function pushToStudio(requestBody, appToken, remoteUrl) {
|
|
112
|
+
const url = new URL("/db/push", remoteUrl);
|
|
80
113
|
const response = await safeFetch(
|
|
81
114
|
url,
|
|
82
115
|
{
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { getManagedAppTokenOrExit } from "@astrojs/studio";
|
|
2
1
|
import { sql } from "drizzle-orm";
|
|
3
2
|
import {
|
|
4
3
|
createLocalDatabaseClient,
|
|
@@ -7,7 +6,7 @@ import {
|
|
|
7
6
|
import { normalizeDatabaseUrl } from "../../../../runtime/index.js";
|
|
8
7
|
import { DB_PATH } from "../../../consts.js";
|
|
9
8
|
import { SHELL_QUERY_MISSING_ERROR } from "../../../errors.js";
|
|
10
|
-
import { getAstroEnv,
|
|
9
|
+
import { getAstroEnv, getManagedRemoteToken, getRemoteDatabaseInfo } from "../../../utils.js";
|
|
11
10
|
async function cmd({
|
|
12
11
|
flags,
|
|
13
12
|
astroConfig
|
|
@@ -17,9 +16,14 @@ async function cmd({
|
|
|
17
16
|
console.error(SHELL_QUERY_MISSING_ERROR);
|
|
18
17
|
process.exit(1);
|
|
19
18
|
}
|
|
19
|
+
const dbInfo = getRemoteDatabaseInfo();
|
|
20
20
|
if (flags.remote) {
|
|
21
|
-
const appToken = await
|
|
22
|
-
const db = createRemoteDatabaseClient(
|
|
21
|
+
const appToken = await getManagedRemoteToken(flags.token, dbInfo);
|
|
22
|
+
const db = createRemoteDatabaseClient({
|
|
23
|
+
dbType: dbInfo.type,
|
|
24
|
+
remoteUrl: dbInfo.url,
|
|
25
|
+
appToken: appToken.token
|
|
26
|
+
});
|
|
23
27
|
const result = await db.run(sql.raw(query));
|
|
24
28
|
await appToken.destroy();
|
|
25
29
|
console.log(result);
|
|
@@ -29,7 +33,7 @@ async function cmd({
|
|
|
29
33
|
ASTRO_DATABASE_FILE,
|
|
30
34
|
new URL(DB_PATH, astroConfig.root).href
|
|
31
35
|
);
|
|
32
|
-
const db = createLocalDatabaseClient({ dbUrl });
|
|
36
|
+
const db = createLocalDatabaseClient({ dbUrl, enableTransations: dbInfo.type === "libsql" });
|
|
33
37
|
const result = await db.run(sql.raw(query));
|
|
34
38
|
console.log(result);
|
|
35
39
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getManagedRemoteToken, getRemoteDatabaseInfo } from "../../../utils.js";
|
|
2
2
|
import {
|
|
3
3
|
createCurrentSnapshot,
|
|
4
4
|
createEmptySnapshot,
|
|
@@ -11,8 +11,12 @@ async function cmd({
|
|
|
11
11
|
flags
|
|
12
12
|
}) {
|
|
13
13
|
const isJson = flags.json;
|
|
14
|
-
const
|
|
15
|
-
const
|
|
14
|
+
const dbInfo = getRemoteDatabaseInfo();
|
|
15
|
+
const appToken = await getManagedRemoteToken(flags.token, dbInfo);
|
|
16
|
+
const productionSnapshot = await getProductionCurrentSnapshot({
|
|
17
|
+
dbInfo,
|
|
18
|
+
appToken: appToken.token
|
|
19
|
+
});
|
|
16
20
|
const currentSnapshot = createCurrentSnapshot(dbConfig);
|
|
17
21
|
const { queries: migrationQueries, confirmations } = await getMigrationQueries({
|
|
18
22
|
oldSnapshot: productionSnapshot || createEmptySnapshot(),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { DBConfig, DBSnapshot, ResolvedDBTable } from '../types.js';
|
|
2
|
+
import type { RemoteDatabaseInfo } from '../utils.js';
|
|
2
3
|
export declare function getMigrationQueries({ oldSnapshot, newSnapshot, reset, }: {
|
|
3
4
|
oldSnapshot: DBSnapshot;
|
|
4
5
|
newSnapshot: DBSnapshot;
|
|
@@ -15,7 +16,8 @@ export declare function getTableChangeQueries({ tableName, oldTable, newTable, }
|
|
|
15
16
|
queries: string[];
|
|
16
17
|
confirmations: string[];
|
|
17
18
|
}>;
|
|
18
|
-
export declare function getProductionCurrentSnapshot(
|
|
19
|
+
export declare function getProductionCurrentSnapshot(options: {
|
|
20
|
+
dbInfo: RemoteDatabaseInfo;
|
|
19
21
|
appToken: string;
|
|
20
22
|
}): Promise<DBSnapshot | undefined>;
|
|
21
23
|
export declare function createCurrentSnapshot({ tables }: DBConfig): DBSnapshot;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import deepDiff from "deep-diff";
|
|
2
|
+
import { sql } from "drizzle-orm";
|
|
2
3
|
import { SQLiteAsyncDialect } from "drizzle-orm/sqlite-core";
|
|
3
4
|
import * as color from "kleur/colors";
|
|
4
5
|
import { customAlphabet } from "nanoid";
|
|
5
6
|
import stripAnsi from "strip-ansi";
|
|
6
7
|
import { hasPrimaryKey } from "../../runtime/index.js";
|
|
8
|
+
import { createRemoteDatabaseClient } from "../../runtime/index.js";
|
|
7
9
|
import { isSerializedSQL } from "../../runtime/types.js";
|
|
8
10
|
import { safeFetch } from "../../runtime/utils.js";
|
|
9
11
|
import { MIGRATION_VERSION } from "../consts.js";
|
|
@@ -18,9 +20,6 @@ import {
|
|
|
18
20
|
schemaTypeToSqlType
|
|
19
21
|
} from "../queries.js";
|
|
20
22
|
import { columnSchema } from "../schemas.js";
|
|
21
|
-
import {
|
|
22
|
-
} from "../types.js";
|
|
23
|
-
import { getRemoteDatabaseUrl } from "../utils.js";
|
|
24
23
|
const sqlite = new SQLiteAsyncDialect();
|
|
25
24
|
const genTempTableName = customAlphabet("abcdefghijklmnopqrstuvwxyz", 10);
|
|
26
25
|
async function getMigrationQueries({
|
|
@@ -304,10 +303,30 @@ function canChangeTypeWithoutQuery(oldColumn, newColumn) {
|
|
|
304
303
|
function hasRuntimeDefault(column) {
|
|
305
304
|
return !!(column.schema.default && isSerializedSQL(column.schema.default));
|
|
306
305
|
}
|
|
307
|
-
|
|
308
|
-
appToken
|
|
309
|
-
}
|
|
310
|
-
|
|
306
|
+
function getProductionCurrentSnapshot(options) {
|
|
307
|
+
return options.dbInfo.type === "studio" ? getStudioCurrentSnapshot(options.appToken, options.dbInfo.url) : getDbCurrentSnapshot(options.appToken, options.dbInfo.url);
|
|
308
|
+
}
|
|
309
|
+
async function getDbCurrentSnapshot(appToken, remoteUrl) {
|
|
310
|
+
const client = createRemoteDatabaseClient({
|
|
311
|
+
dbType: "libsql",
|
|
312
|
+
appToken,
|
|
313
|
+
remoteUrl
|
|
314
|
+
});
|
|
315
|
+
try {
|
|
316
|
+
const res = await client.get(
|
|
317
|
+
// Latest snapshot
|
|
318
|
+
sql`select snapshot from _astro_db_snapshot order by id desc limit 1;`
|
|
319
|
+
);
|
|
320
|
+
return JSON.parse(res.snapshot);
|
|
321
|
+
} catch (error) {
|
|
322
|
+
if (error.code === "SQLITE_UNKNOWN") {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
throw error;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
async function getStudioCurrentSnapshot(appToken, remoteUrl) {
|
|
329
|
+
const url = new URL("/db/schema", remoteUrl);
|
|
311
330
|
const response = await safeFetch(
|
|
312
331
|
url,
|
|
313
332
|
{
|
|
@@ -2,7 +2,6 @@ import { existsSync } from "node:fs";
|
|
|
2
2
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
3
|
import { dirname } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { getManagedAppTokenOrExit } from "@astrojs/studio";
|
|
6
5
|
import { LibsqlError } from "@libsql/client";
|
|
7
6
|
import { blue, yellow } from "kleur/colors";
|
|
8
7
|
import {
|
|
@@ -16,7 +15,7 @@ import { CONFIG_FILE_NAMES, DB_PATH } from "../consts.js";
|
|
|
16
15
|
import { EXEC_DEFAULT_EXPORT_ERROR, EXEC_ERROR } from "../errors.js";
|
|
17
16
|
import { resolveDbConfig } from "../load-file.js";
|
|
18
17
|
import { SEED_DEV_FILE_NAME } from "../queries.js";
|
|
19
|
-
import { getDbDirectoryUrl } from "../utils.js";
|
|
18
|
+
import { getDbDirectoryUrl, getManagedRemoteToken } from "../utils.js";
|
|
20
19
|
import { fileURLIntegration } from "./file-url.js";
|
|
21
20
|
import { getDtsContent } from "./typegen.js";
|
|
22
21
|
import {
|
|
@@ -24,7 +23,7 @@ import {
|
|
|
24
23
|
vitePluginDb
|
|
25
24
|
} from "./vite-plugin-db.js";
|
|
26
25
|
function astroDBIntegration() {
|
|
27
|
-
let
|
|
26
|
+
let connectToRemote = false;
|
|
28
27
|
let configFileDependencies = [];
|
|
29
28
|
let root;
|
|
30
29
|
let appToken;
|
|
@@ -46,22 +45,21 @@ function astroDBIntegration() {
|
|
|
46
45
|
inProgress: false
|
|
47
46
|
};
|
|
48
47
|
let command;
|
|
49
|
-
let
|
|
48
|
+
let finalBuildOutput;
|
|
50
49
|
return {
|
|
51
50
|
name: "astro:db",
|
|
52
51
|
hooks: {
|
|
53
52
|
"astro:config:setup": async ({ updateConfig, config, command: _command, logger }) => {
|
|
54
53
|
command = _command;
|
|
55
54
|
root = config.root;
|
|
56
|
-
output = config.output;
|
|
57
55
|
if (command === "preview") return;
|
|
58
56
|
let dbPlugin = void 0;
|
|
59
57
|
const args = parseArgs(process.argv.slice(3));
|
|
60
|
-
|
|
61
|
-
if (
|
|
62
|
-
appToken = await
|
|
58
|
+
connectToRemote = process.env.ASTRO_INTERNAL_TEST_REMOTE || args["remote"];
|
|
59
|
+
if (connectToRemote) {
|
|
60
|
+
appToken = await getManagedRemoteToken();
|
|
63
61
|
dbPlugin = vitePluginDb({
|
|
64
|
-
connectToStudio,
|
|
62
|
+
connectToStudio: connectToRemote,
|
|
65
63
|
appToken: appToken.token,
|
|
66
64
|
tables,
|
|
67
65
|
root: config.root,
|
|
@@ -88,14 +86,15 @@ function astroDBIntegration() {
|
|
|
88
86
|
}
|
|
89
87
|
});
|
|
90
88
|
},
|
|
91
|
-
"astro:config:done": async ({ config, injectTypes }) => {
|
|
89
|
+
"astro:config:done": async ({ config, injectTypes, buildOutput }) => {
|
|
92
90
|
if (command === "preview") return;
|
|
91
|
+
finalBuildOutput = buildOutput;
|
|
93
92
|
const { dbConfig, dependencies, integrationSeedPaths } = await resolveDbConfig(config);
|
|
94
93
|
tables.get = () => dbConfig.tables;
|
|
95
94
|
seedFiles.get = () => integrationSeedPaths;
|
|
96
95
|
configFileDependencies = dependencies;
|
|
97
96
|
const localDbUrl = new URL(DB_PATH, config.root);
|
|
98
|
-
if (!
|
|
97
|
+
if (!connectToRemote && !existsSync(localDbUrl)) {
|
|
99
98
|
await mkdir(dirname(fileURLToPath(localDbUrl)), { recursive: true });
|
|
100
99
|
await writeFile(localDbUrl, "");
|
|
101
100
|
}
|
|
@@ -120,9 +119,9 @@ function astroDBIntegration() {
|
|
|
120
119
|
});
|
|
121
120
|
setTimeout(() => {
|
|
122
121
|
logger.info(
|
|
123
|
-
|
|
122
|
+
connectToRemote ? "Connected to remote database." : "New local database created."
|
|
124
123
|
);
|
|
125
|
-
if (
|
|
124
|
+
if (connectToRemote) return;
|
|
126
125
|
const localSeedPaths = SEED_DEV_FILE_NAME.map(
|
|
127
126
|
(name) => new URL(name, getDbDirectoryUrl(root))
|
|
128
127
|
);
|
|
@@ -134,12 +133,12 @@ function astroDBIntegration() {
|
|
|
134
133
|
}, 100);
|
|
135
134
|
},
|
|
136
135
|
"astro:build:start": async ({ logger }) => {
|
|
137
|
-
if (!
|
|
136
|
+
if (!connectToRemote && !databaseFileEnvDefined() && finalBuildOutput === "server") {
|
|
138
137
|
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.`;
|
|
139
138
|
const hint = "Learn more connecting to Studio: https://docs.astro.build/en/guides/astro-db/#connect-to-astro-studio";
|
|
140
139
|
throw new AstroDbError(message, hint);
|
|
141
140
|
}
|
|
142
|
-
logger.info("database: " + (
|
|
141
|
+
logger.info("database: " + (connectToRemote ? yellow("remote") : blue("local database.")));
|
|
143
142
|
},
|
|
144
143
|
"astro:build:setup": async ({ vite }) => {
|
|
145
144
|
tempViteServer = await getTempViteServer({ viteConfig: vite });
|
|
@@ -7,7 +7,11 @@ import { normalizeDatabaseUrl } from "../../runtime/index.js";
|
|
|
7
7
|
import { DB_PATH, RUNTIME_IMPORT, RUNTIME_VIRTUAL_IMPORT, VIRTUAL_MODULE_ID } from "../consts.js";
|
|
8
8
|
import { getResolvedFileUrl } from "../load-file.js";
|
|
9
9
|
import { SEED_DEV_FILE_NAME, getCreateIndexQueries, getCreateTableQuery } from "../queries.js";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
getAstroEnv,
|
|
12
|
+
getDbDirectoryUrl,
|
|
13
|
+
getRemoteDatabaseInfo
|
|
14
|
+
} from "../utils.js";
|
|
11
15
|
const resolved = {
|
|
12
16
|
module: "\0" + VIRTUAL_MODULE_ID,
|
|
13
17
|
importedFromSeedFile: "\0" + VIRTUAL_MODULE_ID + ":seed"
|
|
@@ -70,12 +74,13 @@ function getLocalVirtualModContents({
|
|
|
70
74
|
tables,
|
|
71
75
|
root
|
|
72
76
|
}) {
|
|
77
|
+
const dbInfo = getRemoteDatabaseInfo();
|
|
73
78
|
const dbUrl = new URL(DB_PATH, root);
|
|
74
79
|
return `
|
|
75
80
|
import { asDrizzleTable, createLocalDatabaseClient, normalizeDatabaseUrl } from ${RUNTIME_IMPORT};
|
|
76
81
|
|
|
77
82
|
const dbUrl = normalizeDatabaseUrl(import.meta.env.ASTRO_DATABASE_FILE, ${JSON.stringify(dbUrl)});
|
|
78
|
-
export const db = createLocalDatabaseClient({ dbUrl });
|
|
83
|
+
export const db = createLocalDatabaseClient({ dbUrl, enableTransactions: ${dbInfo.url === "libsql"} });
|
|
79
84
|
|
|
80
85
|
export * from ${RUNTIME_VIRTUAL_IMPORT};
|
|
81
86
|
|
|
@@ -87,25 +92,31 @@ function getStudioVirtualModContents({
|
|
|
87
92
|
isBuild,
|
|
88
93
|
output
|
|
89
94
|
}) {
|
|
95
|
+
const dbInfo = getRemoteDatabaseInfo();
|
|
90
96
|
function appTokenArg() {
|
|
91
97
|
if (isBuild) {
|
|
98
|
+
const envPrefix = dbInfo.type === "studio" ? "ASTRO_STUDIO" : "ASTRO_DB";
|
|
92
99
|
if (output === "server") {
|
|
93
|
-
return
|
|
100
|
+
return `process.env.${envPrefix}_APP_TOKEN`;
|
|
94
101
|
} else {
|
|
95
|
-
return `process.env
|
|
102
|
+
return `process.env.${envPrefix}_APP_TOKEN ?? ${JSON.stringify(appToken)}`;
|
|
96
103
|
}
|
|
97
104
|
} else {
|
|
98
105
|
return JSON.stringify(appToken);
|
|
99
106
|
}
|
|
100
107
|
}
|
|
101
108
|
function dbUrlArg() {
|
|
102
|
-
const dbStr = JSON.stringify(
|
|
103
|
-
return `import.meta.env.ASTRO_STUDIO_REMOTE_DB_URL ?? ${dbStr}`;
|
|
109
|
+
const dbStr = JSON.stringify(dbInfo.url);
|
|
110
|
+
return dbInfo.type === "studio" ? `import.meta.env.ASTRO_STUDIO_REMOTE_DB_URL ?? ${dbStr}` : `import.meta.env.ASTRO_DB_REMOTE_URL ?? ${dbStr}`;
|
|
104
111
|
}
|
|
105
112
|
return `
|
|
106
113
|
import {asDrizzleTable, createRemoteDatabaseClient} from ${RUNTIME_IMPORT};
|
|
107
114
|
|
|
108
|
-
export const db = await createRemoteDatabaseClient(
|
|
115
|
+
export const db = await createRemoteDatabaseClient({
|
|
116
|
+
dbType: ${JSON.stringify(dbInfo.type)},
|
|
117
|
+
remoteUrl: ${dbUrlArg()},
|
|
118
|
+
appToken: ${appTokenArg()},
|
|
119
|
+
});
|
|
109
120
|
|
|
110
121
|
export * from ${RUNTIME_VIRTUAL_IMPORT};
|
|
111
122
|
|
|
@@ -121,9 +132,10 @@ function getStringifiedTableExports(tables) {
|
|
|
121
132
|
}
|
|
122
133
|
const sqlite = new SQLiteAsyncDialect();
|
|
123
134
|
async function recreateTables({ tables, root }) {
|
|
135
|
+
const dbInfo = getRemoteDatabaseInfo();
|
|
124
136
|
const { ASTRO_DATABASE_FILE } = getAstroEnv();
|
|
125
137
|
const dbUrl = normalizeDatabaseUrl(ASTRO_DATABASE_FILE, new URL(DB_PATH, root).href);
|
|
126
|
-
const db = createLocalDatabaseClient({ dbUrl });
|
|
138
|
+
const db = createLocalDatabaseClient({ dbUrl, enableTransations: dbInfo.type === "libsql" });
|
|
127
139
|
const setupQueries = [];
|
|
128
140
|
for (const [name, table] of Object.entries(tables.get() ?? {})) {
|
|
129
141
|
const dropQuery = sql.raw(`DROP TABLE IF EXISTS ${sqlite.escapeName(name)}`);
|
package/dist/core/load-file.js
CHANGED
|
@@ -116,6 +116,7 @@ async function bundleFile({
|
|
|
116
116
|
metafile: true,
|
|
117
117
|
define: {
|
|
118
118
|
"import.meta.env.ASTRO_STUDIO_REMOTE_DB_URL": "undefined",
|
|
119
|
+
"import.meta.env.ASTRO_DB_REMOTE_DB_URL": "undefined",
|
|
119
120
|
"import.meta.env.ASTRO_DATABASE_FILE": JSON.stringify(ASTRO_DATABASE_FILE ?? "")
|
|
120
121
|
},
|
|
121
122
|
plugins: [
|
package/dist/core/queries.js
CHANGED
package/dist/core/utils.d.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
import { type ManagedAppToken } from '@astrojs/studio';
|
|
1
2
|
import type { AstroConfig, AstroIntegration } from 'astro';
|
|
2
3
|
import './types.js';
|
|
3
4
|
export type VitePlugin = Required<AstroConfig['vite']>['plugins'][number];
|
|
4
5
|
export declare function getAstroEnv(envMode?: string): Record<`ASTRO_${string}`, string>;
|
|
5
|
-
export
|
|
6
|
+
export type RemoteDatabaseInfo = {
|
|
7
|
+
type: 'libsql' | 'studio';
|
|
8
|
+
url: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function getRemoteDatabaseInfo(): RemoteDatabaseInfo;
|
|
11
|
+
export declare function getManagedRemoteToken(token?: string, dbInfo?: RemoteDatabaseInfo): Promise<ManagedAppToken>;
|
|
6
12
|
export declare function getDbDirectoryUrl(root: URL | string): URL;
|
|
7
13
|
export declare function defineDbIntegration(integration: AstroIntegration): AstroIntegration;
|
|
8
14
|
export type Result<T> = {
|
package/dist/core/utils.js
CHANGED
|
@@ -1,13 +1,39 @@
|
|
|
1
|
-
import { getAstroStudioEnv } from "@astrojs/studio";
|
|
1
|
+
import { getAstroStudioEnv, getManagedAppTokenOrExit } from "@astrojs/studio";
|
|
2
2
|
import { loadEnv } from "vite";
|
|
3
3
|
import "./types.js";
|
|
4
4
|
function getAstroEnv(envMode = "") {
|
|
5
5
|
const env = loadEnv(envMode, process.cwd(), "ASTRO_");
|
|
6
6
|
return env;
|
|
7
7
|
}
|
|
8
|
-
function
|
|
9
|
-
const
|
|
10
|
-
|
|
8
|
+
function getRemoteDatabaseInfo() {
|
|
9
|
+
const astroEnv = getAstroEnv();
|
|
10
|
+
const studioEnv = getAstroStudioEnv();
|
|
11
|
+
if (studioEnv.ASTRO_STUDIO_REMOTE_DB_URL)
|
|
12
|
+
return {
|
|
13
|
+
type: "studio",
|
|
14
|
+
url: studioEnv.ASTRO_STUDIO_REMOTE_DB_URL
|
|
15
|
+
};
|
|
16
|
+
if (astroEnv.ASTRO_DB_REMOTE_URL)
|
|
17
|
+
return {
|
|
18
|
+
type: "libsql",
|
|
19
|
+
url: astroEnv.ASTRO_DB_REMOTE_URL
|
|
20
|
+
};
|
|
21
|
+
return {
|
|
22
|
+
type: "studio",
|
|
23
|
+
url: "https://db.services.astro.build"
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function getManagedRemoteToken(token, dbInfo) {
|
|
27
|
+
dbInfo ??= getRemoteDatabaseInfo();
|
|
28
|
+
if (dbInfo.type === "studio") {
|
|
29
|
+
return getManagedAppTokenOrExit(token);
|
|
30
|
+
}
|
|
31
|
+
const astroEnv = getAstroEnv();
|
|
32
|
+
return Promise.resolve({
|
|
33
|
+
token: token ?? astroEnv.ASTRO_DB_APP_TOKEN,
|
|
34
|
+
renew: () => Promise.resolve(),
|
|
35
|
+
destroy: () => Promise.resolve()
|
|
36
|
+
});
|
|
11
37
|
}
|
|
12
38
|
function getDbDirectoryUrl(root) {
|
|
13
39
|
return new URL("db/", root);
|
|
@@ -24,6 +50,7 @@ export {
|
|
|
24
50
|
defineDbIntegration,
|
|
25
51
|
getAstroEnv,
|
|
26
52
|
getDbDirectoryUrl,
|
|
27
|
-
|
|
53
|
+
getManagedRemoteToken,
|
|
54
|
+
getRemoteDatabaseInfo,
|
|
28
55
|
mapObject
|
|
29
56
|
};
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import type { LibSQLDatabase } from 'drizzle-orm/libsql';
|
|
2
2
|
import { type SqliteRemoteDatabase } from 'drizzle-orm/sqlite-proxy';
|
|
3
|
-
|
|
3
|
+
type LocalDbClientOptions = {
|
|
4
4
|
dbUrl: string;
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
enableTransations: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare function createLocalDatabaseClient(options: LocalDbClientOptions): LibSQLDatabase;
|
|
8
|
+
type RemoteDbClientOptions = {
|
|
9
|
+
dbType: 'studio' | 'libsql';
|
|
10
|
+
appToken: string;
|
|
11
|
+
remoteUrl: string | URL;
|
|
12
|
+
};
|
|
13
|
+
export declare function createRemoteDatabaseClient(options: RemoteDbClientOptions): SqliteRemoteDatabase<Record<string, never>> | LibSQLDatabase<Record<string, never>>;
|
|
14
|
+
export {};
|
|
@@ -13,11 +13,13 @@ function applyTransactionNotSupported(db) {
|
|
|
13
13
|
}
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
|
-
function createLocalDatabaseClient(
|
|
17
|
-
const url = isWebContainer ? "file:content.db" : dbUrl;
|
|
16
|
+
function createLocalDatabaseClient(options) {
|
|
17
|
+
const url = isWebContainer ? "file:content.db" : options.dbUrl;
|
|
18
18
|
const client = createClient({ url });
|
|
19
19
|
const db = drizzleLibsql(client);
|
|
20
|
-
|
|
20
|
+
if (!options.enableTransations) {
|
|
21
|
+
applyTransactionNotSupported(db);
|
|
22
|
+
}
|
|
21
23
|
return db;
|
|
22
24
|
}
|
|
23
25
|
const remoteResultSchema = z.object({
|
|
@@ -27,7 +29,21 @@ const remoteResultSchema = z.object({
|
|
|
27
29
|
rowsAffected: z.number(),
|
|
28
30
|
lastInsertRowid: z.unknown().optional()
|
|
29
31
|
});
|
|
30
|
-
function createRemoteDatabaseClient(
|
|
32
|
+
function createRemoteDatabaseClient(options) {
|
|
33
|
+
const remoteUrl = new URL(options.remoteUrl);
|
|
34
|
+
return options.dbType === "studio" ? createStudioDatabaseClient(options.appToken, remoteUrl) : createRemoteLibSQLClient(options.appToken, remoteUrl);
|
|
35
|
+
}
|
|
36
|
+
function createRemoteLibSQLClient(appToken, remoteDbURL) {
|
|
37
|
+
const options = Object.fromEntries(remoteDbURL.searchParams.entries());
|
|
38
|
+
remoteDbURL.search = "";
|
|
39
|
+
const client = createClient({
|
|
40
|
+
...options,
|
|
41
|
+
authToken: appToken,
|
|
42
|
+
url: remoteDbURL.protocol === "memory:" ? ":memory:" : remoteDbURL.toString()
|
|
43
|
+
});
|
|
44
|
+
return drizzleLibsql(client);
|
|
45
|
+
}
|
|
46
|
+
function createStudioDatabaseClient(appToken, remoteDbURL) {
|
|
31
47
|
if (appToken == null) {
|
|
32
48
|
throw new Error(`Cannot create a remote client: missing app token.`);
|
|
33
49
|
}
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ColumnDataType } from 'drizzle-orm';
|
|
2
|
-
import {
|
|
2
|
+
import type { LibSQLDatabase } from 'drizzle-orm/libsql';
|
|
3
3
|
import type { DBColumn, DBTable } from '../core/types.js';
|
|
4
4
|
export type Database = Omit<LibSQLDatabase, 'transaction'>;
|
|
5
5
|
export type { Table } from './types.js';
|
package/dist/runtime/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrojs/db",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0-beta.1",
|
|
4
4
|
"description": "Add libSQL and Astro Studio support to your Astro site",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"astro-integration"
|
|
63
63
|
],
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@libsql/client": "^0.
|
|
65
|
+
"@libsql/client": "^0.10.0",
|
|
66
66
|
"async-listen": "^3.0.1",
|
|
67
67
|
"deep-diff": "^1.0.2",
|
|
68
68
|
"drizzle-orm": "^0.31.2",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"kleur": "^4.1.5",
|
|
71
71
|
"nanoid": "^5.0.7",
|
|
72
72
|
"open": "^10.1.0",
|
|
73
|
-
"ora": "^8.0
|
|
73
|
+
"ora": "^8.1.0",
|
|
74
74
|
"prompts": "^2.4.2",
|
|
75
75
|
"strip-ansi": "^7.1.0",
|
|
76
76
|
"yargs-parser": "^21.1.1",
|
|
@@ -83,8 +83,8 @@
|
|
|
83
83
|
"@types/yargs-parser": "^21.0.3",
|
|
84
84
|
"cheerio": "1.0.0",
|
|
85
85
|
"typescript": "^5.5.4",
|
|
86
|
-
"vite": "^5.4.
|
|
87
|
-
"astro": "
|
|
86
|
+
"vite": "^5.4.3",
|
|
87
|
+
"astro": "5.0.0-beta.1",
|
|
88
88
|
"astro-scripts": "0.0.14"
|
|
89
89
|
},
|
|
90
90
|
"scripts": {
|