@noego/proper 0.2.0 → 0.2.2

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/bin/cli.js CHANGED
@@ -192,6 +192,16 @@ var DatabaseConnectionError = class _DatabaseConnectionError extends MigrationEr
192
192
  return new _DatabaseConnectionError(`Authentication failed for ${dbType} database`);
193
193
  }
194
194
  };
195
+ var MigrationStampError = class _MigrationStampError extends MigrationError {
196
+ constructor(migrationKey) {
197
+ super(
198
+ `Migration '${migrationKey}' cannot be migrated: its timestamp ends in "000", so it does not look like it was generated by 'proper create'. Recreate it with 'proper create <name>' and move the SQL into the generated files.`
199
+ );
200
+ this.migrationKey = migrationKey;
201
+ this.name = "MigrationStampError";
202
+ Object.setPrototypeOf(this, _MigrationStampError.prototype);
203
+ }
204
+ };
195
205
  var MigrationExecutionError = class _MigrationExecutionError extends MigrationError {
196
206
  constructor(message, migrationName, sql, originalError) {
197
207
  let fullMessage = `Migration Execution Error${migrationName ? ` in '${migrationName}'` : ""}: ${message}`;
@@ -454,8 +464,19 @@ var SqlMigrationBuilder = class {
454
464
  // framework/MigrationManifest.ts
455
465
  var import_fs = __toESM(require("fs"));
456
466
  var import_path = __toESM(require("path"));
467
+ var MIGRATION_FILE_REGEX = /(?:\.(mysql|sqlite|pg))?\.(up|down)\.(sql|js)$/i;
468
+ function isMigrationFile(fileName) {
469
+ return MIGRATION_FILE_REGEX.test(fileName);
470
+ }
457
471
  function canonicalMigrationKey(value) {
458
- return value.replace(/(?:\.(mysql|sqlite|pg))?\.(up|down)\.(sql|js)$/i, "").toLowerCase();
472
+ return value.replace(MIGRATION_FILE_REGEX, "").toLowerCase();
473
+ }
474
+ function mintMigrationStamp(now = Date.now()) {
475
+ return now % 10 === 0 ? now + 1 : now;
476
+ }
477
+ function isHandStampedKey(key) {
478
+ const stamp = key.split("_")[0];
479
+ return /^\d+$/.test(stamp) && /000$/.test(stamp);
459
480
  }
460
481
  function resolveMigrationFile(directory, baseName, direction, dialect) {
461
482
  const dialectExt = dialect === "sql" ? "mysql" : dialect;
@@ -468,7 +489,7 @@ function resolveMigrationFile(directory, baseName, direction, dialect) {
468
489
  function loadMigrationManifest(directory, dialect) {
469
490
  const manifest = /* @__PURE__ */ new Map();
470
491
  if (!import_fs.default.existsSync(directory)) return manifest;
471
- const files = import_fs.default.readdirSync(directory, { withFileTypes: true }).filter((f) => f.isFile()).map((f) => f.name);
492
+ const files = import_fs.default.readdirSync(directory, { withFileTypes: true }).filter((f) => f.isFile()).map((f) => f.name).filter(isMigrationFile);
472
493
  const uniqueKeys = /* @__PURE__ */ new Set();
473
494
  files.forEach((file) => uniqueKeys.add(canonicalMigrationKey(file)));
474
495
  uniqueKeys.forEach((key) => {
@@ -505,7 +526,7 @@ var MigrationDirectoryReader = class {
505
526
  }
506
527
  loadMigrations(table, connection) {
507
528
  import_fs2.default.existsSync(this.directory) || import_fs2.default.mkdirSync(this.directory);
508
- const dir_content = import_fs2.default.readdirSync(this.directory, { withFileTypes: true }).filter((file) => file.isFile()).map((file) => file.name);
529
+ const dir_content = import_fs2.default.readdirSync(this.directory, { withFileTypes: true }).filter((file) => file.isFile()).map((file) => file.name).filter(isMigrationFile);
509
530
  const uniqueKeys = /* @__PURE__ */ new Set();
510
531
  dir_content.forEach((file) => {
511
532
  const key = canonicalMigrationKey(file);
@@ -1353,7 +1374,7 @@ var PatchCreator = class _PatchCreator {
1353
1374
  if (!import_fs5.default.existsSync(this.patchFolder)) {
1354
1375
  import_fs5.default.mkdirSync(this.patchFolder, { recursive: true });
1355
1376
  }
1356
- let stamp = Date.now();
1377
+ let stamp = mintMigrationStamp();
1357
1378
  for (let attempt = 0; attempt < 1e3; attempt++) {
1358
1379
  const filePath = import_path4.default.join(this.patchFolder, `${stamp}_${normalized}.yaml`);
1359
1380
  try {
@@ -1361,7 +1382,7 @@ var PatchCreator = class _PatchCreator {
1361
1382
  return filePath;
1362
1383
  } catch (error) {
1363
1384
  if (error && error.code === "EEXIST") {
1364
- stamp += 1;
1385
+ stamp = mintMigrationStamp(stamp + 1);
1365
1386
  continue;
1366
1387
  }
1367
1388
  throw error;
@@ -1952,6 +1973,14 @@ var MySQLMigrationRunner = class {
1952
1973
  migrate(migrationNodes, forward) {
1953
1974
  return __async(this, null, function* () {
1954
1975
  yield this.setup();
1976
+ if (forward) {
1977
+ for (const node of migrationNodes) {
1978
+ const key = node.get_key();
1979
+ if (isHandStampedKey(key) && !(yield node.status()).completed) {
1980
+ throw new MigrationStampError(key);
1981
+ }
1982
+ }
1983
+ }
1955
1984
  for (let node of migrationNodes) {
1956
1985
  try {
1957
1986
  if (forward) {
@@ -2089,7 +2118,7 @@ var MigrationCreator = class {
2089
2118
  if (!import_fs6.default.existsSync(this.config.migration_folder)) {
2090
2119
  import_fs6.default.mkdirSync(this.config.migration_folder, { recursive: true });
2091
2120
  }
2092
- const now_timestamp = Date.now();
2121
+ const now_timestamp = mintMigrationStamp();
2093
2122
  const filename_up = `${now_timestamp}_${name}.up.sql`;
2094
2123
  const filename_down = `${now_timestamp}_${name}.down.sql`;
2095
2124
  import_fs6.default.writeFileSync(`${this.config.migration_folder}/${filename_up}`, `