offsite 0.0.32 → 0.0.34
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/apps/server/dist/main.mjs +89 -6
- package/apps/server/dist/main.mjs.map +1 -1
- package/apps/web/dist/assets/{dist-Dce5gUb9.js → dist-BYXo5M-b.js} +1 -1
- package/apps/web/dist/assets/index-BiXADRAn.js +782 -0
- package/apps/web/dist/assets/index-CwgEGzdv.css +2 -0
- package/apps/web/dist/index.html +2 -2
- package/apps/web/dist/sw.js +1 -1
- package/package.json +1 -1
- package/apps/web/dist/assets/index-BNP3kNP8.css +0 -2
- package/apps/web/dist/assets/index-D1dHWaOx.js +0 -782
|
@@ -24,6 +24,7 @@ import { integer, snakeCase, text } from "drizzle-orm/sqlite-core";
|
|
|
24
24
|
import { promisify } from "node:util";
|
|
25
25
|
import webPush from "web-push";
|
|
26
26
|
import { createProxyServer } from "http-proxy-3";
|
|
27
|
+
import { OUTGOING_PASSES } from "http-proxy-3/dist/lib/http-proxy/passes/web-outgoing.js";
|
|
27
28
|
import { spawn as spawn$1 } from "@lydell/node-pty";
|
|
28
29
|
//#region ../core/src/media.ts
|
|
29
30
|
const mediaTypes = /* @__PURE__ */ new Map([
|
|
@@ -890,6 +891,7 @@ function accountSchema(provider) {
|
|
|
890
891
|
id: z.string(),
|
|
891
892
|
provider: z.literal(provider),
|
|
892
893
|
name: z.string(),
|
|
894
|
+
color: z.string().regex(/^#[0-9a-f]{6}$/i, "must be a hex color like #3b82f6").nullable().default(null),
|
|
893
895
|
configDir: platformDirs,
|
|
894
896
|
enabled: z.boolean().default(true),
|
|
895
897
|
hiddenModels: z.record(z.string(), z.boolean()).default({})
|
|
@@ -3584,6 +3586,7 @@ function addAccount(provider, name, configDir) {
|
|
|
3584
3586
|
id: randomUUID(),
|
|
3585
3587
|
provider,
|
|
3586
3588
|
name: account.name,
|
|
3589
|
+
color: null,
|
|
3587
3590
|
configDir: { [platform()]: account.configDir },
|
|
3588
3591
|
enabled: true,
|
|
3589
3592
|
hiddenModels: {}
|
|
@@ -3601,6 +3604,7 @@ async function updateAccount(update) {
|
|
|
3601
3604
|
[key]: config[key].map((item) => item.id === update.id ? {
|
|
3602
3605
|
...item,
|
|
3603
3606
|
name: account.name,
|
|
3607
|
+
color: update.color,
|
|
3604
3608
|
configDir: {
|
|
3605
3609
|
...item.configDir,
|
|
3606
3610
|
[platform()]: account.configDir
|
|
@@ -5094,6 +5098,46 @@ function resolveProjectFile(cwd, file) {
|
|
|
5094
5098
|
//#endregion
|
|
5095
5099
|
//#region src/services/proxy.ts
|
|
5096
5100
|
const proxies = /* @__PURE__ */ new Map();
|
|
5101
|
+
const pageScriptPath = "/__offsite/browser.js";
|
|
5102
|
+
function pageScript(origin) {
|
|
5103
|
+
return `(() => {
|
|
5104
|
+
if (window.parent === window || window.navigation === undefined) {
|
|
5105
|
+
return
|
|
5106
|
+
}
|
|
5107
|
+
const post = (message) =>
|
|
5108
|
+
window.parent.postMessage({ offsite: 'browser', ...message }, '*')
|
|
5109
|
+
const report = () =>
|
|
5110
|
+
post({
|
|
5111
|
+
event: 'location',
|
|
5112
|
+
url: ${JSON.stringify(origin)} + location.pathname + location.search + location.hash,
|
|
5113
|
+
proxied: location.href,
|
|
5114
|
+
back: navigation.canGoBack,
|
|
5115
|
+
forward: navigation.canGoForward,
|
|
5116
|
+
})
|
|
5117
|
+
addEventListener('pageshow', report)
|
|
5118
|
+
navigation.addEventListener('currententrychange', report)
|
|
5119
|
+
navigation.addEventListener('navigate', (event) => {
|
|
5120
|
+
if (!event.destination.sameDocument && event.downloadRequest === null) {
|
|
5121
|
+
post({ event: 'navigate' })
|
|
5122
|
+
}
|
|
5123
|
+
})
|
|
5124
|
+
addEventListener('message', (event) => {
|
|
5125
|
+
if (event.source !== window.parent || event.data?.offsite !== 'browser') {
|
|
5126
|
+
return
|
|
5127
|
+
}
|
|
5128
|
+
if (event.data.command === 'back') {
|
|
5129
|
+
navigation.back()
|
|
5130
|
+
}
|
|
5131
|
+
if (event.data.command === 'forward') {
|
|
5132
|
+
navigation.forward()
|
|
5133
|
+
}
|
|
5134
|
+
if (event.data.command === 'reload') {
|
|
5135
|
+
location.reload()
|
|
5136
|
+
}
|
|
5137
|
+
})
|
|
5138
|
+
})()
|
|
5139
|
+
`;
|
|
5140
|
+
}
|
|
5097
5141
|
function proxyPort(origin) {
|
|
5098
5142
|
const target = new URL(origin);
|
|
5099
5143
|
if (target.protocol !== "http:" && target.protocol !== "https:") throw new Error(`${origin} is not an http or https address`);
|
|
@@ -5105,21 +5149,43 @@ function proxyPort(origin) {
|
|
|
5105
5149
|
return started;
|
|
5106
5150
|
}
|
|
5107
5151
|
function startProxy(target) {
|
|
5108
|
-
const
|
|
5109
|
-
target
|
|
5152
|
+
const options = {
|
|
5153
|
+
target,
|
|
5110
5154
|
changeOrigin: true,
|
|
5111
5155
|
ws: true,
|
|
5112
5156
|
secure: false,
|
|
5113
5157
|
autoRewrite: true,
|
|
5114
5158
|
protocolRewrite: "http",
|
|
5115
|
-
cookieDomainRewrite: ""
|
|
5159
|
+
cookieDomainRewrite: "",
|
|
5160
|
+
selfHandleResponse: true
|
|
5161
|
+
};
|
|
5162
|
+
const proxy = createProxyServer(options);
|
|
5163
|
+
proxy.on("proxyReq", (outgoing, request) => {
|
|
5164
|
+
rewriteOrigin(target, outgoing, request);
|
|
5165
|
+
if (request.headers.accept?.startsWith("text/html") === true) outgoing.removeHeader("accept-encoding");
|
|
5116
5166
|
});
|
|
5117
|
-
proxy.on("proxyReq", (outgoing, request) => rewriteOrigin(target, outgoing, request));
|
|
5118
5167
|
proxy.on("proxyReqWs", (outgoing, request) => rewriteOrigin(target, outgoing, request));
|
|
5119
|
-
proxy.on("proxyRes", (incoming) => {
|
|
5168
|
+
proxy.on("proxyRes", async (incoming, request, response) => {
|
|
5169
|
+
try {
|
|
5170
|
+
await rewriteRedirect(target, incoming, request);
|
|
5171
|
+
} catch (error) {
|
|
5172
|
+
response.writeHead(502, { "content-type": "text/plain; charset=utf-8" });
|
|
5173
|
+
response.end(`Could not follow the redirect from ${target.origin}: ${error instanceof Error ? error.message : String(error)}`);
|
|
5174
|
+
return;
|
|
5175
|
+
}
|
|
5120
5176
|
delete incoming.headers["x-frame-options"];
|
|
5121
5177
|
delete incoming.headers["content-security-policy"];
|
|
5122
5178
|
if (incoming.headers["set-cookie"] !== void 0) incoming.headers["set-cookie"] = incoming.headers["set-cookie"].map((cookie) => cookie.replace(/;\s*secure/i, "").replace(/;\s*samesite=none/i, ""));
|
|
5179
|
+
const page = request.method === "GET" && request.headers.accept?.startsWith("text/html") === true && incoming.statusCode !== 204 && incoming.statusCode !== 304 && /^text\/html/i.test(incoming.headers["content-type"] ?? "") && incoming.headers["content-encoding"] === void 0;
|
|
5180
|
+
if (page) delete incoming.headers["content-length"];
|
|
5181
|
+
for (const pass of Object.values(OUTGOING_PASSES)) pass(request, response, incoming, options);
|
|
5182
|
+
if (!page) {
|
|
5183
|
+
incoming.pipe(response);
|
|
5184
|
+
return;
|
|
5185
|
+
}
|
|
5186
|
+
const chunks = [];
|
|
5187
|
+
incoming.on("data", (chunk) => chunks.push(chunk));
|
|
5188
|
+
incoming.on("end", () => response.end(Buffer.from(Buffer.concat(chunks).toString("latin1").replace(/^(\xEF\xBB\xBF)?\s*(<!doctype[^>]*>)?/i, `$&<script src="${pageScriptPath}"><\/script>`), "latin1")));
|
|
5123
5189
|
});
|
|
5124
5190
|
proxy.on("error", (error, _request, response) => {
|
|
5125
5191
|
if (!(response instanceof http.ServerResponse)) {
|
|
@@ -5129,7 +5195,14 @@ function startProxy(target) {
|
|
|
5129
5195
|
if (!response.headersSent) response.writeHead(502, { "content-type": "text/plain; charset=utf-8" });
|
|
5130
5196
|
response.end(`Could not reach ${target.origin}: ${error.message}`);
|
|
5131
5197
|
});
|
|
5132
|
-
const server = http.createServer((request, response) =>
|
|
5198
|
+
const server = http.createServer((request, response) => {
|
|
5199
|
+
if (request.url === pageScriptPath) {
|
|
5200
|
+
response.writeHead(200, { "content-type": "text/javascript; charset=utf-8" });
|
|
5201
|
+
response.end(pageScript(target.origin));
|
|
5202
|
+
return;
|
|
5203
|
+
}
|
|
5204
|
+
proxy.web(request, response);
|
|
5205
|
+
});
|
|
5133
5206
|
server.on("upgrade", (request, socket, head) => proxy.ws(request, socket, head));
|
|
5134
5207
|
return new Promise((resolve, reject) => {
|
|
5135
5208
|
server.once("error", reject);
|
|
@@ -5143,6 +5216,16 @@ function startProxy(target) {
|
|
|
5143
5216
|
});
|
|
5144
5217
|
});
|
|
5145
5218
|
}
|
|
5219
|
+
async function rewriteRedirect(target, incoming, request) {
|
|
5220
|
+
const location = incoming.headers.location;
|
|
5221
|
+
if (location === void 0 || !/^30[1278]$/.test(String(incoming.statusCode))) return;
|
|
5222
|
+
const next = new URL(location, target);
|
|
5223
|
+
if (next.origin === target.origin || next.protocol !== "http:" && next.protocol !== "https:") return;
|
|
5224
|
+
if (request.headers.host === void 0) throw new Error("the redirected request has no host");
|
|
5225
|
+
const proxied = new URL(`http://${request.headers.host}`);
|
|
5226
|
+
proxied.port = String(await proxyPort(next.origin));
|
|
5227
|
+
incoming.headers.location = `${proxied.origin}${next.pathname}${next.search}${next.hash}`;
|
|
5228
|
+
}
|
|
5146
5229
|
function rewriteOrigin(target, outgoing, request) {
|
|
5147
5230
|
if (request.headers.origin !== void 0) outgoing.setHeader("origin", target.origin);
|
|
5148
5231
|
if (request.headers.referer !== void 0) outgoing.setHeader("referer", request.headers.referer.replace(`http://${request.headers.host}`, target.origin));
|