@supacloud/cli 0.12.2 → 0.12.4

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 (2) hide show
  1. package/dist/index.js +45 -22
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -6462,6 +6462,16 @@ var MAX_MIGRATION_VERSION = 9223372036854775807n;
6462
6462
  var FALLBACK_MIGRATION_VERSION_BASE = 8000000000000000000n;
6463
6463
  var FALLBACK_MIGRATION_VERSION_RANGE = 1000000000000000000n;
6464
6464
  var FALLBACK_MIGRATION_VERSION_LIMIT = FALLBACK_MIGRATION_VERSION_BASE + FALLBACK_MIGRATION_VERSION_RANGE;
6465
+ function readMigrationFile(dir, file) {
6466
+ const rawBytes = readFileSync2(join(dir, file));
6467
+ return {
6468
+ file,
6469
+ name: basename(file, ".sql"),
6470
+ version: migrationVersionFromFilename(file),
6471
+ sql: Buffer.from(rawBytes).toString("utf8"),
6472
+ rawBytes
6473
+ };
6474
+ }
6465
6475
  function migrationVersionFromFilename(file) {
6466
6476
  const match = basename(file).match(/^(\d{8,20})[_-]/);
6467
6477
  if (match) {
@@ -6515,17 +6525,40 @@ function migrationRows(data) {
6515
6525
  const rows = Array.isArray(data) ? data : data?.rows || [];
6516
6526
  return Array.isArray(rows) ? rows.filter((row) => Boolean(row && typeof row === "object")) : [];
6517
6527
  }
6518
- function baselineMigrationKey(version, name) {
6528
+ function migrationIdentityKey(version, name) {
6519
6529
  return `${version}\x00${name}`;
6520
6530
  }
6521
- function baselineMigrationKeys(data) {
6531
+ function nameBoundMigrationMarkerKeys(data) {
6522
6532
  const keys = new Set;
6523
6533
  for (const row of migrationRows(data)) {
6524
6534
  if (row.version == null || row.name == null || !Array.isArray(row.statements))
6525
6535
  continue;
6526
- if (row.statements.length !== 1 || row.statements[0] !== `baseline:${String(row.name)}`)
6536
+ if (row.statements.length !== 1)
6537
+ continue;
6538
+ const name = String(row.name);
6539
+ const marker = row.statements[0];
6540
+ if (marker !== `baseline:${name}` && marker !== `direct-apply:${name}`)
6541
+ continue;
6542
+ keys.add(migrationIdentityKey(String(row.version), String(row.name)));
6543
+ }
6544
+ return keys;
6545
+ }
6546
+ function historicalChecksumMarkerKeys(data, migrationFiles) {
6547
+ const filesByKey = new Map(migrationFiles.map((migration) => [migrationIdentityKey(migration.version, migration.name), migration]));
6548
+ const keys = new Set;
6549
+ for (const row of migrationRows(data)) {
6550
+ if (row.version == null || row.name == null || !Array.isArray(row.statements) || row.statements.length !== 1)
6551
+ continue;
6552
+ const marker = row.statements[0];
6553
+ if (typeof marker !== "string" || !/^sha256:[0-9a-f]{64}$/.test(marker))
6554
+ continue;
6555
+ const key = migrationIdentityKey(String(row.version), String(row.name));
6556
+ const migration = filesByKey.get(key);
6557
+ if (!migration)
6527
6558
  continue;
6528
- keys.add(baselineMigrationKey(String(row.version), String(row.name)));
6559
+ const checksum = createHash("sha256").update(migration.rawBytes).digest("hex");
6560
+ if (marker === `sha256:${checksum}`)
6561
+ keys.add(key);
6529
6562
  }
6530
6563
  return keys;
6531
6564
  }
@@ -6747,11 +6780,7 @@ Actions: ${allActions.join(", ")}${readOnly ? " (read-only mode)" : ""}`, {
6747
6780
  text = `No .sql migration files found in ${dir}`;
6748
6781
  break;
6749
6782
  }
6750
- const migrationFiles = sortMigrationFiles(files.map((file) => ({
6751
- file,
6752
- name: basename(file, ".sql"),
6753
- version: migrationVersionFromFilename(file)
6754
- })));
6783
+ const migrationFiles = sortMigrationFiles(files.map((file) => readMigrationFile(dir, file)));
6755
6784
  const migrationsResult = await http.get(`/v1/projects/${ref}/database/migrations`);
6756
6785
  if (!migrationsResult.ok) {
6757
6786
  text = `❌ Failed to load applied migrations (${migrationsResult.status}): ${JSON.stringify(migrationsResult.data)}`;
@@ -6761,10 +6790,7 @@ Actions: ${allActions.join(", ")}${readOnly ? " (read-only mode)" : ""}`, {
6761
6790
  const appliedKeys = appliedMigrationKeys(migrationsResult.data);
6762
6791
  const pending = migrationFiles.filter(({ name, version }) => !appliedKeys.has(name) && !appliedKeys.has(String(version)));
6763
6792
  const alreadyApplied = migrationFiles.filter(({ name, version }) => appliedKeys.has(name) || appliedKeys.has(String(version)));
6764
- const pendingWithSql = pending.map((migration) => ({
6765
- ...migration,
6766
- sql: readFileSync2(join(dir, migration.file), "utf-8")
6767
- }));
6793
+ const pendingWithSql = pending;
6768
6794
  let vectorEnabled = null;
6769
6795
  if (pendingWithSql.some(({ sql }) => sqlReferencesVector(sql) || sqlCreatesVectorExtension(sql))) {
6770
6796
  const extResult = await execSql("SELECT extname AS name FROM pg_extension WHERE extname = 'vector';");
@@ -6787,13 +6813,14 @@ Actions: ${allActions.join(", ")}${readOnly ? " (read-only mode)" : ""}`, {
6787
6813
  }
6788
6814
  const applied = [];
6789
6815
  const skipped = [];
6790
- const baselineKeys = baselineMigrationKeys(migrationsResult.data);
6791
- for (const { file, name, version } of migrationFiles) {
6792
- if (baselineKeys.has(baselineMigrationKey(version, name))) {
6816
+ const nameBoundMarkerKeys = nameBoundMigrationMarkerKeys(migrationsResult.data);
6817
+ const historicalChecksumKeys = historicalChecksumMarkerKeys(migrationsResult.data, migrationFiles);
6818
+ for (const { file, name, version, sql } of migrationFiles) {
6819
+ const migrationKey = migrationIdentityKey(version, name);
6820
+ if (nameBoundMarkerKeys.has(migrationKey) || historicalChecksumKeys.has(migrationKey)) {
6793
6821
  skipped.push(file);
6794
6822
  continue;
6795
6823
  }
6796
- const sql = readFileSync2(join(dir, file), "utf-8");
6797
6824
  const r = await http.post(`/v1/projects/${ref}/database/migrations`, { name, sql, version });
6798
6825
  if (r.ok) {
6799
6826
  applied.push(file);
@@ -6831,11 +6858,7 @@ Actions: ${allActions.join(", ")}${readOnly ? " (read-only mode)" : ""}`, {
6831
6858
  text = `No .sql migration files found in ${dir}`;
6832
6859
  break;
6833
6860
  }
6834
- const migrationFiles = sortMigrationFiles(files.map((file) => ({
6835
- file,
6836
- name: basename(file, ".sql"),
6837
- version: migrationVersionFromFilename(file)
6838
- })));
6861
+ const migrationFiles = sortMigrationFiles(files.map((file) => readMigrationFile(dir, file)));
6839
6862
  const r = await http.get(`/v1/projects/${ref}/database/migrations`);
6840
6863
  if (!r.ok) {
6841
6864
  text = `❌ Failed to load applied migrations (${r.status}): ${JSON.stringify(r.data)}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supacloud/cli",
3
- "version": "0.12.2",
3
+ "version": "0.12.4",
4
4
  "description": "Project-scoped CLI for SupaCloud users",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",