directus-deploy-cli 0.2.0 → 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.
package/dist/cli.js CHANGED
@@ -88,14 +88,50 @@ async function execute(mode, flags) {
88
88
  process.stderr.write(`verify: drift detected (${report.counts.created} would-create, ${report.counts.updated} would-update)\n`);
89
89
  return 1;
90
90
  }
91
+ // Server-side gate: any `directus_fields.type = 'unknown'` row on the
92
+ // target means a raw-SQL column was added but never registered — either
93
+ // via `migrations/register/<table>.json` or by a Directus-native field
94
+ // definition. Fail fast so the miss surfaces here, not in a UI 500.
95
+ const unknowns = await fetchUnknownFields(client);
96
+ if (unknowns === null) {
97
+ process.stderr.write(`verify: could not query directus_fields for type=unknown (raw-query endpoint unavailable?) — skipping check\n`);
98
+ }
99
+ else if (unknowns.length > 0) {
100
+ process.stderr.write(`verify: ${unknowns.length} field(s) have type='unknown' on target — add a register manifest or Directus field definition:\n`);
101
+ for (const u of unknowns) {
102
+ process.stderr.write(` ${u.collection}.${u.field}\n`);
103
+ }
104
+ return 1;
105
+ }
91
106
  }
92
107
  return 0;
93
108
  }
109
+ async function fetchUnknownFields(client) {
110
+ try {
111
+ const r = (await client.postRaw("/raw-query/execute", {
112
+ query: "SELECT collection, field FROM directus_fields WHERE type = 'unknown' ORDER BY collection, field",
113
+ }));
114
+ const inner = r?.results?.[0];
115
+ if (!r?.success || !inner?.success)
116
+ return null;
117
+ const out = [];
118
+ for (const row of inner.data ?? []) {
119
+ if (row && typeof row === "object" && "collection" in row && "field" in row) {
120
+ const rr = row;
121
+ out.push({ collection: String(rr.collection), field: String(rr.field) });
122
+ }
123
+ }
124
+ return out;
125
+ }
126
+ catch {
127
+ return null;
128
+ }
129
+ }
94
130
  const program = new Command();
95
131
  program
96
132
  .name("directus-deploy")
97
133
  .description("Reconcile a Directus environment to the state described in directus_config/snapshot/. Per-entity, non-atomic.")
98
- .version("0.1.0");
134
+ .version("0.3.0");
99
135
  function attachCommon(cmd) {
100
136
  return cmd
101
137
  .option("--url <url>", "Directus base URL (env: DIRECTUS_URL)")
@@ -107,7 +143,7 @@ function attachCommon(cmd) {
107
143
  .option("--config-dir <path>", "path to directus_config/collections (holds policies.json, permissions.json, roles.json, …)", "./directus_config/collections")
108
144
  .option("--register-dir <path>", "path to migrations/register", "./migrations/register")
109
145
  .option("--seed-dir <path>", "path to directus_config/seed (Tractr-style {collection, meta, data} files)", "./directus_config/seed")
110
- .option("--migrations-dir <path>", "path to migrations/*.sql (raw SQL, tracked in lola_deploy_migrations)", "./migrations")
146
+ .option("--migrations-dir <path>", "path to migrations/*.sql (raw SQL, tracked in _directus_deploy_migrations)", "./migrations")
111
147
  .option("--json", "emit JSON report instead of human-readable");
112
148
  }
113
149
  attachCommon(program.command("plan"))
@@ -125,6 +161,76 @@ attachCommon(program.command("verify"))
125
161
  .action(async (_, cmd) => {
126
162
  process.exit(await execute({ dryRun: true, strict: true }, cmd.optsWithGlobals()));
127
163
  });
164
+ // migrations adopt: bootstrap the tracker on an env whose migrations were
165
+ // applied via some prior mechanism. Inserts (filename, sha256) rows without
166
+ // executing any SQL. Idempotent — re-adopting is a no-op when hashes match.
167
+ const migrationsGroup = program
168
+ .command("migrations")
169
+ .description("migration-specific commands");
170
+ migrationsGroup
171
+ .command("adopt")
172
+ .description("Insert current migrations/*.sql into the tracker WITHOUT running them. Use once per env when cutting over from a prior deploy mechanism.")
173
+ .option("--url <url>", "Directus base URL (env: DIRECTUS_URL)")
174
+ .option("--token <token>", "Directus admin token (env: DIRECTUS_TOKEN)")
175
+ .option("--target <label>", "friendly label for logs (default: URL hostname)")
176
+ .option("--migrations-dir <path>", "path to migrations/*.sql", "./migrations")
177
+ .option("--dry-run", "report what would be adopted, don't write")
178
+ .option("--json", "emit JSON report instead of human-readable")
179
+ .action(async (opts) => {
180
+ const url = opts.url ?? process.env.DIRECTUS_URL;
181
+ const token = opts.token ?? process.env.DIRECTUS_TOKEN;
182
+ if (!url)
183
+ throw new Error("--url or DIRECTUS_URL required");
184
+ if (!token)
185
+ throw new Error("--token or DIRECTUS_TOKEN required");
186
+ const target = opts.target ?? new URL(url).hostname;
187
+ const client = createDirectusClient({ baseUrl: url, token });
188
+ const { adoptMigrations } = await import("./reconcilers/migrations.js");
189
+ const results = await adoptMigrations({
190
+ migrationsDir: opts.migrationsDir,
191
+ client,
192
+ opts: { dryRun: Boolean(opts.dryRun) },
193
+ });
194
+ const counts = { created: 0, updated: 0, unchanged: 0, skipped: 0, failed: 0 };
195
+ for (const r of results)
196
+ counts[r.action] += 1;
197
+ const report = { target, results, counts };
198
+ if (opts.json) {
199
+ process.stdout.write(formatJson(report) + "\n");
200
+ }
201
+ else {
202
+ process.stdout.write(formatHuman(report) + "\n");
203
+ }
204
+ process.exit(counts.failed > 0 ? 1 : 0);
205
+ });
206
+ migrationsGroup
207
+ .command("lint")
208
+ .description("Static check: every CREATE TABLE / ADD COLUMN in migrations/*.sql must be covered by a register manifest or a real (non-'unknown') snapshot field definition. No network calls.")
209
+ .option("--migrations-dir <path>", "path to migrations/*.sql", "./migrations")
210
+ .option("--register-dir <path>", "path to migrations/register", "./migrations/register")
211
+ .option("--snapshot-dir <path>", "path to directus_config/snapshot", "./directus_config/snapshot")
212
+ .option("--json", "emit JSON output")
213
+ .action(async (opts) => {
214
+ const { lintMigrations } = await import("./lint.js");
215
+ const { violations, scanned } = await lintMigrations({
216
+ migrationsDir: opts.migrationsDir,
217
+ registerDir: opts.registerDir,
218
+ snapshotDir: opts.snapshotDir,
219
+ });
220
+ if (opts.json) {
221
+ process.stdout.write(JSON.stringify({ scanned, violations }, null, 2) + "\n");
222
+ }
223
+ else if (violations.length === 0) {
224
+ process.stdout.write(`migrations lint: ${scanned} file(s) scanned, no violations.\n`);
225
+ }
226
+ else {
227
+ process.stderr.write(`migrations lint: ${violations.length} violation(s) across ${scanned} file(s):\n`);
228
+ for (const v of violations) {
229
+ process.stderr.write(` ${v.file}: ${v.reason}\n`);
230
+ }
231
+ }
232
+ process.exit(violations.length === 0 ? 0 : 1);
233
+ });
128
234
  program.parseAsync(process.argv).catch((e) => {
129
235
  process.stderr.write(`directus-deploy: ${e.message}\n`);
130
236
  process.exit(2);
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
package/dist/lint.js ADDED
@@ -0,0 +1,131 @@
1
+ import { readdir, readFile } from "node:fs/promises";
2
+ import { existsSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ async function readManifests(dir) {
5
+ const map = new Map();
6
+ let entries;
7
+ try {
8
+ entries = await readdir(dir);
9
+ }
10
+ catch {
11
+ return map;
12
+ }
13
+ for (const f of entries) {
14
+ if (!f.endsWith(".json"))
15
+ continue;
16
+ try {
17
+ const parsed = JSON.parse(await readFile(join(dir, f), "utf8"));
18
+ if (parsed?.table)
19
+ map.set(parsed.table, parsed);
20
+ }
21
+ catch {
22
+ /* malformed manifest surfaces via other tooling */
23
+ }
24
+ }
25
+ return map;
26
+ }
27
+ // Parse a SQL file for `CREATE TABLE (IF NOT EXISTS)? name`
28
+ // and `ALTER TABLE name ADD COLUMN (IF NOT EXISTS)? col`.
29
+ // Case-insensitive; multi-column ALTER TABLE ADD is handled by matching each
30
+ // ADD COLUMN clause independently.
31
+ function parseSql(sql) {
32
+ const createTables = [];
33
+ const addColumns = [];
34
+ // Strip block + line comments to simplify matching. We keep offsets rough —
35
+ // this is a lint, not a compiler.
36
+ const stripped = sql
37
+ .replace(/\/\*[\s\S]*?\*\//g, " ")
38
+ .replace(/--[^\n]*\n/g, "\n");
39
+ const createRe = /\bCREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?"?([a-z_][a-z0-9_]*)"?\s*\(/gi;
40
+ let m;
41
+ while ((m = createRe.exec(stripped)) !== null) {
42
+ createTables.push(m[1].toLowerCase());
43
+ }
44
+ // Find each `ALTER TABLE <t> …` block, then within that block find every
45
+ // `ADD COLUMN (IF NOT EXISTS)? <c>`. This handles the common
46
+ // ALTER TABLE t
47
+ // ADD COLUMN a int,
48
+ // ADD COLUMN b int;
49
+ // shape.
50
+ const alterRe = /\bALTER\s+TABLE\s+(?:ONLY\s+)?"?([a-z_][a-z0-9_]*)"?\s*([\s\S]*?);/gi;
51
+ while ((m = alterRe.exec(stripped)) !== null) {
52
+ const table = m[1].toLowerCase();
53
+ const body = m[2];
54
+ const colRe = /\bADD\s+COLUMN\s+(?:IF\s+NOT\s+EXISTS\s+)?"?([a-z_][a-z0-9_]*)"?/gi;
55
+ let cm;
56
+ while ((cm = colRe.exec(body)) !== null) {
57
+ addColumns.push({ table, column: cm[1].toLowerCase() });
58
+ }
59
+ }
60
+ return { createTables, addColumns };
61
+ }
62
+ async function fieldSnapshotType(snapshotDir, table, column) {
63
+ const path = join(snapshotDir, "fields", table, `${column}.json`);
64
+ if (!existsSync(path))
65
+ return null;
66
+ try {
67
+ const parsed = JSON.parse(await readFile(path, "utf8"));
68
+ return typeof parsed.type === "string" ? parsed.type : null;
69
+ }
70
+ catch {
71
+ return null;
72
+ }
73
+ }
74
+ function collectionSnapshotExists(snapshotDir, table) {
75
+ return existsSync(join(snapshotDir, "collections", `${table}.json`));
76
+ }
77
+ export async function lintMigrations(input) {
78
+ const violations = [];
79
+ let scanned = 0;
80
+ const manifests = await readManifests(input.registerDir);
81
+ let files;
82
+ try {
83
+ files = (await readdir(input.migrationsDir))
84
+ .filter((f) => f.endsWith(".sql") && !f.startsWith("_"))
85
+ .sort();
86
+ }
87
+ catch {
88
+ return { violations, scanned: 0 };
89
+ }
90
+ for (const f of files) {
91
+ const sql = await readFile(join(input.migrationsDir, f), "utf8");
92
+ const { createTables, addColumns } = parseSql(sql);
93
+ scanned += 1;
94
+ for (const table of createTables) {
95
+ const hasManifest = manifests.has(table);
96
+ const hasSnapshot = collectionSnapshotExists(input.snapshotDir, table);
97
+ if (!hasManifest && !hasSnapshot) {
98
+ violations.push({
99
+ kind: "table",
100
+ file: f,
101
+ table,
102
+ reason: `CREATE TABLE ${table} — needs migrations/register/${table}.json or directus_config/snapshot/collections/${table}.json`,
103
+ });
104
+ }
105
+ }
106
+ for (const { table, column } of addColumns) {
107
+ // Manifest match: table is listed AND either fields[column] exists or
108
+ // fields is undefined (walk-all-unregistered mode).
109
+ const manifest = manifests.get(table);
110
+ const manifestCovers = !!manifest &&
111
+ (manifest.fields === undefined ||
112
+ Object.prototype.hasOwnProperty.call(manifest.fields, column));
113
+ if (manifestCovers)
114
+ continue;
115
+ const snapshotType = await fieldSnapshotType(input.snapshotDir, table, column);
116
+ if (snapshotType && snapshotType !== "unknown")
117
+ continue;
118
+ violations.push({
119
+ kind: "column",
120
+ file: f,
121
+ table,
122
+ column,
123
+ reason: snapshotType === "unknown"
124
+ ? `${table}.${column} present in snapshot with type='unknown' — add migrations/register/${table}.json`
125
+ : `${table}.${column} — no manifest and no snapshot field definition`,
126
+ });
127
+ }
128
+ }
129
+ return { violations, scanned };
130
+ }
131
+ //# sourceMappingURL=lint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint.js","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,37 @@
1
1
  import { readdir, readFile } from "node:fs/promises";
2
+ import { createHash } from "node:crypto";
2
3
  import { join, extname } from "node:path";
3
4
  import { splitSql } from "../sql.js";
5
+ // Migration reconciler with a content-hash tracker table.
6
+ //
7
+ // Tracker shape:
8
+ //
9
+ // CREATE TABLE _directus_deploy_migrations (
10
+ // filename TEXT PRIMARY KEY,
11
+ // sha256 TEXT NOT NULL,
12
+ // applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
13
+ // )
14
+ //
15
+ // Per-file classification:
16
+ //
17
+ // filename absent from tracker → NEW (apply, then insert)
18
+ // filename present, hash matches → UNCHANGED (skip execution)
19
+ // filename present, hash differs → MUTATED (fail hard, don't touch DB)
20
+ //
21
+ // Bootstrap (see adoptMigrations): a fresh env whose migrations were applied
22
+ // via some prior mechanism needs a one-shot import that inserts each file's
23
+ // (name, hash) WITHOUT running the SQL. Prevents duplicate application.
24
+ //
25
+ // Uses Directus's /raw-query/execute endpoint. A missing endpoint yields a
26
+ // clean skip rather than N confusing errors.
27
+ const TRACKER_TABLE = "_directus_deploy_migrations";
28
+ const CREATE_TRACKER = `
29
+ CREATE TABLE IF NOT EXISTS ${TRACKER_TABLE} (
30
+ filename TEXT PRIMARY KEY,
31
+ sha256 TEXT NOT NULL,
32
+ applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
33
+ );
34
+ `;
4
35
  async function rawQuery(client, sql) {
5
36
  try {
6
37
  const r = (await client.postRaw("/raw-query/execute", { query: sql }));
@@ -38,6 +69,59 @@ function stripLeadingComments(s) {
38
69
  }
39
70
  return s.slice(i);
40
71
  }
72
+ function sha256(s) {
73
+ return createHash("sha256").update(s).digest("hex");
74
+ }
75
+ async function ensureTracker(client) {
76
+ const r = await rawQuery(client, CREATE_TRACKER);
77
+ return !!r?.success && !!r?.results?.[0]?.success;
78
+ }
79
+ async function fetchTracker(client) {
80
+ const r = await rawQuery(client, `SELECT filename, sha256 FROM ${TRACKER_TABLE}`);
81
+ if (r === null)
82
+ return null;
83
+ if (!r.success)
84
+ return null;
85
+ const first = r.results?.[0];
86
+ if (!first?.success)
87
+ return null;
88
+ const map = new Map();
89
+ for (const row of first.data ?? []) {
90
+ if (row && typeof row === "object" && "filename" in row && "sha256" in row) {
91
+ const rr = row;
92
+ map.set(String(rr.filename), String(rr.sha256));
93
+ }
94
+ }
95
+ return map;
96
+ }
97
+ function sqlLiteral(s) {
98
+ return `'${s.replace(/'/g, "''")}'`;
99
+ }
100
+ async function insertTrackerRow(client, filename, hash) {
101
+ const r = await rawQuery(client, `INSERT INTO ${TRACKER_TABLE} (filename, sha256) VALUES (${sqlLiteral(filename)}, ${sqlLiteral(hash)}) ON CONFLICT (filename) DO NOTHING`);
102
+ const inner = r?.results?.[0];
103
+ if (!r?.success || !inner?.success) {
104
+ return { ok: false, reason: inner?.error ?? "tracker insert failed" };
105
+ }
106
+ return { ok: true };
107
+ }
108
+ async function readMigrationFiles(dir) {
109
+ let entries;
110
+ try {
111
+ entries = await readdir(dir);
112
+ }
113
+ catch {
114
+ return [];
115
+ }
116
+ const names = entries.filter((f) => extname(f) === ".sql" && !f.startsWith("_")).sort();
117
+ const out = [];
118
+ for (const filename of names) {
119
+ const path = join(dir, filename);
120
+ const raw = await readFile(path, "utf8");
121
+ out.push({ filename, path, raw, hash: sha256(raw) });
122
+ }
123
+ return out;
124
+ }
41
125
  export async function reconcileMigrations(input) {
42
126
  const results = [];
43
127
  const probe = await rawQuery(input.client, "SELECT 1 AS ok");
@@ -50,28 +134,44 @@ export async function reconcileMigrations(input) {
50
134
  });
51
135
  return results;
52
136
  }
53
- let entries;
54
- try {
55
- entries = await readdir(input.migrationsDir);
56
- }
57
- catch {
58
- return results;
59
- }
60
- const files = entries.filter((f) => extname(f) === ".sql" && !f.startsWith("_")).sort();
137
+ const files = await readMigrationFiles(input.migrationsDir);
61
138
  if (files.length === 0)
62
139
  return results;
63
- for (const filename of files) {
64
- const label = `migrations/${filename}`;
65
- const full = join(input.migrationsDir, filename);
66
- let raw;
67
- try {
68
- raw = await readFile(full, "utf8");
69
- }
70
- catch (e) {
71
- results.push({ kind: "migrations", label, action: "failed", reason: e.message });
140
+ // Tracker create is a schema mutation → do it only outside dry-run. In
141
+ // dry-run, if the tracker is missing, treat everything as NEW (accurate).
142
+ if (!input.opts.dryRun) {
143
+ const ok = await ensureTracker(input.client);
144
+ if (!ok) {
145
+ results.push({
146
+ kind: "migrations",
147
+ label: `migrations/${TRACKER_TABLE}`,
148
+ action: "failed",
149
+ reason: "could not create tracker table",
150
+ });
151
+ return results;
152
+ }
153
+ }
154
+ const tracker = (await fetchTracker(input.client)) ?? new Map();
155
+ for (const file of files) {
156
+ const label = `migrations/${file.filename}`;
157
+ const recordedHash = tracker.get(file.filename);
158
+ // UNCHANGED — already applied at this hash.
159
+ if (recordedHash === file.hash) {
160
+ results.push({ kind: "migrations", label, action: "unchanged" });
161
+ continue;
162
+ }
163
+ // MUTATED — recorded under a different hash. Never rewrite silently.
164
+ if (recordedHash !== undefined && recordedHash !== file.hash) {
165
+ results.push({
166
+ kind: "migrations",
167
+ label,
168
+ action: "failed",
169
+ reason: `content mismatch: tracker recorded sha256 ${recordedHash.slice(0, 12)}…, file now hashes to ${file.hash.slice(0, 12)}…. Migrations are immutable — add a new migration instead.`,
170
+ });
72
171
  continue;
73
172
  }
74
- const statements = splitSql(raw).filter((s) => {
173
+ // NEW.
174
+ const statements = splitSql(file.raw).filter((s) => {
75
175
  const stripped = stripLeadingComments(s.trim()).trim();
76
176
  return stripped.length > 0 && stripped !== ";";
77
177
  });
@@ -101,8 +201,94 @@ export async function reconcileMigrations(input) {
101
201
  results.push({ kind: "migrations", label, action: "failed", reason: failedReason });
102
202
  continue;
103
203
  }
204
+ const rec = await insertTrackerRow(input.client, file.filename, file.hash);
205
+ if (!rec.ok) {
206
+ results.push({
207
+ kind: "migrations",
208
+ label,
209
+ action: "failed",
210
+ reason: `applied SQL but tracker insert failed: ${rec.reason}`,
211
+ });
212
+ continue;
213
+ }
104
214
  results.push({ kind: "migrations", label, action: "created" });
105
215
  }
106
216
  return results;
107
217
  }
218
+ // Bootstrap for envs whose migrations were applied via a prior mechanism.
219
+ // Inserts (filename, sha256) rows without executing any SQL. Idempotent:
220
+ // re-adopting is a no-op when hashes match. Fails on hash conflict, which
221
+ // tells the caller the file was edited since the target env applied it.
222
+ export async function adoptMigrations(input) {
223
+ const results = [];
224
+ const probe = await rawQuery(input.client, "SELECT 1 AS ok");
225
+ if (probe === null) {
226
+ results.push({
227
+ kind: "migrations",
228
+ label: "migrations",
229
+ action: "skipped",
230
+ reason: "/raw-query/execute not available on this target",
231
+ });
232
+ return results;
233
+ }
234
+ const files = await readMigrationFiles(input.migrationsDir);
235
+ if (files.length === 0)
236
+ return results;
237
+ if (!input.opts.dryRun) {
238
+ const ok = await ensureTracker(input.client);
239
+ if (!ok) {
240
+ results.push({
241
+ kind: "migrations",
242
+ label: `migrations/${TRACKER_TABLE}`,
243
+ action: "failed",
244
+ reason: "could not create tracker table",
245
+ });
246
+ return results;
247
+ }
248
+ }
249
+ const tracker = (await fetchTracker(input.client)) ?? new Map();
250
+ for (const file of files) {
251
+ const label = `migrations/${file.filename}`;
252
+ const recordedHash = tracker.get(file.filename);
253
+ if (recordedHash === file.hash) {
254
+ results.push({ kind: "migrations", label, action: "unchanged" });
255
+ continue;
256
+ }
257
+ if (recordedHash !== undefined) {
258
+ results.push({
259
+ kind: "migrations",
260
+ label,
261
+ action: "failed",
262
+ reason: `already adopted with sha256 ${recordedHash.slice(0, 12)}…, refusing to overwrite with ${file.hash.slice(0, 12)}…`,
263
+ });
264
+ continue;
265
+ }
266
+ if (input.opts.dryRun) {
267
+ results.push({
268
+ kind: "migrations",
269
+ label,
270
+ action: "created",
271
+ reason: `would adopt (sha256 ${file.hash.slice(0, 12)}…)`,
272
+ });
273
+ continue;
274
+ }
275
+ const rec = await insertTrackerRow(input.client, file.filename, file.hash);
276
+ if (!rec.ok) {
277
+ results.push({
278
+ kind: "migrations",
279
+ label,
280
+ action: "failed",
281
+ reason: rec.reason,
282
+ });
283
+ continue;
284
+ }
285
+ results.push({
286
+ kind: "migrations",
287
+ label,
288
+ action: "created",
289
+ reason: `adopted (sha256 ${file.hash.slice(0, 12)}…)`,
290
+ });
291
+ }
292
+ return results;
293
+ }
108
294
  //# sourceMappingURL=migrations.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../src/reconcilers/migrations.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../src/reconcilers/migrations.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "directus-deploy-cli",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Per-entity, non-atomic Directus deployment tool. Reconciles collections/fields/relations/roles/policies/permissions/flows/operations/migrations/seeds from git to any environment.",
5
5
  "type": "module",
6
6
  "bin": {