Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d8bf4b1db8 | |||
| fb2351ffe7 | |||
| 12f7d2b484 |
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
---
|
||||
|
||||
## [1.6.3] — 2026-02-28
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **Database data preservation on upgrade** — Previously, upgrading from older versions (e.g. v1.2.0 → v1.6.x) could cause data loss by renaming the existing database when a legacy `schema_migrations` table was detected. Now checks for actual data before deciding to reset ([#146](https://github.com/diegosouzapw/OmniRoute/issues/146))
|
||||
- **Hardcoded build-machine paths in npm package** — Next.js standalone output baked absolute paths from the build machine into `server.js` and `required-server-files.json`. On other machines these paths don't exist, causing `ENOENT` errors. The prepublish script now sanitizes all build paths to relative ([#147](https://github.com/diegosouzapw/OmniRoute/issues/147))
|
||||
|
||||
---
|
||||
|
||||
## [1.6.2] — 2026-02-27
|
||||
|
||||
### ✨ New Features
|
||||
@@ -769,6 +778,7 @@ New environment variables:
|
||||
|
||||
---
|
||||
|
||||
[1.6.3]: https://github.com/diegosouzapw/OmniRoute/releases/tag/v1.6.3
|
||||
[1.6.2]: https://github.com/diegosouzapw/OmniRoute/releases/tag/v1.6.2
|
||||
[1.6.1]: https://github.com/diegosouzapw/OmniRoute/releases/tag/v1.6.1
|
||||
[1.6.0]: https://github.com/diegosouzapw/OmniRoute/releases/tag/v1.6.0
|
||||
|
||||
Generated
+15
-2
@@ -1,12 +1,13 @@
|
||||
{
|
||||
"name": "omniroute",
|
||||
"version": "1.5.0",
|
||||
"version": "1.6.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "omniroute",
|
||||
"version": "1.5.0",
|
||||
"version": "1.6.2",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"open-sse"
|
||||
@@ -5886,6 +5887,7 @@
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
@@ -7951,6 +7953,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/next-intl/node_modules/@swc/helpers": {
|
||||
"version": "0.5.19",
|
||||
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.19.tgz",
|
||||
"integrity": "sha512-QamiFeIK3txNjgUTNppE6MiG3p7TdninpZu0E0PbqVh1a9FNLT2FRhisaa4NcaX52XVhA5l7Pk58Ft7Sqi/2sA==",
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/next/node_modules/postcss": {
|
||||
"version": "8.4.31",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "omniroute",
|
||||
"version": "1.6.2",
|
||||
"version": "1.6.3",
|
||||
"description": "Smart AI Router with auto fallback — route to FREE & cheap models, zero downtime. Works with Cursor, Cline, Claude Desktop, Codex, and any OpenAI-compatible tool.",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
|
||||
@@ -51,6 +51,38 @@ console.log(" 📋 Copying standalone build to app/...");
|
||||
mkdirSync(APP_DIR, { recursive: true });
|
||||
cpSync(standaloneDir, APP_DIR, { recursive: true });
|
||||
|
||||
// ── Step 5.5: Sanitize hardcoded build-machine paths ───────
|
||||
// Next.js standalone bakes absolute build-time paths into server.js and
|
||||
// required-server-files.json (outputFileTracingRoot, appDir, turbopack root).
|
||||
// Replace the build machine's absolute path with "." (current directory)
|
||||
// so paths resolve relative to wherever the standalone app/ is installed.
|
||||
console.log(" 🧹 Sanitizing build-machine paths...");
|
||||
const buildRoot = ROOT.replace(/\\/g, "/"); // normalise for regex safety
|
||||
const sanitizeTargets = [
|
||||
join(APP_DIR, "server.js"),
|
||||
join(APP_DIR, ".next", "required-server-files.json"),
|
||||
];
|
||||
let sanitisedCount = 0;
|
||||
for (const filePath of sanitizeTargets) {
|
||||
if (!existsSync(filePath)) continue;
|
||||
let content = readFileSync(filePath, "utf8");
|
||||
// Escape special regex characters in the path
|
||||
const escaped = buildRoot.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
const re = new RegExp(escaped, "g");
|
||||
const matches = content.match(re);
|
||||
if (matches) {
|
||||
// Replace with "." so Next.js resolves paths relative to the standalone dir
|
||||
content = content.replace(re, ".");
|
||||
writeFileSync(filePath, content);
|
||||
sanitisedCount += matches.length;
|
||||
}
|
||||
}
|
||||
if (sanitisedCount > 0) {
|
||||
console.log(` ✅ Sanitised ${sanitisedCount} hardcoded path references`);
|
||||
} else {
|
||||
console.log(" ℹ️ No hardcoded paths found to sanitise");
|
||||
}
|
||||
|
||||
// ── Step 6: Copy static assets ─────────────────────────────
|
||||
const staticSrc = join(ROOT, ".next", "static");
|
||||
const staticDest = join(APP_DIR, ".next", "static");
|
||||
|
||||
+43
-11
@@ -322,28 +322,60 @@ export function getDbInstance() {
|
||||
return _db;
|
||||
}
|
||||
|
||||
// Detect and replace old incompatible schema
|
||||
// Detect and handle old schema format — preserve data when possible (#146)
|
||||
if (fs.existsSync(SQLITE_FILE)) {
|
||||
try {
|
||||
const probe = new Database(SQLITE_FILE, { readonly: true });
|
||||
const hasOldSchema = probe
|
||||
.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='schema_migrations'")
|
||||
.get();
|
||||
probe.close();
|
||||
|
||||
if (hasOldSchema) {
|
||||
const oldPath = SQLITE_FILE + ".old-schema";
|
||||
console.log(
|
||||
`[DB] Old incompatible schema detected — renaming to ${path.basename(oldPath)}`
|
||||
);
|
||||
fs.renameSync(SQLITE_FILE, oldPath);
|
||||
for (const ext of ["-wal", "-shm"]) {
|
||||
// Check if the DB has actual data we should preserve
|
||||
let hasData = false;
|
||||
try {
|
||||
const count = probe.prepare("SELECT COUNT(*) as c FROM provider_connections").get() as
|
||||
| { c: number }
|
||||
| undefined;
|
||||
hasData = count && count.c > 0;
|
||||
} catch {
|
||||
// Table might not exist at all — truly incompatible
|
||||
}
|
||||
probe.close();
|
||||
|
||||
if (hasData) {
|
||||
// Data exists — preserve it! Just drop the old migration tracking table
|
||||
// and let our new migration system (CREATE TABLE IF NOT EXISTS) take over
|
||||
console.log(
|
||||
`[DB] Old schema_migrations table found but data exists — preserving data (#146)`
|
||||
);
|
||||
const fixDb = new Database(SQLITE_FILE);
|
||||
try {
|
||||
if (fs.existsSync(SQLITE_FILE + ext)) fs.unlinkSync(SQLITE_FILE + ext);
|
||||
} catch {
|
||||
/* ok */
|
||||
fixDb.exec("DROP TABLE IF EXISTS schema_migrations");
|
||||
// Clean up WAL/SHM files that might be stale
|
||||
fixDb.pragma("wal_checkpoint(TRUNCATE)");
|
||||
} catch (e) {
|
||||
console.warn("[DB] Could not clean up old schema table:", e.message);
|
||||
} finally {
|
||||
fixDb.close();
|
||||
}
|
||||
} else {
|
||||
// No data — safe to rename and start fresh
|
||||
const oldPath = SQLITE_FILE + ".old-schema";
|
||||
console.log(
|
||||
`[DB] Old incompatible schema detected (empty) — renaming to ${path.basename(oldPath)}`
|
||||
);
|
||||
fs.renameSync(SQLITE_FILE, oldPath);
|
||||
for (const ext of ["-wal", "-shm"]) {
|
||||
try {
|
||||
if (fs.existsSync(SQLITE_FILE + ext)) fs.unlinkSync(SQLITE_FILE + ext);
|
||||
} catch {
|
||||
/* ok */
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
probe.close();
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("[DB] Could not probe existing DB, will create fresh:", e.message);
|
||||
|
||||
Reference in New Issue
Block a user