@runfusion/fusion 0.70.2 → 0.71.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/bin.js +174 -7
- package/dist/child-process-worker.js +30 -6
- package/dist/client/.vite/manifest.json +246 -246
- package/dist/client/assets/{AgentDetailView-UMM9DyW-.js → AgentDetailView-BvY24zNh.js} +1 -1
- package/dist/client/assets/{AgentPermissionPolicyEditor-BfNZUiDb.js → AgentPermissionPolicyEditor-CYvJw48-.js} +1 -1
- package/dist/client/assets/{AgentsView-DtC-DVyX.js → AgentsView-BWkWEfNs.js} +3 -3
- package/dist/client/assets/{ChatView-sDJXcOwT.js → ChatView-BhlVq9Re.js} +1 -1
- package/dist/client/assets/{CommandCenter-B7BECRSV.js → CommandCenter-DingokjC.js} +1 -1
- package/dist/client/assets/{DevServerView-CyW7l6rY.js → DevServerView-kfNJk83M.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-BT3OeDJ3.js → DirectoryPicker-Cluyep4u.js} +1 -1
- package/dist/client/assets/{DocumentsView-Dbn8T4ZT.js → DocumentsView-Bwc5HSg7.js} +1 -1
- package/dist/client/assets/{EvalsView-DGOBPt3P.js → EvalsView-BEr_MhJ4.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-Beno0EK8.js → ExperimentalAgentOnboardingModal-CZK-KtFP.js} +1 -1
- package/dist/client/assets/{GoalsView-BLxtocMB.js → GoalsView-B_Qrm8po.js} +1 -1
- package/dist/client/assets/{InsightsView-DjTpiw1S.js → InsightsView-BfbclBHM.js} +1 -1
- package/dist/client/assets/{MemoryView-BvAhPVCo.js → MemoryView-V9Y08BtR.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-Di3Q9J6V.js → PiExtensionsManager-B7fl5l3O.js} +1 -1
- package/dist/client/assets/{PluginManager-reQpowmU.js → PluginManager-H32X557C.js} +1 -1
- package/dist/client/assets/{PullRequestView-DLDz9RXL.js → PullRequestView-Dhz86tnJ.js} +1 -1
- package/dist/client/assets/{ResearchView-BpdpPwyr.js → ResearchView-DEObk9J2.js} +1 -1
- package/dist/client/assets/{SecretsView-BHu1JHnH.js → SecretsView-DFEWUbXI.js} +1 -1
- package/dist/client/assets/{SessionTerminal-rtlAx2uQ.js → SessionTerminal-CwfTrmor.js} +1 -1
- package/dist/client/assets/{SettingsModal-B7m-bZlG.js → SettingsModal-2mlwjfVZ.js} +1 -1
- package/dist/client/assets/{SettingsModal-Dxz7-SNa.js → SettingsModal-H1TNebmF.js} +3 -3
- package/dist/client/assets/{SettingsTextareaRow-5Vb6XYSC.js → SettingsTextareaRow-ByeSU4Pi.js} +1 -1
- package/dist/client/assets/{SetupWizardModal-BixsaVgv.js → SetupWizardModal-BFZnVJX1.js} +2 -2
- package/dist/client/assets/{SkillsView-CNQaKfLx.js → SkillsView-DScNdDRz.js} +1 -1
- package/dist/client/assets/{ThemeDropdown-Bhz3TH1Z.js → ThemeDropdown-BKl0kouU.js} +1 -1
- package/dist/client/assets/{TodoView-Ccr5rxPw.js → TodoView-_HojIE_Y.js} +1 -1
- package/dist/client/assets/{WorkflowNodeEditor-BeY_3iQR.js → WorkflowNodeEditor-CoQYdUYX.js} +1 -1
- package/dist/client/assets/{app-bX7Aarj6.js → app-0sCAWTFb.js} +1 -1
- package/dist/client/assets/{app-BFkCDjfl.js → app-Cndq8AGV.js} +1 -1
- package/dist/client/assets/{app-Bx4Tg9WL.js → app-CqpqmC8O.js} +1 -1
- package/dist/client/assets/{app-BwKqEIVs.js → app-DjxXVWX9.js} +1 -1
- package/dist/client/assets/{app-gasJpw6T.js → app-DrnsOtt9.js} +1 -1
- package/dist/client/assets/{app-BLTqCjPk.js → app-Kb21Gl_h.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-DbmZMyHk.js → architectureDiagram-3BPJPVTR-vIoH_tGm.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-BkspaqvN.js → blockDiagram-GPEHLZMM-BqjSE9AM.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-BfOk6DAf.js → c4Diagram-AAUBKEIU-TWEWVE4T.js} +1 -1
- package/dist/client/assets/channel-hhQEu5zM.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-DbL54v_S.js → chunk-2J33WTMH-CJM3p9Fh.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-VAUWnfVr.js → chunk-4BX2VUAB-Bf_1wJ7O.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-C5h7MxPM.js → chunk-55IACEB6-CI4ThikJ.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-CCc56jyj.js → chunk-727SXJPM-C2TasaKk.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-CUK6s79q.js → chunk-AQP2D5EJ-BqKUxt3g.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-COFczZ8r.js → chunk-FMBD7UC4-CdK77AxG.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-BXTcFeIM.js → chunk-ND2GUHAM-TE8zbIZ3.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-BEYAo7eA.js → chunk-QZHKN3VN-7lgttGIx.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-C2Thhy7D.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-C2Thhy7D.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-DqQ74MrB.js → cose-bilkent-S5V4N54A-DsK8EBeo.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-D1DsLIdG.js → dagre-BM42HDAG-COza1ss6.js} +1 -1
- package/dist/client/assets/{dashboard-view-DFy7Ta-E.js → dashboard-view-D_etacMS.js} +1 -1
- package/dist/client/assets/{dashboard-view-D5F_ho0i.js → dashboard-view-ILJ_vnYK.js} +1 -1
- package/dist/client/assets/{dashboard-view-CgBE7XiJ.js → dashboard-view-JEFD-Zgw.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-p-547bXh.js → diagram-2AECGRRQ-Co_F0-vp.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-BE9UnZuh.js → diagram-5GNKFQAL-BD_n7vU0.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-BHTLL-vQ.js → diagram-KO2AKTUF-SFnuzet_.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-CWLbQcuj.js → diagram-LMA3HP47-CFYeR0mH.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-CXUiMHIE.js → diagram-OG6HWLK6-DOVfqKgw.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-Dre62Vsd.js → erDiagram-TEJ5UH35-DkeW3bDN.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-BFeMnep3.js → flowDiagram-I6XJVG4X-CVaNMQl_.js} +1 -1
- package/dist/client/assets/{folder-open-s7aQO2Ib.js → folder-open-BY1Gp9Wf.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-CfrUWiHI.js → ganttDiagram-6RSMTGT7-BQJ0x5Hq.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-KjKsgpva.js → gitGraphDiagram-PVQCEYII-CIt0P2Lg.js} +1 -1
- package/dist/client/assets/{index-DF2cd-e3.js → index-ClPjlOHJ.js} +168 -168
- package/dist/client/assets/index-GJLKrqhe.css +1 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-Cb_8B_3K.js → infoDiagram-5YYISTIA-B1KKCn80.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-8jtlcCaf.js → ishikawaDiagram-YF4QCWOH-CzG1cEeg.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-O6X0tJvH.js → journeyDiagram-JHISSGLW-CNB7oM4Q.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-BetEnps7.js → kanban-definition-UN3LZRKU-D8vXTzfs.js} +1 -1
- package/dist/client/assets/{mermaid.core-CZbT2qhF.js → mermaid.core-BUhJJv1M.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-BRjDmxQK.js → mindmap-definition-RKZ34NQL-y_XyU0Us.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-CJHx1ZvR.js → pieDiagram-4H26LBE5-MB9aZtTc.js} +1 -1
- package/dist/client/assets/{puzzle-BJEQBgfR.js → puzzle-CE00Ce2g.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-D49nAI3y.js → quadrantDiagram-W4KKPZXB-hF7q33gK.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-BM4Uv6Jr.js → requirementDiagram-4Y6WPE33-BIOIzbEd.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-RSKSlyjr.js → sankeyDiagram-5OEKKPKP-BpLzUxJ8.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-BXpcHAnr.js → sequenceDiagram-3UESZ5HK-CLXamQhZ.js} +1 -1
- package/dist/client/assets/{shield-alert-DcsqJWMG.js → shield-alert-BhLVV0rp.js} +1 -1
- package/dist/client/assets/{standing-instructions-template-CUYzx5D8.js → standing-instructions-template-96KSNan7.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-CavU8Ef4.js → stateDiagram-AJRCARHV-CPRWhQtZ.js} +1 -1
- package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-Cq-9bJPI.js → stateDiagram-v2-BHNVJYJU-8GvpOVMc.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-7fHh3hS9.js → timeline-definition-PNZ67QCA-BAAldJMW.js} +1 -1
- package/dist/client/assets/{upload-DNwFaPfV.js → upload-DbKZcYCW.js} +1 -1
- package/dist/client/assets/{users-D-kPhpXu.js → users-ccVe3aKQ.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-mCh9G6D5.js → vennDiagram-CIIHVFJN-DGSAcrfx.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-DEu4AYE9.js → wardley-L42UT6IY-CLGvNiAx.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-DRL0ZyeQ.js → wardleyDiagram-YWT4CUSO-BhU8FLGx.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-DUpC-GBX.js → xychartDiagram-2RQKCTM6-BQ6AzTfE.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/version.json +1 -1
- package/dist/extension.js +30 -6
- package/dist/plugins/fusion-plugin-dependency-graph/.bundled.reload-1.js +8084 -0
- package/dist/plugins/fusion-plugin-grok-runtime/.bundled.reload-2.js +26479 -0
- package/package.json +1 -1
- package/dist/client/assets/channel-CABKCAbA.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-DgshwmmF.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DgshwmmF.js +0 -1
- package/dist/client/assets/index-Co20nJU4.css +0 -1
package/dist/bin.js
CHANGED
|
@@ -47419,6 +47419,25 @@ function classifyColumnType(pgCol) {
|
|
|
47419
47419
|
}
|
|
47420
47420
|
return "plain";
|
|
47421
47421
|
}
|
|
47422
|
+
function stripNulChars(text2) {
|
|
47423
|
+
return text2.includes("\0") ? text2.replace(NUL_CHAR_RE, "") : text2;
|
|
47424
|
+
}
|
|
47425
|
+
function deepStripNulChars(value) {
|
|
47426
|
+
if (typeof value === "string") {
|
|
47427
|
+
return stripNulChars(value);
|
|
47428
|
+
}
|
|
47429
|
+
if (Array.isArray(value)) {
|
|
47430
|
+
return value.map(deepStripNulChars);
|
|
47431
|
+
}
|
|
47432
|
+
if (value !== null && typeof value === "object") {
|
|
47433
|
+
return Object.fromEntries(
|
|
47434
|
+
Object.entries(value).map(
|
|
47435
|
+
([key, entry]) => [stripNulChars(key), deepStripNulChars(entry)]
|
|
47436
|
+
)
|
|
47437
|
+
);
|
|
47438
|
+
}
|
|
47439
|
+
return value;
|
|
47440
|
+
}
|
|
47422
47441
|
function convertValue(value, type, nullJsonbFallback, preserveEmptyJsonbString = false) {
|
|
47423
47442
|
if (value === null || value === void 0) {
|
|
47424
47443
|
return type === "jsonb" && nullJsonbFallback !== void 0 ? nullJsonbFallback : null;
|
|
@@ -47431,12 +47450,12 @@ function convertValue(value, type, nullJsonbFallback, preserveEmptyJsonbString =
|
|
|
47431
47450
|
return nullJsonbFallback ?? (preserveEmptyJsonbString ? JSON.stringify(value) : null);
|
|
47432
47451
|
}
|
|
47433
47452
|
try {
|
|
47434
|
-
return JSON.stringify(JSON.parse(trimmed));
|
|
47453
|
+
return JSON.stringify(deepStripNulChars(JSON.parse(trimmed)));
|
|
47435
47454
|
} catch {
|
|
47436
|
-
return JSON.stringify(value);
|
|
47455
|
+
return JSON.stringify(stripNulChars(value));
|
|
47437
47456
|
}
|
|
47438
47457
|
}
|
|
47439
|
-
return JSON.stringify(value);
|
|
47458
|
+
return JSON.stringify(deepStripNulChars(value));
|
|
47440
47459
|
}
|
|
47441
47460
|
case "bytea": {
|
|
47442
47461
|
if (Buffer.isBuffer(value)) {
|
|
@@ -47454,7 +47473,7 @@ function convertValue(value, type, nullJsonbFallback, preserveEmptyJsonbString =
|
|
|
47454
47473
|
case "identity":
|
|
47455
47474
|
case "generated":
|
|
47456
47475
|
default:
|
|
47457
|
-
return value;
|
|
47476
|
+
return typeof value === "string" ? stripNulChars(value) : value;
|
|
47458
47477
|
}
|
|
47459
47478
|
}
|
|
47460
47479
|
function createQuarterProgressReporter(sourceRows, onCopyProgress) {
|
|
@@ -47479,7 +47498,7 @@ function tagLegacyCell(value) {
|
|
|
47479
47498
|
if (typeof value === "number" || typeof value === "bigint") {
|
|
47480
47499
|
return { type: "number", value: Object.is(value, -0) ? "-0" : String(value) };
|
|
47481
47500
|
}
|
|
47482
|
-
return { type: "text", value: String(value) };
|
|
47501
|
+
return { type: "text", value: stripNulChars(String(value)) };
|
|
47483
47502
|
}
|
|
47484
47503
|
function canonicalizeLegacyRows(rows, occurrences = /* @__PURE__ */ new Map()) {
|
|
47485
47504
|
return rows.map((row) => {
|
|
@@ -47947,7 +47966,7 @@ async function computeTargetCanonicalRows(db, pgSchema2, table, cols, projectId)
|
|
|
47947
47966
|
return canonical;
|
|
47948
47967
|
}).sort();
|
|
47949
47968
|
}
|
|
47950
|
-
var log4, INSERT_BATCH_SIZE, LEGACY_PRESERVATION_TARGETS, SQLITE_MIGRATION_STATE_TABLE, CENTRAL_SQLITE_MIGRATION_KEY, DryRunRollback;
|
|
47969
|
+
var log4, INSERT_BATCH_SIZE, LEGACY_PRESERVATION_TARGETS, SQLITE_MIGRATION_STATE_TABLE, CENTRAL_SQLITE_MIGRATION_KEY, DryRunRollback, NUL_CHAR_RE;
|
|
47951
47970
|
var init_sqlite_migrator = __esm({
|
|
47952
47971
|
"../core/src/postgres/sqlite-migrator.ts"() {
|
|
47953
47972
|
"use strict";
|
|
@@ -47972,6 +47991,7 @@ var init_sqlite_migrator = __esm({
|
|
|
47972
47991
|
this.name = "DryRunRollback";
|
|
47973
47992
|
}
|
|
47974
47993
|
};
|
|
47994
|
+
NUL_CHAR_RE = /\u0000/g;
|
|
47975
47995
|
}
|
|
47976
47996
|
});
|
|
47977
47997
|
|
|
@@ -59739,6 +59759,10 @@ async function createTaskStoreForBackend(options) {
|
|
|
59739
59759
|
*/
|
|
59740
59760
|
onProgress: (event) => {
|
|
59741
59761
|
log5.log(`startup-factory: SQLite migration \u2014 ${formatMigrationProgress2(event)}`);
|
|
59762
|
+
try {
|
|
59763
|
+
options.onMigrationProgress?.(event);
|
|
59764
|
+
} catch {
|
|
59765
|
+
}
|
|
59742
59766
|
}
|
|
59743
59767
|
});
|
|
59744
59768
|
const failedTables = report.tables.filter((table) => !table.skipped && !table.verified);
|
|
@@ -382718,6 +382742,137 @@ var init_port_prompt = __esm({
|
|
|
382718
382742
|
}
|
|
382719
382743
|
});
|
|
382720
382744
|
|
|
382745
|
+
// src/commands/migration-holding-server.ts
|
|
382746
|
+
import { createServer as createServer6 } from "node:http";
|
|
382747
|
+
function renderHoldingPage() {
|
|
382748
|
+
return `<!doctype html>
|
|
382749
|
+
<html lang="en">
|
|
382750
|
+
<head>
|
|
382751
|
+
<meta charset="utf-8">
|
|
382752
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
382753
|
+
<title>Fusion \u2014 starting</title>
|
|
382754
|
+
<style>
|
|
382755
|
+
:root { color-scheme: dark; }
|
|
382756
|
+
body {
|
|
382757
|
+
margin: 0; min-height: 100vh; display: flex; align-items: center; justify-content: center;
|
|
382758
|
+
background: #0b0e14; color: #e6e9ef;
|
|
382759
|
+
font: 15px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
382760
|
+
}
|
|
382761
|
+
.card { max-width: 30rem; padding: 2rem; text-align: center; }
|
|
382762
|
+
.spinner {
|
|
382763
|
+
width: 2.25rem; height: 2.25rem; margin: 0 auto 1.25rem;
|
|
382764
|
+
border: 3px solid rgba(59, 130, 246, 0.25); border-top-color: #3b82f6;
|
|
382765
|
+
border-radius: 50%; animation: spin 0.9s linear infinite;
|
|
382766
|
+
}
|
|
382767
|
+
@keyframes spin { to { transform: rotate(360deg); } }
|
|
382768
|
+
h1 { font-size: 1.15rem; margin: 0 0 0.5rem; font-weight: 600; }
|
|
382769
|
+
p { margin: 0 0 0.75rem; color: #9aa4b2; }
|
|
382770
|
+
.progress { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.85rem; color: #7fb1ff; min-height: 1.5em; overflow-wrap: anywhere; }
|
|
382771
|
+
.offline { color: #f0883e; }
|
|
382772
|
+
</style>
|
|
382773
|
+
</head>
|
|
382774
|
+
<body>
|
|
382775
|
+
<div class="card" role="status" aria-live="polite">
|
|
382776
|
+
<div class="spinner" aria-hidden="true"></div>
|
|
382777
|
+
<h1 id="title">Fusion is starting\u2026</h1>
|
|
382778
|
+
<p id="subtitle">If a database migration is needed it runs now and can take a few minutes for large projects. This page reloads automatically when the dashboard is ready.</p>
|
|
382779
|
+
<div class="progress" id="progress"></div>
|
|
382780
|
+
</div>
|
|
382781
|
+
<script>
|
|
382782
|
+
(function () {
|
|
382783
|
+
var failures = 0;
|
|
382784
|
+
var sawMigration = false;
|
|
382785
|
+
async function poll() {
|
|
382786
|
+
try {
|
|
382787
|
+
var res = await fetch("/api/health", { cache: "no-store" });
|
|
382788
|
+
if (!res.ok) return;
|
|
382789
|
+
failures = 0;
|
|
382790
|
+
var data = await res.json();
|
|
382791
|
+
if (data && (data.status === "starting" || data.status === "migrating")) {
|
|
382792
|
+
if (data.status === "migrating") {
|
|
382793
|
+
sawMigration = true;
|
|
382794
|
+
document.getElementById("title").textContent = "Database migration in progress";
|
|
382795
|
+
}
|
|
382796
|
+
var label = data.migration && data.migration.label;
|
|
382797
|
+
if (label) document.getElementById("progress").textContent = label;
|
|
382798
|
+
return;
|
|
382799
|
+
}
|
|
382800
|
+
location.reload();
|
|
382801
|
+
} catch (err) {
|
|
382802
|
+
failures += 1;
|
|
382803
|
+
if (failures >= 8) {
|
|
382804
|
+
document.getElementById("progress").innerHTML =
|
|
382805
|
+
'<span class="offline">Cannot reach Fusion \u2014 it may have stopped. Check the terminal, then reload.</span>';
|
|
382806
|
+
}
|
|
382807
|
+
}
|
|
382808
|
+
}
|
|
382809
|
+
poll();
|
|
382810
|
+
setInterval(poll, 1500);
|
|
382811
|
+
})();
|
|
382812
|
+
</script>
|
|
382813
|
+
</body>
|
|
382814
|
+
</html>`;
|
|
382815
|
+
}
|
|
382816
|
+
async function startMigrationHoldingServer(options) {
|
|
382817
|
+
let latest = null;
|
|
382818
|
+
const server = createServer6((req, res) => {
|
|
382819
|
+
const url2 = req.url ?? "/";
|
|
382820
|
+
if (url2 === "/api/health" || url2.startsWith("/api/health?")) {
|
|
382821
|
+
res.writeHead(200, { "content-type": "application/json", "cache-control": "no-store" });
|
|
382822
|
+
res.end(JSON.stringify({
|
|
382823
|
+
status: latest ? "migrating" : "starting",
|
|
382824
|
+
holding: true,
|
|
382825
|
+
migration: latest ? {
|
|
382826
|
+
active: true,
|
|
382827
|
+
phase: latest.phase,
|
|
382828
|
+
label: formatMigrationProgress(latest),
|
|
382829
|
+
..."table" in latest ? { table: latest.table, tableIndex: latest.tableIndex, tableCount: latest.tableCount } : {},
|
|
382830
|
+
...latest.phase === "table-progress" ? { processedRows: latest.processedRows, sourceRows: latest.sourceRows } : {}
|
|
382831
|
+
} : { active: false }
|
|
382832
|
+
}));
|
|
382833
|
+
return;
|
|
382834
|
+
}
|
|
382835
|
+
if (url2.startsWith("/api/")) {
|
|
382836
|
+
res.writeHead(503, { "content-type": "application/json", "retry-after": "2" });
|
|
382837
|
+
res.end(JSON.stringify({ error: "Fusion is starting (database migration may be in progress)" }));
|
|
382838
|
+
return;
|
|
382839
|
+
}
|
|
382840
|
+
res.writeHead(503, { "content-type": "text/html; charset=utf-8", "retry-after": "2", "cache-control": "no-store" });
|
|
382841
|
+
res.end(renderHoldingPage());
|
|
382842
|
+
});
|
|
382843
|
+
const bound = await new Promise((resolve96) => {
|
|
382844
|
+
server.once("error", (error48) => {
|
|
382845
|
+
options.log?.(`migration holding page not available (${error48.code ?? error48.message}); continuing boot without it`);
|
|
382846
|
+
resolve96(false);
|
|
382847
|
+
});
|
|
382848
|
+
server.listen(options.port, options.host, () => resolve96(true));
|
|
382849
|
+
});
|
|
382850
|
+
if (!bound) return null;
|
|
382851
|
+
const address = server.address();
|
|
382852
|
+
const port = typeof address === "object" && address !== null ? address.port : options.port;
|
|
382853
|
+
let closed = null;
|
|
382854
|
+
return {
|
|
382855
|
+
port,
|
|
382856
|
+
setMigrationProgress(event) {
|
|
382857
|
+
latest = event;
|
|
382858
|
+
},
|
|
382859
|
+
close() {
|
|
382860
|
+
if (closed) return closed;
|
|
382861
|
+
closed = new Promise((resolve96) => {
|
|
382862
|
+
server.close(() => resolve96());
|
|
382863
|
+
server.closeAllConnections();
|
|
382864
|
+
});
|
|
382865
|
+
return closed;
|
|
382866
|
+
}
|
|
382867
|
+
};
|
|
382868
|
+
}
|
|
382869
|
+
var init_migration_holding_server = __esm({
|
|
382870
|
+
"src/commands/migration-holding-server.ts"() {
|
|
382871
|
+
"use strict";
|
|
382872
|
+
init_src2();
|
|
382873
|
+
}
|
|
382874
|
+
});
|
|
382875
|
+
|
|
382721
382876
|
// src/commands/ensure-project-registered.ts
|
|
382722
382877
|
import { exec as exec48 } from "node:child_process";
|
|
382723
382878
|
import { existsSync as existsSync83, mkdirSync as mkdirSync17 } from "node:fs";
|
|
@@ -392638,9 +392793,17 @@ async function runDashboard(port, opts = {}) {
|
|
|
392638
392793
|
}
|
|
392639
392794
|
ensureProcessDiagnostics(runtimeLogger);
|
|
392640
392795
|
const logPhase = (message, scope = "dashboard") => logSink.log(message, scope);
|
|
392796
|
+
const migrationHoldingServer = await startMigrationHoldingServer({
|
|
392797
|
+
port: selectedPort,
|
|
392798
|
+
host: selectedHost,
|
|
392799
|
+
log: (message) => logSink.log(message, "dashboard")
|
|
392800
|
+
});
|
|
392641
392801
|
const dashboardBackendBoot = await phaseTime(
|
|
392642
392802
|
"backend.factory",
|
|
392643
|
-
() => createTaskStoreForBackend({
|
|
392803
|
+
() => createTaskStoreForBackend({
|
|
392804
|
+
rootDir: cwd,
|
|
392805
|
+
onMigrationProgress: (event) => migrationHoldingServer?.setMigrationProgress(event)
|
|
392806
|
+
}),
|
|
392644
392807
|
logPhase
|
|
392645
392808
|
);
|
|
392646
392809
|
store = dashboardBackendBoot.taskStore;
|
|
@@ -393839,6 +394002,9 @@ async function runDashboard(port, opts = {}) {
|
|
|
393839
394002
|
}
|
|
393840
394003
|
}, POLL_MS).unref();
|
|
393841
394004
|
}
|
|
394005
|
+
if (migrationHoldingServer) {
|
|
394006
|
+
await migrationHoldingServer.close();
|
|
394007
|
+
}
|
|
393842
394008
|
const server = app.listen(selectedPort, selectedHost);
|
|
393843
394009
|
server.on("error", (err) => {
|
|
393844
394010
|
if (err.code === "EADDRINUSE") {
|
|
@@ -394548,6 +394714,7 @@ var init_dashboard = __esm({
|
|
|
394548
394714
|
init_extension();
|
|
394549
394715
|
init_task_lifecycle();
|
|
394550
394716
|
init_port_prompt();
|
|
394717
|
+
init_migration_holding_server();
|
|
394551
394718
|
init_ensure_project_registered();
|
|
394552
394719
|
init_provider_settings();
|
|
394553
394720
|
init_provider_auth2();
|
|
@@ -47494,6 +47494,25 @@ function classifyColumnType(pgCol) {
|
|
|
47494
47494
|
}
|
|
47495
47495
|
return "plain";
|
|
47496
47496
|
}
|
|
47497
|
+
function stripNulChars(text2) {
|
|
47498
|
+
return text2.includes("\0") ? text2.replace(NUL_CHAR_RE, "") : text2;
|
|
47499
|
+
}
|
|
47500
|
+
function deepStripNulChars(value) {
|
|
47501
|
+
if (typeof value === "string") {
|
|
47502
|
+
return stripNulChars(value);
|
|
47503
|
+
}
|
|
47504
|
+
if (Array.isArray(value)) {
|
|
47505
|
+
return value.map(deepStripNulChars);
|
|
47506
|
+
}
|
|
47507
|
+
if (value !== null && typeof value === "object") {
|
|
47508
|
+
return Object.fromEntries(
|
|
47509
|
+
Object.entries(value).map(
|
|
47510
|
+
([key, entry]) => [stripNulChars(key), deepStripNulChars(entry)]
|
|
47511
|
+
)
|
|
47512
|
+
);
|
|
47513
|
+
}
|
|
47514
|
+
return value;
|
|
47515
|
+
}
|
|
47497
47516
|
function convertValue(value, type, nullJsonbFallback, preserveEmptyJsonbString = false) {
|
|
47498
47517
|
if (value === null || value === void 0) {
|
|
47499
47518
|
return type === "jsonb" && nullJsonbFallback !== void 0 ? nullJsonbFallback : null;
|
|
@@ -47506,12 +47525,12 @@ function convertValue(value, type, nullJsonbFallback, preserveEmptyJsonbString =
|
|
|
47506
47525
|
return nullJsonbFallback ?? (preserveEmptyJsonbString ? JSON.stringify(value) : null);
|
|
47507
47526
|
}
|
|
47508
47527
|
try {
|
|
47509
|
-
return JSON.stringify(JSON.parse(trimmed));
|
|
47528
|
+
return JSON.stringify(deepStripNulChars(JSON.parse(trimmed)));
|
|
47510
47529
|
} catch {
|
|
47511
|
-
return JSON.stringify(value);
|
|
47530
|
+
return JSON.stringify(stripNulChars(value));
|
|
47512
47531
|
}
|
|
47513
47532
|
}
|
|
47514
|
-
return JSON.stringify(value);
|
|
47533
|
+
return JSON.stringify(deepStripNulChars(value));
|
|
47515
47534
|
}
|
|
47516
47535
|
case "bytea": {
|
|
47517
47536
|
if (Buffer.isBuffer(value)) {
|
|
@@ -47529,7 +47548,7 @@ function convertValue(value, type, nullJsonbFallback, preserveEmptyJsonbString =
|
|
|
47529
47548
|
case "identity":
|
|
47530
47549
|
case "generated":
|
|
47531
47550
|
default:
|
|
47532
|
-
return value;
|
|
47551
|
+
return typeof value === "string" ? stripNulChars(value) : value;
|
|
47533
47552
|
}
|
|
47534
47553
|
}
|
|
47535
47554
|
function createQuarterProgressReporter(sourceRows, onCopyProgress) {
|
|
@@ -47554,7 +47573,7 @@ function tagLegacyCell(value) {
|
|
|
47554
47573
|
if (typeof value === "number" || typeof value === "bigint") {
|
|
47555
47574
|
return { type: "number", value: Object.is(value, -0) ? "-0" : String(value) };
|
|
47556
47575
|
}
|
|
47557
|
-
return { type: "text", value: String(value) };
|
|
47576
|
+
return { type: "text", value: stripNulChars(String(value)) };
|
|
47558
47577
|
}
|
|
47559
47578
|
function canonicalizeLegacyRows(rows, occurrences = /* @__PURE__ */ new Map()) {
|
|
47560
47579
|
return rows.map((row) => {
|
|
@@ -48022,7 +48041,7 @@ async function computeTargetCanonicalRows(db, pgSchema2, table, cols, projectId)
|
|
|
48022
48041
|
return canonical;
|
|
48023
48042
|
}).sort();
|
|
48024
48043
|
}
|
|
48025
|
-
var log4, INSERT_BATCH_SIZE, LEGACY_PRESERVATION_TARGETS, SQLITE_MIGRATION_STATE_TABLE, CENTRAL_SQLITE_MIGRATION_KEY, DryRunRollback;
|
|
48044
|
+
var log4, INSERT_BATCH_SIZE, LEGACY_PRESERVATION_TARGETS, SQLITE_MIGRATION_STATE_TABLE, CENTRAL_SQLITE_MIGRATION_KEY, DryRunRollback, NUL_CHAR_RE;
|
|
48026
48045
|
var init_sqlite_migrator = __esm({
|
|
48027
48046
|
"../core/src/postgres/sqlite-migrator.ts"() {
|
|
48028
48047
|
"use strict";
|
|
@@ -48047,6 +48066,7 @@ var init_sqlite_migrator = __esm({
|
|
|
48047
48066
|
this.name = "DryRunRollback";
|
|
48048
48067
|
}
|
|
48049
48068
|
};
|
|
48069
|
+
NUL_CHAR_RE = /\u0000/g;
|
|
48050
48070
|
}
|
|
48051
48071
|
});
|
|
48052
48072
|
|
|
@@ -59814,6 +59834,10 @@ async function createTaskStoreForBackend(options) {
|
|
|
59814
59834
|
*/
|
|
59815
59835
|
onProgress: (event) => {
|
|
59816
59836
|
log5.log(`startup-factory: SQLite migration \u2014 ${formatMigrationProgress2(event)}`);
|
|
59837
|
+
try {
|
|
59838
|
+
options.onMigrationProgress?.(event);
|
|
59839
|
+
} catch {
|
|
59840
|
+
}
|
|
59817
59841
|
}
|
|
59818
59842
|
});
|
|
59819
59843
|
const failedTables = report.tables.filter((table) => !table.skipped && !table.verified);
|