@astrojs/db 0.0.0-10646-20240402132948

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 (78) hide show
  1. package/LICENSE +59 -0
  2. package/README.md +38 -0
  3. package/dist/_internal/core/integration/error-map.d.ts +6 -0
  4. package/dist/_internal/core/schemas.d.ts +4034 -0
  5. package/dist/_internal/core/types.d.ts +59 -0
  6. package/dist/_internal/core/utils.d.ts +20 -0
  7. package/dist/_internal/runtime/config.d.ts +154 -0
  8. package/dist/_internal/runtime/types.d.ts +69 -0
  9. package/dist/core/cli/commands/execute/index.d.ts +8 -0
  10. package/dist/core/cli/commands/execute/index.js +66 -0
  11. package/dist/core/cli/commands/link/index.d.ts +20 -0
  12. package/dist/core/cli/commands/link/index.js +252 -0
  13. package/dist/core/cli/commands/login/index.d.ts +8 -0
  14. package/dist/core/cli/commands/login/index.js +55 -0
  15. package/dist/core/cli/commands/logout/index.d.ts +1 -0
  16. package/dist/core/cli/commands/logout/index.js +9 -0
  17. package/dist/core/cli/commands/push/index.d.ts +8 -0
  18. package/dist/core/cli/commands/push/index.js +93 -0
  19. package/dist/core/cli/commands/shell/index.d.ts +8 -0
  20. package/dist/core/cli/commands/shell/index.js +33 -0
  21. package/dist/core/cli/commands/verify/index.d.ts +8 -0
  22. package/dist/core/cli/commands/verify/index.js +46 -0
  23. package/dist/core/cli/index.d.ts +6 -0
  24. package/dist/core/cli/index.js +76 -0
  25. package/dist/core/cli/migration-queries.d.ts +23 -0
  26. package/dist/core/cli/migration-queries.js +386 -0
  27. package/dist/core/cli/print-help.d.ts +11 -0
  28. package/dist/core/cli/print-help.js +55 -0
  29. package/dist/core/consts.d.ts +8 -0
  30. package/dist/core/consts.js +21 -0
  31. package/dist/core/errors.d.ts +10 -0
  32. package/dist/core/errors.js +56 -0
  33. package/dist/core/integration/error-map.d.ts +6 -0
  34. package/dist/core/integration/error-map.js +79 -0
  35. package/dist/core/integration/file-url.d.ts +2 -0
  36. package/dist/core/integration/file-url.js +81 -0
  37. package/dist/core/integration/index.d.ts +2 -0
  38. package/dist/core/integration/index.js +160 -0
  39. package/dist/core/integration/typegen.d.ts +7 -0
  40. package/dist/core/integration/typegen.js +33 -0
  41. package/dist/core/integration/vite-plugin-db.d.ts +39 -0
  42. package/dist/core/integration/vite-plugin-db.js +134 -0
  43. package/dist/core/integration/vite-plugin-inject-env-ts.d.ts +11 -0
  44. package/dist/core/integration/vite-plugin-inject-env-ts.js +53 -0
  45. package/dist/core/load-file.d.ts +253 -0
  46. package/dist/core/load-file.js +170 -0
  47. package/dist/core/schemas.d.ts +4034 -0
  48. package/dist/core/schemas.js +186 -0
  49. package/dist/core/tokens.d.ts +11 -0
  50. package/dist/core/tokens.js +181 -0
  51. package/dist/core/types.d.ts +59 -0
  52. package/dist/core/types.js +0 -0
  53. package/dist/core/utils.d.ts +20 -0
  54. package/dist/core/utils.js +32 -0
  55. package/dist/index.d.ts +4 -0
  56. package/dist/index.js +8 -0
  57. package/dist/runtime/config.js +111 -0
  58. package/dist/runtime/db-client.d.ts +6 -0
  59. package/dist/runtime/db-client.js +148 -0
  60. package/dist/runtime/drizzle.d.ts +1 -0
  61. package/dist/runtime/drizzle.js +48 -0
  62. package/dist/runtime/errors.d.ts +5 -0
  63. package/dist/runtime/errors.js +31 -0
  64. package/dist/runtime/index.d.ts +26 -0
  65. package/dist/runtime/index.js +131 -0
  66. package/dist/runtime/queries.d.ts +71 -0
  67. package/dist/runtime/queries.js +169 -0
  68. package/dist/runtime/seed-local.d.ts +10 -0
  69. package/dist/runtime/seed-local.js +55 -0
  70. package/dist/runtime/types.d.ts +69 -0
  71. package/dist/runtime/types.js +8 -0
  72. package/dist/runtime/utils.d.ts +8 -0
  73. package/dist/runtime/utils.js +17 -0
  74. package/dist/utils.d.ts +2 -0
  75. package/dist/utils.js +6 -0
  76. package/index.d.ts +3 -0
  77. package/package.json +95 -0
  78. package/virtual.d.ts +45 -0
@@ -0,0 +1,148 @@
1
+ import { createClient } from "@libsql/client";
2
+ import { drizzle as drizzleLibsql } from "drizzle-orm/libsql";
3
+ import { drizzle as drizzleProxy } from "drizzle-orm/sqlite-proxy";
4
+ import { z } from "zod";
5
+ import { AstroDbError, safeFetch } from "./utils.js";
6
+ const isWebContainer = !!process.versions?.webcontainer;
7
+ function applyTransactionNotSupported(db) {
8
+ Object.assign(db, {
9
+ transaction() {
10
+ throw new Error(
11
+ "`db.transaction()` is not currently supported. We recommend `db.batch()` for automatic error rollbacks across multiple queries."
12
+ );
13
+ }
14
+ });
15
+ }
16
+ function createLocalDatabaseClient({ dbUrl }) {
17
+ const url = isWebContainer ? "file:content.db" : dbUrl;
18
+ const client = createClient({ url });
19
+ const db = drizzleLibsql(client);
20
+ applyTransactionNotSupported(db);
21
+ return db;
22
+ }
23
+ const remoteResultSchema = z.object({
24
+ columns: z.array(z.string()),
25
+ columnTypes: z.array(z.string()),
26
+ rows: z.array(z.array(z.unknown())),
27
+ rowsAffected: z.number(),
28
+ lastInsertRowid: z.unknown().optional()
29
+ });
30
+ function createRemoteDatabaseClient(appToken, remoteDbURL) {
31
+ if (appToken == null) {
32
+ throw new Error(`Cannot create a remote client: missing app token.`);
33
+ }
34
+ const url = new URL("/db/query", remoteDbURL);
35
+ const db = drizzleProxy(
36
+ async (sql, parameters, method) => {
37
+ const requestBody = { sql, args: parameters };
38
+ const res = await safeFetch(
39
+ url,
40
+ {
41
+ method: "POST",
42
+ headers: {
43
+ Authorization: `Bearer ${appToken}`,
44
+ "Content-Type": "application/json"
45
+ },
46
+ body: JSON.stringify(requestBody)
47
+ },
48
+ async (response) => {
49
+ throw await parseRemoteError(response);
50
+ }
51
+ );
52
+ let remoteResult;
53
+ try {
54
+ const json = await res.json();
55
+ remoteResult = remoteResultSchema.parse(json);
56
+ } catch (e) {
57
+ throw new AstroDbError(await getUnexpectedResponseMessage(res));
58
+ }
59
+ if (method === "run")
60
+ return remoteResult;
61
+ const rowValues = [];
62
+ for (const row of remoteResult.rows) {
63
+ if (row != null && typeof row === "object") {
64
+ rowValues.push(Object.values(row));
65
+ }
66
+ }
67
+ if (method === "get") {
68
+ return { rows: rowValues[0] };
69
+ }
70
+ return { rows: rowValues };
71
+ },
72
+ async (queries) => {
73
+ const stmts = queries.map(({ sql, params }) => ({ sql, args: params }));
74
+ const res = await safeFetch(
75
+ url,
76
+ {
77
+ method: "POST",
78
+ headers: {
79
+ Authorization: `Bearer ${appToken}`,
80
+ "Content-Type": "application/json"
81
+ },
82
+ body: JSON.stringify(stmts)
83
+ },
84
+ async (response) => {
85
+ throw await parseRemoteError(response);
86
+ }
87
+ );
88
+ let remoteResults;
89
+ try {
90
+ const json = await res.json();
91
+ remoteResults = z.array(remoteResultSchema).parse(json);
92
+ } catch (e) {
93
+ throw new AstroDbError(await getUnexpectedResponseMessage(res));
94
+ }
95
+ let results = [];
96
+ for (const [idx, rawResult] of remoteResults.entries()) {
97
+ if (queries[idx]?.method === "run") {
98
+ results.push(rawResult);
99
+ continue;
100
+ }
101
+ const rowValues = [];
102
+ for (const row of rawResult.rows) {
103
+ if (row != null && typeof row === "object") {
104
+ rowValues.push(Object.values(row));
105
+ }
106
+ }
107
+ if (queries[idx]?.method === "get") {
108
+ results.push({ rows: rowValues[0] });
109
+ }
110
+ results.push({ rows: rowValues });
111
+ }
112
+ return results;
113
+ }
114
+ );
115
+ applyTransactionNotSupported(db);
116
+ return db;
117
+ }
118
+ const errorSchema = z.object({
119
+ success: z.boolean(),
120
+ error: z.object({
121
+ code: z.string(),
122
+ details: z.string().optional()
123
+ })
124
+ });
125
+ const KNOWN_ERROR_CODES = {
126
+ SQL_QUERY_FAILED: "SQL_QUERY_FAILED"
127
+ };
128
+ const getUnexpectedResponseMessage = async (response) => `Unexpected response from remote database:
129
+ (Status ${response.status}) ${await response.text()}`;
130
+ async function parseRemoteError(response) {
131
+ let error;
132
+ try {
133
+ error = errorSchema.parse(await response.json()).error;
134
+ } catch (e) {
135
+ return new AstroDbError(await getUnexpectedResponseMessage(response));
136
+ }
137
+ let details = error.details?.replace(/.*SQLite error: /, "") ?? `(Code ${error.code})
138
+ Error querying remote database.`;
139
+ let hint = `See the Astro DB guide for query and push instructions: https://docs.astro.build/en/guides/astro-db/#query-your-database`;
140
+ if (error.code === KNOWN_ERROR_CODES.SQL_QUERY_FAILED && details.includes("no such table")) {
141
+ hint = `Did you run \`astro db push\` to push your latest table schemas?`;
142
+ }
143
+ return new AstroDbError(details, hint);
144
+ }
145
+ export {
146
+ createLocalDatabaseClient,
147
+ createRemoteDatabaseClient
148
+ };
@@ -0,0 +1 @@
1
+ export { sql, eq, gt, gte, lt, lte, ne, isNull, isNotNull, inArray, notInArray, exists, notExists, between, notBetween, like, notIlike, not, asc, desc, and, or, } from 'drizzle-orm';
@@ -0,0 +1,48 @@
1
+ import {
2
+ sql,
3
+ eq,
4
+ gt,
5
+ gte,
6
+ lt,
7
+ lte,
8
+ ne,
9
+ isNull,
10
+ isNotNull,
11
+ inArray,
12
+ notInArray,
13
+ exists,
14
+ notExists,
15
+ between,
16
+ notBetween,
17
+ like,
18
+ notIlike,
19
+ not,
20
+ asc,
21
+ desc,
22
+ and,
23
+ or
24
+ } from "drizzle-orm";
25
+ export {
26
+ and,
27
+ asc,
28
+ between,
29
+ desc,
30
+ eq,
31
+ exists,
32
+ gt,
33
+ gte,
34
+ inArray,
35
+ isNotNull,
36
+ isNull,
37
+ like,
38
+ lt,
39
+ lte,
40
+ ne,
41
+ not,
42
+ notBetween,
43
+ notExists,
44
+ notIlike,
45
+ notInArray,
46
+ or,
47
+ sql
48
+ };
@@ -0,0 +1,5 @@
1
+ export declare const FOREIGN_KEY_DNE_ERROR: (tableName: string) => string;
2
+ export declare const FOREIGN_KEY_REFERENCES_LENGTH_ERROR: (tableName: string) => string;
3
+ export declare const FOREIGN_KEY_REFERENCES_EMPTY_ERROR: (tableName: string) => string;
4
+ export declare const REFERENCE_DNE_ERROR: (columnName: string) => string;
5
+ export declare const SEED_DEFAULT_EXPORT_ERROR: (fileName: string) => string;
@@ -0,0 +1,31 @@
1
+ import { bold, red } from "kleur/colors";
2
+ const FOREIGN_KEY_DNE_ERROR = (tableName) => {
3
+ return `Table ${bold(
4
+ tableName
5
+ )} references a table that does not exist. Did you apply the referenced table to the \`tables\` object in your db config?`;
6
+ };
7
+ const FOREIGN_KEY_REFERENCES_LENGTH_ERROR = (tableName) => {
8
+ return `Foreign key on ${bold(
9
+ tableName
10
+ )} is misconfigured. \`columns\` and \`references\` must be the same length.`;
11
+ };
12
+ const FOREIGN_KEY_REFERENCES_EMPTY_ERROR = (tableName) => {
13
+ return `Foreign key on ${bold(
14
+ tableName
15
+ )} is misconfigured. \`references\` array cannot be empty.`;
16
+ };
17
+ const REFERENCE_DNE_ERROR = (columnName) => {
18
+ return `Column ${bold(
19
+ columnName
20
+ )} references a table that does not exist. Did you apply the referenced table to the \`tables\` object in your db config?`;
21
+ };
22
+ const SEED_DEFAULT_EXPORT_ERROR = (fileName) => {
23
+ return `Missing default function export in ${bold(fileName)}`;
24
+ };
25
+ export {
26
+ FOREIGN_KEY_DNE_ERROR,
27
+ FOREIGN_KEY_REFERENCES_EMPTY_ERROR,
28
+ FOREIGN_KEY_REFERENCES_LENGTH_ERROR,
29
+ REFERENCE_DNE_ERROR,
30
+ SEED_DEFAULT_EXPORT_ERROR
31
+ };
@@ -0,0 +1,26 @@
1
+ import { type ColumnDataType } from 'drizzle-orm';
2
+ import { type DBColumn, type DBTable } from '../core/types.js';
3
+ export type { Table } from './types.js';
4
+ export { createRemoteDatabaseClient, createLocalDatabaseClient } from './db-client.js';
5
+ export { seedLocal } from './seed-local.js';
6
+ export declare function hasPrimaryKey(column: DBColumn): boolean;
7
+ export declare function asDrizzleTable(name: string, table: DBTable): import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
8
+ name: string;
9
+ schema: undefined;
10
+ columns: {
11
+ [x: string]: import("drizzle-orm/sqlite-core").SQLiteColumn<{
12
+ name: string;
13
+ tableName: string;
14
+ dataType: ColumnDataType;
15
+ columnType: string;
16
+ data: unknown;
17
+ driverParam: unknown;
18
+ notNull: false;
19
+ hasDefault: false;
20
+ enumValues: string[] | undefined;
21
+ baseColumn: never;
22
+ }, object>;
23
+ };
24
+ dialect: "sqlite";
25
+ }>;
26
+ export declare function normalizeDatabaseUrl(envDbUrl: string | undefined, defaultDbUrl: string): string;
@@ -0,0 +1,131 @@
1
+ import { pathToFileURL } from "url";
2
+ import { sql } from "drizzle-orm";
3
+ import {
4
+ customType,
5
+ index,
6
+ integer,
7
+ sqliteTable,
8
+ text
9
+ } from "drizzle-orm/sqlite-core";
10
+ import {} from "../core/types.js";
11
+ import { isSerializedSQL } from "./types.js";
12
+ import { createRemoteDatabaseClient, createLocalDatabaseClient } from "./db-client.js";
13
+ import { seedLocal } from "./seed-local.js";
14
+ function hasPrimaryKey(column) {
15
+ return "primaryKey" in column.schema && !!column.schema.primaryKey;
16
+ }
17
+ const dateType = customType({
18
+ dataType() {
19
+ return "text";
20
+ },
21
+ toDriver(value) {
22
+ return value.toISOString();
23
+ },
24
+ fromDriver(value) {
25
+ return new Date(value);
26
+ }
27
+ });
28
+ const jsonType = customType({
29
+ dataType() {
30
+ return "text";
31
+ },
32
+ toDriver(value) {
33
+ return JSON.stringify(value);
34
+ },
35
+ fromDriver(value) {
36
+ return JSON.parse(value);
37
+ }
38
+ });
39
+ function asDrizzleTable(name, table) {
40
+ const columns = {};
41
+ if (!Object.entries(table.columns).some(([, column]) => hasPrimaryKey(column))) {
42
+ columns["_id"] = integer("_id").primaryKey();
43
+ }
44
+ for (const [columnName, column] of Object.entries(table.columns)) {
45
+ columns[columnName] = columnMapper(columnName, column);
46
+ }
47
+ const drizzleTable = sqliteTable(name, columns, (ormTable) => {
48
+ const indexes = {};
49
+ for (const [indexName, indexProps] of Object.entries(table.indexes ?? {})) {
50
+ const onColNames = Array.isArray(indexProps.on) ? indexProps.on : [indexProps.on];
51
+ const onCols = onColNames.map((colName) => ormTable[colName]);
52
+ if (!atLeastOne(onCols))
53
+ continue;
54
+ indexes[indexName] = index(indexName).on(...onCols);
55
+ }
56
+ return indexes;
57
+ });
58
+ return drizzleTable;
59
+ }
60
+ function atLeastOne(arr) {
61
+ return arr.length > 0;
62
+ }
63
+ function columnMapper(columnName, column) {
64
+ let c;
65
+ switch (column.type) {
66
+ case "text": {
67
+ c = text(columnName);
68
+ if (column.schema.default !== void 0)
69
+ c = c.default(handleSerializedSQL(column.schema.default));
70
+ if (column.schema.primaryKey === true)
71
+ c = c.primaryKey();
72
+ break;
73
+ }
74
+ case "number": {
75
+ c = integer(columnName);
76
+ if (column.schema.default !== void 0)
77
+ c = c.default(handleSerializedSQL(column.schema.default));
78
+ if (column.schema.primaryKey === true)
79
+ c = c.primaryKey();
80
+ break;
81
+ }
82
+ case "boolean": {
83
+ c = integer(columnName, { mode: "boolean" });
84
+ if (column.schema.default !== void 0)
85
+ c = c.default(handleSerializedSQL(column.schema.default));
86
+ break;
87
+ }
88
+ case "json":
89
+ c = jsonType(columnName);
90
+ if (column.schema.default !== void 0)
91
+ c = c.default(column.schema.default);
92
+ break;
93
+ case "date": {
94
+ c = dateType(columnName);
95
+ if (column.schema.default !== void 0) {
96
+ const def = handleSerializedSQL(column.schema.default);
97
+ c = c.default(typeof def === "string" ? new Date(def) : def);
98
+ }
99
+ break;
100
+ }
101
+ }
102
+ if (!column.schema.optional)
103
+ c = c.notNull();
104
+ if (column.schema.unique)
105
+ c = c.unique();
106
+ return c;
107
+ }
108
+ function handleSerializedSQL(def) {
109
+ if (isSerializedSQL(def)) {
110
+ return sql.raw(def.sql);
111
+ }
112
+ return def;
113
+ }
114
+ function normalizeDatabaseUrl(envDbUrl, defaultDbUrl) {
115
+ if (envDbUrl) {
116
+ if (envDbUrl.startsWith("file://")) {
117
+ return envDbUrl;
118
+ }
119
+ return new URL(envDbUrl, pathToFileURL(process.cwd())).toString();
120
+ } else {
121
+ return defaultDbUrl;
122
+ }
123
+ }
124
+ export {
125
+ asDrizzleTable,
126
+ createLocalDatabaseClient,
127
+ createRemoteDatabaseClient,
128
+ hasPrimaryKey,
129
+ normalizeDatabaseUrl,
130
+ seedLocal
131
+ };
@@ -0,0 +1,71 @@
1
+ import type { BooleanColumn, ColumnType, DBColumn, DBTable, DateColumn, JsonColumn, NumberColumn, TextColumn } from '../core/types.js';
2
+ export declare const SEED_DEV_FILE_NAME: string[];
3
+ export declare function getDropTableIfExistsQuery(tableName: string): string;
4
+ export declare function getCreateTableQuery(tableName: string, table: DBTable): string;
5
+ export declare function getCreateIndexQueries(tableName: string, table: Pick<DBTable, 'indexes'>): string[];
6
+ export declare function getCreateForeignKeyQueries(tableName: string, table: DBTable): string[];
7
+ export declare function schemaTypeToSqlType(type: ColumnType): 'text' | 'integer';
8
+ export declare function getModifiers(columnName: string, column: DBColumn): string;
9
+ export declare function getReferencesConfig(column: DBColumn): {
10
+ type: "number";
11
+ schema: ({
12
+ unique: boolean;
13
+ deprecated: boolean;
14
+ name?: string | undefined;
15
+ label?: string | undefined;
16
+ collection?: string | undefined;
17
+ } & {
18
+ optional: boolean;
19
+ primaryKey: false;
20
+ default?: number | import("./types.js").SerializedSQL | undefined;
21
+ } & {
22
+ references?: any | undefined;
23
+ }) | ({
24
+ unique: boolean;
25
+ deprecated: boolean;
26
+ name?: string | undefined;
27
+ label?: string | undefined;
28
+ collection?: string | undefined;
29
+ } & {
30
+ primaryKey: true;
31
+ optional?: false | undefined;
32
+ default?: undefined;
33
+ } & {
34
+ references?: any | undefined;
35
+ });
36
+ } | {
37
+ type: "text";
38
+ schema: ({
39
+ unique: boolean;
40
+ deprecated: boolean;
41
+ name?: string | undefined;
42
+ label?: string | undefined;
43
+ collection?: string | undefined;
44
+ default?: string | import("./types.js").SerializedSQL | undefined;
45
+ multiline?: boolean | undefined;
46
+ } & {
47
+ optional: boolean;
48
+ primaryKey: false;
49
+ } & {
50
+ references?: any | undefined;
51
+ }) | ({
52
+ unique: boolean;
53
+ deprecated: boolean;
54
+ name?: string | undefined;
55
+ label?: string | undefined;
56
+ collection?: string | undefined;
57
+ default?: string | import("./types.js").SerializedSQL | undefined;
58
+ multiline?: boolean | undefined;
59
+ } & {
60
+ primaryKey: true;
61
+ optional?: false | undefined;
62
+ } & {
63
+ references?: any | undefined;
64
+ });
65
+ } | undefined;
66
+ type WithDefaultDefined<T extends DBColumn> = T & {
67
+ schema: Required<Pick<T['schema'], 'default'>>;
68
+ };
69
+ type DBColumnWithDefault = WithDefaultDefined<TextColumn> | WithDefaultDefined<DateColumn> | WithDefaultDefined<NumberColumn> | WithDefaultDefined<BooleanColumn> | WithDefaultDefined<JsonColumn>;
70
+ export declare function hasDefault(column: DBColumn): column is DBColumnWithDefault;
71
+ export {};
@@ -0,0 +1,169 @@
1
+ import {} from "drizzle-orm";
2
+ import { SQLiteAsyncDialect } from "drizzle-orm/sqlite-core";
3
+ import { bold } from "kleur/colors";
4
+ import {
5
+ FOREIGN_KEY_DNE_ERROR,
6
+ FOREIGN_KEY_REFERENCES_EMPTY_ERROR,
7
+ FOREIGN_KEY_REFERENCES_LENGTH_ERROR,
8
+ REFERENCE_DNE_ERROR
9
+ } from "./errors.js";
10
+ import { hasPrimaryKey } from "./index.js";
11
+ import { isSerializedSQL } from "./types.js";
12
+ const sqlite = new SQLiteAsyncDialect();
13
+ const SEED_DEV_FILE_NAME = ["seed.ts", "seed.js", "seed.mjs", "seed.mts"];
14
+ function getDropTableIfExistsQuery(tableName) {
15
+ return `DROP TABLE IF EXISTS ${sqlite.escapeName(tableName)}`;
16
+ }
17
+ function getCreateTableQuery(tableName, table) {
18
+ let query = `CREATE TABLE ${sqlite.escapeName(tableName)} (`;
19
+ const colQueries = [];
20
+ const colHasPrimaryKey = Object.entries(table.columns).find(
21
+ ([, column]) => hasPrimaryKey(column)
22
+ );
23
+ if (!colHasPrimaryKey) {
24
+ colQueries.push("_id INTEGER PRIMARY KEY");
25
+ }
26
+ for (const [columnName, column] of Object.entries(table.columns)) {
27
+ const colQuery = `${sqlite.escapeName(columnName)} ${schemaTypeToSqlType(
28
+ column.type
29
+ )}${getModifiers(columnName, column)}`;
30
+ colQueries.push(colQuery);
31
+ }
32
+ colQueries.push(...getCreateForeignKeyQueries(tableName, table));
33
+ query += colQueries.join(", ") + ")";
34
+ return query;
35
+ }
36
+ function getCreateIndexQueries(tableName, table) {
37
+ let queries = [];
38
+ for (const [indexName, indexProps] of Object.entries(table.indexes ?? {})) {
39
+ const onColNames = asArray(indexProps.on);
40
+ const onCols = onColNames.map((colName) => sqlite.escapeName(colName));
41
+ const unique = indexProps.unique ? "UNIQUE " : "";
42
+ const indexQuery = `CREATE ${unique}INDEX ${sqlite.escapeName(
43
+ indexName
44
+ )} ON ${sqlite.escapeName(tableName)} (${onCols.join(", ")})`;
45
+ queries.push(indexQuery);
46
+ }
47
+ return queries;
48
+ }
49
+ function getCreateForeignKeyQueries(tableName, table) {
50
+ let queries = [];
51
+ for (const foreignKey of table.foreignKeys ?? []) {
52
+ const columns = asArray(foreignKey.columns);
53
+ const references = asArray(foreignKey.references);
54
+ if (columns.length !== references.length) {
55
+ throw new Error(FOREIGN_KEY_REFERENCES_LENGTH_ERROR(tableName));
56
+ }
57
+ const firstReference = references[0];
58
+ if (!firstReference) {
59
+ throw new Error(FOREIGN_KEY_REFERENCES_EMPTY_ERROR(tableName));
60
+ }
61
+ const referencedTable = firstReference.schema.collection;
62
+ if (!referencedTable) {
63
+ throw new Error(FOREIGN_KEY_DNE_ERROR(tableName));
64
+ }
65
+ const query = `FOREIGN KEY (${columns.map((f) => sqlite.escapeName(f)).join(", ")}) REFERENCES ${sqlite.escapeName(referencedTable)}(${references.map((r) => sqlite.escapeName(r.schema.name)).join(", ")})`;
66
+ queries.push(query);
67
+ }
68
+ return queries;
69
+ }
70
+ function asArray(value) {
71
+ return Array.isArray(value) ? value : [value];
72
+ }
73
+ function schemaTypeToSqlType(type) {
74
+ switch (type) {
75
+ case "date":
76
+ case "text":
77
+ case "json":
78
+ return "text";
79
+ case "number":
80
+ case "boolean":
81
+ return "integer";
82
+ }
83
+ }
84
+ function getModifiers(columnName, column) {
85
+ let modifiers = "";
86
+ if (hasPrimaryKey(column)) {
87
+ return " PRIMARY KEY";
88
+ }
89
+ if (!column.schema.optional) {
90
+ modifiers += " NOT NULL";
91
+ }
92
+ if (column.schema.unique) {
93
+ modifiers += " UNIQUE";
94
+ }
95
+ if (hasDefault(column)) {
96
+ modifiers += ` DEFAULT ${getDefaultValueSql(columnName, column)}`;
97
+ }
98
+ const references = getReferencesConfig(column);
99
+ if (references) {
100
+ const { collection: tableName, name } = references.schema;
101
+ if (!tableName || !name) {
102
+ throw new Error(REFERENCE_DNE_ERROR(columnName));
103
+ }
104
+ modifiers += ` REFERENCES ${sqlite.escapeName(tableName)} (${sqlite.escapeName(name)})`;
105
+ }
106
+ return modifiers;
107
+ }
108
+ function getReferencesConfig(column) {
109
+ const canHaveReferences = column.type === "number" || column.type === "text";
110
+ if (!canHaveReferences)
111
+ return void 0;
112
+ return column.schema.references;
113
+ }
114
+ function hasDefault(column) {
115
+ if (column.schema.default !== void 0) {
116
+ return true;
117
+ }
118
+ if (hasPrimaryKey(column) && column.type === "number") {
119
+ return true;
120
+ }
121
+ return false;
122
+ }
123
+ function toDefault(def) {
124
+ const type = typeof def;
125
+ if (type === "string") {
126
+ return sqlite.escapeString(def);
127
+ } else if (type === "boolean") {
128
+ return def ? "TRUE" : "FALSE";
129
+ } else {
130
+ return def + "";
131
+ }
132
+ }
133
+ function getDefaultValueSql(columnName, column) {
134
+ if (isSerializedSQL(column.schema.default)) {
135
+ return column.schema.default.sql;
136
+ }
137
+ switch (column.type) {
138
+ case "boolean":
139
+ case "number":
140
+ case "text":
141
+ case "date":
142
+ return toDefault(column.schema.default);
143
+ case "json": {
144
+ let stringified = "";
145
+ try {
146
+ stringified = JSON.stringify(column.schema.default);
147
+ } catch (e) {
148
+ console.log(
149
+ `Invalid default value for column ${bold(
150
+ columnName
151
+ )}. Defaults must be valid JSON when using the \`json()\` type.`
152
+ );
153
+ process.exit(0);
154
+ }
155
+ return sqlite.escapeString(stringified);
156
+ }
157
+ }
158
+ }
159
+ export {
160
+ SEED_DEV_FILE_NAME,
161
+ getCreateForeignKeyQueries,
162
+ getCreateIndexQueries,
163
+ getCreateTableQuery,
164
+ getDropTableIfExistsQuery,
165
+ getModifiers,
166
+ getReferencesConfig,
167
+ hasDefault,
168
+ schemaTypeToSqlType
169
+ };
@@ -0,0 +1,10 @@
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>;