@kizenapps/cli 0.5.0 → 0.7.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/electron/icon.png +0 -0
- package/dist/electron/main.js +38 -2
- package/dist/electron/main.js.map +1 -1
- package/dist/index.js +85 -9
- package/dist/index.js.map +1 -1
- package/dist/viewer/assets/fa-core-BU3ZZt7W.js +558 -0
- package/dist/viewer/assets/fa-pro-icons-D4afj0tU.js +1 -0
- package/dist/viewer/assets/index--m1PKX6N.js +17 -0
- package/dist/viewer/assets/index-2OcBnmZB.js +17 -0
- package/dist/viewer/assets/index-7ah1RuPy.js +17 -0
- package/dist/viewer/assets/index-B3gNsKTt.js +17 -0
- package/dist/viewer/assets/index-B40AtXqk.js +17 -0
- package/dist/viewer/assets/index-B4ikC-wc.js +17 -0
- package/dist/viewer/assets/index-BKOfPpLS.js +17 -0
- package/dist/viewer/assets/index-BM3JrC-1.js +17 -0
- package/dist/viewer/assets/index-BUnK11-F.js +17 -0
- package/dist/viewer/assets/index-Bc7IZVr6.js +17 -0
- package/dist/viewer/assets/index-C1KzcpVj.js +17 -0
- package/dist/viewer/assets/index-CBBwr2o_.js +17 -0
- package/dist/viewer/assets/index-CHtXWYIY.js +17 -0
- package/dist/viewer/assets/index-CN9NvJkQ.js +17 -0
- package/dist/viewer/assets/index-CNKPBxhv.js +17 -0
- package/dist/viewer/assets/index-C_6izRRh.js +17 -0
- package/dist/viewer/assets/index-CgzK6zig.js +17 -0
- package/dist/viewer/assets/index-Cw2cxYy2.js +17 -0
- package/dist/viewer/assets/index-D06uhGtQ.js +17 -0
- package/dist/viewer/assets/index-DAHWT-g0.js +17 -0
- package/dist/viewer/assets/index-DAxJgHat.js +17 -0
- package/dist/viewer/assets/index-DF_geUaW.js +17 -0
- package/dist/viewer/assets/index-DUgUEouL.css +2 -0
- package/dist/viewer/assets/index-DcGGXuA3.js +17 -0
- package/dist/viewer/assets/index-DlVmY-nR.js +17 -0
- package/dist/viewer/assets/index-FZw9Ev_R.js +17 -0
- package/dist/viewer/assets/index-M1Obm_99.js +17 -0
- package/dist/viewer/assets/index-_kM1Ri7v.js +17 -0
- package/dist/viewer/assets/index-aTt_sTlu.js +17 -0
- package/dist/viewer/assets/index-vYFGGFc2.js +17 -0
- package/dist/viewer/assets/react-C90crogl.js +9 -0
- package/dist/viewer/assets/rolldown-runtime-DF2fYuay.js +1 -0
- package/dist/viewer/icon.png +0 -0
- package/dist/viewer/index.html +6 -2
- package/package.json +6 -4
- package/dist/viewer/1024.png +0 -0
- package/dist/viewer/assets/index-B0d3If0o.js +0 -582
- package/dist/viewer/assets/index-B1mMv9H8.css +0 -2
- package/dist/viewer/assets/index-BTLnOfRu.css +0 -2
- package/dist/viewer/assets/index-B_uo-pdA.js +0 -582
- package/dist/viewer/assets/index-Bp6umXGR.js +0 -582
- package/dist/viewer/assets/index-Bsja5bOD.js +0 -582
- package/dist/viewer/assets/index-CAej9s9R.js +0 -582
- package/dist/viewer/assets/index-CCMFzDS-.css +0 -2
- package/dist/viewer/assets/index-Ci4aelpQ.js +0 -582
- package/dist/viewer/assets/index-CuVHD6vO.css +0 -2
- package/dist/viewer/assets/index-DQZ1fN2j.js +0 -582
- package/dist/viewer/assets/index-DSeA5UDI.js +0 -582
- package/dist/viewer/assets/index-w7OW3o4t.js +0 -582
- package/dist/viewer/favicon.png +0 -0
- package/dist/viewer/favicon.svg +0 -4
package/dist/electron/icon.png
CHANGED
|
Binary file
|
package/dist/electron/main.js
CHANGED
|
@@ -107,6 +107,17 @@ void app.whenReady().then(() => {
|
|
|
107
107
|
if (prop.type === "object" && prop.value === "null") {
|
|
108
108
|
return null;
|
|
109
109
|
}
|
|
110
|
+
if (prop.type === "object" && prop.valuePreview) {
|
|
111
|
+
const { valuePreview } = prop;
|
|
112
|
+
if (valuePreview.subtype === "array") {
|
|
113
|
+
return valuePreview.properties.filter((p) => /^\d+$/.test(p.name)).sort((a, b) => parseInt(a.name) - parseInt(b.name)).map(parseProp);
|
|
114
|
+
}
|
|
115
|
+
const obj = {};
|
|
116
|
+
for (const p of valuePreview.properties) {
|
|
117
|
+
obj[p.name] = parseProp(p);
|
|
118
|
+
}
|
|
119
|
+
return obj;
|
|
120
|
+
}
|
|
110
121
|
return prop.value ?? `[${prop.type}]`;
|
|
111
122
|
}
|
|
112
123
|
function serializeArg(arg) {
|
|
@@ -140,7 +151,28 @@ void app.whenReady().then(() => {
|
|
|
140
151
|
waitForDebuggerOnStart: false,
|
|
141
152
|
flatten: true
|
|
142
153
|
});
|
|
143
|
-
|
|
154
|
+
async function serializeArgAsync(arg, sessionId) {
|
|
155
|
+
if (arg.type === "object" && arg.objectId) {
|
|
156
|
+
try {
|
|
157
|
+
const result = await win.webContents.debugger.sendCommand(
|
|
158
|
+
"Runtime.callFunctionOn",
|
|
159
|
+
{
|
|
160
|
+
objectId: arg.objectId,
|
|
161
|
+
functionDeclaration: 'function() { const seen = new WeakSet(); return JSON.stringify(this, function(k, v) { if (typeof v === "object" && v !== null) { if (seen.has(v)) return "[Circular]"; seen.add(v); } return v; }); }',
|
|
162
|
+
returnByValue: true
|
|
163
|
+
},
|
|
164
|
+
sessionId
|
|
165
|
+
);
|
|
166
|
+
const val = result.result.value;
|
|
167
|
+
if (typeof val === "string") {
|
|
168
|
+
return JSON.parse(val);
|
|
169
|
+
}
|
|
170
|
+
} catch {
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return serializeArg(arg);
|
|
174
|
+
}
|
|
175
|
+
win.webContents.debugger.on("message", (_event, method, params, sessionId) => {
|
|
144
176
|
if (method === "Target.attachedToTarget") {
|
|
145
177
|
const { sessionId: childSessionId } = params;
|
|
146
178
|
enableRuntime(childSessionId);
|
|
@@ -154,7 +186,11 @@ void app.whenReady().then(() => {
|
|
|
154
186
|
return;
|
|
155
187
|
}
|
|
156
188
|
const level = type === "warning" ? "warn" : ["log", "warn", "error", "info"].includes(type) ? type : "log";
|
|
157
|
-
|
|
189
|
+
void Promise.all(args2.map((arg) => serializeArgAsync(arg, sessionId))).then(
|
|
190
|
+
(serializedArgs) => {
|
|
191
|
+
win.webContents.send("console-message", { level, args: serializedArgs });
|
|
192
|
+
}
|
|
193
|
+
);
|
|
158
194
|
});
|
|
159
195
|
void win.loadURL(`http://localhost:${String(port)}`);
|
|
160
196
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/electron/main.ts"],"sourcesContent":["import { app, BrowserWindow, session, nativeImage, Menu, ipcMain } from 'electron';\nimport { join, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst args = process.argv.slice(2);\nconst port = parseInt(args.find((a) => a.startsWith('--port='))?.slice(7) ?? '3121', 10);\nconst userDataDir = args.find((a) => a.startsWith('--user-data-dir='))?.slice(16);\n\nif (userDataDir) {\n app.setPath('userData', userDataDir);\n}\n\napp.setName('Kizen App Builder');\n\nconst CSP_HEADERS = new Set([\n 'content-security-policy',\n 'content-security-policy-report-only',\n 'x-frame-options',\n]);\n\nconst KIZEN_DOMAINS = ['kizen.dev', 'kizen.com'];\n\nfunction isKizenUrl(url: string): boolean {\n try {\n const { hostname } = new URL(url);\n return KIZEN_DOMAINS.some((d) => hostname === d || hostname.endsWith('.' + d));\n } catch {\n return false;\n }\n}\n\nfunction setupSession(): void {\n // Strip CSP headers and fix SameSite cookies on Kizen responses.\n session.defaultSession.webRequest.onHeadersReceived((details, callback) => {\n const headers: Record<string, string[]> = {};\n\n for (const [key, value] of Object.entries(details.responseHeaders ?? {})) {\n if (!CSP_HEADERS.has(key.toLowerCase())) {\n headers[key] = value;\n }\n }\n\n if (isKizenUrl(details.url) && headers['set-cookie']) {\n headers['set-cookie'] = headers['set-cookie'].map((cookie) => {\n if (!/SameSite=/i.test(cookie)) {\n return cookie + '; SameSite=None; Secure';\n }\n\n return cookie.replace(/SameSite=\\w+/i, 'SameSite=None');\n });\n }\n\n callback({ responseHeaders: headers });\n });\n\n // Periodically re-patch existing Kizen cookies that arrived without SameSite=None.\n // Needed for cookies set before the interceptor was active or via JS document.cookie.\n setInterval(() => {\n void (async () => {\n for (const domain of KIZEN_DOMAINS) {\n try {\n const cookies = await session.defaultSession.cookies.get({ domain });\n for (const cookie of cookies) {\n if (cookie.sameSite !== 'no_restriction') {\n const raw = cookie.domain ?? domain;\n const bare = raw.startsWith('.') ? raw.slice(1) : raw;\n await session.defaultSession.cookies.set({\n url: `https://${bare}`,\n name: cookie.name,\n value: cookie.value,\n domain: raw,\n path: cookie.path ?? '/',\n secure: true,\n ...(cookie.httpOnly !== undefined && { httpOnly: cookie.httpOnly }),\n ...(cookie.expirationDate !== undefined && {\n expirationDate: cookie.expirationDate,\n }),\n sameSite: 'no_restriction',\n });\n }\n }\n } catch {\n /* ignore */\n }\n }\n })();\n }, 2000);\n}\n\nvoid app.whenReady().then(() => {\n Menu.setApplicationMenu(null);\n\n setupSession();\n\n const iconPath = join(dirname(fileURLToPath(import.meta.url)), 'icon.png');\n const icon = nativeImage.createFromPath(iconPath);\n\n if (process.platform === 'darwin' && !icon.isEmpty()) {\n app.dock?.setIcon(icon);\n }\n\n const win = new BrowserWindow({\n width: 1920,\n height: 1080,\n title: 'Kizen App Builder',\n icon,\n webPreferences: {\n nodeIntegration: false,\n contextIsolation: true,\n sandbox: false,\n preload: join(dirname(fileURLToPath(import.meta.url)), 'preload.cjs'),\n },\n });\n\n ipcMain.on('open-devtools', () => {\n win.webContents.openDevTools();\n });\n\n interface PropertyPreview {\n name: string;\n type: string;\n value?: string;\n subtype?: string;\n }\n interface ObjectPreview {\n type: string;\n subtype?: string;\n overflow: boolean;\n properties: PropertyPreview[];\n }\n interface RemoteObject {\n type: string;\n subtype?: string;\n value?: unknown;\n description?: string;\n preview?: ObjectPreview;\n }\n interface ConsoleApiCalledParams {\n type: string;\n args: RemoteObject[];\n }\n\n function parseProp(prop: PropertyPreview): unknown {\n if (prop.type === 'number') {\n return Number(prop.value);\n }\n if (prop.type === 'boolean') {\n return prop.value === 'true';\n }\n if (prop.type === 'undefined') {\n return undefined;\n }\n if (prop.type === 'object' && prop.value === 'null') {\n return null;\n }\n return prop.value ?? `[${prop.type}]`;\n }\n\n function serializeArg(arg: RemoteObject): unknown {\n if (arg.value !== undefined) {\n return arg.value;\n }\n if (arg.preview) {\n const { preview } = arg;\n if (preview.subtype === 'array') {\n return preview.properties\n .filter((p) => /^\\d+$/.test(p.name))\n .sort((a, b) => parseInt(a.name) - parseInt(b.name))\n .map(parseProp);\n }\n const obj: Record<string, unknown> = {};\n for (const prop of preview.properties) {\n obj[prop.name] = parseProp(prop);\n }\n return obj;\n }\n return arg.description ?? `[${arg.type}]`;\n }\n\n const enableRuntime = (sessionId?: string): void => {\n void win.webContents.debugger.sendCommand(\n 'Runtime.enable',\n { generatePreview: true },\n sessionId,\n );\n };\n\n win.webContents.debugger.attach('1.3');\n enableRuntime();\n void win.webContents.debugger.sendCommand('Target.setAutoAttach', {\n autoAttach: true,\n waitForDebuggerOnStart: false,\n flatten: true,\n });\n\n win.webContents.debugger.on('message', (_event, method, params) => {\n if (method === 'Target.attachedToTarget') {\n const { sessionId: childSessionId } = params as { sessionId: string };\n enableRuntime(childSessionId);\n return;\n }\n\n if (method !== 'Runtime.consoleAPICalled') {\n return;\n }\n const { type, args } = params as ConsoleApiCalledParams;\n if (args[0]?.type === 'string' && String(args[0].value).includes('Electron Security Warning')) {\n return;\n }\n const level =\n type === 'warning' ? 'warn' : ['log', 'warn', 'error', 'info'].includes(type) ? type : 'log';\n win.webContents.send('console-message', { level, args: args.map(serializeArg) });\n });\n\n void win.loadURL(`http://localhost:${String(port)}`);\n});\n\napp.on('window-all-closed', () => {\n app.quit();\n});\n"],"mappings":"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","names":["args"]}
|
|
1
|
+
{"version":3,"sources":["../../src/electron/main.ts"],"sourcesContent":["import { app, BrowserWindow, session, nativeImage, Menu, ipcMain } from 'electron';\nimport { join, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst args = process.argv.slice(2);\nconst port = parseInt(args.find((a) => a.startsWith('--port='))?.slice(7) ?? '3121', 10);\nconst userDataDir = args.find((a) => a.startsWith('--user-data-dir='))?.slice(16);\n\nif (userDataDir) {\n app.setPath('userData', userDataDir);\n}\n\napp.setName('Kizen App Builder');\n\nconst CSP_HEADERS = new Set([\n 'content-security-policy',\n 'content-security-policy-report-only',\n 'x-frame-options',\n]);\n\nconst KIZEN_DOMAINS = ['kizen.dev', 'kizen.com'];\n\nfunction isKizenUrl(url: string): boolean {\n try {\n const { hostname } = new URL(url);\n return KIZEN_DOMAINS.some((d) => hostname === d || hostname.endsWith('.' + d));\n } catch {\n return false;\n }\n}\n\nfunction setupSession(): void {\n // Strip CSP headers and fix SameSite cookies on Kizen responses.\n session.defaultSession.webRequest.onHeadersReceived((details, callback) => {\n const headers: Record<string, string[]> = {};\n\n for (const [key, value] of Object.entries(details.responseHeaders ?? {})) {\n if (!CSP_HEADERS.has(key.toLowerCase())) {\n headers[key] = value;\n }\n }\n\n if (isKizenUrl(details.url) && headers['set-cookie']) {\n headers['set-cookie'] = headers['set-cookie'].map((cookie) => {\n if (!/SameSite=/i.test(cookie)) {\n return cookie + '; SameSite=None; Secure';\n }\n\n return cookie.replace(/SameSite=\\w+/i, 'SameSite=None');\n });\n }\n\n callback({ responseHeaders: headers });\n });\n\n // Periodically re-patch existing Kizen cookies that arrived without SameSite=None.\n // Needed for cookies set before the interceptor was active or via JS document.cookie.\n setInterval(() => {\n void (async () => {\n for (const domain of KIZEN_DOMAINS) {\n try {\n const cookies = await session.defaultSession.cookies.get({ domain });\n for (const cookie of cookies) {\n if (cookie.sameSite !== 'no_restriction') {\n const raw = cookie.domain ?? domain;\n const bare = raw.startsWith('.') ? raw.slice(1) : raw;\n await session.defaultSession.cookies.set({\n url: `https://${bare}`,\n name: cookie.name,\n value: cookie.value,\n domain: raw,\n path: cookie.path ?? '/',\n secure: true,\n ...(cookie.httpOnly !== undefined && { httpOnly: cookie.httpOnly }),\n ...(cookie.expirationDate !== undefined && {\n expirationDate: cookie.expirationDate,\n }),\n sameSite: 'no_restriction',\n });\n }\n }\n } catch {\n /* ignore */\n }\n }\n })();\n }, 2000);\n}\n\nvoid app.whenReady().then(() => {\n Menu.setApplicationMenu(null);\n\n setupSession();\n\n const iconPath = join(dirname(fileURLToPath(import.meta.url)), 'icon.png');\n const icon = nativeImage.createFromPath(iconPath);\n\n if (process.platform === 'darwin' && !icon.isEmpty()) {\n app.dock?.setIcon(icon);\n }\n\n const win = new BrowserWindow({\n width: 1920,\n height: 1080,\n title: 'Kizen App Builder',\n icon,\n webPreferences: {\n nodeIntegration: false,\n contextIsolation: true,\n sandbox: false,\n preload: join(dirname(fileURLToPath(import.meta.url)), 'preload.cjs'),\n },\n });\n\n ipcMain.on('open-devtools', () => {\n win.webContents.openDevTools();\n });\n\n interface PropertyPreview {\n name: string;\n type: string;\n value?: string;\n subtype?: string;\n valuePreview?: ObjectPreview;\n }\n interface ObjectPreview {\n type: string;\n subtype?: string;\n overflow: boolean;\n properties: PropertyPreview[];\n }\n interface RemoteObject {\n type: string;\n subtype?: string;\n value?: unknown;\n description?: string;\n preview?: ObjectPreview;\n objectId?: string;\n }\n interface ConsoleApiCalledParams {\n type: string;\n args: RemoteObject[];\n }\n\n function parseProp(prop: PropertyPreview): unknown {\n if (prop.type === 'number') {\n return Number(prop.value);\n }\n if (prop.type === 'boolean') {\n return prop.value === 'true';\n }\n if (prop.type === 'undefined') {\n return undefined;\n }\n if (prop.type === 'object' && prop.value === 'null') {\n return null;\n }\n if (prop.type === 'object' && prop.valuePreview) {\n const { valuePreview } = prop;\n if (valuePreview.subtype === 'array') {\n return valuePreview.properties\n .filter((p) => /^\\d+$/.test(p.name))\n .sort((a, b) => parseInt(a.name) - parseInt(b.name))\n .map(parseProp);\n }\n const obj: Record<string, unknown> = {};\n for (const p of valuePreview.properties) {\n obj[p.name] = parseProp(p);\n }\n return obj;\n }\n return prop.value ?? `[${prop.type}]`;\n }\n\n function serializeArg(arg: RemoteObject): unknown {\n if (arg.value !== undefined) {\n return arg.value;\n }\n if (arg.preview) {\n const { preview } = arg;\n if (preview.subtype === 'array') {\n return preview.properties\n .filter((p) => /^\\d+$/.test(p.name))\n .sort((a, b) => parseInt(a.name) - parseInt(b.name))\n .map(parseProp);\n }\n const obj: Record<string, unknown> = {};\n for (const prop of preview.properties) {\n obj[prop.name] = parseProp(prop);\n }\n return obj;\n }\n return arg.description ?? `[${arg.type}]`;\n }\n\n const enableRuntime = (sessionId?: string): void => {\n void win.webContents.debugger.sendCommand(\n 'Runtime.enable',\n { generatePreview: true },\n sessionId,\n );\n };\n\n win.webContents.debugger.attach('1.3');\n enableRuntime();\n void win.webContents.debugger.sendCommand('Target.setAutoAttach', {\n autoAttach: true,\n waitForDebuggerOnStart: false,\n flatten: true,\n });\n\n async function serializeArgAsync(arg: RemoteObject, sessionId?: string): Promise<unknown> {\n if (arg.type === 'object' && arg.objectId) {\n try {\n const result: unknown = await win.webContents.debugger.sendCommand(\n 'Runtime.callFunctionOn',\n {\n objectId: arg.objectId,\n functionDeclaration:\n 'function() { const seen = new WeakSet(); return JSON.stringify(this, function(k, v) { if (typeof v === \"object\" && v !== null) { if (seen.has(v)) return \"[Circular]\"; seen.add(v); } return v; }); }',\n returnByValue: true,\n },\n sessionId,\n );\n const val = (result as { result: { value?: string } }).result.value;\n if (typeof val === 'string') {\n return JSON.parse(val);\n }\n } catch {\n // fall through to preview-based serialization\n }\n }\n return serializeArg(arg);\n }\n\n win.webContents.debugger.on('message', (_event, method, params, sessionId) => {\n if (method === 'Target.attachedToTarget') {\n const { sessionId: childSessionId } = params as { sessionId: string };\n enableRuntime(childSessionId);\n return;\n }\n\n if (method !== 'Runtime.consoleAPICalled') {\n return;\n }\n const { type, args } = params as ConsoleApiCalledParams;\n if (args[0]?.type === 'string' && String(args[0].value).includes('Electron Security Warning')) {\n return;\n }\n const level =\n type === 'warning' ? 'warn' : ['log', 'warn', 'error', 'info'].includes(type) ? type : 'log';\n void Promise.all(args.map((arg) => serializeArgAsync(arg, sessionId as string | undefined))).then(\n (serializedArgs) => {\n win.webContents.send('console-message', { level, args: serializedArgs });\n },\n );\n });\n\n void win.loadURL(`http://localhost:${String(port)}`);\n});\n\napp.on('window-all-closed', () => {\n app.quit();\n});\n"],"mappings":"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","names":["args"]}
|
package/dist/index.js
CHANGED
|
@@ -238,6 +238,37 @@ import { dirname as dirname2, extname, join as join6 } from "path";
|
|
|
238
238
|
import { fileURLToPath } from "url";
|
|
239
239
|
import { WebSocketServer } from "ws";
|
|
240
240
|
|
|
241
|
+
// src/lib/proxyCache.ts
|
|
242
|
+
function createProxyCache() {
|
|
243
|
+
const cache = /* @__PURE__ */ new Map();
|
|
244
|
+
return {
|
|
245
|
+
get(key, fetcher) {
|
|
246
|
+
const existing = cache.get(key);
|
|
247
|
+
if (existing !== void 0) {
|
|
248
|
+
return existing.then((response) => ({ response, fromCache: true }));
|
|
249
|
+
}
|
|
250
|
+
const pending = fetcher().then(async (response) => {
|
|
251
|
+
const headers = Object.fromEntries(response.headers);
|
|
252
|
+
delete headers["content-encoding"];
|
|
253
|
+
delete headers["content-length"];
|
|
254
|
+
return {
|
|
255
|
+
status: response.status,
|
|
256
|
+
headers,
|
|
257
|
+
body: Buffer.from(await response.arrayBuffer())
|
|
258
|
+
};
|
|
259
|
+
}).catch((error) => {
|
|
260
|
+
cache.delete(key);
|
|
261
|
+
throw error;
|
|
262
|
+
});
|
|
263
|
+
cache.set(key, pending);
|
|
264
|
+
return pending.then((response) => ({ response, fromCache: false }));
|
|
265
|
+
},
|
|
266
|
+
clear() {
|
|
267
|
+
cache.clear();
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
|
|
241
272
|
// src/lib/config.ts
|
|
242
273
|
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
243
274
|
import { join as join4 } from "path";
|
|
@@ -506,6 +537,13 @@ var CredentialSetupUI = ({
|
|
|
506
537
|
|
|
507
538
|
// src/ui/DevUI.tsx
|
|
508
539
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
540
|
+
function proxyLogEntryToString(entry) {
|
|
541
|
+
if (entry.kind === "info") {
|
|
542
|
+
return entry.message;
|
|
543
|
+
}
|
|
544
|
+
const cache = entry.fromCache ? " [cache]" : "";
|
|
545
|
+
return `${entry.method} ${entry.url} \u2192 ${String(entry.status)}${cache}`;
|
|
546
|
+
}
|
|
509
547
|
var SKIP_WATCH_PREFIXES = [".kizenapp", ".git"];
|
|
510
548
|
var LOG_LIMIT = 50;
|
|
511
549
|
var LOG_DISPLAY = 8;
|
|
@@ -554,6 +592,7 @@ async function fileExists(filePath) {
|
|
|
554
592
|
}
|
|
555
593
|
}
|
|
556
594
|
function createRequestHandler(viewerPath, createServerLog, createProxyLog, credentialsRef) {
|
|
595
|
+
const proxyCache = createProxyCache();
|
|
557
596
|
return (req, res) => {
|
|
558
597
|
void (async () => {
|
|
559
598
|
const url = req.url ?? "/";
|
|
@@ -576,6 +615,13 @@ function createRequestHandler(viewerPath, createServerLog, createProxyLog, crede
|
|
|
576
615
|
}
|
|
577
616
|
return;
|
|
578
617
|
}
|
|
618
|
+
if (url === "/api/proxy-cache/clear") {
|
|
619
|
+
proxyCache.clear();
|
|
620
|
+
createProxyLog({ kind: "info", message: "Proxy cache cleared" });
|
|
621
|
+
res.writeHead(200, { "Content-Type": "application/json; charset=utf-8" });
|
|
622
|
+
res.end('{"ok":true}');
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
579
625
|
if (url.startsWith("/api/proxy")) {
|
|
580
626
|
const proxyTarget = req.headers["x-proxy-target"];
|
|
581
627
|
if (typeof proxyTarget !== "string") {
|
|
@@ -585,19 +631,46 @@ function createRequestHandler(viewerPath, createServerLog, createProxyLog, crede
|
|
|
585
631
|
}
|
|
586
632
|
const upstreamPath = url.slice("/api/proxy".length) || "/";
|
|
587
633
|
const upstreamUrl = `${proxyTarget}${upstreamPath}`;
|
|
634
|
+
const method = req.method ?? "GET";
|
|
588
635
|
const chunks = [];
|
|
589
636
|
for await (const chunk of req) {
|
|
590
637
|
chunks.push(chunk);
|
|
591
638
|
}
|
|
592
|
-
const body = chunks.length > 0 ? Buffer.concat(chunks) : void 0;
|
|
593
639
|
const { host, "x-proxy-target": _drop, ...forwardHeaders } = req.headers;
|
|
640
|
+
if (method === "GET") {
|
|
641
|
+
const cacheKey = `GET::${upstreamUrl}`;
|
|
642
|
+
const { response: cached, fromCache } = await proxyCache.get(
|
|
643
|
+
cacheKey,
|
|
644
|
+
() => fetch(upstreamUrl, {
|
|
645
|
+
method: "GET",
|
|
646
|
+
headers: forwardHeaders
|
|
647
|
+
})
|
|
648
|
+
);
|
|
649
|
+
createProxyLog({
|
|
650
|
+
kind: "request",
|
|
651
|
+
method: "GET",
|
|
652
|
+
status: cached.status,
|
|
653
|
+
fromCache,
|
|
654
|
+
url: upstreamPath
|
|
655
|
+
});
|
|
656
|
+
res.writeHead(cached.status, cached.headers);
|
|
657
|
+
res.end(cached.body);
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
const body = chunks.length > 0 ? Buffer.concat(chunks) : void 0;
|
|
594
661
|
const resolvedBody = body && body.length > 0 ? body : void 0;
|
|
595
662
|
const upstream = await fetch(upstreamUrl, {
|
|
596
|
-
|
|
663
|
+
method,
|
|
597
664
|
headers: forwardHeaders,
|
|
598
665
|
...resolvedBody !== void 0 && { body: resolvedBody }
|
|
599
666
|
});
|
|
600
|
-
createProxyLog(
|
|
667
|
+
createProxyLog({
|
|
668
|
+
kind: "request",
|
|
669
|
+
method,
|
|
670
|
+
status: upstream.status,
|
|
671
|
+
fromCache: false,
|
|
672
|
+
url: upstreamPath
|
|
673
|
+
});
|
|
601
674
|
const responseHeaders = Object.fromEntries(upstream.headers);
|
|
602
675
|
delete responseHeaders["content-encoding"];
|
|
603
676
|
delete responseHeaders["content-length"];
|
|
@@ -613,9 +686,10 @@ function createRequestHandler(viewerPath, createServerLog, createProxyLog, crede
|
|
|
613
686
|
res.writeHead(200, { "Content-Type": mimeType });
|
|
614
687
|
createReadStream(resolvedPath).pipe(res);
|
|
615
688
|
} catch (err) {
|
|
616
|
-
createProxyLog(
|
|
617
|
-
|
|
618
|
-
|
|
689
|
+
createProxyLog({
|
|
690
|
+
kind: "info",
|
|
691
|
+
message: `Error handling ${url}: ${err instanceof Error ? err.message : String(err)}`
|
|
692
|
+
});
|
|
619
693
|
if (!res.headersSent) {
|
|
620
694
|
res.writeHead(502);
|
|
621
695
|
res.end("Bad Gateway");
|
|
@@ -708,11 +782,13 @@ var DevUI = ({
|
|
|
708
782
|
[outputDir, broadcast]
|
|
709
783
|
);
|
|
710
784
|
const createProxyLog = useCallback2(
|
|
711
|
-
(
|
|
785
|
+
(entry) => {
|
|
712
786
|
setProxyLogHistory(
|
|
713
|
-
(h) => [...h, `${(/* @__PURE__ */ new Date()).toLocaleTimeString()}: ${
|
|
787
|
+
(h) => [...h, `${(/* @__PURE__ */ new Date()).toLocaleTimeString()}: ${proxyLogEntryToString(entry)}`].slice(
|
|
788
|
+
-LOG_LIMIT
|
|
789
|
+
)
|
|
714
790
|
);
|
|
715
|
-
broadcast({ type: "proxy-log",
|
|
791
|
+
broadcast({ type: "proxy-log", entry });
|
|
716
792
|
},
|
|
717
793
|
[broadcast]
|
|
718
794
|
);
|