@astrojs/db 0.3.5 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/core/cli/commands/link/index.js +7 -3
  2. package/dist/core/cli/commands/push/index.js +3 -3
  3. package/dist/core/cli/migration-queries.d.ts +4 -4
  4. package/dist/core/cli/migration-queries.js +73 -73
  5. package/dist/core/cli/migrations.js +15 -7
  6. package/dist/core/errors.js +7 -3
  7. package/dist/core/integration/file-url.js +2 -1
  8. package/dist/core/integration/index.js +106 -57
  9. package/dist/core/integration/typegen.d.ts +3 -3
  10. package/dist/core/integration/typegen.js +8 -8
  11. package/dist/core/integration/vite-plugin-db.d.ts +14 -9
  12. package/dist/core/integration/vite-plugin-db.js +15 -12
  13. package/dist/core/integration/vite-plugin-inject-env-ts.d.ts +4 -2
  14. package/dist/core/integration/vite-plugin-inject-env-ts.js +8 -4
  15. package/dist/core/queries.d.ts +12 -12
  16. package/dist/core/queries.js +49 -46
  17. package/dist/core/types.d.ts +232 -231
  18. package/dist/core/types.js +56 -55
  19. package/dist/core/utils.js +1 -1
  20. package/dist/index.d.ts +1 -1
  21. package/dist/index.js +4 -4
  22. package/dist/runtime/db-client.d.ts +9 -4
  23. package/dist/runtime/db-client.js +11 -7
  24. package/dist/runtime/index.d.ts +7 -7
  25. package/dist/runtime/index.js +27 -29
  26. package/dist/runtime/types.d.ts +7 -7
  27. package/package.json +3 -5
  28. package/components/Renderer.astro +0 -14
  29. package/components/astro-env.d.ts +0 -1
  30. package/components/index.ts +0 -2
  31. package/components/tsconfig.json +0 -7
  32. package/dist/cli/commands/push/index.d.ts +0 -6
  33. package/dist/cli/commands/shell/index.d.ts +0 -6
  34. package/dist/cli/commands/sync/index.d.ts +0 -6
  35. package/dist/cli/commands/verify/index.d.ts +0 -6
  36. package/dist/cli/index.d.ts +0 -6
  37. package/dist/cli/queries.d.ts +0 -18
  38. package/dist/cli/seed.d.ts +0 -6
  39. package/dist/cli/sync/admin.d.ts +0 -33
  40. package/dist/cli/sync/index.d.ts +0 -1
  41. package/dist/cli/sync/migrate.d.ts +0 -1
  42. package/dist/cli/sync/queries.d.ts +0 -19
  43. package/dist/cli/sync/remote-db.d.ts +0 -1
  44. package/dist/config.d.ts +0 -1374
  45. package/dist/consts.d.ts +0 -7
  46. package/dist/core/cli/commands/sync/index.d.ts +0 -6
  47. package/dist/error-map.d.ts +0 -6
  48. package/dist/errors.d.ts +0 -3
  49. package/dist/file-url-integration.d.ts +0 -2
  50. package/dist/integration.d.ts +0 -2
  51. package/dist/internal-drizzle.d.ts +0 -1
  52. package/dist/internal.d.ts +0 -47
  53. package/dist/load-astro-config.d.ts +0 -6
  54. package/dist/migrations.d.ts +0 -12
  55. package/dist/root.d.ts +0 -3
  56. package/dist/typegen.d.ts +0 -5
  57. package/dist/types.d.ts +0 -1604
  58. package/dist/utils-runtime.d.ts +0 -1
  59. package/dist/utils.d.ts +0 -59
  60. package/dist/vite-plugin-db.d.ts +0 -19
  61. package/dist/vite-plugin-inject-env-ts.d.ts +0 -9
@@ -27,12 +27,16 @@ async function cmd({ flags }) {
27
27
  });
28
28
  if (!response.ok) {
29
29
  if (response.status === 401) {
30
- console.error(`${bgRed("Unauthorized")}
30
+ console.error(
31
+ `${bgRed("Unauthorized")}
31
32
 
32
33
  Are you logged in?
33
- Run ${cyan("astro db login")} to authenticate and then try linking again.
34
+ Run ${cyan(
35
+ "astro db login"
36
+ )} to authenticate and then try linking again.
34
37
 
35
- `);
38
+ `
39
+ );
36
40
  process.exit(1);
37
41
  }
38
42
  console.error(`Failed to link project: ${response.status} ${response.statusText}`);
@@ -6,7 +6,7 @@ import { red } from "kleur/colors";
6
6
  import prompts from "prompts";
7
7
  import { recreateTables, seedData } from "../../../queries.js";
8
8
  import { getManagedAppTokenOrExit } from "../../../tokens.js";
9
- import { collectionsSchema } from "../../../types.js";
9
+ import { tablesSchema } from "../../../types.js";
10
10
  import { getRemoteDatabaseUrl } from "../../../utils.js";
11
11
  import { getMigrationQueries } from "../../migration-queries.js";
12
12
  import {
@@ -112,9 +112,9 @@ async function pushData({
112
112
  const libsqlClient = createClient({ url: ":memory:" });
113
113
  await recreateTables({
114
114
  db: drizzleLibsql(libsqlClient),
115
- collections: collectionsSchema.parse(config.db.collections ?? {})
115
+ tables: tablesSchema.parse(config.db.tables ?? {})
116
116
  });
117
- for (const [collectionName, { writable }] of Object.entries(config.db.collections ?? {})) {
117
+ for (const [collectionName, { writable }] of Object.entries(config.db.tables ?? {})) {
118
118
  if (!writable) {
119
119
  queries.push({
120
120
  sql: `DELETE FROM ${sqlite.escapeName(collectionName)}`,
@@ -1,8 +1,8 @@
1
- import { type DBCollection, type DBSnapshot } from '../types.js';
1
+ import { type DBTable, type DBSnapshot } from '../types.js';
2
2
  /** Dependency injected for unit testing */
3
3
  type AmbiguityResponses = {
4
4
  collectionRenames: Record<string, string>;
5
- fieldRenames: {
5
+ columnRenames: {
6
6
  [collectionName: string]: Record<string, string>;
7
7
  };
8
8
  };
@@ -16,8 +16,8 @@ export declare function getMigrationQueries({ oldSnapshot, newSnapshot, ambiguit
16
16
  }>;
17
17
  export declare function getCollectionChangeQueries({ collectionName, oldCollection, newCollection, ambiguityResponses, }: {
18
18
  collectionName: string;
19
- oldCollection: DBCollection;
20
- newCollection: DBCollection;
19
+ oldCollection: DBTable;
20
+ newCollection: DBTable;
21
21
  ambiguityResponses?: AmbiguityResponses;
22
22
  }): Promise<{
23
23
  queries: string[];
@@ -1,7 +1,7 @@
1
1
  import * as color from "kleur/colors";
2
2
  import deepDiff from "deep-diff";
3
3
  import {
4
- fieldSchema
4
+ columnSchema
5
5
  } from "../types.js";
6
6
  import { SQLiteAsyncDialect } from "drizzle-orm/sqlite-core";
7
7
  import { customAlphabet } from "nanoid";
@@ -68,9 +68,9 @@ async function getCollectionChangeQueries({
68
68
  }) {
69
69
  const queries = [];
70
70
  const confirmations = [];
71
- const updated = getUpdatedFields(oldCollection.fields, newCollection.fields);
72
- let added = getAdded(oldCollection.fields, newCollection.fields);
73
- let dropped = getDropped(oldCollection.fields, newCollection.fields);
71
+ const updated = getUpdatedColumns(oldCollection.columns, newCollection.columns);
72
+ let added = getAdded(oldCollection.columns, newCollection.columns);
73
+ let dropped = getDropped(oldCollection.columns, newCollection.columns);
74
74
  const hasForeignKeyChanges = Boolean(
75
75
  deepDiff(oldCollection.foreignKeys, newCollection.foreignKeys)
76
76
  );
@@ -85,10 +85,10 @@ async function getCollectionChangeQueries({
85
85
  };
86
86
  }
87
87
  if (!hasForeignKeyChanges && !isEmpty(added) && !isEmpty(dropped)) {
88
- const resolved = await resolveFieldRenames(collectionName, added, dropped, ambiguityResponses);
88
+ const resolved = await resolveColumnRenames(collectionName, added, dropped, ambiguityResponses);
89
89
  added = resolved.added;
90
90
  dropped = resolved.dropped;
91
- queries.push(...getFieldRenameQueries(collectionName, resolved.renamed));
91
+ queries.push(...getColumnRenameQueries(collectionName, resolved.renamed));
92
92
  }
93
93
  if (!hasForeignKeyChanges && isEmpty(updated) && Object.values(dropped).every(canAlterTableDropColumn) && Object.values(added).every(canAlterTableAddColumn)) {
94
94
  queries.push(
@@ -103,33 +103,33 @@ async function getCollectionChangeQueries({
103
103
  }
104
104
  const dataLossCheck = canRecreateTableWithoutDataLoss(added, updated);
105
105
  if (dataLossCheck.dataLoss) {
106
- const { reason, fieldName } = dataLossCheck;
106
+ const { reason, columnName } = dataLossCheck;
107
107
  const reasonMsgs = {
108
- "added-required": `New field ${color.bold(
109
- collectionName + "." + fieldName
108
+ "added-required": `New column ${color.bold(
109
+ collectionName + "." + columnName
110
110
  )} is required with no default value.
111
111
  This requires deleting existing data in the ${color.bold(
112
112
  collectionName
113
113
  )} collection.`,
114
- "added-unique": `New field ${color.bold(
115
- collectionName + "." + fieldName
114
+ "added-unique": `New column ${color.bold(
115
+ collectionName + "." + columnName
116
116
  )} is marked as unique.
117
117
  This requires deleting existing data in the ${color.bold(
118
118
  collectionName
119
119
  )} collection.`,
120
- "updated-type": `Updated field ${color.bold(
121
- collectionName + "." + fieldName
122
- )} cannot convert data to new field data type.
120
+ "updated-type": `Updated column ${color.bold(
121
+ collectionName + "." + columnName
122
+ )} cannot convert data to new column data type.
123
123
  This requires deleting existing data in the ${color.bold(
124
124
  collectionName
125
125
  )} collection.`
126
126
  };
127
127
  confirmations.push(reasonMsgs[reason]);
128
128
  }
129
- const primaryKeyExists = Object.entries(newCollection.fields).find(
130
- ([, field]) => hasPrimaryKey(field)
129
+ const primaryKeyExists = Object.entries(newCollection.columns).find(
130
+ ([, column]) => hasPrimaryKey(column)
131
131
  );
132
- const droppedPrimaryKey = Object.entries(dropped).find(([, field]) => hasPrimaryKey(field));
132
+ const droppedPrimaryKey = Object.entries(dropped).find(([, column]) => hasPrimaryKey(column));
133
133
  const recreateTableQueries = getRecreateTableQueries({
134
134
  collectionName,
135
135
  newCollection,
@@ -158,20 +158,20 @@ function getChangeIndexQueries({
158
158
  queries.push(...getCreateIndexQueries(collectionName, { indexes: added }));
159
159
  return queries;
160
160
  }
161
- async function resolveFieldRenames(collectionName, mightAdd, mightDrop, ambiguityResponses) {
161
+ async function resolveColumnRenames(collectionName, mightAdd, mightDrop, ambiguityResponses) {
162
162
  const added = {};
163
163
  const dropped = {};
164
164
  const renamed = [];
165
- for (const [fieldName, field] of Object.entries(mightAdd)) {
166
- let oldFieldName = ambiguityResponses ? ambiguityResponses.fieldRenames[collectionName]?.[fieldName] ?? "__NEW__" : void 0;
167
- if (!oldFieldName) {
165
+ for (const [columnName, column] of Object.entries(mightAdd)) {
166
+ let oldColumnName = ambiguityResponses ? ambiguityResponses.columnRenames[collectionName]?.[columnName] ?? "__NEW__" : void 0;
167
+ if (!oldColumnName) {
168
168
  const res = await prompts(
169
169
  {
170
170
  type: "select",
171
- name: "fieldName",
172
- message: "New field " + color.blue(color.bold(`${collectionName}.${fieldName}`)) + " detected. Was this renamed from an existing field?",
171
+ name: "columnName",
172
+ message: "New column " + color.blue(color.bold(`${collectionName}.${columnName}`)) + " detected. Was this renamed from an existing column?",
173
173
  choices: [
174
- { title: "New field (not renamed from existing)", value: "__NEW__" },
174
+ { title: "New column (not renamed from existing)", value: "__NEW__" },
175
175
  ...Object.keys(mightDrop).filter((key) => !(key in renamed)).map((key) => ({ title: key, value: key }))
176
176
  ]
177
177
  },
@@ -181,17 +181,17 @@ async function resolveFieldRenames(collectionName, mightAdd, mightDrop, ambiguit
181
181
  }
182
182
  }
183
183
  );
184
- oldFieldName = res.fieldName;
184
+ oldColumnName = res.columnName;
185
185
  }
186
- if (oldFieldName === "__NEW__") {
187
- added[fieldName] = field;
186
+ if (oldColumnName === "__NEW__") {
187
+ added[columnName] = column;
188
188
  } else {
189
- renamed.push({ from: oldFieldName, to: fieldName });
189
+ renamed.push({ from: oldColumnName, to: columnName });
190
190
  }
191
191
  }
192
- for (const [droppedFieldName, droppedField] of Object.entries(mightDrop)) {
193
- if (!renamed.find((r) => r.from === droppedFieldName)) {
194
- dropped[droppedFieldName] = droppedField;
192
+ for (const [droppedColumnName, droppedColumn] of Object.entries(mightDrop)) {
193
+ if (!renamed.find((r) => r.from === droppedColumnName)) {
194
+ dropped[droppedColumnName] = droppedColumn;
195
195
  }
196
196
  }
197
197
  return { added, dropped, renamed };
@@ -250,7 +250,7 @@ function getDroppedCollections(oldCollections, newCollections) {
250
250
  }
251
251
  return dropped;
252
252
  }
253
- function getFieldRenameQueries(unescapedCollectionName, renamed) {
253
+ function getColumnRenameQueries(unescapedCollectionName, renamed) {
254
254
  const queries = [];
255
255
  const collectionName = sqlite.escapeName(unescapedCollectionName);
256
256
  for (const { from, to } of renamed) {
@@ -264,18 +264,18 @@ function getFieldRenameQueries(unescapedCollectionName, renamed) {
264
264
  function getAlterTableQueries(unescapedCollectionName, added, dropped) {
265
265
  const queries = [];
266
266
  const collectionName = sqlite.escapeName(unescapedCollectionName);
267
- for (const [unescFieldName, field] of Object.entries(added)) {
268
- const fieldName = sqlite.escapeName(unescFieldName);
269
- const type = schemaTypeToSqlType(field.type);
270
- const q = `ALTER TABLE ${collectionName} ADD COLUMN ${fieldName} ${type}${getModifiers(
271
- fieldName,
272
- field
267
+ for (const [unescColumnName, column] of Object.entries(added)) {
268
+ const columnName = sqlite.escapeName(unescColumnName);
269
+ const type = schemaTypeToSqlType(column.type);
270
+ const q = `ALTER TABLE ${collectionName} ADD COLUMN ${columnName} ${type}${getModifiers(
271
+ columnName,
272
+ column
273
273
  )}`;
274
274
  queries.push(q);
275
275
  }
276
- for (const unescFieldName of Object.keys(dropped)) {
277
- const fieldName = sqlite.escapeName(unescFieldName);
278
- const q = `ALTER TABLE ${collectionName} DROP COLUMN ${fieldName}`;
276
+ for (const unescColumnName of Object.keys(dropped)) {
277
+ const columnName = sqlite.escapeName(unescColumnName);
278
+ const q = `ALTER TABLE ${collectionName} DROP COLUMN ${columnName}`;
279
279
  queries.push(q);
280
280
  }
281
281
  return queries;
@@ -296,7 +296,7 @@ function getRecreateTableQueries({
296
296
  getCreateTableQuery(unescCollectionName, newCollection)
297
297
  ];
298
298
  }
299
- const newColumns = [...Object.keys(newCollection.fields)];
299
+ const newColumns = [...Object.keys(newCollection.columns)];
300
300
  if (migrateHiddenPrimaryKey) {
301
301
  newColumns.unshift("_id");
302
302
  }
@@ -311,41 +311,41 @@ function getRecreateTableQueries({
311
311
  function isEmpty(obj) {
312
312
  return Object.keys(obj).length === 0;
313
313
  }
314
- function canAlterTableAddColumn(field) {
315
- if (field.schema.unique)
314
+ function canAlterTableAddColumn(column) {
315
+ if (column.schema.unique)
316
316
  return false;
317
- if (hasRuntimeDefault(field))
317
+ if (hasRuntimeDefault(column))
318
318
  return false;
319
- if (!field.schema.optional && !hasDefault(field))
319
+ if (!column.schema.optional && !hasDefault(column))
320
320
  return false;
321
- if (hasPrimaryKey(field))
321
+ if (hasPrimaryKey(column))
322
322
  return false;
323
- if (getReferencesConfig(field))
323
+ if (getReferencesConfig(column))
324
324
  return false;
325
325
  return true;
326
326
  }
327
- function canAlterTableDropColumn(field) {
328
- if (field.schema.unique)
327
+ function canAlterTableDropColumn(column) {
328
+ if (column.schema.unique)
329
329
  return false;
330
- if (hasPrimaryKey(field))
330
+ if (hasPrimaryKey(column))
331
331
  return false;
332
332
  return true;
333
333
  }
334
334
  function canRecreateTableWithoutDataLoss(added, updated) {
335
- for (const [fieldName, a] of Object.entries(added)) {
335
+ for (const [columnName, a] of Object.entries(added)) {
336
336
  if (hasPrimaryKey(a) && a.type !== "number" && !hasDefault(a)) {
337
- return { dataLoss: true, fieldName, reason: "added-required" };
337
+ return { dataLoss: true, columnName, reason: "added-required" };
338
338
  }
339
339
  if (!a.schema.optional && !hasDefault(a)) {
340
- return { dataLoss: true, fieldName, reason: "added-required" };
340
+ return { dataLoss: true, columnName, reason: "added-required" };
341
341
  }
342
342
  if (!a.schema.optional && a.schema.unique) {
343
- return { dataLoss: true, fieldName, reason: "added-unique" };
343
+ return { dataLoss: true, columnName, reason: "added-unique" };
344
344
  }
345
345
  }
346
- for (const [fieldName, u] of Object.entries(updated)) {
346
+ for (const [columnName, u] of Object.entries(updated)) {
347
347
  if (u.old.type !== u.new.type && !canChangeTypeWithoutQuery(u.old, u.new)) {
348
- return { dataLoss: true, fieldName, reason: "updated-type" };
348
+ return { dataLoss: true, columnName, reason: "updated-type" };
349
349
  }
350
350
  }
351
351
  return { dataLoss: false };
@@ -377,24 +377,24 @@ function getUpdated(oldObj, newObj) {
377
377
  }
378
378
  return updated;
379
379
  }
380
- function getUpdatedFields(oldFields, newFields) {
380
+ function getUpdatedColumns(oldColumns, newColumns) {
381
381
  const updated = {};
382
- for (const [key, newField] of Object.entries(newFields)) {
383
- let oldField = oldFields[key];
384
- if (!oldField)
382
+ for (const [key, newColumn] of Object.entries(newColumns)) {
383
+ let oldColumn = oldColumns[key];
384
+ if (!oldColumn)
385
385
  continue;
386
- if (oldField.type !== newField.type && canChangeTypeWithoutQuery(oldField, newField)) {
387
- const asNewField = fieldSchema.safeParse({
388
- type: newField.type,
389
- schema: oldField.schema
386
+ if (oldColumn.type !== newColumn.type && canChangeTypeWithoutQuery(oldColumn, newColumn)) {
387
+ const asNewColumn = columnSchema.safeParse({
388
+ type: newColumn.type,
389
+ schema: oldColumn.schema
390
390
  });
391
- if (asNewField.success) {
392
- oldField = asNewField.data;
391
+ if (asNewColumn.success) {
392
+ oldColumn = asNewColumn.data;
393
393
  }
394
394
  }
395
- const diff = deepDiff(oldField, newField);
395
+ const diff = deepDiff(oldColumn, newColumn);
396
396
  if (diff) {
397
- updated[key] = { old: oldField, new: newField };
397
+ updated[key] = { old: oldColumn, new: newColumn };
398
398
  }
399
399
  }
400
400
  return updated;
@@ -404,13 +404,13 @@ const typeChangesWithoutQuery = [
404
404
  { from: "date", to: "text" },
405
405
  { from: "json", to: "text" }
406
406
  ];
407
- function canChangeTypeWithoutQuery(oldField, newField) {
407
+ function canChangeTypeWithoutQuery(oldColumn, newColumn) {
408
408
  return typeChangesWithoutQuery.some(
409
- ({ from, to }) => oldField.type === from && newField.type === to
409
+ ({ from, to }) => oldColumn.type === from && newColumn.type === to
410
410
  );
411
411
  }
412
- function hasRuntimeDefault(field) {
413
- return !!(field.schema.default && isSerializedSQL(field.schema.default));
412
+ function hasRuntimeDefault(column) {
413
+ return !!(column.schema.default && isSerializedSQL(column.schema.default));
414
414
  }
415
415
  export {
416
416
  getCollectionChangeQueries,
@@ -1,6 +1,6 @@
1
1
  import deepDiff from "deep-diff";
2
2
  import { mkdir, readFile, readdir, writeFile } from "fs/promises";
3
- import { collectionsSchema } from "../types.js";
3
+ import { tablesSchema } from "../types.js";
4
4
  import { cyan, green, yellow } from "kleur/colors";
5
5
  const { applyChange, diff: generateDiff } = deepDiff;
6
6
  async function getMigrationStatus(config) {
@@ -31,20 +31,28 @@ async function getMigrationStatus(config) {
31
31
  currentSnapshot
32
32
  };
33
33
  }
34
- const MIGRATIONS_CREATED = `${green("\u25A0 Migrations initialized!")}
34
+ const MIGRATIONS_CREATED = `${green(
35
+ "\u25A0 Migrations initialized!"
36
+ )}
35
37
 
36
38
  To execute your migrations, run
37
39
  ${cyan("astro db push")}`;
38
- const MIGRATIONS_UP_TO_DATE = `${green("\u25A0 No migrations needed!")}
40
+ const MIGRATIONS_UP_TO_DATE = `${green(
41
+ "\u25A0 No migrations needed!"
42
+ )}
39
43
 
40
44
  Your database is up to date.
41
45
  `;
42
- const MIGRATIONS_NOT_INITIALIZED = `${yellow("\u25B6 No migrations found!")}
46
+ const MIGRATIONS_NOT_INITIALIZED = `${yellow(
47
+ "\u25B6 No migrations found!"
48
+ )}
43
49
 
44
50
  To scaffold your migrations folder, run
45
51
  ${cyan("astro db sync")}
46
52
  `;
47
- const MIGRATION_NEEDED = `${yellow("\u25B6 Changes detected!")}
53
+ const MIGRATION_NEEDED = `${yellow(
54
+ "\u25B6 Changes detected!"
55
+ )}
48
56
 
49
57
  To create the necessary migration file, run
50
58
  ${cyan("astro db sync")}
@@ -98,8 +106,8 @@ async function initializeFromMigrations(allMigrationFiles) {
98
106
  return prevSnapshot;
99
107
  }
100
108
  function createCurrentSnapshot(config) {
101
- const collectionsConfig = collectionsSchema.parse(config.db?.collections ?? {});
102
- const schema = JSON.parse(JSON.stringify(collectionsConfig));
109
+ const tablesConfig = tablesSchema.parse(config.db?.tables ?? {});
110
+ const schema = JSON.parse(JSON.stringify(tablesConfig));
103
111
  return { experimentalVersion: 1, schema };
104
112
  }
105
113
  function createEmptySnapshot() {
@@ -10,13 +10,17 @@ const MISSING_PROJECT_ID_ERROR = `${red("\u25B6 Directory not linked.")}
10
10
  ${cyan("astro db link")}
11
11
  `;
12
12
  const STUDIO_CONFIG_MISSING_WRITABLE_COLLECTIONS_ERROR = (collectionName) => `${red(
13
- `\u25B6 Writable collection ${bold(collectionName)} requires Astro Studio or the ${yellow("unsafeWritable")} option.`
13
+ `\u25B6 Writable collection ${bold(collectionName)} requires Astro Studio or the ${yellow(
14
+ "unsafeWritable"
15
+ )} option.`
14
16
  )}
15
17
 
16
18
  Visit ${cyan("https://astro.build/studio")} to create your account
17
19
  and set ${green("studio: true")} in your astro.config.mjs file to enable Studio.
18
20
  `;
19
- const UNSAFE_WRITABLE_WARNING = `${yellow("unsafeWritable")} option is enabled and you are using writable collections.
21
+ const UNSAFE_WRITABLE_WARNING = `${yellow(
22
+ "unsafeWritable"
23
+ )} option is enabled and you are using writable tables.
20
24
  Redeploying your app may result in wiping away your database.
21
25
  I hope you know what you are doing.
22
26
  `;
@@ -34,7 +38,7 @@ const MIGRATIONS_NOT_INITIALIZED = `${yellow(
34
38
  `;
35
39
  const SEED_WRITABLE_IN_PROD_ERROR = (collectionName) => {
36
40
  return `${red(
37
- `Writable collections should not be seeded in production with data().`
41
+ `Writable tables should not be seeded in production with data().`
38
42
  )} You can seed ${bold(
39
43
  collectionName
40
44
  )} in development mode only using the "mode" flag. See the docs for more: https://www.notion.so/astroinc/astrojs-db-README-dcf6fa10de9a4f528be56cee96e8c054?pvs=4#278aed3fc37e4cec80240d1552ff6ac5`;
@@ -8,7 +8,7 @@ async function copyFile(toDir, fromUrl, toUrl) {
8
8
  function fileURLIntegration() {
9
9
  const fileNames = [];
10
10
  function createVitePlugin(command) {
11
- const referenceIds = [];
11
+ let referenceIds = [];
12
12
  return {
13
13
  name: "@astrojs/db/file-url",
14
14
  enforce: "pre",
@@ -34,6 +34,7 @@ function fileURLIntegration() {
34
34
  for (const referenceId of referenceIds) {
35
35
  fileNames.push(this.getFileName(referenceId));
36
36
  }
37
+ referenceIds = [];
37
38
  }
38
39
  };
39
40
  }
@@ -1,3 +1,43 @@
1
+ var __knownSymbol = (name, symbol) => {
2
+ return (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
3
+ };
4
+ var __using = (stack, value, async) => {
5
+ if (value != null) {
6
+ if (typeof value !== "object" && typeof value !== "function")
7
+ throw TypeError("Object expected");
8
+ var dispose;
9
+ if (async)
10
+ dispose = value[__knownSymbol("asyncDispose")];
11
+ if (dispose === void 0)
12
+ dispose = value[__knownSymbol("dispose")];
13
+ if (typeof dispose !== "function")
14
+ throw TypeError("Object not disposable");
15
+ stack.push([async, dispose, value]);
16
+ } else if (async) {
17
+ stack.push([async]);
18
+ }
19
+ return value;
20
+ };
21
+ var __callDispose = (stack, error, hasError) => {
22
+ var E = typeof SuppressedError === "function" ? SuppressedError : function(e, s, m, _) {
23
+ return _ = Error(m), _.name = "SuppressedError", _.error = e, _.suppressed = s, _;
24
+ };
25
+ var fail = (e) => error = hasError ? new E(e, error, "An error was suppressed during disposal") : (hasError = true, e);
26
+ var next = (it) => {
27
+ while (it = stack.pop()) {
28
+ try {
29
+ var result = it[1] && it[1].call(it[2]);
30
+ if (it[0])
31
+ return Promise.resolve(result).then(next, (e) => (fail(e), next()));
32
+ } catch (e) {
33
+ fail(e);
34
+ }
35
+ }
36
+ if (hasError)
37
+ throw error;
38
+ };
39
+ return next();
40
+ };
1
41
  import { vitePluginDb } from "./vite-plugin-db.js";
2
42
  import { vitePluginInjectEnvTs } from "./vite-plugin-inject-env-ts.js";
3
43
  import { typegen } from "./typegen.js";
@@ -7,7 +47,10 @@ import { DB_PATH } from "../consts.js";
7
47
  import { createLocalDatabaseClient } from "../../runtime/db-client.js";
8
48
  import { astroConfigWithDbSchema } from "../types.js";
9
49
  import {} from "../utils.js";
10
- import { STUDIO_CONFIG_MISSING_WRITABLE_COLLECTIONS_ERROR, UNSAFE_WRITABLE_WARNING } from "../errors.js";
50
+ import {
51
+ STUDIO_CONFIG_MISSING_WRITABLE_COLLECTIONS_ERROR,
52
+ UNSAFE_WRITABLE_WARNING
53
+ } from "../errors.js";
11
54
  import { errorMap } from "./error-map.js";
12
55
  import { dirname } from "path";
13
56
  import { fileURLToPath } from "url";
@@ -18,85 +61,91 @@ import { getManagedAppTokenOrExit } from "../tokens.js";
18
61
  function astroDBIntegration() {
19
62
  let connectedToRemote = false;
20
63
  let appToken;
64
+ let schemas = {
65
+ tables() {
66
+ throw new Error("tables not found");
67
+ }
68
+ };
69
+ let command;
21
70
  return {
22
71
  name: "astro:db",
23
72
  hooks: {
24
- "astro:config:setup": async ({ logger, updateConfig, config, command }) => {
25
- if (command === "preview")
73
+ "astro:config:setup": async ({ updateConfig, config, command: _command, logger }) => {
74
+ command = _command;
75
+ if (_command === "preview")
26
76
  return;
27
- const configWithDb = astroConfigWithDbSchema.parse(config, { errorMap });
28
- const collections = configWithDb.db?.collections ?? {};
29
- const studio = configWithDb.db?.studio ?? false;
30
- const unsafeWritable = Boolean(configWithDb.db?.unsafeWritable);
31
- const foundWritableCollection = Object.entries(collections).find(([, c]) => c.writable);
32
- const writableAllowed = studio || unsafeWritable;
33
- if (!writableAllowed && foundWritableCollection) {
34
- logger.error(
35
- STUDIO_CONFIG_MISSING_WRITABLE_COLLECTIONS_ERROR(foundWritableCollection[0])
36
- );
37
- process.exit(1);
38
- } else if (unsafeWritable && foundWritableCollection) {
39
- logger.warn(UNSAFE_WRITABLE_WARNING);
40
- }
41
- let dbPlugin;
77
+ let dbPlugin = void 0;
78
+ const studio = config.db?.studio ?? false;
42
79
  if (studio && command === "build" && process.env.ASTRO_DB_TEST_ENV !== "1") {
43
80
  appToken = await getManagedAppTokenOrExit();
44
81
  connectedToRemote = true;
45
82
  dbPlugin = vitePluginDb({
46
83
  connectToStudio: true,
47
- collections,
48
84
  appToken: appToken.token,
85
+ schemas,
49
86
  root: config.root
50
87
  });
51
88
  } else {
52
- const dbUrl = new URL(DB_PATH, config.root);
53
- if (existsSync(dbUrl)) {
54
- await rm(dbUrl);
55
- }
56
- await mkdir(dirname(fileURLToPath(dbUrl)), { recursive: true });
57
- await writeFile(dbUrl, "");
58
- const db = await createLocalDatabaseClient({
59
- collections,
60
- dbUrl: dbUrl.toString(),
61
- seeding: true
62
- });
63
- await recreateTables({ db, collections });
64
- if (configWithDb.db?.data) {
65
- await seedData({
66
- db,
67
- data: configWithDb.db.data,
68
- logger,
69
- mode: command === "dev" ? "dev" : "build"
70
- });
71
- }
72
- logger.debug("Database setup complete.");
73
89
  dbPlugin = vitePluginDb({
74
90
  connectToStudio: false,
75
- collections,
91
+ schemas,
76
92
  root: config.root
77
93
  });
78
94
  }
79
95
  updateConfig({
80
96
  vite: {
81
97
  assetsInclude: [DB_PATH],
82
- plugins: [
83
- dbPlugin,
84
- vitePluginInjectEnvTs(config),
85
- {
86
- name: "my-plugin",
87
- resolveId(id) {
88
- if (id.endsWith("?server-path")) {
89
- }
90
- },
91
- load(id) {
92
- if (id.endsWith("?server-path")) {
93
- }
94
- }
95
- }
96
- ]
98
+ plugins: [dbPlugin, vitePluginInjectEnvTs(config, logger)]
97
99
  }
98
100
  });
99
- await typegen({ collections, root: config.root });
101
+ },
102
+ "astro:config:done": async ({ config, logger }) => {
103
+ const configWithDb = astroConfigWithDbSchema.parse(config, { errorMap });
104
+ const tables = configWithDb.db?.tables ?? {};
105
+ schemas.tables = () => tables;
106
+ const studio = configWithDb.db?.studio ?? false;
107
+ const unsafeWritable = Boolean(configWithDb.db?.unsafeWritable);
108
+ const foundWritableCollection = Object.entries(tables).find(([, c]) => c.writable);
109
+ const writableAllowed = studio || unsafeWritable;
110
+ if (!writableAllowed && foundWritableCollection) {
111
+ logger.error(
112
+ STUDIO_CONFIG_MISSING_WRITABLE_COLLECTIONS_ERROR(foundWritableCollection[0])
113
+ );
114
+ process.exit(1);
115
+ } else if (unsafeWritable && foundWritableCollection) {
116
+ logger.warn(UNSAFE_WRITABLE_WARNING);
117
+ }
118
+ if (!connectedToRemote) {
119
+ var _stack = [];
120
+ try {
121
+ const dbUrl = new URL(DB_PATH, config.root);
122
+ if (existsSync(dbUrl)) {
123
+ await rm(dbUrl);
124
+ }
125
+ await mkdir(dirname(fileURLToPath(dbUrl)), { recursive: true });
126
+ await writeFile(dbUrl, "");
127
+ const db = __using(_stack, await createLocalDatabaseClient({
128
+ tables,
129
+ dbUrl: dbUrl.toString(),
130
+ seeding: true
131
+ }));
132
+ await recreateTables({ db, tables });
133
+ if (configWithDb.db?.data) {
134
+ await seedData({
135
+ db,
136
+ data: configWithDb.db.data,
137
+ logger,
138
+ mode: command === "dev" ? "dev" : "build"
139
+ });
140
+ }
141
+ logger.debug("Database setup complete.");
142
+ } catch (_) {
143
+ var _error = _, _hasError = true;
144
+ } finally {
145
+ __callDispose(_stack, _error, _hasError);
146
+ }
147
+ }
148
+ await typegen({ tables, root: config.root });
100
149
  },
101
150
  "astro:server:start": async ({ logger }) => {
102
151
  setTimeout(() => {
@@ -1,5 +1,5 @@
1
- import type { DBCollections } from '../types.js';
2
- export declare function typegen({ collections, root }: {
3
- collections: DBCollections;
1
+ import type { DBTables } from '../types.js';
2
+ export declare function typegen({ tables, root }: {
3
+ tables: DBTables;
4
4
  root: URL;
5
5
  }): Promise<void>;