@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/index.js CHANGED
@@ -157,6 +157,16 @@ var DatabaseConnectionError = class _DatabaseConnectionError extends MigrationEr
157
157
  return new _DatabaseConnectionError(`Authentication failed for ${dbType} database`);
158
158
  }
159
159
  };
160
+ var MigrationStampError = class _MigrationStampError extends MigrationError {
161
+ constructor(migrationKey) {
162
+ super(
163
+ `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.`
164
+ );
165
+ this.migrationKey = migrationKey;
166
+ this.name = "MigrationStampError";
167
+ Object.setPrototypeOf(this, _MigrationStampError.prototype);
168
+ }
169
+ };
160
170
  var MigrationExecutionError = class _MigrationExecutionError extends MigrationError {
161
171
  constructor(message, migrationName, sql, originalError) {
162
172
  let fullMessage = `Migration Execution Error${migrationName ? ` in '${migrationName}'` : ""}: ${message}`;
@@ -419,8 +429,19 @@ var SqlMigrationBuilder = class {
419
429
  // framework/MigrationManifest.ts
420
430
  var import_fs = __toESM(require("fs"));
421
431
  var import_path = __toESM(require("path"));
432
+ var MIGRATION_FILE_REGEX = /(?:\.(mysql|sqlite|pg))?\.(up|down)\.(sql|js)$/i;
433
+ function isMigrationFile(fileName) {
434
+ return MIGRATION_FILE_REGEX.test(fileName);
435
+ }
422
436
  function canonicalMigrationKey(value) {
423
- return value.replace(/(?:\.(mysql|sqlite|pg))?\.(up|down)\.(sql|js)$/i, "").toLowerCase();
437
+ return value.replace(MIGRATION_FILE_REGEX, "").toLowerCase();
438
+ }
439
+ function mintMigrationStamp(now = Date.now()) {
440
+ return now % 10 === 0 ? now + 1 : now;
441
+ }
442
+ function isHandStampedKey(key) {
443
+ const stamp = key.split("_")[0];
444
+ return /^\d+$/.test(stamp) && /000$/.test(stamp);
424
445
  }
425
446
  function resolveMigrationFile(directory, baseName, direction, dialect) {
426
447
  const dialectExt = dialect === "sql" ? "mysql" : dialect;
@@ -433,7 +454,7 @@ function resolveMigrationFile(directory, baseName, direction, dialect) {
433
454
  function loadMigrationManifest(directory, dialect) {
434
455
  const manifest = /* @__PURE__ */ new Map();
435
456
  if (!import_fs.default.existsSync(directory)) return manifest;
436
- const files = import_fs.default.readdirSync(directory, { withFileTypes: true }).filter((f) => f.isFile()).map((f) => f.name);
457
+ const files = import_fs.default.readdirSync(directory, { withFileTypes: true }).filter((f) => f.isFile()).map((f) => f.name).filter(isMigrationFile);
437
458
  const uniqueKeys = /* @__PURE__ */ new Set();
438
459
  files.forEach((file) => uniqueKeys.add(canonicalMigrationKey(file)));
439
460
  uniqueKeys.forEach((key) => {
@@ -470,7 +491,7 @@ var MigrationDirectoryReader = class {
470
491
  }
471
492
  loadMigrations(table, connection) {
472
493
  import_fs2.default.existsSync(this.directory) || import_fs2.default.mkdirSync(this.directory);
473
- const dir_content = import_fs2.default.readdirSync(this.directory, { withFileTypes: true }).filter((file) => file.isFile()).map((file) => file.name);
494
+ const dir_content = import_fs2.default.readdirSync(this.directory, { withFileTypes: true }).filter((file) => file.isFile()).map((file) => file.name).filter(isMigrationFile);
474
495
  const uniqueKeys = /* @__PURE__ */ new Set();
475
496
  dir_content.forEach((file) => {
476
497
  const key = canonicalMigrationKey(file);
@@ -1333,7 +1354,7 @@ var PatchCreator = class _PatchCreator {
1333
1354
  if (!import_fs5.default.existsSync(this.patchFolder)) {
1334
1355
  import_fs5.default.mkdirSync(this.patchFolder, { recursive: true });
1335
1356
  }
1336
- let stamp = Date.now();
1357
+ let stamp = mintMigrationStamp();
1337
1358
  for (let attempt = 0; attempt < 1e3; attempt++) {
1338
1359
  const filePath = import_path4.default.join(this.patchFolder, `${stamp}_${normalized}.yaml`);
1339
1360
  try {
@@ -1341,7 +1362,7 @@ var PatchCreator = class _PatchCreator {
1341
1362
  return filePath;
1342
1363
  } catch (error) {
1343
1364
  if (error && error.code === "EEXIST") {
1344
- stamp += 1;
1365
+ stamp = mintMigrationStamp(stamp + 1);
1345
1366
  continue;
1346
1367
  }
1347
1368
  throw error;
@@ -1936,6 +1957,14 @@ var MySQLMigrationRunner = class {
1936
1957
  migrate(migrationNodes, forward) {
1937
1958
  return __async(this, null, function* () {
1938
1959
  yield this.setup();
1960
+ if (forward) {
1961
+ for (const node of migrationNodes) {
1962
+ const key = node.get_key();
1963
+ if (isHandStampedKey(key) && !(yield node.status()).completed) {
1964
+ throw new MigrationStampError(key);
1965
+ }
1966
+ }
1967
+ }
1939
1968
  for (let node of migrationNodes) {
1940
1969
  try {
1941
1970
  if (forward) {
@@ -2073,7 +2102,7 @@ var MigrationCreator = class {
2073
2102
  if (!import_fs6.default.existsSync(this.config.migration_folder)) {
2074
2103
  import_fs6.default.mkdirSync(this.config.migration_folder, { recursive: true });
2075
2104
  }
2076
- const now_timestamp = Date.now();
2105
+ const now_timestamp = mintMigrationStamp();
2077
2106
  const filename_up = `${now_timestamp}_${name}.up.sql`;
2078
2107
  const filename_down = `${now_timestamp}_${name}.down.sql`;
2079
2108
  import_fs6.default.writeFileSync(`${this.config.migration_folder}/${filename_up}`, `