@astrojs/db 0.10.7 → 0.11.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 +1 -0
- package/dist/core/cli/commands/execute/index.d.ts +1 -1
- package/dist/core/cli/commands/execute/index.js +1 -4
- package/dist/core/cli/commands/shell/index.js +8 -2
- package/dist/core/cli/migration-queries.js +20 -35
- package/dist/core/cli/print-help.js +1 -1
- package/dist/core/integration/error-map.js +2 -4
- package/dist/core/integration/index.js +73 -36
- package/dist/core/integration/vite-plugin-db.d.ts +11 -6
- package/dist/core/integration/vite-plugin-db.js +62 -50
- package/dist/core/integration/vite-plugin-inject-env-ts.js +1 -2
- package/dist/core/load-file.d.ts +1 -0
- package/dist/core/load-file.js +12 -9
- package/dist/{runtime → core}/queries.d.ts +3 -3
- package/dist/{runtime → core}/queries.js +4 -5
- package/dist/core/utils.d.ts +1 -0
- package/dist/core/utils.js +5 -0
- package/dist/runtime/db-client.js +1 -2
- package/dist/runtime/index.d.ts +0 -1
- package/dist/runtime/index.js +11 -15
- package/dist/runtime/utils.d.ts +0 -1
- package/dist/runtime/utils.js +0 -1
- package/package.json +7 -7
- package/dist/runtime/seed-local.d.ts +0 -10
- package/dist/runtime/seed-local.js +0 -55
|
@@ -2,6 +2,7 @@ import type { AstroConfig, AstroIntegration } from 'astro';
|
|
|
2
2
|
import type { AstroDbIntegration } from './types.js';
|
|
3
3
|
export type VitePlugin = Required<AstroConfig['vite']>['plugins'][number];
|
|
4
4
|
export declare function getAstroStudioEnv(envMode?: string): Record<`ASTRO_STUDIO_${string}`, string>;
|
|
5
|
+
export declare function getAstroEnv(envMode?: string): Record<`ASTRO_${string}`, string>;
|
|
5
6
|
export declare function getRemoteDatabaseUrl(): string;
|
|
6
7
|
export declare function getAstroStudioUrl(): string;
|
|
7
8
|
export declare function getDbDirectoryUrl(root: URL | string): URL;
|
|
@@ -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({ astroConfig, dbConfig, flags, }: {
|
|
5
5
|
astroConfig: AstroConfig;
|
|
6
6
|
dbConfig: DBConfig;
|
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
} from "../../../integration/vite-plugin-db.js";
|
|
14
14
|
import { bundleFile, importBundledFile } from "../../../load-file.js";
|
|
15
15
|
import { getManagedAppTokenOrExit } from "../../../tokens.js";
|
|
16
|
-
import {} from "../../../types.js";
|
|
17
16
|
async function cmd({
|
|
18
17
|
astroConfig,
|
|
19
18
|
dbConfig,
|
|
@@ -41,9 +40,7 @@ async function cmd({
|
|
|
41
40
|
} else {
|
|
42
41
|
virtualModContents = getLocalVirtualModContents({
|
|
43
42
|
tables: dbConfig.tables ?? {},
|
|
44
|
-
root: astroConfig.root
|
|
45
|
-
shouldSeed: false,
|
|
46
|
-
seedFiles: []
|
|
43
|
+
root: astroConfig.root
|
|
47
44
|
});
|
|
48
45
|
}
|
|
49
46
|
const { code } = await bundleFile({ virtualModContents, root: astroConfig.root, fileUrl });
|
|
@@ -3,10 +3,11 @@ import {
|
|
|
3
3
|
createLocalDatabaseClient,
|
|
4
4
|
createRemoteDatabaseClient
|
|
5
5
|
} from "../../../../runtime/db-client.js";
|
|
6
|
+
import { normalizeDatabaseUrl } from "../../../../runtime/index.js";
|
|
6
7
|
import { DB_PATH } from "../../../consts.js";
|
|
7
8
|
import { SHELL_QUERY_MISSING_ERROR } from "../../../errors.js";
|
|
8
9
|
import { getManagedAppTokenOrExit } from "../../../tokens.js";
|
|
9
|
-
import { getRemoteDatabaseUrl } from "../../../utils.js";
|
|
10
|
+
import { getAstroEnv, getRemoteDatabaseUrl } from "../../../utils.js";
|
|
10
11
|
async function cmd({
|
|
11
12
|
flags,
|
|
12
13
|
astroConfig
|
|
@@ -23,7 +24,12 @@ async function cmd({
|
|
|
23
24
|
await appToken.destroy();
|
|
24
25
|
console.log(result);
|
|
25
26
|
} else {
|
|
26
|
-
const
|
|
27
|
+
const { ASTRO_DATABASE_FILE } = getAstroEnv();
|
|
28
|
+
const dbUrl = normalizeDatabaseUrl(
|
|
29
|
+
ASTRO_DATABASE_FILE,
|
|
30
|
+
new URL(DB_PATH, astroConfig.root).href
|
|
31
|
+
);
|
|
32
|
+
const db = createLocalDatabaseClient({ dbUrl });
|
|
27
33
|
const result = await db.run(sql.raw(query));
|
|
28
34
|
console.log(result);
|
|
29
35
|
}
|
|
@@ -4,6 +4,10 @@ import * as color from "kleur/colors";
|
|
|
4
4
|
import { customAlphabet } from "nanoid";
|
|
5
5
|
import stripAnsi from "strip-ansi";
|
|
6
6
|
import { hasPrimaryKey } from "../../runtime/index.js";
|
|
7
|
+
import { isSerializedSQL } from "../../runtime/types.js";
|
|
8
|
+
import { safeFetch } from "../../runtime/utils.js";
|
|
9
|
+
import { MIGRATION_VERSION } from "../consts.js";
|
|
10
|
+
import { RENAME_COLUMN_ERROR, RENAME_TABLE_ERROR } from "../errors.js";
|
|
7
11
|
import {
|
|
8
12
|
getCreateIndexQueries,
|
|
9
13
|
getCreateTableQuery,
|
|
@@ -12,11 +16,7 @@ import {
|
|
|
12
16
|
getReferencesConfig,
|
|
13
17
|
hasDefault,
|
|
14
18
|
schemaTypeToSqlType
|
|
15
|
-
} from "
|
|
16
|
-
import { isSerializedSQL } from "../../runtime/types.js";
|
|
17
|
-
import { safeFetch } from "../../runtime/utils.js";
|
|
18
|
-
import { MIGRATION_VERSION } from "../consts.js";
|
|
19
|
-
import { RENAME_COLUMN_ERROR, RENAME_TABLE_ERROR } from "../errors.js";
|
|
19
|
+
} from "../queries.js";
|
|
20
20
|
import { columnSchema } from "../schemas.js";
|
|
21
21
|
import {
|
|
22
22
|
} from "../types.js";
|
|
@@ -55,8 +55,7 @@ async function getMigrationQueries({
|
|
|
55
55
|
}
|
|
56
56
|
for (const [tableName, newTable] of Object.entries(newSnapshot.schema)) {
|
|
57
57
|
const oldTable = oldSnapshot.schema[tableName];
|
|
58
|
-
if (!oldTable)
|
|
59
|
-
continue;
|
|
58
|
+
if (!oldTable) continue;
|
|
60
59
|
const addedColumns = getAdded(oldTable.columns, newTable.columns);
|
|
61
60
|
const droppedColumns = getDropped(oldTable.columns, newTable.columns);
|
|
62
61
|
const notDeprecatedDroppedColumns = Object.fromEntries(
|
|
@@ -161,16 +160,14 @@ function getChangeIndexQueries({
|
|
|
161
160
|
function getAddedTables(oldTables, newTables) {
|
|
162
161
|
const added = {};
|
|
163
162
|
for (const [key, newTable] of Object.entries(newTables.schema)) {
|
|
164
|
-
if (!(key in oldTables.schema))
|
|
165
|
-
added[key] = newTable;
|
|
163
|
+
if (!(key in oldTables.schema)) added[key] = newTable;
|
|
166
164
|
}
|
|
167
165
|
return added;
|
|
168
166
|
}
|
|
169
167
|
function getDroppedTables(oldTables, newTables) {
|
|
170
168
|
const dropped = {};
|
|
171
169
|
for (const [key, oldTable] of Object.entries(oldTables.schema)) {
|
|
172
|
-
if (!(key in newTables.schema))
|
|
173
|
-
dropped[key] = oldTable;
|
|
170
|
+
if (!(key in newTables.schema)) dropped[key] = oldTable;
|
|
174
171
|
}
|
|
175
172
|
return dropped;
|
|
176
173
|
}
|
|
@@ -222,23 +219,16 @@ function isEmpty(obj) {
|
|
|
222
219
|
return Object.keys(obj).length === 0;
|
|
223
220
|
}
|
|
224
221
|
function canAlterTableAddColumn(column) {
|
|
225
|
-
if (column.schema.unique)
|
|
226
|
-
|
|
227
|
-
if (
|
|
228
|
-
|
|
229
|
-
if (
|
|
230
|
-
return false;
|
|
231
|
-
if (hasPrimaryKey(column))
|
|
232
|
-
return false;
|
|
233
|
-
if (getReferencesConfig(column))
|
|
234
|
-
return false;
|
|
222
|
+
if (column.schema.unique) return false;
|
|
223
|
+
if (hasRuntimeDefault(column)) return false;
|
|
224
|
+
if (!column.schema.optional && !hasDefault(column)) return false;
|
|
225
|
+
if (hasPrimaryKey(column)) return false;
|
|
226
|
+
if (getReferencesConfig(column)) return false;
|
|
235
227
|
return true;
|
|
236
228
|
}
|
|
237
229
|
function canAlterTableDropColumn(column) {
|
|
238
|
-
if (column.schema.unique)
|
|
239
|
-
|
|
240
|
-
if (hasPrimaryKey(column))
|
|
241
|
-
return false;
|
|
230
|
+
if (column.schema.unique) return false;
|
|
231
|
+
if (hasPrimaryKey(column)) return false;
|
|
242
232
|
return true;
|
|
243
233
|
}
|
|
244
234
|
function canRecreateTableWithoutDataLoss(added, updated) {
|
|
@@ -260,16 +250,14 @@ function canRecreateTableWithoutDataLoss(added, updated) {
|
|
|
260
250
|
function getAdded(oldObj, newObj) {
|
|
261
251
|
const added = {};
|
|
262
252
|
for (const [key, value] of Object.entries(newObj)) {
|
|
263
|
-
if (!(key in oldObj))
|
|
264
|
-
added[key] = value;
|
|
253
|
+
if (!(key in oldObj)) added[key] = value;
|
|
265
254
|
}
|
|
266
255
|
return added;
|
|
267
256
|
}
|
|
268
257
|
function getDropped(oldObj, newObj) {
|
|
269
258
|
const dropped = {};
|
|
270
259
|
for (const [key, value] of Object.entries(oldObj)) {
|
|
271
|
-
if (!(key in newObj))
|
|
272
|
-
dropped[key] = value;
|
|
260
|
+
if (!(key in newObj)) dropped[key] = value;
|
|
273
261
|
}
|
|
274
262
|
return dropped;
|
|
275
263
|
}
|
|
@@ -277,10 +265,8 @@ function getUpdated(oldObj, newObj) {
|
|
|
277
265
|
const updated = {};
|
|
278
266
|
for (const [key, value] of Object.entries(newObj)) {
|
|
279
267
|
const oldValue = oldObj[key];
|
|
280
|
-
if (!oldValue)
|
|
281
|
-
|
|
282
|
-
if (deepDiff(oldValue, value))
|
|
283
|
-
updated[key] = value;
|
|
268
|
+
if (!oldValue) continue;
|
|
269
|
+
if (deepDiff(oldValue, value)) updated[key] = value;
|
|
284
270
|
}
|
|
285
271
|
return updated;
|
|
286
272
|
}
|
|
@@ -288,8 +274,7 @@ function getUpdatedColumns(oldColumns, newColumns) {
|
|
|
288
274
|
const updated = {};
|
|
289
275
|
for (const [key, newColumn] of Object.entries(newColumns)) {
|
|
290
276
|
let oldColumn = oldColumns[key];
|
|
291
|
-
if (!oldColumn)
|
|
292
|
-
continue;
|
|
277
|
+
if (!oldColumn) continue;
|
|
293
278
|
if (oldColumn.type !== newColumn.type && canChangeTypeWithoutQuery(oldColumn, newColumn)) {
|
|
294
279
|
const asNewColumn = columnSchema.safeParse({
|
|
295
280
|
type: newColumn.type,
|
|
@@ -52,8 +52,7 @@ const errorMap = (baseError, ctx) => {
|
|
|
52
52
|
}
|
|
53
53
|
};
|
|
54
54
|
const getTypeOrLiteralMsg = (error) => {
|
|
55
|
-
if (error.received === "undefined")
|
|
56
|
-
return "Required";
|
|
55
|
+
if (error.received === "undefined") return "Required";
|
|
57
56
|
const expectedDeduped = new Set(error.expected);
|
|
58
57
|
switch (error.code) {
|
|
59
58
|
case "invalid_type":
|
|
@@ -68,8 +67,7 @@ const getTypeOrLiteralMsg = (error) => {
|
|
|
68
67
|
};
|
|
69
68
|
const prefix = (key, msg) => key.length ? `**${key}**: ${msg}` : msg;
|
|
70
69
|
const unionExpectedVals = (expectedVals) => [...expectedVals].map((expectedVal, idx) => {
|
|
71
|
-
if (idx === 0)
|
|
72
|
-
return JSON.stringify(expectedVal);
|
|
70
|
+
if (idx === 0) return JSON.stringify(expectedVal);
|
|
73
71
|
const sep = " | ";
|
|
74
72
|
return `${sep}${JSON.stringify(expectedVal)}`;
|
|
75
73
|
}).join("");
|
|
@@ -1,25 +1,35 @@
|
|
|
1
1
|
import { existsSync } from "fs";
|
|
2
2
|
import { dirname } from "path";
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
|
+
import { LibsqlError } from "@libsql/client";
|
|
4
5
|
import { mkdir, writeFile } from "fs/promises";
|
|
5
6
|
import { blue, yellow } from "kleur/colors";
|
|
6
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
createServer,
|
|
9
|
+
loadEnv,
|
|
10
|
+
mergeConfig
|
|
11
|
+
} from "vite";
|
|
7
12
|
import parseArgs from "yargs-parser";
|
|
8
|
-
import { SEED_DEV_FILE_NAME } from "../../runtime/queries.js";
|
|
9
13
|
import { AstroDbError } from "../../runtime/utils.js";
|
|
10
14
|
import { CONFIG_FILE_NAMES, DB_PATH } from "../consts.js";
|
|
15
|
+
import { EXEC_DEFAULT_EXPORT_ERROR, EXEC_ERROR } from "../errors.js";
|
|
11
16
|
import { resolveDbConfig } from "../load-file.js";
|
|
17
|
+
import { SEED_DEV_FILE_NAME } from "../queries.js";
|
|
12
18
|
import { getManagedAppTokenOrExit } from "../tokens.js";
|
|
13
19
|
import { getDbDirectoryUrl } from "../utils.js";
|
|
14
20
|
import { fileURLIntegration } from "./file-url.js";
|
|
15
21
|
import { typegenInternal } from "./typegen.js";
|
|
16
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
resolved,
|
|
24
|
+
vitePluginDb
|
|
25
|
+
} from "./vite-plugin-db.js";
|
|
17
26
|
import { vitePluginInjectEnvTs } from "./vite-plugin-inject-env-ts.js";
|
|
18
27
|
function astroDBIntegration() {
|
|
19
28
|
let connectToStudio = false;
|
|
20
29
|
let configFileDependencies = [];
|
|
21
30
|
let root;
|
|
22
31
|
let appToken;
|
|
32
|
+
let tempViteServer;
|
|
23
33
|
let tables = {
|
|
24
34
|
get() {
|
|
25
35
|
throw new Error("[astro:db] INTERNAL Tables not loaded yet");
|
|
@@ -30,6 +40,12 @@ function astroDBIntegration() {
|
|
|
30
40
|
throw new Error("[astro:db] INTERNAL Seed files not loaded yet");
|
|
31
41
|
}
|
|
32
42
|
};
|
|
43
|
+
let seedHandler = {
|
|
44
|
+
execute: () => {
|
|
45
|
+
throw new Error("[astro:db] INTERNAL Seed handler not loaded yet");
|
|
46
|
+
},
|
|
47
|
+
inProgress: false
|
|
48
|
+
};
|
|
33
49
|
let command;
|
|
34
50
|
let output = "server";
|
|
35
51
|
return {
|
|
@@ -39,8 +55,7 @@ function astroDBIntegration() {
|
|
|
39
55
|
command = _command;
|
|
40
56
|
root = config.root;
|
|
41
57
|
output = config.output;
|
|
42
|
-
if (command === "preview")
|
|
43
|
-
return;
|
|
58
|
+
if (command === "preview") return;
|
|
44
59
|
let dbPlugin = void 0;
|
|
45
60
|
const args = parseArgs(process.argv.slice(3));
|
|
46
61
|
connectToStudio = process.env.ASTRO_INTERNAL_TEST_REMOTE || args["remote"];
|
|
@@ -52,7 +67,8 @@ function astroDBIntegration() {
|
|
|
52
67
|
tables,
|
|
53
68
|
root: config.root,
|
|
54
69
|
srcDir: config.srcDir,
|
|
55
|
-
output: config.output
|
|
70
|
+
output: config.output,
|
|
71
|
+
seedHandler
|
|
56
72
|
});
|
|
57
73
|
} else {
|
|
58
74
|
dbPlugin = vitePluginDb({
|
|
@@ -61,7 +77,9 @@ function astroDBIntegration() {
|
|
|
61
77
|
seedFiles,
|
|
62
78
|
root: config.root,
|
|
63
79
|
srcDir: config.srcDir,
|
|
64
|
-
output: config.output
|
|
80
|
+
output: config.output,
|
|
81
|
+
logger,
|
|
82
|
+
seedHandler
|
|
65
83
|
});
|
|
66
84
|
}
|
|
67
85
|
updateConfig({
|
|
@@ -72,8 +90,7 @@ function astroDBIntegration() {
|
|
|
72
90
|
});
|
|
73
91
|
},
|
|
74
92
|
"astro:config:done": async ({ config }) => {
|
|
75
|
-
if (command === "preview")
|
|
76
|
-
return;
|
|
93
|
+
if (command === "preview") return;
|
|
77
94
|
const { dbConfig, dependencies, integrationSeedPaths } = await resolveDbConfig(config);
|
|
78
95
|
tables.get = () => dbConfig.tables;
|
|
79
96
|
seedFiles.get = () => integrationSeedPaths;
|
|
@@ -86,6 +103,9 @@ function astroDBIntegration() {
|
|
|
86
103
|
await typegenInternal({ tables: tables.get() ?? {}, root: config.root });
|
|
87
104
|
},
|
|
88
105
|
"astro:server:setup": async ({ server, logger }) => {
|
|
106
|
+
seedHandler.execute = async (fileUrl) => {
|
|
107
|
+
await executeSeedFile({ fileUrl, viteServer: server });
|
|
108
|
+
};
|
|
89
109
|
const filesToWatch = [
|
|
90
110
|
...CONFIG_FILE_NAMES.map((c) => new URL(c, getDbDirectoryUrl(root))),
|
|
91
111
|
...configFileDependencies.map((c) => new URL(c, root))
|
|
@@ -100,38 +120,13 @@ function astroDBIntegration() {
|
|
|
100
120
|
logger.info(
|
|
101
121
|
connectToStudio ? "Connected to remote database." : "New local database created."
|
|
102
122
|
);
|
|
103
|
-
if (connectToStudio)
|
|
104
|
-
return;
|
|
123
|
+
if (connectToStudio) return;
|
|
105
124
|
const localSeedPaths = SEED_DEV_FILE_NAME.map(
|
|
106
125
|
(name) => new URL(name, getDbDirectoryUrl(root))
|
|
107
126
|
);
|
|
108
|
-
let seedInFlight = false;
|
|
109
127
|
if (seedFiles.get().length || localSeedPaths.find((path) => existsSync(path))) {
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
const eagerReloadIntegrationSeedPaths = seedFiles.get().map((s) => typeof s === "string" && s.startsWith(".") ? new URL(s, root) : s).filter((s) => s instanceof URL);
|
|
113
|
-
const eagerReloadSeedPaths = [...eagerReloadIntegrationSeedPaths, ...localSeedPaths];
|
|
114
|
-
server.watcher.on("all", (event, relativeEntry) => {
|
|
115
|
-
if (event === "unlink" || event === "unlinkDir")
|
|
116
|
-
return;
|
|
117
|
-
const entry = new URL(relativeEntry, root);
|
|
118
|
-
if (eagerReloadSeedPaths.find((path) => entry.href === path.href)) {
|
|
119
|
-
loadSeedModule();
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
function loadSeedModule() {
|
|
123
|
-
if (seedInFlight)
|
|
124
|
-
return;
|
|
125
|
-
seedInFlight = true;
|
|
126
|
-
const mod = server.moduleGraph.getModuleById(resolved.seedVirtual);
|
|
127
|
-
if (mod)
|
|
128
|
-
server.moduleGraph.invalidateModule(mod);
|
|
129
|
-
server.ssrLoadModule(resolved.seedVirtual).then(() => {
|
|
130
|
-
logger.info("Seeded database.");
|
|
131
|
-
}).catch((e) => {
|
|
128
|
+
server.ssrLoadModule(resolved.module).catch((e) => {
|
|
132
129
|
logger.error(e instanceof Error ? e.message : String(e));
|
|
133
|
-
}).finally(() => {
|
|
134
|
-
seedInFlight = false;
|
|
135
130
|
});
|
|
136
131
|
}
|
|
137
132
|
}, 100);
|
|
@@ -144,8 +139,15 @@ function astroDBIntegration() {
|
|
|
144
139
|
}
|
|
145
140
|
logger.info("database: " + (connectToStudio ? yellow("remote") : blue("local database.")));
|
|
146
141
|
},
|
|
142
|
+
"astro:build:setup": async ({ vite }) => {
|
|
143
|
+
tempViteServer = await getTempViteServer({ viteConfig: vite });
|
|
144
|
+
seedHandler.execute = async (fileUrl) => {
|
|
145
|
+
await executeSeedFile({ fileUrl, viteServer: tempViteServer });
|
|
146
|
+
};
|
|
147
|
+
},
|
|
147
148
|
"astro:build:done": async ({}) => {
|
|
148
149
|
await appToken?.destroy();
|
|
150
|
+
await tempViteServer?.close();
|
|
149
151
|
}
|
|
150
152
|
}
|
|
151
153
|
};
|
|
@@ -157,6 +159,41 @@ function databaseFileEnvDefined() {
|
|
|
157
159
|
function integration() {
|
|
158
160
|
return [astroDBIntegration(), fileURLIntegration()];
|
|
159
161
|
}
|
|
162
|
+
async function executeSeedFile({
|
|
163
|
+
fileUrl,
|
|
164
|
+
viteServer
|
|
165
|
+
}) {
|
|
166
|
+
const mod = await viteServer.ssrLoadModule(fileUrl.pathname);
|
|
167
|
+
if (typeof mod.default !== "function") {
|
|
168
|
+
throw new AstroDbError(EXEC_DEFAULT_EXPORT_ERROR(fileURLToPath(fileUrl)));
|
|
169
|
+
}
|
|
170
|
+
try {
|
|
171
|
+
await mod.default();
|
|
172
|
+
} catch (e) {
|
|
173
|
+
if (e instanceof LibsqlError) {
|
|
174
|
+
throw new AstroDbError(EXEC_ERROR(e.message));
|
|
175
|
+
}
|
|
176
|
+
throw e;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
async function getTempViteServer({ viteConfig }) {
|
|
180
|
+
const tempViteServer = await createServer(
|
|
181
|
+
mergeConfig(viteConfig, {
|
|
182
|
+
server: { middlewareMode: true, hmr: false, watch: null },
|
|
183
|
+
optimizeDeps: { noDiscovery: true },
|
|
184
|
+
ssr: { external: [] },
|
|
185
|
+
logLevel: "silent"
|
|
186
|
+
})
|
|
187
|
+
);
|
|
188
|
+
const hotSend = tempViteServer.hot.send;
|
|
189
|
+
tempViteServer.hot.send = (payload) => {
|
|
190
|
+
if (payload.type === "error") {
|
|
191
|
+
throw payload.err;
|
|
192
|
+
}
|
|
193
|
+
return hotSend(payload);
|
|
194
|
+
};
|
|
195
|
+
return tempViteServer;
|
|
196
|
+
}
|
|
160
197
|
export {
|
|
161
198
|
integration
|
|
162
199
|
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { AstroConfig } from 'astro';
|
|
1
|
+
import type { AstroConfig, AstroIntegrationLogger } from 'astro';
|
|
2
2
|
import type { DBTables } from '../types.js';
|
|
3
3
|
import { type VitePlugin } from '../utils.js';
|
|
4
4
|
export declare const resolved: {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
module: string;
|
|
6
|
+
importedFromSeedFile: string;
|
|
7
7
|
};
|
|
8
8
|
export type LateTables = {
|
|
9
9
|
get: () => DBTables;
|
|
@@ -11,13 +11,19 @@ export type LateTables = {
|
|
|
11
11
|
export type LateSeedFiles = {
|
|
12
12
|
get: () => Array<string | URL>;
|
|
13
13
|
};
|
|
14
|
+
export type SeedHandler = {
|
|
15
|
+
inProgress: boolean;
|
|
16
|
+
execute: (fileUrl: URL) => Promise<void>;
|
|
17
|
+
};
|
|
14
18
|
type VitePluginDBParams = {
|
|
15
19
|
connectToStudio: false;
|
|
16
20
|
tables: LateTables;
|
|
17
21
|
seedFiles: LateSeedFiles;
|
|
18
22
|
srcDir: URL;
|
|
19
23
|
root: URL;
|
|
24
|
+
logger?: AstroIntegrationLogger;
|
|
20
25
|
output: AstroConfig['output'];
|
|
26
|
+
seedHandler: SeedHandler;
|
|
21
27
|
} | {
|
|
22
28
|
connectToStudio: true;
|
|
23
29
|
tables: LateTables;
|
|
@@ -25,14 +31,13 @@ type VitePluginDBParams = {
|
|
|
25
31
|
srcDir: URL;
|
|
26
32
|
root: URL;
|
|
27
33
|
output: AstroConfig['output'];
|
|
34
|
+
seedHandler: SeedHandler;
|
|
28
35
|
};
|
|
29
36
|
export declare function vitePluginDb(params: VitePluginDBParams): VitePlugin;
|
|
30
37
|
export declare function getConfigVirtualModContents(): string;
|
|
31
|
-
export declare function getLocalVirtualModContents({ tables, root,
|
|
38
|
+
export declare function getLocalVirtualModContents({ tables, root, }: {
|
|
32
39
|
tables: DBTables;
|
|
33
|
-
seedFiles: Array<string | URL>;
|
|
34
40
|
root: URL;
|
|
35
|
-
shouldSeed: boolean;
|
|
36
41
|
}): string;
|
|
37
42
|
export declare function getStudioVirtualModContents({ tables, appToken, isBuild, output, }: {
|
|
38
43
|
tables: DBTables;
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
1
2
|
import { fileURLToPath } from "node:url";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
3
|
+
import { sql } from "drizzle-orm";
|
|
4
|
+
import { SQLiteAsyncDialect } from "drizzle-orm/sqlite-core";
|
|
5
|
+
import { createLocalDatabaseClient } from "../../runtime/db-client.js";
|
|
6
|
+
import { normalizeDatabaseUrl } from "../../runtime/index.js";
|
|
4
7
|
import { DB_PATH, RUNTIME_IMPORT, RUNTIME_VIRTUAL_IMPORT, VIRTUAL_MODULE_ID } from "../consts.js";
|
|
5
|
-
import {
|
|
6
|
-
|
|
8
|
+
import { getResolvedFileUrl } from "../load-file.js";
|
|
9
|
+
import { SEED_DEV_FILE_NAME, getCreateIndexQueries, getCreateTableQuery } from "../queries.js";
|
|
10
|
+
import { getAstroEnv, getDbDirectoryUrl, getRemoteDatabaseUrl } from "../utils.js";
|
|
7
11
|
const resolved = {
|
|
8
|
-
|
|
9
|
-
|
|
12
|
+
module: "\0" + VIRTUAL_MODULE_ID,
|
|
13
|
+
importedFromSeedFile: "\0" + VIRTUAL_MODULE_ID + ":seed"
|
|
10
14
|
};
|
|
11
15
|
function vitePluginDb(params) {
|
|
12
|
-
const srcDirPath = normalizePath(fileURLToPath(params.srcDir));
|
|
13
|
-
const dbDirPath = normalizePath(fileURLToPath(getDbDirectoryUrl(params.root)));
|
|
14
16
|
let command = "build";
|
|
15
17
|
return {
|
|
16
18
|
name: "astro:db",
|
|
@@ -18,22 +20,15 @@ function vitePluginDb(params) {
|
|
|
18
20
|
configResolved(resolvedConfig) {
|
|
19
21
|
command = resolvedConfig.command;
|
|
20
22
|
},
|
|
21
|
-
async resolveId(id
|
|
22
|
-
if (id !== VIRTUAL_MODULE_ID)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return resolved.virtual;
|
|
26
|
-
const importer = rawImporter ? await this.resolve(rawImporter) : null;
|
|
27
|
-
if (!importer)
|
|
28
|
-
return resolved.virtual;
|
|
29
|
-
if (importer.id.startsWith(srcDirPath) && !importer.id.startsWith(dbDirPath)) {
|
|
30
|
-
return resolved.seedVirtual;
|
|
23
|
+
async resolveId(id) {
|
|
24
|
+
if (id !== VIRTUAL_MODULE_ID) return;
|
|
25
|
+
if (params.seedHandler.inProgress) {
|
|
26
|
+
return resolved.importedFromSeedFile;
|
|
31
27
|
}
|
|
32
|
-
return resolved.
|
|
28
|
+
return resolved.module;
|
|
33
29
|
},
|
|
34
30
|
async load(id) {
|
|
35
|
-
if (id !== resolved.
|
|
36
|
-
return;
|
|
31
|
+
if (id !== resolved.module && id !== resolved.importedFromSeedFile) return;
|
|
37
32
|
if (params.connectToStudio) {
|
|
38
33
|
return getStudioVirtualModContents({
|
|
39
34
|
appToken: params.appToken,
|
|
@@ -42,11 +37,28 @@ function vitePluginDb(params) {
|
|
|
42
37
|
output: params.output
|
|
43
38
|
});
|
|
44
39
|
}
|
|
40
|
+
if (id === resolved.importedFromSeedFile) {
|
|
41
|
+
return getLocalVirtualModContents({
|
|
42
|
+
root: params.root,
|
|
43
|
+
tables: params.tables.get()
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
await recreateTables(params);
|
|
47
|
+
const seedFiles = getResolvedSeedFiles(params);
|
|
48
|
+
for await (const seedFile of seedFiles) {
|
|
49
|
+
this.addWatchFile(fileURLToPath(seedFile));
|
|
50
|
+
if (existsSync(seedFile)) {
|
|
51
|
+
params.seedHandler.inProgress = true;
|
|
52
|
+
await params.seedHandler.execute(seedFile);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (params.seedHandler.inProgress) {
|
|
56
|
+
(params.logger ?? console).info("Seeded database.");
|
|
57
|
+
params.seedHandler.inProgress = false;
|
|
58
|
+
}
|
|
45
59
|
return getLocalVirtualModContents({
|
|
46
60
|
root: params.root,
|
|
47
|
-
tables: params.tables.get()
|
|
48
|
-
seedFiles: params.seedFiles.get(),
|
|
49
|
-
shouldSeed: id === resolved.seedVirtual
|
|
61
|
+
tables: params.tables.get()
|
|
50
62
|
});
|
|
51
63
|
}
|
|
52
64
|
};
|
|
@@ -56,40 +68,15 @@ function getConfigVirtualModContents() {
|
|
|
56
68
|
}
|
|
57
69
|
function getLocalVirtualModContents({
|
|
58
70
|
tables,
|
|
59
|
-
root
|
|
60
|
-
seedFiles,
|
|
61
|
-
shouldSeed
|
|
71
|
+
root
|
|
62
72
|
}) {
|
|
63
|
-
const userSeedFilePaths = SEED_DEV_FILE_NAME.map(
|
|
64
|
-
// Format as /db/[name].ts
|
|
65
|
-
// for Vite import.meta.glob
|
|
66
|
-
(name) => new URL(name, getDbDirectoryUrl("file:///")).pathname
|
|
67
|
-
);
|
|
68
|
-
const resolveId = (id) => id.startsWith(".") ? normalizePath(fileURLToPath(new URL(id, root))) : id;
|
|
69
|
-
const integrationSeedImportStatements = [];
|
|
70
|
-
const integrationSeedImportNames = [];
|
|
71
|
-
seedFiles.forEach((pathOrUrl, index) => {
|
|
72
|
-
const path = typeof pathOrUrl === "string" ? resolveId(pathOrUrl) : pathOrUrl.pathname;
|
|
73
|
-
const importName = "integration_seed_" + index;
|
|
74
|
-
integrationSeedImportStatements.push(`import ${importName} from ${JSON.stringify(path)};`);
|
|
75
|
-
integrationSeedImportNames.push(importName);
|
|
76
|
-
});
|
|
77
73
|
const dbUrl = new URL(DB_PATH, root);
|
|
78
74
|
return `
|
|
79
75
|
import { asDrizzleTable, createLocalDatabaseClient, normalizeDatabaseUrl } from ${RUNTIME_IMPORT};
|
|
80
|
-
${shouldSeed ? `import { seedLocal } from ${RUNTIME_IMPORT};` : ""}
|
|
81
|
-
${shouldSeed ? integrationSeedImportStatements.join("\n") : ""}
|
|
82
76
|
|
|
83
77
|
const dbUrl = normalizeDatabaseUrl(import.meta.env.ASTRO_DATABASE_FILE, ${JSON.stringify(dbUrl)});
|
|
84
78
|
export const db = createLocalDatabaseClient({ dbUrl });
|
|
85
79
|
|
|
86
|
-
${shouldSeed ? `await seedLocal({
|
|
87
|
-
db,
|
|
88
|
-
tables: ${JSON.stringify(tables)},
|
|
89
|
-
userSeedGlob: import.meta.glob(${JSON.stringify(userSeedFilePaths)}, { eager: true }),
|
|
90
|
-
integrationSeedFunctions: [${integrationSeedImportNames.join(",")}],
|
|
91
|
-
});` : ""}
|
|
92
|
-
|
|
93
80
|
export * from ${RUNTIME_VIRTUAL_IMPORT};
|
|
94
81
|
|
|
95
82
|
${getStringifiedTableExports(tables)}`;
|
|
@@ -132,6 +119,31 @@ function getStringifiedTableExports(tables) {
|
|
|
132
119
|
)}, false)`
|
|
133
120
|
).join("\n");
|
|
134
121
|
}
|
|
122
|
+
const sqlite = new SQLiteAsyncDialect();
|
|
123
|
+
async function recreateTables({ tables, root }) {
|
|
124
|
+
const { ASTRO_DATABASE_FILE } = getAstroEnv();
|
|
125
|
+
const dbUrl = normalizeDatabaseUrl(ASTRO_DATABASE_FILE, new URL(DB_PATH, root).href);
|
|
126
|
+
const db = createLocalDatabaseClient({ dbUrl });
|
|
127
|
+
const setupQueries = [];
|
|
128
|
+
for (const [name, table] of Object.entries(tables.get() ?? {})) {
|
|
129
|
+
const dropQuery = sql.raw(`DROP TABLE IF EXISTS ${sqlite.escapeName(name)}`);
|
|
130
|
+
const createQuery = sql.raw(getCreateTableQuery(name, table));
|
|
131
|
+
const indexQueries = getCreateIndexQueries(name, table);
|
|
132
|
+
setupQueries.push(dropQuery, createQuery, ...indexQueries.map((s) => sql.raw(s)));
|
|
133
|
+
}
|
|
134
|
+
await db.batch([
|
|
135
|
+
db.run(sql`pragma defer_foreign_keys=true;`),
|
|
136
|
+
...setupQueries.map((q) => db.run(q))
|
|
137
|
+
]);
|
|
138
|
+
}
|
|
139
|
+
function getResolvedSeedFiles({
|
|
140
|
+
root,
|
|
141
|
+
seedFiles
|
|
142
|
+
}) {
|
|
143
|
+
const localSeedFiles = SEED_DEV_FILE_NAME.map((name) => new URL(name, getDbDirectoryUrl(root)));
|
|
144
|
+
const integrationSeedFiles = seedFiles.get().map((s) => getResolvedFileUrl(root, s));
|
|
145
|
+
return [...integrationSeedFiles, ...localSeedFiles];
|
|
146
|
+
}
|
|
135
147
|
export {
|
|
136
148
|
getConfigVirtualModContents,
|
|
137
149
|
getLocalVirtualModContents,
|
|
@@ -26,8 +26,7 @@ async function setUpEnvTs({
|
|
|
26
26
|
if (existsSync(envTsPath)) {
|
|
27
27
|
let typesEnvContents = await readFile(envTsPath, "utf-8");
|
|
28
28
|
const dotAstroDir = new URL(".astro/", root);
|
|
29
|
-
if (!existsSync(dotAstroDir))
|
|
30
|
-
return;
|
|
29
|
+
if (!existsSync(dotAstroDir)) return;
|
|
31
30
|
const dbTypeReference = getDBTypeReference({ srcDir, dotAstroDir });
|
|
32
31
|
if (!typesEnvContents.includes(dbTypeReference)) {
|
|
33
32
|
typesEnvContents = `${dbTypeReference}
|
package/dist/core/load-file.d.ts
CHANGED
|
@@ -172,6 +172,7 @@ export declare function resolveDbConfig({ root, integrations, }: Pick<AstroConfi
|
|
|
172
172
|
/** Additional `astro:db` seed file paths provided by integrations. */
|
|
173
173
|
integrationSeedPaths: (string | URL)[];
|
|
174
174
|
}>;
|
|
175
|
+
export declare function getResolvedFileUrl(root: URL, filePathOrUrl: string | URL): URL;
|
|
175
176
|
/**
|
|
176
177
|
* Bundle arbitrary `mjs` or `ts` file.
|
|
177
178
|
* Simplified fork from Vite's `bundleConfigFile` function.
|
package/dist/core/load-file.js
CHANGED
|
@@ -9,7 +9,7 @@ import { errorMap } from "./integration/error-map.js";
|
|
|
9
9
|
import { getConfigVirtualModContents } from "./integration/vite-plugin-db.js";
|
|
10
10
|
import { dbConfigSchema } from "./schemas.js";
|
|
11
11
|
import {} from "./types.js";
|
|
12
|
-
import { getDbDirectoryUrl } from "./utils.js";
|
|
12
|
+
import { getAstroEnv, getDbDirectoryUrl } from "./utils.js";
|
|
13
13
|
const isDbIntegration = (integration) => "astro:db:setup" in integration.hooks;
|
|
14
14
|
async function resolveDbConfig({
|
|
15
15
|
root,
|
|
@@ -21,8 +21,7 @@ async function resolveDbConfig({
|
|
|
21
21
|
const integrationDbConfigPaths = [];
|
|
22
22
|
const integrationSeedPaths = [];
|
|
23
23
|
for (const integration of integrations) {
|
|
24
|
-
if (!isDbIntegration(integration))
|
|
25
|
-
continue;
|
|
24
|
+
if (!isDbIntegration(integration)) continue;
|
|
26
25
|
const { name, hooks } = integration;
|
|
27
26
|
if (hooks["astro:db:setup"]) {
|
|
28
27
|
hooks["astro:db:setup"]({
|
|
@@ -70,15 +69,16 @@ async function loadUserConfigFile(root) {
|
|
|
70
69
|
}
|
|
71
70
|
return await loadAndBundleDbConfigFile({ root, fileUrl: configFileUrl });
|
|
72
71
|
}
|
|
73
|
-
|
|
74
|
-
let fileUrl;
|
|
72
|
+
function getResolvedFileUrl(root, filePathOrUrl) {
|
|
75
73
|
if (typeof filePathOrUrl === "string") {
|
|
76
74
|
const { resolve } = createRequire(root);
|
|
77
75
|
const resolvedFilePath = resolve(filePathOrUrl);
|
|
78
|
-
|
|
79
|
-
} else {
|
|
80
|
-
fileUrl = filePathOrUrl;
|
|
76
|
+
return pathToFileURL(resolvedFilePath);
|
|
81
77
|
}
|
|
78
|
+
return filePathOrUrl;
|
|
79
|
+
}
|
|
80
|
+
async function loadIntegrationConfigFile(root, filePathOrUrl) {
|
|
81
|
+
const fileUrl = getResolvedFileUrl(root, filePathOrUrl);
|
|
82
82
|
return await loadAndBundleDbConfigFile({ root, fileUrl });
|
|
83
83
|
}
|
|
84
84
|
async function loadAndBundleDbConfigFile({
|
|
@@ -103,6 +103,7 @@ async function bundleFile({
|
|
|
103
103
|
root,
|
|
104
104
|
virtualModContents
|
|
105
105
|
}) {
|
|
106
|
+
const { ASTRO_DATABASE_FILE } = getAstroEnv();
|
|
106
107
|
const result = await esbuild({
|
|
107
108
|
absWorkingDir: process.cwd(),
|
|
108
109
|
entryPoints: [fileURLToPath(fileUrl)],
|
|
@@ -116,7 +117,8 @@ async function bundleFile({
|
|
|
116
117
|
sourcemap: "inline",
|
|
117
118
|
metafile: true,
|
|
118
119
|
define: {
|
|
119
|
-
"import.meta.env.ASTRO_STUDIO_REMOTE_DB_URL": "undefined"
|
|
120
|
+
"import.meta.env.ASTRO_STUDIO_REMOTE_DB_URL": "undefined",
|
|
121
|
+
"import.meta.env.ASTRO_DATABASE_FILE": JSON.stringify(ASTRO_DATABASE_FILE ?? "")
|
|
120
122
|
},
|
|
121
123
|
plugins: [
|
|
122
124
|
{
|
|
@@ -165,6 +167,7 @@ async function importBundledFile({
|
|
|
165
167
|
}
|
|
166
168
|
export {
|
|
167
169
|
bundleFile,
|
|
170
|
+
getResolvedFileUrl,
|
|
168
171
|
importBundledFile,
|
|
169
172
|
resolveDbConfig
|
|
170
173
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BooleanColumn, ColumnType, DBColumn, DBTable, DateColumn, JsonColumn, NumberColumn, TextColumn } from '
|
|
1
|
+
import type { BooleanColumn, ColumnType, DBColumn, DBTable, DateColumn, JsonColumn, NumberColumn, TextColumn } from './types.js';
|
|
2
2
|
export declare const SEED_DEV_FILE_NAME: string[];
|
|
3
3
|
export declare function getDropTableIfExistsQuery(tableName: string): string;
|
|
4
4
|
export declare function getCreateTableQuery(tableName: string, table: DBTable): string;
|
|
@@ -17,7 +17,7 @@ export declare function getReferencesConfig(column: DBColumn): {
|
|
|
17
17
|
} & ({
|
|
18
18
|
optional: boolean;
|
|
19
19
|
primaryKey: false;
|
|
20
|
-
default?: number | import("
|
|
20
|
+
default?: number | import("../runtime/types.js").SerializedSQL | undefined;
|
|
21
21
|
} | {
|
|
22
22
|
primaryKey: true;
|
|
23
23
|
optional?: false | undefined;
|
|
@@ -33,7 +33,7 @@ export declare function getReferencesConfig(column: DBColumn): {
|
|
|
33
33
|
name?: string | undefined;
|
|
34
34
|
label?: string | undefined;
|
|
35
35
|
collection?: string | undefined;
|
|
36
|
-
default?: string | import("
|
|
36
|
+
default?: string | import("../runtime/types.js").SerializedSQL | undefined;
|
|
37
37
|
multiline?: boolean | undefined;
|
|
38
38
|
} & ({
|
|
39
39
|
optional: boolean;
|
|
@@ -6,9 +6,9 @@ import {
|
|
|
6
6
|
FOREIGN_KEY_REFERENCES_EMPTY_ERROR,
|
|
7
7
|
FOREIGN_KEY_REFERENCES_LENGTH_ERROR,
|
|
8
8
|
REFERENCE_DNE_ERROR
|
|
9
|
-
} from "
|
|
10
|
-
import { hasPrimaryKey } from "
|
|
11
|
-
import { isSerializedSQL } from "
|
|
9
|
+
} from "../runtime/errors.js";
|
|
10
|
+
import { hasPrimaryKey } from "../runtime/index.js";
|
|
11
|
+
import { isSerializedSQL } from "../runtime/types.js";
|
|
12
12
|
const sqlite = new SQLiteAsyncDialect();
|
|
13
13
|
const SEED_DEV_FILE_NAME = ["seed.ts", "seed.js", "seed.mjs", "seed.mts"];
|
|
14
14
|
function getDropTableIfExistsQuery(tableName) {
|
|
@@ -107,8 +107,7 @@ function getModifiers(columnName, column) {
|
|
|
107
107
|
}
|
|
108
108
|
function getReferencesConfig(column) {
|
|
109
109
|
const canHaveReferences = column.type === "number" || column.type === "text";
|
|
110
|
-
if (!canHaveReferences)
|
|
111
|
-
return void 0;
|
|
110
|
+
if (!canHaveReferences) return void 0;
|
|
112
111
|
return column.schema.references;
|
|
113
112
|
}
|
|
114
113
|
function hasDefault(column) {
|
package/dist/core/utils.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { AstroConfig, AstroIntegration } from 'astro';
|
|
|
2
2
|
import type { AstroDbIntegration } from './types.js';
|
|
3
3
|
export type VitePlugin = Required<AstroConfig['vite']>['plugins'][number];
|
|
4
4
|
export declare function getAstroStudioEnv(envMode?: string): Record<`ASTRO_STUDIO_${string}`, string>;
|
|
5
|
+
export declare function getAstroEnv(envMode?: string): Record<`ASTRO_${string}`, string>;
|
|
5
6
|
export declare function getRemoteDatabaseUrl(): string;
|
|
6
7
|
export declare function getAstroStudioUrl(): string;
|
|
7
8
|
export declare function getDbDirectoryUrl(root: URL | string): URL;
|
package/dist/core/utils.js
CHANGED
|
@@ -3,6 +3,10 @@ function getAstroStudioEnv(envMode = "") {
|
|
|
3
3
|
const env = loadEnv(envMode, process.cwd(), "ASTRO_STUDIO_");
|
|
4
4
|
return env;
|
|
5
5
|
}
|
|
6
|
+
function getAstroEnv(envMode = "") {
|
|
7
|
+
const env = loadEnv(envMode, process.cwd(), "ASTRO_");
|
|
8
|
+
return env;
|
|
9
|
+
}
|
|
6
10
|
function getRemoteDatabaseUrl() {
|
|
7
11
|
const env = getAstroStudioEnv();
|
|
8
12
|
return env.ASTRO_STUDIO_REMOTE_DB_URL || "https://db.services.astro.build";
|
|
@@ -24,6 +28,7 @@ function mapObject(item, callback) {
|
|
|
24
28
|
}
|
|
25
29
|
export {
|
|
26
30
|
defineDbIntegration,
|
|
31
|
+
getAstroEnv,
|
|
27
32
|
getAstroStudioEnv,
|
|
28
33
|
getAstroStudioUrl,
|
|
29
34
|
getDbDirectoryUrl,
|
|
@@ -56,8 +56,7 @@ function createRemoteDatabaseClient(appToken, remoteDbURL) {
|
|
|
56
56
|
} catch (e) {
|
|
57
57
|
throw new AstroDbError(await getUnexpectedResponseMessage(res));
|
|
58
58
|
}
|
|
59
|
-
if (method === "run")
|
|
60
|
-
return remoteResult;
|
|
59
|
+
if (method === "run") return remoteResult;
|
|
61
60
|
const rowValues = [];
|
|
62
61
|
for (const row of remoteResult.rows) {
|
|
63
62
|
if (row != null && typeof row === "object") {
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { type ColumnDataType } from 'drizzle-orm';
|
|
|
2
2
|
import type { DBColumn, DBTable } from '../core/types.js';
|
|
3
3
|
export type { Table } from './types.js';
|
|
4
4
|
export { createRemoteDatabaseClient, createLocalDatabaseClient } from './db-client.js';
|
|
5
|
-
export { seedLocal } from './seed-local.js';
|
|
6
5
|
export declare function hasPrimaryKey(column: DBColumn): boolean;
|
|
7
6
|
export declare function asDrizzleTable(name: string, table: DBTable): import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
|
|
8
7
|
name: string;
|
package/dist/runtime/index.js
CHANGED
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
import { isSerializedSQL } from "./types.js";
|
|
10
10
|
import { pathToFileURL } from "./utils.js";
|
|
11
11
|
import { createRemoteDatabaseClient, createLocalDatabaseClient } from "./db-client.js";
|
|
12
|
-
import { seedLocal } from "./seed-local.js";
|
|
13
12
|
function hasPrimaryKey(column) {
|
|
14
13
|
return "primaryKey" in column.schema && !!column.schema.primaryKey;
|
|
15
14
|
}
|
|
15
|
+
const isISODateString = (str) => /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/.test(str);
|
|
16
16
|
const dateType = customType({
|
|
17
17
|
dataType() {
|
|
18
18
|
return "text";
|
|
@@ -21,6 +21,9 @@ const dateType = customType({
|
|
|
21
21
|
return value.toISOString();
|
|
22
22
|
},
|
|
23
23
|
fromDriver(value) {
|
|
24
|
+
if (!isISODateString(value)) {
|
|
25
|
+
value += "Z";
|
|
26
|
+
}
|
|
24
27
|
return new Date(value);
|
|
25
28
|
}
|
|
26
29
|
});
|
|
@@ -48,8 +51,7 @@ function asDrizzleTable(name, table) {
|
|
|
48
51
|
for (const [indexName, indexProps] of Object.entries(table.indexes ?? {})) {
|
|
49
52
|
const onColNames = Array.isArray(indexProps.on) ? indexProps.on : [indexProps.on];
|
|
50
53
|
const onCols = onColNames.map((colName) => ormTable[colName]);
|
|
51
|
-
if (!atLeastOne(onCols))
|
|
52
|
-
continue;
|
|
54
|
+
if (!atLeastOne(onCols)) continue;
|
|
53
55
|
indexes[indexName] = index(indexName).on(...onCols);
|
|
54
56
|
}
|
|
55
57
|
return indexes;
|
|
@@ -66,16 +68,14 @@ function columnMapper(columnName, column) {
|
|
|
66
68
|
c = text(columnName);
|
|
67
69
|
if (column.schema.default !== void 0)
|
|
68
70
|
c = c.default(handleSerializedSQL(column.schema.default));
|
|
69
|
-
if (column.schema.primaryKey === true)
|
|
70
|
-
c = c.primaryKey();
|
|
71
|
+
if (column.schema.primaryKey === true) c = c.primaryKey();
|
|
71
72
|
break;
|
|
72
73
|
}
|
|
73
74
|
case "number": {
|
|
74
75
|
c = integer(columnName);
|
|
75
76
|
if (column.schema.default !== void 0)
|
|
76
77
|
c = c.default(handleSerializedSQL(column.schema.default));
|
|
77
|
-
if (column.schema.primaryKey === true)
|
|
78
|
-
c = c.primaryKey();
|
|
78
|
+
if (column.schema.primaryKey === true) c = c.primaryKey();
|
|
79
79
|
break;
|
|
80
80
|
}
|
|
81
81
|
case "boolean": {
|
|
@@ -86,8 +86,7 @@ function columnMapper(columnName, column) {
|
|
|
86
86
|
}
|
|
87
87
|
case "json":
|
|
88
88
|
c = jsonType(columnName);
|
|
89
|
-
if (column.schema.default !== void 0)
|
|
90
|
-
c = c.default(column.schema.default);
|
|
89
|
+
if (column.schema.default !== void 0) c = c.default(column.schema.default);
|
|
91
90
|
break;
|
|
92
91
|
case "date": {
|
|
93
92
|
c = dateType(columnName);
|
|
@@ -98,10 +97,8 @@ function columnMapper(columnName, column) {
|
|
|
98
97
|
break;
|
|
99
98
|
}
|
|
100
99
|
}
|
|
101
|
-
if (!column.schema.optional)
|
|
102
|
-
|
|
103
|
-
if (column.schema.unique)
|
|
104
|
-
c = c.unique();
|
|
100
|
+
if (!column.schema.optional) c = c.notNull();
|
|
101
|
+
if (column.schema.unique) c = c.unique();
|
|
105
102
|
return c;
|
|
106
103
|
}
|
|
107
104
|
function handleSerializedSQL(def) {
|
|
@@ -125,6 +122,5 @@ export {
|
|
|
125
122
|
createLocalDatabaseClient,
|
|
126
123
|
createRemoteDatabaseClient,
|
|
127
124
|
hasPrimaryKey,
|
|
128
|
-
normalizeDatabaseUrl
|
|
129
|
-
seedLocal
|
|
125
|
+
normalizeDatabaseUrl
|
|
130
126
|
};
|
package/dist/runtime/utils.d.ts
CHANGED
package/dist/runtime/utils.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrojs/db",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "Add libSQL and Astro Studio support to your Astro site",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"async-listen": "^3.0.1",
|
|
67
67
|
"ci-info": "^4.0.0",
|
|
68
68
|
"deep-diff": "^1.0.2",
|
|
69
|
-
"drizzle-orm": "^0.30.
|
|
69
|
+
"drizzle-orm": "^0.30.10",
|
|
70
70
|
"github-slugger": "^2.0.0",
|
|
71
71
|
"kleur": "^4.1.5",
|
|
72
72
|
"nanoid": "^5.0.7",
|
|
@@ -75,12 +75,12 @@
|
|
|
75
75
|
"prompts": "^2.4.2",
|
|
76
76
|
"strip-ansi": "^7.1.0",
|
|
77
77
|
"yargs-parser": "^21.1.1",
|
|
78
|
-
"zod": "^3.23.
|
|
78
|
+
"zod": "^3.23.8"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
|
-
"@types/chai": "^4.3.
|
|
81
|
+
"@types/chai": "^4.3.16",
|
|
82
82
|
"@types/deep-diff": "^1.0.5",
|
|
83
|
-
"@types/diff": "^5.2.
|
|
83
|
+
"@types/diff": "^5.2.1",
|
|
84
84
|
"@types/mocha": "^10.0.6",
|
|
85
85
|
"@types/prompts": "^2.4.9",
|
|
86
86
|
"@types/yargs-parser": "^21.0.3",
|
|
@@ -88,8 +88,8 @@
|
|
|
88
88
|
"cheerio": "1.0.0-rc.12",
|
|
89
89
|
"mocha": "^10.4.0",
|
|
90
90
|
"typescript": "^5.4.5",
|
|
91
|
-
"vite": "^5.2.
|
|
92
|
-
"astro": "4.
|
|
91
|
+
"vite": "^5.2.11",
|
|
92
|
+
"astro": "4.8.0",
|
|
93
93
|
"astro-scripts": "0.0.14"
|
|
94
94
|
},
|
|
95
95
|
"scripts": {
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { LibSQLDatabase } from 'drizzle-orm/libsql';
|
|
2
|
-
import { type DBTables } from '../core/types.js';
|
|
3
|
-
export declare function seedLocal({ db, tables, userSeedGlob, integrationSeedFunctions, }: {
|
|
4
|
-
db: LibSQLDatabase;
|
|
5
|
-
tables: DBTables;
|
|
6
|
-
userSeedGlob: Record<string, {
|
|
7
|
-
default?: () => Promise<void>;
|
|
8
|
-
}>;
|
|
9
|
-
integrationSeedFunctions: Array<() => Promise<void>>;
|
|
10
|
-
}): Promise<void>;
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { LibsqlError } from "@libsql/client";
|
|
2
|
-
import { sql } from "drizzle-orm";
|
|
3
|
-
import { SQLiteAsyncDialect } from "drizzle-orm/sqlite-core";
|
|
4
|
-
import {} from "../core/types.js";
|
|
5
|
-
import { SEED_DEFAULT_EXPORT_ERROR } from "./errors.js";
|
|
6
|
-
import { getCreateIndexQueries, getCreateTableQuery } from "./queries.js";
|
|
7
|
-
import { AstroDbError } from "./utils.js";
|
|
8
|
-
const sqlite = new SQLiteAsyncDialect();
|
|
9
|
-
async function seedLocal({
|
|
10
|
-
db,
|
|
11
|
-
tables,
|
|
12
|
-
// Glob all potential seed files to catch renames and deletions.
|
|
13
|
-
userSeedGlob,
|
|
14
|
-
integrationSeedFunctions
|
|
15
|
-
}) {
|
|
16
|
-
await recreateTables({ db, tables });
|
|
17
|
-
const seedFunctions = [];
|
|
18
|
-
const seedFilePath = Object.keys(userSeedGlob)[0];
|
|
19
|
-
if (seedFilePath) {
|
|
20
|
-
const mod = userSeedGlob[seedFilePath];
|
|
21
|
-
if (!mod.default)
|
|
22
|
-
throw new AstroDbError(SEED_DEFAULT_EXPORT_ERROR(seedFilePath));
|
|
23
|
-
seedFunctions.push(mod.default);
|
|
24
|
-
}
|
|
25
|
-
for (const seedFn of integrationSeedFunctions) {
|
|
26
|
-
seedFunctions.push(seedFn);
|
|
27
|
-
}
|
|
28
|
-
for (const seed of seedFunctions) {
|
|
29
|
-
try {
|
|
30
|
-
await seed();
|
|
31
|
-
} catch (e) {
|
|
32
|
-
if (e instanceof LibsqlError) {
|
|
33
|
-
throw new AstroDbError(`Failed to seed database:
|
|
34
|
-
${e.message}`);
|
|
35
|
-
}
|
|
36
|
-
throw e;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
async function recreateTables({ db, tables }) {
|
|
41
|
-
const setupQueries = [];
|
|
42
|
-
for (const [name, table] of Object.entries(tables)) {
|
|
43
|
-
const dropQuery = sql.raw(`DROP TABLE IF EXISTS ${sqlite.escapeName(name)}`);
|
|
44
|
-
const createQuery = sql.raw(getCreateTableQuery(name, table));
|
|
45
|
-
const indexQueries = getCreateIndexQueries(name, table);
|
|
46
|
-
setupQueries.push(dropQuery, createQuery, ...indexQueries.map((s) => sql.raw(s)));
|
|
47
|
-
}
|
|
48
|
-
await db.batch([
|
|
49
|
-
db.run(sql`pragma defer_foreign_keys=true;`),
|
|
50
|
-
...setupQueries.map((q) => db.run(q))
|
|
51
|
-
]);
|
|
52
|
-
}
|
|
53
|
-
export {
|
|
54
|
-
seedLocal
|
|
55
|
-
};
|