@astrojs/db 0.3.2 → 0.3.3

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.
@@ -1,4 +1,5 @@
1
1
  import { mkdir, writeFile } from "node:fs/promises";
2
+ import { red } from "kleur/colors";
2
3
  import prompts from "prompts";
3
4
  import { PROJECT_ID_FILE, getSessionIdFromFile } from "../../../tokens.js";
4
5
  import { getAstroStudioUrl } from "../../../utils.js";
@@ -25,6 +26,12 @@ async function cmd({ flags }) {
25
26
  body: JSON.stringify(body)
26
27
  });
27
28
  if (!response.ok) {
29
+ if (response.status === 401) {
30
+ console.error(`${red("Unauthorized")}.
31
+
32
+ Are you logged in? Run \`astro db login\` to authenticate and then try linking again.`);
33
+ process.exit(1);
34
+ }
28
35
  console.error(`Failed to link project: ${response.status} ${response.statusText}`);
29
36
  process.exit(1);
30
37
  }
@@ -1,8 +1,10 @@
1
1
  import { createClient } from "@libsql/client";
2
- import { drizzle } from "drizzle-orm/sqlite-proxy";
2
+ import { drizzle as drizzleProxy } from "drizzle-orm/sqlite-proxy";
3
+ import { drizzle as drizzleLibsql } from "drizzle-orm/libsql";
4
+ import { SQLiteAsyncDialect } from "drizzle-orm/sqlite-core";
3
5
  import { red } from "kleur/colors";
4
6
  import prompts from "prompts";
5
- import { setupDbTables } from "../../../queries.js";
7
+ import { recreateTables, seedData } from "../../../queries.js";
6
8
  import { getManagedAppTokenOrExit } from "../../../tokens.js";
7
9
  import { collectionsSchema } from "../../../types.js";
8
10
  import { getRemoteDatabaseUrl } from "../../../utils.js";
@@ -99,6 +101,7 @@ async function pushSchema({
99
101
  }, initialMigrationBatch);
100
102
  await runMigrateQuery({ queries, migrations, snapshot: currentSnapshot, appToken, isDryRun });
101
103
  }
104
+ const sqlite = new SQLiteAsyncDialect();
102
105
  async function pushData({
103
106
  config,
104
107
  appToken,
@@ -107,7 +110,19 @@ async function pushData({
107
110
  const queries = [];
108
111
  if (config.db?.data) {
109
112
  const libsqlClient = createClient({ url: ":memory:" });
110
- const db = await drizzle(async (sqlQuery, params, method) => {
113
+ await recreateTables({
114
+ db: drizzleLibsql(libsqlClient),
115
+ collections: collectionsSchema.parse(config.db.collections ?? {})
116
+ });
117
+ for (const [collectionName, { writable }] of Object.entries(config.db.collections ?? {})) {
118
+ if (!writable) {
119
+ queries.push({
120
+ sql: `DELETE FROM ${sqlite.escapeName(collectionName)}`,
121
+ args: []
122
+ });
123
+ }
124
+ }
125
+ const db = await drizzleProxy(async (sqlQuery, params, method) => {
111
126
  const stmt = { sql: sqlQuery, args: params };
112
127
  queries.push(stmt);
113
128
  const { rows } = await libsqlClient.execute(stmt);
@@ -122,10 +137,9 @@ async function pushData({
122
137
  }
123
138
  return { rows: rowValues };
124
139
  });
125
- await setupDbTables({
140
+ await seedData({
126
141
  db,
127
142
  mode: "build",
128
- collections: collectionsSchema.parse(config.db.collections ?? {}),
129
143
  data: config.db.data
130
144
  });
131
145
  }
@@ -1,8 +1,20 @@
1
1
  import { getMigrationStatus, MIGRATION_NEEDED, MIGRATIONS_NOT_INITIALIZED, MIGRATIONS_UP_TO_DATE } from "../../migrations.js";
2
+ import { getMigrationQueries } from "../../migration-queries.js";
2
3
  async function cmd({ config, flags }) {
3
4
  const status = await getMigrationStatus(config);
4
5
  const { state } = status;
5
6
  if (flags.json) {
7
+ if (state === "ahead") {
8
+ const { queries: migrationQueries } = await getMigrationQueries({
9
+ oldSnapshot: status.oldSnapshot,
10
+ newSnapshot: status.newSnapshot
11
+ });
12
+ const newFileContent = {
13
+ diff: status.diff,
14
+ db: migrationQueries
15
+ };
16
+ status.newFileContent = JSON.stringify(newFileContent, null, 2);
17
+ }
6
18
  console.log(JSON.stringify(status));
7
19
  process.exit(state === "up-to-date" ? 0 : 1);
8
20
  }
@@ -11,6 +11,7 @@ export type MigrationStatus = {
11
11
  diff: deepDiff.Diff<DBSnapshot, DBSnapshot>[];
12
12
  newFilename: string;
13
13
  summary: string;
14
+ newFileContent?: string;
14
15
  } | {
15
16
  state: 'up-to-date';
16
17
  currentSnapshot: DBSnapshot;
@@ -13,7 +13,7 @@ import { dirname } from "path";
13
13
  import { fileURLToPath } from "url";
14
14
  import { blue, yellow } from "kleur/colors";
15
15
  import { fileURLIntegration } from "./file-url.js";
16
- import { setupDbTables } from "../queries.js";
16
+ import { recreateTables, seedData } from "../queries.js";
17
17
  import { getManagedAppTokenOrExit } from "../tokens.js";
18
18
  function astroDBIntegration() {
19
19
  let connectedToRemote = false;
@@ -56,13 +56,15 @@ function astroDBIntegration() {
56
56
  dbUrl: dbUrl.toString(),
57
57
  seeding: true
58
58
  });
59
- await setupDbTables({
60
- db,
61
- collections,
62
- data: configWithDb.db?.data,
63
- logger,
64
- mode: command === "dev" ? "dev" : "build"
65
- });
59
+ await recreateTables({ db, collections });
60
+ if (configWithDb.db?.data) {
61
+ await seedData({
62
+ db,
63
+ data: configWithDb.db.data,
64
+ logger,
65
+ mode: command === "dev" ? "dev" : "build"
66
+ });
67
+ }
66
68
  logger.debug("Database setup complete.");
67
69
  dbPlugin = vitePluginDb({
68
70
  connectToStudio: false,
@@ -2,10 +2,13 @@ import type { SqliteRemoteDatabase } from 'drizzle-orm/sqlite-proxy';
2
2
  import { type BooleanField, type DBCollection, type DBCollections, type DBField, type DateField, type FieldType, type JsonField, type NumberField, type TextField } from '../core/types.js';
3
3
  import type { AstroIntegrationLogger } from 'astro';
4
4
  import type { DBUserConfig } from '../core/types.js';
5
- export declare function setupDbTables({ db, data, collections, logger, mode, }: {
5
+ export declare function recreateTables({ db, collections, }: {
6
6
  db: SqliteRemoteDatabase;
7
- data?: DBUserConfig['data'];
8
7
  collections: DBCollections;
8
+ }): Promise<void>;
9
+ export declare function seedData({ db, data, logger, mode, }: {
10
+ db: SqliteRemoteDatabase;
11
+ data: DBUserConfig['data'];
9
12
  logger?: AstroIntegrationLogger;
10
13
  mode: 'dev' | 'build';
11
14
  }): Promise<void>;
@@ -6,17 +6,13 @@ import { SQLiteAsyncDialect } from "drizzle-orm/sqlite-core";
6
6
  import { hasPrimaryKey } from "../runtime/index.js";
7
7
  import { isSerializedSQL } from "../runtime/types.js";
8
8
  const sqlite = new SQLiteAsyncDialect();
9
- async function setupDbTables({
9
+ async function recreateTables({
10
10
  db,
11
- data,
12
- collections,
13
- logger,
14
- mode
15
- // TODO: Remove once Turso has foreign key PRAGMA support
11
+ collections
16
12
  }) {
17
13
  const setupQueries = [];
18
14
  for (const [name, collection] of Object.entries(collections)) {
19
- const dropQuery = sql.raw(`DROP TABLE IF EXISTS ${name}`);
15
+ const dropQuery = sql.raw(`DROP TABLE IF EXISTS ${sqlite.escapeName(name)}`);
20
16
  const createQuery = sql.raw(getCreateTableQuery(name, collection));
21
17
  const indexQueries = getCreateIndexQueries(name, collection);
22
18
  setupQueries.push(dropQuery, createQuery, ...indexQueries.map((s) => sql.raw(s)));
@@ -24,22 +20,27 @@ async function setupDbTables({
24
20
  for (const q of setupQueries) {
25
21
  await db.run(q);
26
22
  }
27
- if (data) {
28
- try {
29
- await data({
30
- seed: async ({ table }, values) => {
31
- const result = Array.isArray(values) ? db.insert(table).values(values).returning() : db.insert(table).values(values).returning().get();
32
- return result;
33
- },
34
- db,
35
- mode
36
- });
37
- } catch (error) {
38
- (logger ?? console).error(
39
- `Failed to seed data. Did you update to match recent schema changes?`
40
- );
41
- (logger ?? console).error(error);
42
- }
23
+ }
24
+ async function seedData({
25
+ db,
26
+ data,
27
+ logger,
28
+ mode
29
+ }) {
30
+ try {
31
+ await data({
32
+ seed: async ({ table }, values) => {
33
+ const result = Array.isArray(values) ? db.insert(table).values(values).returning() : db.insert(table).values(values).returning().get();
34
+ return result;
35
+ },
36
+ db,
37
+ mode
38
+ });
39
+ } catch (error) {
40
+ (logger ?? console).error(
41
+ `Failed to seed data. Did you update to match recent schema changes?`
42
+ );
43
+ (logger ?? console).error(error);
43
44
  }
44
45
  }
45
46
  function getCreateTableQuery(collectionName, collection) {
@@ -193,6 +194,7 @@ export {
193
194
  getModifiers,
194
195
  getReferencesConfig,
195
196
  hasDefault,
197
+ recreateTables,
196
198
  schemaTypeToSqlType,
197
- setupDbTables
199
+ seedData
198
200
  };
@@ -51,7 +51,7 @@ export type Table<TTableName extends string, TFields extends Record<string, Pick
51
51
  [K in Extract<keyof TFields, string>]: Column<TFields[K]['type'], {
52
52
  tableName: TTableName;
53
53
  name: K;
54
- hasDefault: TFields[K] extends {
54
+ hasDefault: TFields[K]['schema'] extends {
55
55
  default: NonNullable<unknown>;
56
56
  } ? true : TFields[K]['schema'] extends {
57
57
  primaryKey: true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrojs/db",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "type": "module",