@astrojs/db 0.1.2 → 0.1.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.
- package/dist/cli/commands/push/index.js +11 -11
- package/dist/cli/commands/shell/index.d.ts +6 -0
- package/dist/cli/commands/shell/index.js +17 -0
- package/dist/cli/commands/sync/index.js +4 -3
- package/dist/cli/commands/verify/index.js +2 -5
- package/dist/cli/index.js +4 -0
- package/dist/cli/queries.d.ts +4 -5
- package/dist/cli/queries.js +66 -113
- package/dist/config.d.ts +72 -0
- package/dist/config.js +3 -1
- package/dist/integration.js +7 -1
- package/dist/internal.d.ts +11 -15
- package/dist/internal.js +51 -20
- package/dist/migrations.d.ts +7 -4
- package/dist/migrations.js +17 -1
- package/dist/typegen.js +16 -33
- package/dist/types.d.ts +106 -6
- package/dist/types.js +4 -2
- package/package.json +2 -2
- package/dist/cli/sync/index.js +0 -0
- package/dist/cli/sync/migrate.js +0 -0
|
@@ -4,6 +4,8 @@ import { SQLiteAsyncDialect } from "drizzle-orm/sqlite-core";
|
|
|
4
4
|
import { appTokenError } from "../../../errors.js";
|
|
5
5
|
import { collectionToTable, createLocalDatabaseClient } from "../../../internal.js";
|
|
6
6
|
import {
|
|
7
|
+
createCurrentSnapshot,
|
|
8
|
+
createEmptySnapshot,
|
|
7
9
|
getMigrations,
|
|
8
10
|
initializeFromMigrations,
|
|
9
11
|
loadInitialSnapshot,
|
|
@@ -24,8 +26,7 @@ async function cmd({ config, flags }) {
|
|
|
24
26
|
const isSeedData = flags.seed;
|
|
25
27
|
const isDryRun = flags.dryRun;
|
|
26
28
|
const appToken = flags.token ?? getAstroStudioEnv().ASTRO_STUDIO_APP_TOKEN;
|
|
27
|
-
const
|
|
28
|
-
const currentSnapshot = JSON.parse(JSON.stringify(currentDb));
|
|
29
|
+
const currentSnapshot = createCurrentSnapshot(config);
|
|
29
30
|
const allMigrationFiles = await getMigrations();
|
|
30
31
|
if (allMigrationFiles.length === 0) {
|
|
31
32
|
console.log("Project not yet initialized!");
|
|
@@ -35,6 +36,7 @@ async function cmd({ config, flags }) {
|
|
|
35
36
|
const calculatedDiff = diff(prevSnapshot, currentSnapshot);
|
|
36
37
|
if (calculatedDiff) {
|
|
37
38
|
console.log("Changes detected!");
|
|
39
|
+
console.log(calculatedDiff);
|
|
38
40
|
process.exit(1);
|
|
39
41
|
}
|
|
40
42
|
if (!appToken) {
|
|
@@ -58,7 +60,7 @@ async function cmd({ config, flags }) {
|
|
|
58
60
|
}
|
|
59
61
|
if (isSeedData) {
|
|
60
62
|
console.info("Pushing data...");
|
|
61
|
-
await
|
|
63
|
+
await pushData({ config, appToken, isDryRun });
|
|
62
64
|
}
|
|
63
65
|
console.info("Push complete!");
|
|
64
66
|
}
|
|
@@ -73,8 +75,8 @@ async function pushSchema({
|
|
|
73
75
|
const filteredMigrations = migrations.filter((m) => m !== "0000_snapshot.json");
|
|
74
76
|
const missingMigrationContents = await Promise.all(filteredMigrations.map(loadMigration));
|
|
75
77
|
const initialMigrationBatch = initialSnapshot ? await getMigrationQueries({
|
|
76
|
-
|
|
77
|
-
|
|
78
|
+
oldSnapshot: createEmptySnapshot(),
|
|
79
|
+
newSnapshot: await loadInitialSnapshot()
|
|
78
80
|
}) : [];
|
|
79
81
|
const missingMigrationBatch = missingMigrationContents.reduce((acc, curr) => {
|
|
80
82
|
return [...acc, ...curr.db];
|
|
@@ -84,26 +86,24 @@ async function pushSchema({
|
|
|
84
86
|
await db.insert(migrationsTable).values(migrations.map((m) => ({ name: m })));
|
|
85
87
|
await db.update(adminTable).set({ collections: JSON.stringify(currentSnapshot) }).where(eq(adminTable.id, STUDIO_ADMIN_TABLE_ROW_ID));
|
|
86
88
|
}
|
|
87
|
-
async function
|
|
88
|
-
|
|
89
|
+
async function pushData({
|
|
90
|
+
config,
|
|
89
91
|
appToken,
|
|
90
92
|
isDryRun
|
|
91
93
|
}) {
|
|
92
94
|
const db = await createLocalDatabaseClient({
|
|
93
|
-
collections:
|
|
95
|
+
collections: config.db.collections,
|
|
94
96
|
dbUrl: ":memory:",
|
|
95
97
|
seeding: true
|
|
96
98
|
});
|
|
97
99
|
const queries = [];
|
|
98
|
-
for (const [name, collection] of Object.entries(
|
|
99
|
-
console.log(name, collection);
|
|
100
|
+
for (const [name, collection] of Object.entries(config.db.collections)) {
|
|
100
101
|
if (collection.writable || !collection.data)
|
|
101
102
|
continue;
|
|
102
103
|
const table = collectionToTable(name, collection);
|
|
103
104
|
const insert = db.insert(table).values(await collection.data());
|
|
104
105
|
queries.push(insert.toSQL());
|
|
105
106
|
}
|
|
106
|
-
console.log(queries);
|
|
107
107
|
const url = new URL("/db/query", getRemoteDatabaseUrl());
|
|
108
108
|
const requestBody = queries.map((q) => ({
|
|
109
109
|
sql: q.sql,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { sql } from "drizzle-orm";
|
|
2
|
+
import { appTokenError } from "../../../errors.js";
|
|
3
|
+
import { createRemoteDatabaseClient, getAstroStudioEnv } from "../../../utils.js";
|
|
4
|
+
async function cmd({ config, flags }) {
|
|
5
|
+
const query = flags.query;
|
|
6
|
+
const appToken = flags.token ?? getAstroStudioEnv().ASTRO_STUDIO_APP_TOKEN;
|
|
7
|
+
if (!appToken) {
|
|
8
|
+
console.error(appTokenError);
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
const db = createRemoteDatabaseClient(appToken);
|
|
12
|
+
const result = await db.run(sql.raw(query));
|
|
13
|
+
console.log(result);
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
cmd
|
|
17
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import deepDiff from "deep-diff";
|
|
2
2
|
import { writeFile } from "fs/promises";
|
|
3
3
|
import {
|
|
4
|
+
createCurrentSnapshot,
|
|
4
5
|
getMigrations,
|
|
5
6
|
initializeFromMigrations,
|
|
6
7
|
initializeMigrationsDirectory
|
|
@@ -8,7 +9,7 @@ import {
|
|
|
8
9
|
import { getMigrationQueries } from "../../queries.js";
|
|
9
10
|
const { diff } = deepDiff;
|
|
10
11
|
async function cmd({ config }) {
|
|
11
|
-
const currentSnapshot =
|
|
12
|
+
const currentSnapshot = createCurrentSnapshot(config);
|
|
12
13
|
const allMigrationFiles = await getMigrations();
|
|
13
14
|
if (allMigrationFiles.length === 0) {
|
|
14
15
|
await initializeMigrationsDirectory(currentSnapshot);
|
|
@@ -22,8 +23,8 @@ async function cmd({ config }) {
|
|
|
22
23
|
return;
|
|
23
24
|
}
|
|
24
25
|
const migrationQueries = await getMigrationQueries({
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
oldSnapshot: prevSnapshot,
|
|
27
|
+
newSnapshot: currentSnapshot
|
|
27
28
|
});
|
|
28
29
|
const largestNumber = allMigrationFiles.reduce((acc, curr) => {
|
|
29
30
|
const num = parseInt(curr.split("_")[0]);
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import deepDiff from "deep-diff";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
initializeFromMigrations
|
|
5
|
-
} from "../../../migrations.js";
|
|
6
|
-
const { diff, applyChange } = deepDiff;
|
|
2
|
+
import { getMigrations, initializeFromMigrations } from "../../../migrations.js";
|
|
3
|
+
const { diff } = deepDiff;
|
|
7
4
|
async function cmd({ config }) {
|
|
8
5
|
const currentSnapshot = JSON.parse(JSON.stringify(config.db?.collections ?? {}));
|
|
9
6
|
const allMigrationFiles = await getMigrations();
|
package/dist/cli/index.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
async function cli({ flags, config }) {
|
|
2
2
|
const command = flags._[3];
|
|
3
3
|
switch (command) {
|
|
4
|
+
case "shell": {
|
|
5
|
+
const { cmd: shellCommand } = await import("./commands/shell/index.js");
|
|
6
|
+
return await shellCommand({ config, flags });
|
|
7
|
+
}
|
|
4
8
|
case "sync": {
|
|
5
9
|
const { cmd: syncCommand } = await import("./commands/sync/index.js");
|
|
6
10
|
return await syncCommand({ config, flags });
|
package/dist/cli/queries.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import type { DBCollection,
|
|
1
|
+
import type { DBCollection, DBSnapshot } from '../types.js';
|
|
2
2
|
interface PromptResponses {
|
|
3
3
|
allowDataLoss: boolean;
|
|
4
4
|
fieldRenames: Record<string, string | false>;
|
|
5
5
|
collectionRenames: Record<string, string | false>;
|
|
6
6
|
}
|
|
7
|
-
export declare function getMigrationQueries({
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
export declare function getMigrationQueries({ oldSnapshot, newSnapshot, promptResponses, }: {
|
|
8
|
+
oldSnapshot: DBSnapshot;
|
|
9
|
+
newSnapshot: DBSnapshot;
|
|
10
10
|
promptResponses?: PromptResponses;
|
|
11
11
|
}): Promise<string[]>;
|
|
12
12
|
export declare function getCollectionChangeQueries({ collectionName, oldCollection, newCollection, promptResponses, }: {
|
|
@@ -15,5 +15,4 @@ export declare function getCollectionChangeQueries({ collectionName, oldCollecti
|
|
|
15
15
|
newCollection: DBCollection;
|
|
16
16
|
promptResponses?: PromptResponses;
|
|
17
17
|
}): Promise<string[]>;
|
|
18
|
-
export declare function getCreateTableQuery(collectionName: string, collection: DBCollection): string;
|
|
19
18
|
export {};
|
package/dist/cli/queries.js
CHANGED
|
@@ -2,16 +2,17 @@ import * as color from "kleur/colors";
|
|
|
2
2
|
import { SQLiteAsyncDialect } from "drizzle-orm/sqlite-core";
|
|
3
3
|
import { customAlphabet } from "nanoid";
|
|
4
4
|
import prompts from "prompts";
|
|
5
|
+
import { getCreateTableQuery, getModifiers, hasDefault, hasPrimaryKey, schemaTypeToSqlType } from "../internal.js";
|
|
5
6
|
const sqlite = new SQLiteAsyncDialect();
|
|
6
7
|
const genTempTableName = customAlphabet("abcdefghijklmnopqrstuvwxyz", 10);
|
|
7
8
|
async function getMigrationQueries({
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
oldSnapshot,
|
|
10
|
+
newSnapshot,
|
|
10
11
|
promptResponses
|
|
11
12
|
}) {
|
|
12
13
|
const queries = [];
|
|
13
|
-
let added = getAddedCollections(
|
|
14
|
-
let dropped = getDroppedCollections(
|
|
14
|
+
let added = getAddedCollections(oldSnapshot, newSnapshot);
|
|
15
|
+
let dropped = getDroppedCollections(oldSnapshot, newSnapshot);
|
|
15
16
|
if (!isEmpty(added) && !isEmpty(dropped)) {
|
|
16
17
|
const resolved = await resolveCollectionRenames(
|
|
17
18
|
added,
|
|
@@ -34,8 +35,8 @@ async function getMigrationQueries({
|
|
|
34
35
|
const dropQuery = `DROP TABLE ${sqlite.escapeName(collectionName)}`;
|
|
35
36
|
queries.push(dropQuery);
|
|
36
37
|
}
|
|
37
|
-
for (const [collectionName, newCollection] of Object.entries(
|
|
38
|
-
const oldCollection =
|
|
38
|
+
for (const [collectionName, newCollection] of Object.entries(newSnapshot.schema)) {
|
|
39
|
+
const oldCollection = oldSnapshot.schema[collectionName];
|
|
39
40
|
if (!oldCollection)
|
|
40
41
|
continue;
|
|
41
42
|
const collectionChangeQueries = await getCollectionChangeQueries({
|
|
@@ -89,12 +90,9 @@ async function getCollectionChangeQueries({
|
|
|
89
90
|
)} field ${color.blue(color.bold(fieldName))}. ${color.red(
|
|
90
91
|
"This will delete all existing data in the collection!"
|
|
91
92
|
)} We recommend setting a default value to avoid data loss.`,
|
|
92
|
-
"
|
|
93
|
+
"added-unique": `Adding unique ${color.blue(color.bold(collectionName))} field ${color.blue(
|
|
93
94
|
color.bold(fieldName)
|
|
94
|
-
)}
|
|
95
|
-
"updated-unique": `Changing ${color.blue(color.bold(collectionName))} field ${color.blue(
|
|
96
|
-
color.bold(fieldName)
|
|
97
|
-
)} to unique. ${color.red("This will delete all existing data in the collection!")}`,
|
|
95
|
+
)}. ${color.red("This will delete all existing data in the collection!")}`,
|
|
98
96
|
"updated-type": `Changing the type of ${color.blue(
|
|
99
97
|
color.bold(collectionName)
|
|
100
98
|
)} field ${color.blue(color.bold(fieldName))}. ${color.red(
|
|
@@ -117,11 +115,21 @@ async function getCollectionChangeQueries({
|
|
|
117
115
|
process.exit(0);
|
|
118
116
|
}
|
|
119
117
|
}
|
|
118
|
+
const addedPrimaryKey = Object.entries(added).find(
|
|
119
|
+
([, field]) => hasPrimaryKey(field)
|
|
120
|
+
);
|
|
121
|
+
const droppedPrimaryKey = Object.entries(dropped).find(
|
|
122
|
+
([, field]) => hasPrimaryKey(field)
|
|
123
|
+
);
|
|
124
|
+
const updatedPrimaryKey = Object.entries(updated).find(
|
|
125
|
+
([, field]) => hasPrimaryKey(field.old) || hasPrimaryKey(field.new)
|
|
126
|
+
);
|
|
120
127
|
const recreateTableQueries = getRecreateTableQueries({
|
|
121
|
-
|
|
128
|
+
unescapedCollectionName: collectionName,
|
|
122
129
|
newCollection,
|
|
123
130
|
added,
|
|
124
|
-
hasDataLoss: dataLossCheck.dataLoss
|
|
131
|
+
hasDataLoss: dataLossCheck.dataLoss,
|
|
132
|
+
migrateHiddenPrimaryKey: !addedPrimaryKey && !droppedPrimaryKey && !updatedPrimaryKey
|
|
125
133
|
});
|
|
126
134
|
queries.push(...recreateTableQueries);
|
|
127
135
|
return queries;
|
|
@@ -222,23 +230,23 @@ async function resolveCollectionRenames(mightAdd, mightDrop, renamePromptRespons
|
|
|
222
230
|
}
|
|
223
231
|
function getAddedCollections(oldCollections, newCollections) {
|
|
224
232
|
const added = {};
|
|
225
|
-
for (const [key, newCollection] of Object.entries(newCollections)) {
|
|
226
|
-
if (!(key in oldCollections))
|
|
233
|
+
for (const [key, newCollection] of Object.entries(newCollections.schema)) {
|
|
234
|
+
if (!(key in oldCollections.schema))
|
|
227
235
|
added[key] = newCollection;
|
|
228
236
|
}
|
|
229
237
|
return added;
|
|
230
238
|
}
|
|
231
239
|
function getDroppedCollections(oldCollections, newCollections) {
|
|
232
240
|
const dropped = {};
|
|
233
|
-
for (const [key, oldCollection] of Object.entries(oldCollections)) {
|
|
234
|
-
if (!(key in newCollections))
|
|
241
|
+
for (const [key, oldCollection] of Object.entries(oldCollections.schema)) {
|
|
242
|
+
if (!(key in newCollections.schema))
|
|
235
243
|
dropped[key] = oldCollection;
|
|
236
244
|
}
|
|
237
245
|
return dropped;
|
|
238
246
|
}
|
|
239
|
-
function getFieldRenameQueries(
|
|
247
|
+
function getFieldRenameQueries(unescapedCollectionName, renamed) {
|
|
240
248
|
const queries = [];
|
|
241
|
-
const collectionName = sqlite.escapeName(
|
|
249
|
+
const collectionName = sqlite.escapeName(unescapedCollectionName);
|
|
242
250
|
for (const { from, to } of renamed) {
|
|
243
251
|
const q = `ALTER TABLE ${collectionName} RENAME COLUMN ${sqlite.escapeName(
|
|
244
252
|
from
|
|
@@ -247,9 +255,9 @@ function getFieldRenameQueries(unescCollectionName, renamed) {
|
|
|
247
255
|
}
|
|
248
256
|
return queries;
|
|
249
257
|
}
|
|
250
|
-
function getAlterTableQueries(
|
|
258
|
+
function getAlterTableQueries(unescapedCollectionName, added, dropped) {
|
|
251
259
|
const queries = [];
|
|
252
|
-
const collectionName = sqlite.escapeName(
|
|
260
|
+
const collectionName = sqlite.escapeName(unescapedCollectionName);
|
|
253
261
|
for (const [unescFieldName, field] of Object.entries(added)) {
|
|
254
262
|
const fieldName = sqlite.escapeName(unescFieldName);
|
|
255
263
|
const type = schemaTypeToSqlType(field.type);
|
|
@@ -267,92 +275,67 @@ function getAlterTableQueries(unescCollectionName, added, dropped) {
|
|
|
267
275
|
return queries;
|
|
268
276
|
}
|
|
269
277
|
function getRecreateTableQueries({
|
|
270
|
-
|
|
278
|
+
unescapedCollectionName,
|
|
271
279
|
newCollection,
|
|
272
280
|
added,
|
|
273
|
-
hasDataLoss
|
|
281
|
+
hasDataLoss,
|
|
282
|
+
migrateHiddenPrimaryKey
|
|
274
283
|
}) {
|
|
275
|
-
const unescTempName = `${
|
|
284
|
+
const unescTempName = `${unescapedCollectionName}_${genTempTableName()}`;
|
|
276
285
|
const tempName = sqlite.escapeName(unescTempName);
|
|
277
|
-
const collectionName = sqlite.escapeName(
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
const newColumns = ["id", ...Object.keys(newCollection.fields)];
|
|
281
|
-
const originalColumns = newColumns.filter((i) => !(i in added));
|
|
282
|
-
const escapedColumns = originalColumns.map((c) => sqlite.escapeName(c)).join(", ");
|
|
283
|
-
queries.push(
|
|
284
|
-
`INSERT INTO ${tempName} (${escapedColumns}) SELECT ${escapedColumns} FROM ${collectionName}`
|
|
285
|
-
);
|
|
286
|
+
const collectionName = sqlite.escapeName(unescapedCollectionName);
|
|
287
|
+
if (hasDataLoss) {
|
|
288
|
+
return [`DROP TABLE ${collectionName}`, getCreateTableQuery(collectionName, newCollection)];
|
|
286
289
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
291
|
-
function getCreateTableQuery(collectionName, collection) {
|
|
292
|
-
let query = `CREATE TABLE ${sqlite.escapeName(collectionName)} (`;
|
|
293
|
-
const colQueries = ['"id" text PRIMARY KEY'];
|
|
294
|
-
for (const [columnName, column] of Object.entries(collection.fields)) {
|
|
295
|
-
const colQuery = `${sqlite.escapeName(columnName)} ${schemaTypeToSqlType(
|
|
296
|
-
column.type
|
|
297
|
-
)}${getModifiers(columnName, column)}`;
|
|
298
|
-
colQueries.push(colQuery);
|
|
299
|
-
}
|
|
300
|
-
query += colQueries.join(", ") + ")";
|
|
301
|
-
return query;
|
|
302
|
-
}
|
|
303
|
-
function getModifiers(columnName, column) {
|
|
304
|
-
let modifiers = "";
|
|
305
|
-
if (!column.optional) {
|
|
306
|
-
modifiers += " NOT NULL";
|
|
307
|
-
}
|
|
308
|
-
if (column.unique) {
|
|
309
|
-
modifiers += " UNIQUE";
|
|
310
|
-
}
|
|
311
|
-
if (hasDefault(column)) {
|
|
312
|
-
modifiers += ` DEFAULT ${getDefaultValueSql(columnName, column)}`;
|
|
313
|
-
}
|
|
314
|
-
return modifiers;
|
|
315
|
-
}
|
|
316
|
-
function schemaTypeToSqlType(type) {
|
|
317
|
-
switch (type) {
|
|
318
|
-
case "date":
|
|
319
|
-
case "text":
|
|
320
|
-
case "json":
|
|
321
|
-
return "text";
|
|
322
|
-
case "number":
|
|
323
|
-
case "boolean":
|
|
324
|
-
return "integer";
|
|
290
|
+
const newColumns = [...Object.keys(newCollection.fields)];
|
|
291
|
+
if (migrateHiddenPrimaryKey) {
|
|
292
|
+
newColumns.unshift("_id");
|
|
325
293
|
}
|
|
294
|
+
const escapedColumns = newColumns.filter((i) => !(i in added)).map((c) => sqlite.escapeName(c)).join(", ");
|
|
295
|
+
return [
|
|
296
|
+
getCreateTableQuery(unescTempName, newCollection),
|
|
297
|
+
`INSERT INTO ${tempName} (${escapedColumns}) SELECT ${escapedColumns} FROM ${collectionName}`,
|
|
298
|
+
`DROP TABLE ${collectionName}`,
|
|
299
|
+
`ALTER TABLE ${tempName} RENAME TO ${collectionName}`
|
|
300
|
+
];
|
|
326
301
|
}
|
|
327
302
|
function isEmpty(obj) {
|
|
328
303
|
return Object.keys(obj).length === 0;
|
|
329
304
|
}
|
|
330
|
-
function canAlterTableAddColumn(
|
|
331
|
-
if (
|
|
305
|
+
function canAlterTableAddColumn(field) {
|
|
306
|
+
if (field.unique)
|
|
332
307
|
return false;
|
|
333
|
-
if (hasRuntimeDefault(
|
|
308
|
+
if (hasRuntimeDefault(field))
|
|
334
309
|
return false;
|
|
335
|
-
if (!
|
|
310
|
+
if (!field.optional && !hasDefault(field))
|
|
311
|
+
return false;
|
|
312
|
+
if (hasPrimaryKey(field))
|
|
336
313
|
return false;
|
|
337
314
|
return true;
|
|
338
315
|
}
|
|
339
|
-
function canAlterTableDropColumn(
|
|
340
|
-
if (
|
|
316
|
+
function canAlterTableDropColumn(field) {
|
|
317
|
+
if (field.unique)
|
|
318
|
+
return false;
|
|
319
|
+
if (hasPrimaryKey(field))
|
|
341
320
|
return false;
|
|
342
321
|
return true;
|
|
343
322
|
}
|
|
344
323
|
function canRecreateTableWithoutDataLoss(added, updated) {
|
|
345
324
|
for (const [fieldName, a] of Object.entries(added)) {
|
|
346
|
-
if (
|
|
325
|
+
if (hasPrimaryKey(a) && a.type !== "number" && !hasDefault(a)) {
|
|
326
|
+
return { dataLoss: true, fieldName, reason: "added-required" };
|
|
327
|
+
}
|
|
328
|
+
if (!a.optional && !hasDefault(a)) {
|
|
347
329
|
return { dataLoss: true, fieldName, reason: "added-required" };
|
|
330
|
+
}
|
|
331
|
+
if (a.unique) {
|
|
332
|
+
return { dataLoss: true, fieldName, reason: "added-unique" };
|
|
333
|
+
}
|
|
348
334
|
}
|
|
349
335
|
for (const [fieldName, u] of Object.entries(updated)) {
|
|
350
|
-
if (u.old.
|
|
351
|
-
return { dataLoss: true, fieldName, reason: "updated-required" };
|
|
352
|
-
if (!u.old.unique && u.new.unique)
|
|
353
|
-
return { dataLoss: true, fieldName, reason: "updated-unique" };
|
|
354
|
-
if (u.old.type !== u.new.type && !canChangeTypeWithoutQuery(u.old, u.new))
|
|
336
|
+
if (u.old.type !== u.new.type && !canChangeTypeWithoutQuery(u.old, u.new)) {
|
|
355
337
|
return { dataLoss: true, fieldName, reason: "updated-type" };
|
|
338
|
+
}
|
|
356
339
|
}
|
|
357
340
|
return { dataLoss: false };
|
|
358
341
|
}
|
|
@@ -404,38 +387,9 @@ function canChangeTypeWithoutQuery(oldField, newField) {
|
|
|
404
387
|
({ from, to }) => oldField.type === from && newField.type === to
|
|
405
388
|
);
|
|
406
389
|
}
|
|
407
|
-
function hasDefault(field) {
|
|
408
|
-
return field.default !== void 0;
|
|
409
|
-
}
|
|
410
390
|
function hasRuntimeDefault(field) {
|
|
411
391
|
return field.type === "date" && field.default === "now";
|
|
412
392
|
}
|
|
413
|
-
function getDefaultValueSql(columnName, column) {
|
|
414
|
-
switch (column.type) {
|
|
415
|
-
case "boolean":
|
|
416
|
-
return column.default ? "TRUE" : "FALSE";
|
|
417
|
-
case "number":
|
|
418
|
-
return `${column.default}`;
|
|
419
|
-
case "text":
|
|
420
|
-
return sqlite.escapeString(column.default);
|
|
421
|
-
case "date":
|
|
422
|
-
return column.default === "now" ? "CURRENT_TIMESTAMP" : sqlite.escapeString(column.default);
|
|
423
|
-
case "json": {
|
|
424
|
-
let stringified = "";
|
|
425
|
-
try {
|
|
426
|
-
stringified = JSON.stringify(column.default);
|
|
427
|
-
} catch (e) {
|
|
428
|
-
console.log(
|
|
429
|
-
`Invalid default value for column ${color.bold(
|
|
430
|
-
columnName
|
|
431
|
-
)}. Defaults must be valid JSON when using the \`json()\` type.`
|
|
432
|
-
);
|
|
433
|
-
process.exit(0);
|
|
434
|
-
}
|
|
435
|
-
return sqlite.escapeString(stringified);
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
393
|
function objShallowEqual(a, b) {
|
|
440
394
|
if (Object.keys(a).length !== Object.keys(b).length)
|
|
441
395
|
return false;
|
|
@@ -448,6 +402,5 @@ function objShallowEqual(a, b) {
|
|
|
448
402
|
}
|
|
449
403
|
export {
|
|
450
404
|
getCollectionChangeQueries,
|
|
451
|
-
getCreateTableQuery,
|
|
452
405
|
getMigrationQueries
|
|
453
406
|
};
|