@ductape/cli 0.4.0 → 0.4.1
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/lib/db-types.d.ts
CHANGED
|
@@ -45,7 +45,19 @@ export interface ICreateIndexOp {
|
|
|
45
45
|
order?: 'asc' | 'desc';
|
|
46
46
|
}>;
|
|
47
47
|
unique?: boolean;
|
|
48
|
+
sparse?: boolean;
|
|
48
49
|
ifNotExists?: boolean;
|
|
50
|
+
sqlOptions?: {
|
|
51
|
+
method?: string;
|
|
52
|
+
where?: string;
|
|
53
|
+
include?: string[];
|
|
54
|
+
concurrent?: boolean;
|
|
55
|
+
};
|
|
56
|
+
mongoOptions?: {
|
|
57
|
+
expireAfterSeconds?: number;
|
|
58
|
+
partialFilterExpression?: Record<string, unknown>;
|
|
59
|
+
collation?: Record<string, unknown>;
|
|
60
|
+
};
|
|
49
61
|
}
|
|
50
62
|
export interface IDropIndexOp {
|
|
51
63
|
type: 'dropIndex';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { IMigration } from './db-types.js';
|
|
2
|
+
export declare function validateEquivalentMigrationIndexes(migrations: IMigration[]): void;
|
|
2
3
|
export declare function getMigrationsDir(projectDir: string, dbTag: string): string;
|
|
3
4
|
export declare function loadMigrationFiles(projectDir: string, dbTag: string): IMigration[];
|
|
4
5
|
export declare function writeMigrationFile(projectDir: string, dbTag: string, migration: IMigration, counter: number): string;
|
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { PROJECT_CONFIG_DIR } from './config.js';
|
|
4
|
+
function stable(value) {
|
|
5
|
+
if (Array.isArray(value))
|
|
6
|
+
return `[${value.map(stable).join(',')}]`;
|
|
7
|
+
if (value && typeof value === 'object')
|
|
8
|
+
return `{${Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([key, nested]) => `${JSON.stringify(key)}:${stable(nested)}`).join(',')}}`;
|
|
9
|
+
return JSON.stringify(value);
|
|
10
|
+
}
|
|
11
|
+
export function validateEquivalentMigrationIndexes(migrations) {
|
|
12
|
+
const seen = new Map();
|
|
13
|
+
for (const migration of migrations)
|
|
14
|
+
migration.up.forEach((operation, operationIndex) => {
|
|
15
|
+
if (operation.type !== 'createIndex')
|
|
16
|
+
return;
|
|
17
|
+
const fingerprint = stable({ collection: operation.collection, fields: operation.fields.map((field) => ({ name: field.name, order: field.order ?? 'asc' })), unique: Boolean(operation.unique), sparse: Boolean(operation.sparse), sql: operation.sqlOptions ?? {}, mongo: operation.mongoOptions ?? {} });
|
|
18
|
+
const previous = seen.get(fingerprint);
|
|
19
|
+
if (previous && previous.name !== operation.name) {
|
|
20
|
+
throw new Error(`Equivalent index definitions use different names: migration "${previous.migration}" operation ${previous.operation + 1} creates "${previous.name}", while migration "${migration.tag}" operation ${operationIndex + 1} creates "${operation.name}".`);
|
|
21
|
+
}
|
|
22
|
+
seen.set(fingerprint, { migration: migration.tag, operation: operationIndex, name: operation.name });
|
|
23
|
+
});
|
|
24
|
+
}
|
|
4
25
|
export function getMigrationsDir(projectDir, dbTag) {
|
|
5
26
|
return path.join(projectDir, PROJECT_CONFIG_DIR, 'database', 'migrations', dbTag);
|
|
6
27
|
}
|
|
@@ -12,10 +33,12 @@ export function loadMigrationFiles(projectDir, dbTag) {
|
|
|
12
33
|
.readdirSync(dir)
|
|
13
34
|
.filter((f) => f.endsWith('.json'))
|
|
14
35
|
.sort();
|
|
15
|
-
|
|
36
|
+
const migrations = files.map((file) => {
|
|
16
37
|
const raw = JSON.parse(fs.readFileSync(path.join(dir, file), 'utf8'));
|
|
17
38
|
return raw;
|
|
18
39
|
});
|
|
40
|
+
validateEquivalentMigrationIndexes(migrations);
|
|
41
|
+
return migrations;
|
|
19
42
|
}
|
|
20
43
|
function makeTimestamp(counter) {
|
|
21
44
|
const now = new Date();
|
package/package.json
CHANGED