@agent-native/core 0.15.5 → 0.15.6
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/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +3 -2
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +5 -1
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/components/CodeRequiredDialog.js +1 -1
- package/dist/client/components/CodeRequiredDialog.js.map +1 -1
- package/dist/client/settings/BackgroundAgentSection.d.ts.map +1 -1
- package/dist/client/settings/BackgroundAgentSection.js +2 -1
- package/dist/client/settings/BackgroundAgentSection.js.map +1 -1
- package/dist/client/settings/BrowserSection.d.ts.map +1 -1
- package/dist/client/settings/BrowserSection.js +3 -2
- package/dist/client/settings/BrowserSection.js.map +1 -1
- package/dist/client/settings/SettingsPanel.js +1 -1
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.d.ts.map +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.js +1 -0
- package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -1
- package/dist/client/settings/useBuilderStatus.d.ts +1 -0
- package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
- package/dist/client/settings/useBuilderStatus.js +53 -12
- package/dist/client/settings/useBuilderStatus.js.map +1 -1
- package/dist/client/settings/useBuilderStatus.spec.js +43 -7
- package/dist/client/settings/useBuilderStatus.spec.js.map +1 -1
- package/dist/client/transcription/BuilderTranscriptionCta.d.ts.map +1 -1
- package/dist/client/transcription/BuilderTranscriptionCta.js +7 -2
- package/dist/client/transcription/BuilderTranscriptionCta.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +3 -1
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +19 -2
- package/dist/server/auth.js.map +1 -1
- package/dist/server/builder-browser.d.ts +8 -0
- package/dist/server/builder-browser.d.ts.map +1 -1
- package/dist/server/builder-browser.js +20 -0
- package/dist/server/builder-browser.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +55 -23
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/package.json +1 -1
- package/dist/client/dev-mode.d.ts +0 -14
- package/dist/client/dev-mode.d.ts.map +0 -1
- package/dist/client/dev-mode.js +0 -14
- package/dist/client/dev-mode.js.map +0 -1
- package/dist/client/extensions/EmbeddedTool.d.ts +0 -20
- package/dist/client/extensions/EmbeddedTool.d.ts.map +0 -1
- package/dist/client/extensions/EmbeddedTool.js +0 -199
- package/dist/client/extensions/EmbeddedTool.js.map +0 -1
- package/dist/client/extensions/ToolEditor.d.ts +0 -5
- package/dist/client/extensions/ToolEditor.d.ts.map +0 -1
- package/dist/client/extensions/ToolEditor.js +0 -129
- package/dist/client/extensions/ToolEditor.js.map +0 -1
- package/dist/client/extensions/ToolViewer.d.ts +0 -5
- package/dist/client/extensions/ToolViewer.d.ts.map +0 -1
- package/dist/client/extensions/ToolViewer.js +0 -400
- package/dist/client/extensions/ToolViewer.js.map +0 -1
- package/dist/client/extensions/ToolViewerPage.d.ts +0 -2
- package/dist/client/extensions/ToolViewerPage.d.ts.map +0 -1
- package/dist/client/extensions/ToolViewerPage.js +0 -24
- package/dist/client/extensions/ToolViewerPage.js.map +0 -1
- package/dist/client/extensions/ToolsListPage.d.ts +0 -2
- package/dist/client/extensions/ToolsListPage.d.ts.map +0 -1
- package/dist/client/extensions/ToolsListPage.js +0 -67
- package/dist/client/extensions/ToolsListPage.js.map +0 -1
- package/dist/client/extensions/ToolsSidebarSection.d.ts +0 -2
- package/dist/client/extensions/ToolsSidebarSection.d.ts.map +0 -1
- package/dist/client/extensions/ToolsSidebarSection.js +0 -236
- package/dist/client/extensions/ToolsSidebarSection.js.map +0 -1
- package/dist/client/extensions/tool-order.d.ts +0 -7
- package/dist/client/extensions/tool-order.d.ts.map +0 -1
- package/dist/client/extensions/tool-order.js +0 -47
- package/dist/client/extensions/tool-order.js.map +0 -1
- package/dist/client/tools/EmbeddedTool.d.ts +0 -20
- package/dist/client/tools/EmbeddedTool.d.ts.map +0 -1
- package/dist/client/tools/EmbeddedTool.js +0 -199
- package/dist/client/tools/EmbeddedTool.js.map +0 -1
- package/dist/client/tools/ExtensionSlot.d.ts +0 -27
- package/dist/client/tools/ExtensionSlot.d.ts.map +0 -1
- package/dist/client/tools/ExtensionSlot.js +0 -96
- package/dist/client/tools/ExtensionSlot.js.map +0 -1
- package/dist/client/tools/ToolEditor.d.ts +0 -5
- package/dist/client/tools/ToolEditor.d.ts.map +0 -1
- package/dist/client/tools/ToolEditor.js +0 -129
- package/dist/client/tools/ToolEditor.js.map +0 -1
- package/dist/client/tools/ToolViewer.d.ts +0 -5
- package/dist/client/tools/ToolViewer.d.ts.map +0 -1
- package/dist/client/tools/ToolViewer.js +0 -400
- package/dist/client/tools/ToolViewer.js.map +0 -1
- package/dist/client/tools/ToolViewerPage.d.ts +0 -2
- package/dist/client/tools/ToolViewerPage.d.ts.map +0 -1
- package/dist/client/tools/ToolViewerPage.js +0 -24
- package/dist/client/tools/ToolViewerPage.js.map +0 -1
- package/dist/client/tools/ToolsListPage.d.ts +0 -2
- package/dist/client/tools/ToolsListPage.d.ts.map +0 -1
- package/dist/client/tools/ToolsListPage.js +0 -67
- package/dist/client/tools/ToolsListPage.js.map +0 -1
- package/dist/client/tools/ToolsSidebarSection.d.ts +0 -2
- package/dist/client/tools/ToolsSidebarSection.d.ts.map +0 -1
- package/dist/client/tools/ToolsSidebarSection.js +0 -236
- package/dist/client/tools/ToolsSidebarSection.js.map +0 -1
- package/dist/client/tools/iframe-bridge.d.ts +0 -38
- package/dist/client/tools/iframe-bridge.d.ts.map +0 -1
- package/dist/client/tools/iframe-bridge.js +0 -207
- package/dist/client/tools/iframe-bridge.js.map +0 -1
- package/dist/client/tools/index.d.ts +0 -8
- package/dist/client/tools/index.d.ts.map +0 -1
- package/dist/client/tools/index.js +0 -8
- package/dist/client/tools/index.js.map +0 -1
- package/dist/client/tools/tool-order.d.ts +0 -7
- package/dist/client/tools/tool-order.d.ts.map +0 -1
- package/dist/client/tools/tool-order.js +0 -47
- package/dist/client/tools/tool-order.js.map +0 -1
- package/dist/server/local-migration.d.ts +0 -41
- package/dist/server/local-migration.d.ts.map +0 -1
- package/dist/server/local-migration.js +0 -235
- package/dist/server/local-migration.js.map +0 -1
- package/dist/tools/actions.d.ts +0 -3
- package/dist/tools/actions.d.ts.map +0 -1
- package/dist/tools/actions.js +0 -272
- package/dist/tools/actions.js.map +0 -1
- package/dist/tools/fetch-tool.d.ts +0 -23
- package/dist/tools/fetch-tool.d.ts.map +0 -1
- package/dist/tools/fetch-tool.js +0 -178
- package/dist/tools/fetch-tool.js.map +0 -1
- package/dist/tools/html-shell.d.ts +0 -45
- package/dist/tools/html-shell.d.ts.map +0 -1
- package/dist/tools/html-shell.js +0 -514
- package/dist/tools/html-shell.js.map +0 -1
- package/dist/tools/proxy-security.d.ts +0 -12
- package/dist/tools/proxy-security.d.ts.map +0 -1
- package/dist/tools/proxy-security.js +0 -158
- package/dist/tools/proxy-security.js.map +0 -1
- package/dist/tools/routes.d.ts +0 -2
- package/dist/tools/routes.d.ts.map +0 -1
- package/dist/tools/routes.js +0 -627
- package/dist/tools/routes.js.map +0 -1
- package/dist/tools/schema.d.ts +0 -664
- package/dist/tools/schema.d.ts.map +0 -1
- package/dist/tools/schema.js +0 -146
- package/dist/tools/schema.js.map +0 -1
- package/dist/tools/slots/routes.d.ts +0 -15
- package/dist/tools/slots/routes.d.ts.map +0 -1
- package/dist/tools/slots/routes.js +0 -94
- package/dist/tools/slots/routes.js.map +0 -1
- package/dist/tools/slots/schema.d.ts +0 -303
- package/dist/tools/slots/schema.d.ts.map +0 -1
- package/dist/tools/slots/schema.js +0 -76
- package/dist/tools/slots/schema.js.map +0 -1
- package/dist/tools/slots/store.d.ts +0 -66
- package/dist/tools/slots/store.d.ts.map +0 -1
- package/dist/tools/slots/store.js +0 -227
- package/dist/tools/slots/store.js.map +0 -1
- package/dist/tools/store.d.ts +0 -40
- package/dist/tools/store.d.ts.map +0 -1
- package/dist/tools/store.js +0 -193
- package/dist/tools/store.js.map +0 -1
- package/dist/tools/theme.d.ts +0 -2
- package/dist/tools/theme.d.ts.map +0 -1
- package/dist/tools/theme.js +0 -67
- package/dist/tools/theme.js.map +0 -1
- package/dist/tools/url-safety.d.ts +0 -24
- package/dist/tools/url-safety.d.ts.map +0 -1
- package/dist/tools/url-safety.js +0 -224
- package/dist/tools/url-safety.js.map +0 -1
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export { ToolsSidebarSection } from "./ToolsSidebarSection.js";
|
|
2
|
-
export { ToolViewer, type ToolViewerProps } from "./ToolViewer.js";
|
|
3
|
-
export { ToolEditor, type ToolEditorProps } from "./ToolEditor.js";
|
|
4
|
-
export { ToolsListPage } from "./ToolsListPage.js";
|
|
5
|
-
export { ToolViewerPage } from "./ToolViewerPage.js";
|
|
6
|
-
export { EmbeddedTool, type EmbeddedToolProps } from "./EmbeddedTool.js";
|
|
7
|
-
export { ExtensionSlot, type ExtensionSlotProps } from "./ExtensionSlot.js";
|
|
8
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export { ToolsSidebarSection } from "./ToolsSidebarSection.js";
|
|
2
|
-
export { ToolViewer } from "./ToolViewer.js";
|
|
3
|
-
export { ToolEditor } from "./ToolEditor.js";
|
|
4
|
-
export { ToolsListPage } from "./ToolsListPage.js";
|
|
5
|
-
export { ToolViewerPage } from "./ToolViewerPage.js";
|
|
6
|
-
export { EmbeddedTool } from "./EmbeddedTool.js";
|
|
7
|
-
export { ExtensionSlot } from "./ExtensionSlot.js";
|
|
8
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAwB,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,UAAU,EAAwB,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,YAAY,EAA0B,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,aAAa,EAA2B,MAAM,oBAAoB,CAAC","sourcesContent":["export { ToolsSidebarSection } from \"./ToolsSidebarSection.js\";\nexport { ToolViewer, type ToolViewerProps } from \"./ToolViewer.js\";\nexport { ToolEditor, type ToolEditorProps } from \"./ToolEditor.js\";\nexport { ToolsListPage } from \"./ToolsListPage.js\";\nexport { ToolViewerPage } from \"./ToolViewerPage.js\";\nexport { EmbeddedTool, type EmbeddedToolProps } from \"./EmbeddedTool.js\";\nexport { ExtensionSlot, type ExtensionSlotProps } from \"./ExtensionSlot.js\";\n"]}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export declare const TOOLS_ORDER_CHANGE_EVENT = "tools-order-change";
|
|
2
|
-
export declare function getToolsOrder(): string[];
|
|
3
|
-
export declare function setToolsOrder(order: string[]): void;
|
|
4
|
-
export declare function applyToolsOrder<T extends {
|
|
5
|
-
id: string;
|
|
6
|
-
}>(items: T[], savedOrder: string[]): T[];
|
|
7
|
-
//# sourceMappingURL=tool-order.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tool-order.d.ts","sourceRoot":"","sources":["../../../src/client/tools/tool-order.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAI7D,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAYxC;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,QAU5C;AAED,wBAAgB,eAAe,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACtD,KAAK,EAAE,CAAC,EAAE,EACV,UAAU,EAAE,MAAM,EAAE,GACnB,CAAC,EAAE,CAeL"}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
export const TOOLS_ORDER_CHANGE_EVENT = "tools-order-change";
|
|
2
|
-
const TOOLS_ORDER_KEY = "tools-order";
|
|
3
|
-
export function getToolsOrder() {
|
|
4
|
-
if (typeof window === "undefined")
|
|
5
|
-
return [];
|
|
6
|
-
try {
|
|
7
|
-
const raw = window.localStorage.getItem(TOOLS_ORDER_KEY);
|
|
8
|
-
if (!raw)
|
|
9
|
-
return [];
|
|
10
|
-
const parsed = JSON.parse(raw);
|
|
11
|
-
return Array.isArray(parsed)
|
|
12
|
-
? parsed.filter((id) => typeof id === "string")
|
|
13
|
-
: [];
|
|
14
|
-
}
|
|
15
|
-
catch {
|
|
16
|
-
return [];
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
export function setToolsOrder(order) {
|
|
20
|
-
if (typeof window === "undefined")
|
|
21
|
-
return;
|
|
22
|
-
try {
|
|
23
|
-
window.localStorage.setItem(TOOLS_ORDER_KEY, JSON.stringify(order));
|
|
24
|
-
window.dispatchEvent(new CustomEvent(TOOLS_ORDER_CHANGE_EVENT, { detail: order }));
|
|
25
|
-
}
|
|
26
|
-
catch {
|
|
27
|
-
// localStorage unavailable / quota — ignore, order is best-effort
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
export function applyToolsOrder(items, savedOrder) {
|
|
31
|
-
if (savedOrder.length === 0)
|
|
32
|
-
return items;
|
|
33
|
-
const idToItem = new Map(items.map((item) => [item.id, item]));
|
|
34
|
-
const ordered = [];
|
|
35
|
-
for (const id of savedOrder) {
|
|
36
|
-
const item = idToItem.get(id);
|
|
37
|
-
if (item) {
|
|
38
|
-
ordered.push(item);
|
|
39
|
-
idToItem.delete(id);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
for (const item of idToItem.values()) {
|
|
43
|
-
ordered.push(item);
|
|
44
|
-
}
|
|
45
|
-
return ordered;
|
|
46
|
-
}
|
|
47
|
-
//# sourceMappingURL=tool-order.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tool-order.js","sourceRoot":"","sources":["../../../src/client/tools/tool-order.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,wBAAwB,GAAG,oBAAoB,CAAC;AAE7D,MAAM,eAAe,GAAG,aAAa,CAAC;AAEtC,MAAM,UAAU,aAAa;IAC3B,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,EAAE,CAAC;IAC7C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QACzD,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAC1B,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,KAAK,QAAQ,CAAC;YAC/C,CAAC,CAAC,EAAE,CAAC;IACT,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAe;IAC3C,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO;IAC1C,IAAI,CAAC;QACH,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QACpE,MAAM,CAAC,aAAa,CAClB,IAAI,WAAW,CAAC,wBAAwB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAC7D,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,kEAAkE;IACpE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,KAAU,EACV,UAAoB;IAEpB,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/D,MAAM,OAAO,GAAQ,EAAE,CAAC;IACxB,KAAK,MAAM,EAAE,IAAI,UAAU,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,IAAI,EAAE,CAAC;YACT,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;QACrC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["export const TOOLS_ORDER_CHANGE_EVENT = \"tools-order-change\";\n\nconst TOOLS_ORDER_KEY = \"tools-order\";\n\nexport function getToolsOrder(): string[] {\n if (typeof window === \"undefined\") return [];\n try {\n const raw = window.localStorage.getItem(TOOLS_ORDER_KEY);\n if (!raw) return [];\n const parsed = JSON.parse(raw);\n return Array.isArray(parsed)\n ? parsed.filter((id) => typeof id === \"string\")\n : [];\n } catch {\n return [];\n }\n}\n\nexport function setToolsOrder(order: string[]) {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(TOOLS_ORDER_KEY, JSON.stringify(order));\n window.dispatchEvent(\n new CustomEvent(TOOLS_ORDER_CHANGE_EVENT, { detail: order }),\n );\n } catch {\n // localStorage unavailable / quota — ignore, order is best-effort\n }\n}\n\nexport function applyToolsOrder<T extends { id: string }>(\n items: T[],\n savedOrder: string[],\n): T[] {\n if (savedOrder.length === 0) return items;\n const idToItem = new Map(items.map((item) => [item.id, item]));\n const ordered: T[] = [];\n for (const id of savedOrder) {\n const item = idToItem.get(id);\n if (item) {\n ordered.push(item);\n idToItem.delete(id);\n }\n }\n for (const item of idToItem.values()) {\n ordered.push(item);\n }\n return ordered;\n}\n"]}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Migrate data owned by `local@localhost` to a real account.
|
|
3
|
-
*
|
|
4
|
-
* When a user starts an app in local mode and later signs in to create a real
|
|
5
|
-
* account, this function moves all of their existing data over to the new
|
|
6
|
-
* account so they don't lose anything.
|
|
7
|
-
*
|
|
8
|
-
* Scope of the migration:
|
|
9
|
-
* - `application_state`: rows with `session_id = 'local'`
|
|
10
|
-
* - `settings`: keys prefixed with `u:local@localhost:`
|
|
11
|
-
* - `oauth_tokens`: rows with `owner = 'local@localhost'`
|
|
12
|
-
* - Any template table that has an `owner_email` column: rows with
|
|
13
|
-
* `owner_email = 'local@localhost'`
|
|
14
|
-
*
|
|
15
|
-
* The operation is a no-op if the target email is itself `local@localhost`,
|
|
16
|
-
* empty, or if there is nothing to migrate.
|
|
17
|
-
*/
|
|
18
|
-
export interface LocalMigrationResult {
|
|
19
|
-
/** Whether anything was actually migrated. */
|
|
20
|
-
migrated: boolean;
|
|
21
|
-
/** Per-table row counts that were updated. Omits tables with zero updates. */
|
|
22
|
-
tables: Record<string, number>;
|
|
23
|
-
/** Target email the data now belongs to. */
|
|
24
|
-
targetEmail: string;
|
|
25
|
-
/**
|
|
26
|
-
* Non-fatal per-step errors encountered during migration. One bad table
|
|
27
|
-
* no longer fails the whole upgrade — we migrate everything we can and
|
|
28
|
-
* report any steps that threw here so the UI can surface them.
|
|
29
|
-
*/
|
|
30
|
-
errors?: Array<{
|
|
31
|
-
step: string;
|
|
32
|
-
message: string;
|
|
33
|
-
}>;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Migrate every piece of local-mode data to the given real account email.
|
|
37
|
-
* Safe to call multiple times — it only touches rows that are still attached
|
|
38
|
-
* to `local@localhost`.
|
|
39
|
-
*/
|
|
40
|
-
export declare function migrateLocalUserData(targetEmail: string): Promise<LocalMigrationResult>;
|
|
41
|
-
//# sourceMappingURL=local-migration.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"local-migration.d.ts","sourceRoot":"","sources":["../../src/server/local-migration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAQH,MAAM,WAAW,oBAAoB;IACnC,8CAA8C;IAC9C,QAAQ,EAAE,OAAO,CAAC;IAClB,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnD;AAoLD;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,oBAAoB,CAAC,CAyD/B"}
|
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Migrate data owned by `local@localhost` to a real account.
|
|
3
|
-
*
|
|
4
|
-
* When a user starts an app in local mode and later signs in to create a real
|
|
5
|
-
* account, this function moves all of their existing data over to the new
|
|
6
|
-
* account so they don't lose anything.
|
|
7
|
-
*
|
|
8
|
-
* Scope of the migration:
|
|
9
|
-
* - `application_state`: rows with `session_id = 'local'`
|
|
10
|
-
* - `settings`: keys prefixed with `u:local@localhost:`
|
|
11
|
-
* - `oauth_tokens`: rows with `owner = 'local@localhost'`
|
|
12
|
-
* - Any template table that has an `owner_email` column: rows with
|
|
13
|
-
* `owner_email = 'local@localhost'`
|
|
14
|
-
*
|
|
15
|
-
* The operation is a no-op if the target email is itself `local@localhost`,
|
|
16
|
-
* empty, or if there is nothing to migrate.
|
|
17
|
-
*/
|
|
18
|
-
import { getDbExec, isPostgres } from "../db/client.js";
|
|
19
|
-
const LOCAL_EMAIL = "local@localhost";
|
|
20
|
-
const LOCAL_SESSION_ID = "local";
|
|
21
|
-
const OWNER_COLUMN = "owner_email";
|
|
22
|
-
/**
|
|
23
|
-
* Error messages that indicate a missing/inaccessible table or column — the
|
|
24
|
-
* migration treats these as "feature not enabled" and skips silently.
|
|
25
|
-
*/
|
|
26
|
-
const SCHEMA_SKIP_ERR = /no such table|no such column|does not exist|undefined table|undefined column|relation .* does not exist|column .* does not exist|permission denied|is not a table|cannot update view|cannot change column in a view/i;
|
|
27
|
-
function shouldSkipSchemaError(err) {
|
|
28
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
29
|
-
return SCHEMA_SKIP_ERR.test(message);
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Discover every table (not view) in `public` that has an `owner_email`
|
|
33
|
-
* column. Views and materialized views are excluded — they can't be updated
|
|
34
|
-
* directly and would 500 the migration.
|
|
35
|
-
*/
|
|
36
|
-
async function discoverOwnerEmailTables() {
|
|
37
|
-
const client = getDbExec();
|
|
38
|
-
if (isPostgres()) {
|
|
39
|
-
// Join against information_schema.tables to filter out views and
|
|
40
|
-
// materialized views (anything that isn't a plain BASE TABLE).
|
|
41
|
-
const { rows } = await client.execute({
|
|
42
|
-
sql: `SELECT c.table_name
|
|
43
|
-
FROM information_schema.columns c
|
|
44
|
-
JOIN information_schema.tables t
|
|
45
|
-
ON t.table_schema = c.table_schema
|
|
46
|
-
AND t.table_name = c.table_name
|
|
47
|
-
WHERE c.table_schema = 'public'
|
|
48
|
-
AND c.column_name = $1
|
|
49
|
-
AND t.table_type = 'BASE TABLE'`,
|
|
50
|
-
args: [OWNER_COLUMN],
|
|
51
|
-
});
|
|
52
|
-
return rows.map((r) => r.table_name ?? r[0]).filter(Boolean);
|
|
53
|
-
}
|
|
54
|
-
// SQLite path: iterate tables (type='table', not 'view') and inspect columns via PRAGMA
|
|
55
|
-
const tablesRes = await client.execute(`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'`);
|
|
56
|
-
const tables = tablesRes.rows
|
|
57
|
-
.map((r) => (r.name ?? r[0]))
|
|
58
|
-
.filter(Boolean);
|
|
59
|
-
const withOwner = [];
|
|
60
|
-
for (const table of tables) {
|
|
61
|
-
const escaped = table.replace(/"/g, '""');
|
|
62
|
-
const colsRes = await client.execute(`PRAGMA table_info("${escaped}")`);
|
|
63
|
-
const hasOwner = colsRes.rows.some((row) => (row.name ?? row[1]) === OWNER_COLUMN);
|
|
64
|
-
if (hasOwner)
|
|
65
|
-
withOwner.push(table);
|
|
66
|
-
}
|
|
67
|
-
return withOwner;
|
|
68
|
-
}
|
|
69
|
-
/** Replace `?` placeholders with `$1`, `$2`, … for Postgres. */
|
|
70
|
-
function sqlWithParams(sql) {
|
|
71
|
-
if (!isPostgres())
|
|
72
|
-
return sql;
|
|
73
|
-
let i = 0;
|
|
74
|
-
return sql.replace(/\?/g, () => `$${++i}`);
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Rename `settings` keys so a user's config carries over. Keys are prefixed
|
|
78
|
-
* with `u:<email>:` — moving from one email to another is a prefix swap.
|
|
79
|
-
*
|
|
80
|
-
* If a destination key already exists (unlikely but possible if the user had
|
|
81
|
-
* previously signed in with the same email) we leave the destination alone
|
|
82
|
-
* and drop the local row, so we never clobber real-account state.
|
|
83
|
-
*/
|
|
84
|
-
async function migrateSettings(targetEmail) {
|
|
85
|
-
const client = getDbExec();
|
|
86
|
-
const oldPrefix = `u:${LOCAL_EMAIL}:`;
|
|
87
|
-
const newPrefix = `u:${targetEmail}:`;
|
|
88
|
-
const { rows } = await client.execute({
|
|
89
|
-
sql: sqlWithParams(`SELECT key FROM settings WHERE key LIKE ? ESCAPE '\\'`),
|
|
90
|
-
args: [oldPrefix.replace(/([\\%_])/g, "\\$1") + "%"],
|
|
91
|
-
});
|
|
92
|
-
let updated = 0;
|
|
93
|
-
for (const row of rows) {
|
|
94
|
-
const oldKey = (row.key ?? row[0]);
|
|
95
|
-
if (!oldKey.startsWith(oldPrefix))
|
|
96
|
-
continue;
|
|
97
|
-
const newKey = newPrefix + oldKey.slice(oldPrefix.length);
|
|
98
|
-
// Skip if the destination already exists — don't overwrite real data.
|
|
99
|
-
const existsRes = await client.execute({
|
|
100
|
-
sql: sqlWithParams(`SELECT 1 FROM settings WHERE key = ?`),
|
|
101
|
-
args: [newKey],
|
|
102
|
-
});
|
|
103
|
-
if (existsRes.rows.length > 0) {
|
|
104
|
-
await client.execute({
|
|
105
|
-
sql: sqlWithParams(`DELETE FROM settings WHERE key = ?`),
|
|
106
|
-
args: [oldKey],
|
|
107
|
-
});
|
|
108
|
-
continue;
|
|
109
|
-
}
|
|
110
|
-
await client.execute({
|
|
111
|
-
sql: sqlWithParams(`UPDATE settings SET key = ? WHERE key = ?`),
|
|
112
|
-
args: [newKey, oldKey],
|
|
113
|
-
});
|
|
114
|
-
updated++;
|
|
115
|
-
}
|
|
116
|
-
return updated;
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Move application_state rows from `session_id='local'` to the target email.
|
|
120
|
-
* Rows that already exist for the destination session are left alone.
|
|
121
|
-
*/
|
|
122
|
-
async function migrateApplicationState(targetEmail) {
|
|
123
|
-
const client = getDbExec();
|
|
124
|
-
// Only migrate keys that don't already exist under the destination session.
|
|
125
|
-
const { rows } = await client.execute({
|
|
126
|
-
sql: sqlWithParams(`SELECT key FROM application_state WHERE session_id = ?`),
|
|
127
|
-
args: [LOCAL_SESSION_ID],
|
|
128
|
-
});
|
|
129
|
-
let updated = 0;
|
|
130
|
-
for (const row of rows) {
|
|
131
|
-
const key = (row.key ?? row[0]);
|
|
132
|
-
const existsRes = await client.execute({
|
|
133
|
-
sql: sqlWithParams(`SELECT 1 FROM application_state WHERE session_id = ? AND key = ?`),
|
|
134
|
-
args: [targetEmail, key],
|
|
135
|
-
});
|
|
136
|
-
if (existsRes.rows.length > 0) {
|
|
137
|
-
await client.execute({
|
|
138
|
-
sql: sqlWithParams(`DELETE FROM application_state WHERE session_id = ? AND key = ?`),
|
|
139
|
-
args: [LOCAL_SESSION_ID, key],
|
|
140
|
-
});
|
|
141
|
-
continue;
|
|
142
|
-
}
|
|
143
|
-
await client.execute({
|
|
144
|
-
sql: sqlWithParams(`UPDATE application_state SET session_id = ? WHERE session_id = ? AND key = ?`),
|
|
145
|
-
args: [targetEmail, LOCAL_SESSION_ID, key],
|
|
146
|
-
});
|
|
147
|
-
updated++;
|
|
148
|
-
}
|
|
149
|
-
return updated;
|
|
150
|
-
}
|
|
151
|
-
/** Move oauth_tokens rows. `owner` is the user's email in core tables. */
|
|
152
|
-
async function migrateOauthTokens(targetEmail) {
|
|
153
|
-
const client = getDbExec();
|
|
154
|
-
const res = await client.execute({
|
|
155
|
-
sql: sqlWithParams(`UPDATE oauth_tokens SET owner = ? WHERE owner = ?`),
|
|
156
|
-
args: [targetEmail, LOCAL_EMAIL],
|
|
157
|
-
});
|
|
158
|
-
return res.rowsAffected ?? 0;
|
|
159
|
-
}
|
|
160
|
-
/** Move rows in a template table that uses the `owner_email` convention. */
|
|
161
|
-
async function migrateOwnerEmailTable(table, targetEmail) {
|
|
162
|
-
const client = getDbExec();
|
|
163
|
-
const escaped = table.replace(/"/g, '""');
|
|
164
|
-
const res = await client.execute({
|
|
165
|
-
sql: sqlWithParams(`UPDATE "${escaped}" SET owner_email = ? WHERE owner_email = ?`),
|
|
166
|
-
args: [targetEmail, LOCAL_EMAIL],
|
|
167
|
-
});
|
|
168
|
-
return res.rowsAffected ?? 0;
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Migrate every piece of local-mode data to the given real account email.
|
|
172
|
-
* Safe to call multiple times — it only touches rows that are still attached
|
|
173
|
-
* to `local@localhost`.
|
|
174
|
-
*/
|
|
175
|
-
export async function migrateLocalUserData(targetEmail) {
|
|
176
|
-
const email = targetEmail?.trim().toLowerCase();
|
|
177
|
-
if (!email || email === LOCAL_EMAIL) {
|
|
178
|
-
return { migrated: false, tables: {}, targetEmail: email || "" };
|
|
179
|
-
}
|
|
180
|
-
const tables = {};
|
|
181
|
-
// Core tables — best-effort. A missing table just means the feature isn't
|
|
182
|
-
// enabled in this app (e.g. an app that doesn't use oauth_tokens).
|
|
183
|
-
const coreSteps = [
|
|
184
|
-
["settings", () => migrateSettings(email)],
|
|
185
|
-
["application_state", () => migrateApplicationState(email)],
|
|
186
|
-
["oauth_tokens", () => migrateOauthTokens(email)],
|
|
187
|
-
];
|
|
188
|
-
const errors = [];
|
|
189
|
-
for (const [name, fn] of coreSteps) {
|
|
190
|
-
try {
|
|
191
|
-
const count = await fn();
|
|
192
|
-
if (count > 0)
|
|
193
|
-
tables[name] = count;
|
|
194
|
-
}
|
|
195
|
-
catch (err) {
|
|
196
|
-
// Missing table or column — skip silently. Other errors are logged
|
|
197
|
-
// per-step so one bad table doesn't 500 the entire migration.
|
|
198
|
-
if (!shouldSkipSchemaError(err)) {
|
|
199
|
-
const message = err?.message ?? String(err);
|
|
200
|
-
errors.push({ step: name, message });
|
|
201
|
-
console.error(`[local-migration] ${name} failed:`, err);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
// Template tables — discovered dynamically. If discovery itself fails,
|
|
206
|
-
// fall back to an empty list so the migration doesn't 500.
|
|
207
|
-
let templateTables = [];
|
|
208
|
-
try {
|
|
209
|
-
templateTables = await discoverOwnerEmailTables();
|
|
210
|
-
}
|
|
211
|
-
catch (err) {
|
|
212
|
-
console.error("[local-migration] owner_email table discovery failed:", err);
|
|
213
|
-
templateTables = [];
|
|
214
|
-
}
|
|
215
|
-
for (const table of templateTables) {
|
|
216
|
-
try {
|
|
217
|
-
const count = await migrateOwnerEmailTable(table, email);
|
|
218
|
-
if (count > 0)
|
|
219
|
-
tables[table] = count;
|
|
220
|
-
}
|
|
221
|
-
catch (err) {
|
|
222
|
-
if (!shouldSkipSchemaError(err)) {
|
|
223
|
-
const message = err?.message ?? String(err);
|
|
224
|
-
errors.push({ step: table, message });
|
|
225
|
-
console.error(`[local-migration] ${table} failed:`, err);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
const migrated = Object.values(tables).some((n) => n > 0);
|
|
230
|
-
const result = { migrated, tables, targetEmail: email };
|
|
231
|
-
if (errors.length > 0)
|
|
232
|
-
result.errors = errors;
|
|
233
|
-
return result;
|
|
234
|
-
}
|
|
235
|
-
//# sourceMappingURL=local-migration.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"local-migration.js","sourceRoot":"","sources":["../../src/server/local-migration.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Migrate data owned by `local@localhost` to a real account.\n *\n * When a user starts an app in local mode and later signs in to create a real\n * account, this function moves all of their existing data over to the new\n * account so they don't lose anything.\n *\n * Scope of the migration:\n * - `application_state`: rows with `session_id = 'local'`\n * - `settings`: keys prefixed with `u:local@localhost:`\n * - `oauth_tokens`: rows with `owner = 'local@localhost'`\n * - Any template table that has an `owner_email` column: rows with\n * `owner_email = 'local@localhost'`\n *\n * The operation is a no-op if the target email is itself `local@localhost`,\n * empty, or if there is nothing to migrate.\n */\n\nimport { getDbExec, isPostgres } from \"../db/client.js\";\n\nconst LOCAL_EMAIL = \"local@localhost\";\nconst LOCAL_SESSION_ID = \"local\";\nconst OWNER_COLUMN = \"owner_email\";\n\nexport interface LocalMigrationResult {\n /** Whether anything was actually migrated. */\n migrated: boolean;\n /** Per-table row counts that were updated. Omits tables with zero updates. */\n tables: Record<string, number>;\n /** Target email the data now belongs to. */\n targetEmail: string;\n /**\n * Non-fatal per-step errors encountered during migration. One bad table\n * no longer fails the whole upgrade — we migrate everything we can and\n * report any steps that threw here so the UI can surface them.\n */\n errors?: Array<{ step: string; message: string }>;\n}\n\n/**\n * Error messages that indicate a missing/inaccessible table or column — the\n * migration treats these as \"feature not enabled\" and skips silently.\n */\nconst SCHEMA_SKIP_ERR =\n /no such table|no such column|does not exist|undefined table|undefined column|relation .* does not exist|column .* does not exist|permission denied|is not a table|cannot update view|cannot change column in a view/i;\n\nfunction shouldSkipSchemaError(err: unknown): boolean {\n const message = err instanceof Error ? err.message : String(err);\n return SCHEMA_SKIP_ERR.test(message);\n}\n\n/**\n * Discover every table (not view) in `public` that has an `owner_email`\n * column. Views and materialized views are excluded — they can't be updated\n * directly and would 500 the migration.\n */\nasync function discoverOwnerEmailTables(): Promise<string[]> {\n const client = getDbExec();\n if (isPostgres()) {\n // Join against information_schema.tables to filter out views and\n // materialized views (anything that isn't a plain BASE TABLE).\n const { rows } = await client.execute({\n sql: `SELECT c.table_name\n FROM information_schema.columns c\n JOIN information_schema.tables t\n ON t.table_schema = c.table_schema\n AND t.table_name = c.table_name\n WHERE c.table_schema = 'public'\n AND c.column_name = $1\n AND t.table_type = 'BASE TABLE'`,\n args: [OWNER_COLUMN],\n });\n return rows.map((r: any) => r.table_name ?? r[0]).filter(Boolean);\n }\n\n // SQLite path: iterate tables (type='table', not 'view') and inspect columns via PRAGMA\n const tablesRes = await client.execute(\n `SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'`,\n );\n const tables = tablesRes.rows\n .map((r: any) => (r.name ?? r[0]) as string)\n .filter(Boolean);\n\n const withOwner: string[] = [];\n for (const table of tables) {\n const escaped = table.replace(/\"/g, '\"\"');\n const colsRes = await client.execute(`PRAGMA table_info(\"${escaped}\")`);\n const hasOwner = colsRes.rows.some(\n (row: any) => (row.name ?? row[1]) === OWNER_COLUMN,\n );\n if (hasOwner) withOwner.push(table);\n }\n return withOwner;\n}\n\n/** Replace `?` placeholders with `$1`, `$2`, … for Postgres. */\nfunction sqlWithParams(sql: string): string {\n if (!isPostgres()) return sql;\n let i = 0;\n return sql.replace(/\\?/g, () => `$${++i}`);\n}\n\n/**\n * Rename `settings` keys so a user's config carries over. Keys are prefixed\n * with `u:<email>:` — moving from one email to another is a prefix swap.\n *\n * If a destination key already exists (unlikely but possible if the user had\n * previously signed in with the same email) we leave the destination alone\n * and drop the local row, so we never clobber real-account state.\n */\nasync function migrateSettings(targetEmail: string): Promise<number> {\n const client = getDbExec();\n const oldPrefix = `u:${LOCAL_EMAIL}:`;\n const newPrefix = `u:${targetEmail}:`;\n\n const { rows } = await client.execute({\n sql: sqlWithParams(`SELECT key FROM settings WHERE key LIKE ? ESCAPE '\\\\'`),\n args: [oldPrefix.replace(/([\\\\%_])/g, \"\\\\$1\") + \"%\"],\n });\n\n let updated = 0;\n for (const row of rows) {\n const oldKey = (row.key ?? (row as any)[0]) as string;\n if (!oldKey.startsWith(oldPrefix)) continue;\n const newKey = newPrefix + oldKey.slice(oldPrefix.length);\n\n // Skip if the destination already exists — don't overwrite real data.\n const existsRes = await client.execute({\n sql: sqlWithParams(`SELECT 1 FROM settings WHERE key = ?`),\n args: [newKey],\n });\n if (existsRes.rows.length > 0) {\n await client.execute({\n sql: sqlWithParams(`DELETE FROM settings WHERE key = ?`),\n args: [oldKey],\n });\n continue;\n }\n\n await client.execute({\n sql: sqlWithParams(`UPDATE settings SET key = ? WHERE key = ?`),\n args: [newKey, oldKey],\n });\n updated++;\n }\n return updated;\n}\n\n/**\n * Move application_state rows from `session_id='local'` to the target email.\n * Rows that already exist for the destination session are left alone.\n */\nasync function migrateApplicationState(targetEmail: string): Promise<number> {\n const client = getDbExec();\n // Only migrate keys that don't already exist under the destination session.\n const { rows } = await client.execute({\n sql: sqlWithParams(\n `SELECT key FROM application_state WHERE session_id = ?`,\n ),\n args: [LOCAL_SESSION_ID],\n });\n\n let updated = 0;\n for (const row of rows) {\n const key = (row.key ?? (row as any)[0]) as string;\n const existsRes = await client.execute({\n sql: sqlWithParams(\n `SELECT 1 FROM application_state WHERE session_id = ? AND key = ?`,\n ),\n args: [targetEmail, key],\n });\n if (existsRes.rows.length > 0) {\n await client.execute({\n sql: sqlWithParams(\n `DELETE FROM application_state WHERE session_id = ? AND key = ?`,\n ),\n args: [LOCAL_SESSION_ID, key],\n });\n continue;\n }\n await client.execute({\n sql: sqlWithParams(\n `UPDATE application_state SET session_id = ? WHERE session_id = ? AND key = ?`,\n ),\n args: [targetEmail, LOCAL_SESSION_ID, key],\n });\n updated++;\n }\n return updated;\n}\n\n/** Move oauth_tokens rows. `owner` is the user's email in core tables. */\nasync function migrateOauthTokens(targetEmail: string): Promise<number> {\n const client = getDbExec();\n const res = await client.execute({\n sql: sqlWithParams(`UPDATE oauth_tokens SET owner = ? WHERE owner = ?`),\n args: [targetEmail, LOCAL_EMAIL],\n });\n return res.rowsAffected ?? 0;\n}\n\n/** Move rows in a template table that uses the `owner_email` convention. */\nasync function migrateOwnerEmailTable(\n table: string,\n targetEmail: string,\n): Promise<number> {\n const client = getDbExec();\n const escaped = table.replace(/\"/g, '\"\"');\n const res = await client.execute({\n sql: sqlWithParams(\n `UPDATE \"${escaped}\" SET owner_email = ? WHERE owner_email = ?`,\n ),\n args: [targetEmail, LOCAL_EMAIL],\n });\n return res.rowsAffected ?? 0;\n}\n\n/**\n * Migrate every piece of local-mode data to the given real account email.\n * Safe to call multiple times — it only touches rows that are still attached\n * to `local@localhost`.\n */\nexport async function migrateLocalUserData(\n targetEmail: string,\n): Promise<LocalMigrationResult> {\n const email = targetEmail?.trim().toLowerCase();\n if (!email || email === LOCAL_EMAIL) {\n return { migrated: false, tables: {}, targetEmail: email || \"\" };\n }\n\n const tables: Record<string, number> = {};\n\n // Core tables — best-effort. A missing table just means the feature isn't\n // enabled in this app (e.g. an app that doesn't use oauth_tokens).\n const coreSteps: Array<[string, () => Promise<number>]> = [\n [\"settings\", () => migrateSettings(email)],\n [\"application_state\", () => migrateApplicationState(email)],\n [\"oauth_tokens\", () => migrateOauthTokens(email)],\n ];\n const errors: Array<{ step: string; message: string }> = [];\n for (const [name, fn] of coreSteps) {\n try {\n const count = await fn();\n if (count > 0) tables[name] = count;\n } catch (err: any) {\n // Missing table or column — skip silently. Other errors are logged\n // per-step so one bad table doesn't 500 the entire migration.\n if (!shouldSkipSchemaError(err)) {\n const message = err?.message ?? String(err);\n errors.push({ step: name, message });\n console.error(`[local-migration] ${name} failed:`, err);\n }\n }\n }\n\n // Template tables — discovered dynamically. If discovery itself fails,\n // fall back to an empty list so the migration doesn't 500.\n let templateTables: string[] = [];\n try {\n templateTables = await discoverOwnerEmailTables();\n } catch (err) {\n console.error(\"[local-migration] owner_email table discovery failed:\", err);\n templateTables = [];\n }\n for (const table of templateTables) {\n try {\n const count = await migrateOwnerEmailTable(table, email);\n if (count > 0) tables[table] = count;\n } catch (err: any) {\n if (!shouldSkipSchemaError(err)) {\n const message = err?.message ?? String(err);\n errors.push({ step: table, message });\n console.error(`[local-migration] ${table} failed:`, err);\n }\n }\n }\n\n const migrated = Object.values(tables).some((n) => n > 0);\n const result: LocalMigrationResult = { migrated, tables, targetEmail: email };\n if (errors.length > 0) result.errors = errors;\n return result;\n}\n"]}
|
package/dist/tools/actions.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/tools/actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAYhE,wBAAgB,uBAAuB,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAiRrE"}
|