@astrojs/db 0.4.1 → 0.5.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 (57) hide show
  1. package/dist/core/cli/commands/execute/index.d.ts +8 -0
  2. package/dist/core/cli/commands/execute/index.js +32 -0
  3. package/dist/core/cli/commands/gen/index.d.ts +4 -2
  4. package/dist/core/cli/commands/gen/index.js +17 -9
  5. package/dist/core/cli/commands/link/index.d.ts +20 -8
  6. package/dist/core/cli/commands/link/index.js +191 -31
  7. package/dist/core/cli/commands/login/index.d.ts +4 -2
  8. package/dist/core/cli/commands/login/index.js +31 -22
  9. package/dist/core/cli/commands/logout/index.d.ts +1 -6
  10. package/dist/core/cli/commands/logout/index.js +1 -1
  11. package/dist/core/cli/commands/push/index.d.ts +4 -2
  12. package/dist/core/cli/commands/push/index.js +25 -77
  13. package/dist/core/cli/commands/shell/index.d.ts +4 -2
  14. package/dist/core/cli/commands/shell/index.js +3 -1
  15. package/dist/core/cli/commands/verify/index.d.ts +4 -2
  16. package/dist/core/cli/commands/verify/index.js +10 -6
  17. package/dist/core/cli/index.d.ts +1 -1
  18. package/dist/core/cli/index.js +19 -13
  19. package/dist/core/cli/migration-queries.d.ts +1 -1
  20. package/dist/core/cli/migration-queries.js +6 -6
  21. package/dist/core/cli/migrations.d.ts +12 -9
  22. package/dist/core/cli/migrations.js +27 -21
  23. package/dist/core/consts.d.ts +2 -0
  24. package/dist/core/consts.js +4 -0
  25. package/dist/core/errors.d.ts +7 -6
  26. package/dist/core/errors.js +35 -38
  27. package/dist/core/integration/file-url.js +1 -1
  28. package/dist/core/integration/index.js +56 -112
  29. package/dist/core/integration/typegen.js +1 -13
  30. package/dist/core/integration/vite-plugin-db.d.ts +9 -5
  31. package/dist/core/integration/vite-plugin-db.js +66 -23
  32. package/dist/core/integration/vite-plugin-inject-env-ts.d.ts +1 -1
  33. package/dist/core/load-file.d.ts +31 -0
  34. package/dist/core/load-file.js +98 -0
  35. package/dist/core/tokens.js +1 -1
  36. package/dist/core/types.d.ts +832 -5306
  37. package/dist/core/types.js +16 -84
  38. package/dist/core/utils.d.ts +2 -0
  39. package/dist/core/utils.js +8 -0
  40. package/dist/index.d.ts +2 -3
  41. package/dist/index.js +3 -5
  42. package/dist/runtime/config.d.ts +138 -0
  43. package/dist/runtime/config.js +42 -0
  44. package/dist/runtime/db-client.d.ts +2 -9
  45. package/dist/runtime/db-client.js +8 -39
  46. package/dist/runtime/index.d.ts +5 -4
  47. package/dist/runtime/index.js +12 -10
  48. package/dist/{core → runtime}/queries.d.ts +15 -17
  49. package/dist/{core → runtime}/queries.js +63 -91
  50. package/dist/runtime/types.d.ts +3 -3
  51. package/dist/utils.d.ts +1 -0
  52. package/dist/utils.js +4 -0
  53. package/index.d.ts +5 -3
  54. package/package.json +18 -3
  55. package/config-augment.d.ts +0 -4
  56. package/dist/core/integration/load-astro-config.d.ts +0 -6
  57. package/dist/core/integration/load-astro-config.js +0 -79
@@ -1,127 +1,100 @@
1
- import {
2
- } from "../core/types.js";
3
- import { bold } from "kleur/colors";
4
- import { sql, getTableName } from "drizzle-orm";
1
+ import { LibsqlError } from "@libsql/client";
2
+ import { sql } from "drizzle-orm";
5
3
  import { SQLiteAsyncDialect } from "drizzle-orm/sqlite-core";
6
- import { hasPrimaryKey } from "../runtime/index.js";
7
- import { isSerializedSQL } from "../runtime/types.js";
8
- import { SEED_EMPTY_ARRAY_ERROR, SEED_ERROR, SEED_WRITABLE_IN_PROD_ERROR } from "./errors.js";
4
+ import { bold } from "kleur/colors";
5
+ import {
6
+ FOREIGN_KEY_DNE_ERROR,
7
+ FOREIGN_KEY_REFERENCES_EMPTY_ERROR,
8
+ FOREIGN_KEY_REFERENCES_LENGTH_ERROR,
9
+ REFERENCE_DNE_ERROR,
10
+ SEED_ERROR
11
+ } from "../core/errors.js";
12
+ import { hasPrimaryKey } from "./index.js";
13
+ import { isSerializedSQL } from "./types.js";
9
14
  const sqlite = new SQLiteAsyncDialect();
10
- async function recreateTables({
15
+ const SEED_DEV_FILE_NAME = ["seed.ts", "seed.js", "seed.mjs", "seed.mts"];
16
+ async function seedLocal({
11
17
  db,
12
- tables
18
+ tables,
19
+ // Glob all potential seed files to catch renames and deletions.
20
+ fileGlob
13
21
  }) {
14
- const setupQueries = [];
15
- for (const [name, collection] of Object.entries(tables)) {
16
- const dropQuery = sql.raw(`DROP TABLE IF EXISTS ${sqlite.escapeName(name)}`);
17
- const createQuery = sql.raw(getCreateTableQuery(name, collection));
18
- const indexQueries = getCreateIndexQueries(name, collection);
19
- setupQueries.push(dropQuery, createQuery, ...indexQueries.map((s) => sql.raw(s)));
20
- }
21
- for (const q of setupQueries) {
22
- await db.run(q);
23
- }
24
- }
25
- async function seedData({
26
- db,
27
- data,
28
- logger,
29
- mode
30
- }) {
31
- const dataFns = Array.isArray(data) ? data : [data];
32
- try {
33
- for (const dataFn of dataFns) {
34
- await dataFn({
35
- seed: async (config, values) => {
36
- seedErrorChecks(mode, config, values);
37
- try {
38
- await db.insert(config.table).values(values);
39
- } catch (e) {
40
- const msg = e instanceof Error ? e.message : String(e);
41
- throw new Error(SEED_ERROR(getTableName(config.table), msg));
42
- }
43
- },
44
- seedReturning: async (config, values) => {
45
- seedErrorChecks(mode, config, values);
46
- try {
47
- let result = db.insert(config.table).values(values).returning();
48
- if (!Array.isArray(values)) {
49
- result = result.get();
50
- }
51
- return result;
52
- } catch (e) {
53
- const msg = e instanceof Error ? e.message : String(e);
54
- throw new Error(SEED_ERROR(getTableName(config.table), msg));
55
- }
56
- },
57
- db,
58
- mode
22
+ await recreateTables({ db, tables });
23
+ for (const fileName of SEED_DEV_FILE_NAME) {
24
+ const key = Object.keys(fileGlob).find((f) => f.endsWith(fileName));
25
+ if (key) {
26
+ await fileGlob[key]().catch((e) => {
27
+ if (e instanceof LibsqlError) {
28
+ throw new Error(SEED_ERROR(e.message));
29
+ }
30
+ throw e;
59
31
  });
32
+ return;
60
33
  }
61
- } catch (e) {
62
- if (!(e instanceof Error))
63
- throw e;
64
- (logger ?? console).error(e.message);
65
34
  }
66
35
  }
67
- function seedErrorChecks(mode, { table, writable }, values) {
68
- const tableName = getTableName(table);
69
- if (writable && mode === "build" && process.env.ASTRO_DB_TEST_ENV !== "1") {
70
- throw new Error(SEED_WRITABLE_IN_PROD_ERROR(tableName));
71
- }
72
- if (Array.isArray(values) && values.length === 0) {
73
- throw new Error(SEED_EMPTY_ARRAY_ERROR(tableName));
36
+ async function recreateTables({ db, tables }) {
37
+ const setupQueries = [];
38
+ for (const [name, table] of Object.entries(tables)) {
39
+ const dropQuery = sql.raw(`DROP TABLE IF EXISTS ${sqlite.escapeName(name)}`);
40
+ const createQuery = sql.raw(getCreateTableQuery(name, table));
41
+ const indexQueries = getCreateIndexQueries(name, table);
42
+ setupQueries.push(dropQuery, createQuery, ...indexQueries.map((s) => sql.raw(s)));
74
43
  }
44
+ await db.batch([
45
+ db.run(sql`pragma defer_foreign_keys=true;`),
46
+ ...setupQueries.map((q) => db.run(q))
47
+ ]);
75
48
  }
76
- function getCreateTableQuery(collectionName, collection) {
77
- let query = `CREATE TABLE ${sqlite.escapeName(collectionName)} (`;
49
+ function getCreateTableQuery(tableName, table) {
50
+ let query = `CREATE TABLE ${sqlite.escapeName(tableName)} (`;
78
51
  const colQueries = [];
79
- const colHasPrimaryKey = Object.entries(collection.columns).find(
52
+ const colHasPrimaryKey = Object.entries(table.columns).find(
80
53
  ([, column]) => hasPrimaryKey(column)
81
54
  );
82
55
  if (!colHasPrimaryKey) {
83
56
  colQueries.push("_id INTEGER PRIMARY KEY");
84
57
  }
85
- for (const [columnName, column] of Object.entries(collection.columns)) {
58
+ for (const [columnName, column] of Object.entries(table.columns)) {
86
59
  const colQuery = `${sqlite.escapeName(columnName)} ${schemaTypeToSqlType(
87
60
  column.type
88
61
  )}${getModifiers(columnName, column)}`;
89
62
  colQueries.push(colQuery);
90
63
  }
91
- colQueries.push(...getCreateForeignKeyQueries(collectionName, collection));
64
+ colQueries.push(...getCreateForeignKeyQueries(tableName, table));
92
65
  query += colQueries.join(", ") + ")";
93
66
  return query;
94
67
  }
95
- function getCreateIndexQueries(collectionName, collection) {
68
+ function getCreateIndexQueries(tableName, table) {
96
69
  let queries = [];
97
- for (const [indexName, indexProps] of Object.entries(collection.indexes ?? {})) {
70
+ for (const [indexName, indexProps] of Object.entries(table.indexes ?? {})) {
98
71
  const onColNames = asArray(indexProps.on);
99
72
  const onCols = onColNames.map((colName) => sqlite.escapeName(colName));
100
73
  const unique = indexProps.unique ? "UNIQUE " : "";
101
74
  const indexQuery = `CREATE ${unique}INDEX ${sqlite.escapeName(
102
75
  indexName
103
- )} ON ${sqlite.escapeName(collectionName)} (${onCols.join(", ")})`;
76
+ )} ON ${sqlite.escapeName(tableName)} (${onCols.join(", ")})`;
104
77
  queries.push(indexQuery);
105
78
  }
106
79
  return queries;
107
80
  }
108
- function getCreateForeignKeyQueries(collectionName, collection) {
81
+ function getCreateForeignKeyQueries(tableName, table) {
109
82
  let queries = [];
110
- for (const foreignKey of collection.foreignKeys ?? []) {
83
+ for (const foreignKey of table.foreignKeys ?? []) {
111
84
  const columns = asArray(foreignKey.columns);
112
85
  const references = asArray(foreignKey.references);
113
86
  if (columns.length !== references.length) {
114
- throw new Error(
115
- `Foreign key on ${collectionName} is misconfigured. \`columns\` and \`references\` must be the same length.`
116
- );
87
+ throw new Error(FOREIGN_KEY_REFERENCES_LENGTH_ERROR(tableName));
88
+ }
89
+ const firstReference = references[0];
90
+ if (!firstReference) {
91
+ throw new Error(FOREIGN_KEY_REFERENCES_EMPTY_ERROR(tableName));
117
92
  }
118
- const referencedCollection = references[0]?.schema.collection;
119
- if (!referencedCollection) {
120
- throw new Error(
121
- `Foreign key on ${collectionName} is misconfigured. \`references\` cannot be empty.`
122
- );
93
+ const referencedTable = firstReference.schema.collection;
94
+ if (!referencedTable) {
95
+ throw new Error(FOREIGN_KEY_DNE_ERROR(tableName));
123
96
  }
124
- const query = `FOREIGN KEY (${columns.map((f) => sqlite.escapeName(f)).join(", ")}) REFERENCES ${sqlite.escapeName(referencedCollection)}(${references.map((r) => sqlite.escapeName(r.schema.name)).join(", ")})`;
97
+ const query = `FOREIGN KEY (${columns.map((f) => sqlite.escapeName(f)).join(", ")}) REFERENCES ${sqlite.escapeName(referencedTable)}(${references.map((r) => sqlite.escapeName(r.schema.name)).join(", ")})`;
125
98
  queries.push(query);
126
99
  }
127
100
  return queries;
@@ -156,13 +129,11 @@ function getModifiers(columnName, column) {
156
129
  }
157
130
  const references = getReferencesConfig(column);
158
131
  if (references) {
159
- const { collection, name } = references.schema;
160
- if (!collection || !name) {
161
- throw new Error(
162
- `Column ${collection}.${name} references a collection that does not exist. Did you apply the referenced collection to the \`tables\` object in your Astro config?`
163
- );
132
+ const { collection: tableName, name } = references.schema;
133
+ if (!tableName || !name) {
134
+ throw new Error(REFERENCE_DNE_ERROR(columnName));
164
135
  }
165
- modifiers += ` REFERENCES ${sqlite.escapeName(collection)} (${sqlite.escapeName(name)})`;
136
+ modifiers += ` REFERENCES ${sqlite.escapeName(tableName)} (${sqlite.escapeName(name)})`;
166
137
  }
167
138
  return modifiers;
168
139
  }
@@ -218,6 +189,7 @@ function getDefaultValueSql(columnName, column) {
218
189
  }
219
190
  }
220
191
  export {
192
+ SEED_DEV_FILE_NAME,
221
193
  getCreateForeignKeyQueries,
222
194
  getCreateIndexQueries,
223
195
  getCreateTableQuery,
@@ -226,5 +198,5 @@ export {
226
198
  hasDefault,
227
199
  recreateTables,
228
200
  schemaTypeToSqlType,
229
- seedData
201
+ seedLocal
230
202
  };
@@ -1,6 +1,6 @@
1
- import type { ColumnDataType, ColumnBaseConfig } from 'drizzle-orm';
1
+ import type { ColumnBaseConfig, ColumnDataType } from 'drizzle-orm';
2
2
  import type { SQLiteColumn, SQLiteTableWithColumns } from 'drizzle-orm/sqlite-core';
3
- import type { DBColumn, ColumnsConfig } from '../core/types.js';
3
+ import type { ColumnsConfig, DBColumn, OutputColumnsConfig } from '../core/types.js';
4
4
  type GeneratedConfig<T extends ColumnDataType = ColumnDataType> = Pick<ColumnBaseConfig<T, string>, 'name' | 'tableName' | 'notNull' | 'hasDefault'>;
5
5
  export type AstroText<T extends GeneratedConfig<'string'>> = SQLiteColumn<T & {
6
6
  data: string;
@@ -43,7 +43,7 @@ export type AstroJson<T extends GeneratedConfig<'custom'>> = SQLiteColumn<T & {
43
43
  baseColumn: never;
44
44
  }>;
45
45
  export type Column<T extends DBColumn['type'], S extends GeneratedConfig> = T extends 'boolean' ? AstroBoolean<S> : T extends 'number' ? AstroNumber<S> : T extends 'text' ? AstroText<S> : T extends 'date' ? AstroDate<S> : T extends 'json' ? AstroJson<S> : never;
46
- export type Table<TTableName extends string, TColumns extends ColumnsConfig> = SQLiteTableWithColumns<{
46
+ export type Table<TTableName extends string, TColumns extends OutputColumnsConfig | ColumnsConfig> = SQLiteTableWithColumns<{
47
47
  name: TTableName;
48
48
  schema: undefined;
49
49
  dialect: 'sqlite';
@@ -0,0 +1 @@
1
+ export { asDrizzleTable } from './runtime/index.js';
package/dist/utils.js ADDED
@@ -0,0 +1,4 @@
1
+ import { asDrizzleTable } from "./runtime/index.js";
2
+ export {
3
+ asDrizzleTable
4
+ };
package/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
- /// <reference types="./config-augment.d.ts" />
2
- export * from './dist/index.js';
3
- export { default } from './dist/index.js';
1
+ export { default, cli } from './dist/index.js';
2
+
3
+ declare module 'astro:db' {
4
+ export { defineTable, defineDB, column, sql, NOW, TRUE, FALSE } from './dist/index.js';
5
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrojs/db",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -12,6 +12,10 @@
12
12
  "types": "./index.d.ts",
13
13
  "import": "./dist/index.js"
14
14
  },
15
+ "./utils": {
16
+ "types": "./dist/utils.d.ts",
17
+ "import": "./dist/utils.js"
18
+ },
15
19
  "./runtime": {
16
20
  "types": "./dist/runtime/index.d.ts",
17
21
  "import": "./dist/runtime/index.js"
@@ -20,6 +24,10 @@
20
24
  "types": "./dist/runtime/drizzle.d.ts",
21
25
  "import": "./dist/runtime/drizzle.js"
22
26
  },
27
+ "./runtime/config": {
28
+ "types": "./dist/runtime/config.d.ts",
29
+ "import": "./dist/runtime/config.js"
30
+ },
23
31
  "./package.json": "./package.json"
24
32
  },
25
33
  "typesVersions": {
@@ -27,11 +35,17 @@
27
35
  ".": [
28
36
  "./index.d.ts"
29
37
  ],
38
+ "utils": [
39
+ "./dist/utils.d.ts"
40
+ ],
30
41
  "runtime": [
31
42
  "./dist/runtime/index.d.ts"
32
43
  ],
33
44
  "runtime/drizzle": [
34
45
  "./dist/runtime/drizzle.d.ts"
46
+ ],
47
+ "runtime/config": [
48
+ "./dist/runtime/config.d.ts"
35
49
  ]
36
50
  }
37
51
  },
@@ -46,6 +60,7 @@
46
60
  ],
47
61
  "dependencies": {
48
62
  "@libsql/client": "^0.4.3",
63
+ "async-listen": "^3.0.1",
49
64
  "deep-diff": "^1.0.2",
50
65
  "drizzle-orm": "^0.28.6",
51
66
  "kleur": "^4.1.5",
@@ -67,8 +82,8 @@
67
82
  "cheerio": "1.0.0-rc.12",
68
83
  "mocha": "^10.2.0",
69
84
  "typescript": "^5.2.2",
70
- "vite": "^4.4.11",
71
- "astro": "4.4.5",
85
+ "vite": "^5.1.4",
86
+ "astro": "4.4.9",
72
87
  "astro-scripts": "0.0.14"
73
88
  },
74
89
  "scripts": {
@@ -1,4 +0,0 @@
1
- declare namespace Config {
2
- type DBUserConfig = import('./dist/core/types.js').DBUserConfig;
3
- export interface Database extends DBUserConfig {}
4
- }
@@ -1,6 +0,0 @@
1
- /**
2
- * Pulled from the mothership, Astro core ❤️
3
- *
4
- * @see https://github.com/withastro/astro/blob/main/packages/astro/src/core/config/config.ts#L121
5
- */
6
- export declare function loadAstroConfig(root: string): Promise<Record<string, unknown>>;
@@ -1,79 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import { pathToFileURL } from "node:url";
4
- import { bold, red } from "kleur/colors";
5
- import { createServer } from "vite";
6
- async function loadAstroConfig(root) {
7
- const configPath = search(root);
8
- if (!configPath)
9
- return {};
10
- try {
11
- return await loadConfigWithVite(configPath);
12
- } catch (e) {
13
- console.error(`${bold(red("[astro]"))} Unable to load Astro config.
14
- `);
15
- throw e;
16
- }
17
- }
18
- function search(root) {
19
- const paths = [
20
- "astro.config.mjs",
21
- "astro.config.js",
22
- "astro.config.ts",
23
- "astro.config.mts",
24
- "astro.config.cjs",
25
- "astro.config.cts"
26
- ].map((p) => path.join(root, p));
27
- for (const file of paths) {
28
- if (fs.existsSync(file)) {
29
- return file;
30
- }
31
- }
32
- }
33
- async function loadConfigWithVite(configPath) {
34
- if (/\.[cm]?js$/.test(configPath)) {
35
- try {
36
- const config = await import(
37
- /* @vite-ignore */
38
- pathToFileURL(configPath).toString() + "?t=" + Date.now()
39
- );
40
- return config.default ?? {};
41
- } catch (e) {
42
- }
43
- }
44
- let server;
45
- try {
46
- server = await createViteServer();
47
- const mod = await server.ssrLoadModule(configPath, { fixStacktrace: true });
48
- return mod.default ?? {};
49
- } finally {
50
- if (server) {
51
- await server.close();
52
- }
53
- }
54
- }
55
- async function createViteServer() {
56
- const viteServer = await createServer({
57
- server: { middlewareMode: true, hmr: false, watch: { ignored: ["**"] } },
58
- optimizeDeps: { disabled: true },
59
- clearScreen: false,
60
- appType: "custom",
61
- ssr: {
62
- // NOTE: Vite doesn't externalize linked packages by default. During testing locally,
63
- // these dependencies trip up Vite's dev SSR transform. Awaiting upstream feature:
64
- // https://github.com/vitejs/vite/pull/10939
65
- external: [
66
- "@astrojs/tailwind",
67
- "@astrojs/mdx",
68
- "@astrojs/react",
69
- "@astrojs/preact",
70
- "@astrojs/sitemap",
71
- "@astrojs/markdoc"
72
- ]
73
- }
74
- });
75
- return viteServer;
76
- }
77
- export {
78
- loadAstroConfig
79
- };