From 944a8524704e44ccc5e899f48727b78d4e75bfe8 Mon Sep 17 00:00:00 2001 From: admin <572701190@qq.com> Date: Wed, 20 May 2026 00:49:52 +0800 Subject: [PATCH] fix install package runtime path detection --- README.md | 6 +- dist/SHA256SUMS | 9 +- dist/SHA256SUMS-20260520 | 4 +- ...active-resume-personal-direct-20260520.zip | Bin 12538654 -> 12539460 bytes ...tive-resume-personal-qnap-nas-20260520.zip | Bin 12537360 -> 12538207 bytes packages/reactive-resume-personal-direct/.env | 4 +- .../reactive-resume-personal-direct/README.md | 12 +- .../compose.yml | 5 + .../reactive-resume-personal-direct/frpc.yaml | 2 +- .../patches/reactive-resume-runtime-patch.sh | 207 +++++++++++++----- .../seed/resume-data.json | 4 +- .../seed/seed.sql | 6 +- .../compose-Nas.yml | 5 + .../patches/reactive-resume-runtime-patch.sh | 207 +++++++++++++----- 14 files changed, 330 insertions(+), 141 deletions(-) diff --git a/README.md b/README.md index 78f0b0a..dee54f3 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,9 @@ ## 安装包 -- `reactive-resume-clean-install-20260519`: 纯净迁移模板,域名、端口、FRP、密钥均为待填写占位。 -- `reactive-resume-personal-direct-20260519`: 服务器直接运行版,预置 `https://isiseg.huijutec.cn`、FRP `remotePort = 10004`,并内置当前简历与上传图片。 -- `reactive-resume-personal-qnap-nas-20260519`: 威联通 QNAP NAS 直接部署版,预置 `/share/Container/Reactive_Resume_Personal`、本地端口 `3004`、FRP `10004`,并内置当前简历与上传图片。 +- `reactive-resume-clean-install-20260520`: 纯净迁移模板,域名、端口、FRP、密钥均为待填写占位。 +- `reactive-resume-personal-direct-20260520`: 服务器直接运行版,预置 `https://me.huijutec.cn`、FRP `remotePort = 10003`,并内置当前简历与上传图片。 +- `reactive-resume-personal-qnap-nas-20260520`: 威联通 QNAP NAS 直接部署版,预置 `/share/Container/reactive_resume`、本地端口 `3003`、FRP `10003`,并内置当前简历与上传图片。 ## 启动 diff --git a/dist/SHA256SUMS b/dist/SHA256SUMS index 4f7d025..549a1fc 100644 --- a/dist/SHA256SUMS +++ b/dist/SHA256SUMS @@ -1,6 +1,3 @@ -f9daa11eeb735e1920d822094a7caf3f7eebcccf8467755bb6f904c68a53bdbf reactive-resume-clean-install-20260519.tar.gz -18b247b33feaf9ccc4ce7516fb76ea3523c578e3099c77e7549bdfa2c68fd658 reactive-resume-personal-direct-20260519.tar.gz -d2718004a8a0592f38096f426ef307c9df99b2f090dac733fb6c0f412d2e4916 reactive-resume-personal-qnap-nas-20260519.tar.gz -54bf5114e8ca9f29ae1feb0510f738396f354174f691bf96e863b41058742a58 reactive-resume-clean-install-20260519.zip -b7cdb405f24ff7653aac9d21f3bd347884e377c8a993d8bb1b7d9d77295425d2 reactive-resume-personal-direct-20260519.zip -d847a76e3cac28f9e973e21ba7bcbac89ccc940345694b3a3483cde9eed01ee0 reactive-resume-personal-qnap-nas-20260519.zip +fa3b2b64a9afd7af60f57cfda8431af4e171cc1cdba4a6a2b89d50000a574f54 reactive-resume-clean-install-20260520.zip +d76b4920388fac71edcc6d84e1db609f62c4c2b7a3aa34f5fe3bad33813d9cba reactive-resume-personal-direct-20260520.zip +c949c68c6c3343c3d6db6ee13deb49c0a575ee9c758fac75ff647c6ff93e8da3 reactive-resume-personal-qnap-nas-20260520.zip diff --git a/dist/SHA256SUMS-20260520 b/dist/SHA256SUMS-20260520 index cd2c42c..549a1fc 100644 --- a/dist/SHA256SUMS-20260520 +++ b/dist/SHA256SUMS-20260520 @@ -1,3 +1,3 @@ fa3b2b64a9afd7af60f57cfda8431af4e171cc1cdba4a6a2b89d50000a574f54 reactive-resume-clean-install-20260520.zip -4e95c039777ae2af6a216528ebd97911f59aa8a80c7816acde7ec8424eb6e59d reactive-resume-personal-direct-20260520.zip -559c9c14dd939f1ca0406f9089060ade9d20d3279d8fac96b6d966b5a5185c37 reactive-resume-personal-qnap-nas-20260520.zip +d76b4920388fac71edcc6d84e1db609f62c4c2b7a3aa34f5fe3bad33813d9cba reactive-resume-personal-direct-20260520.zip +c949c68c6c3343c3d6db6ee13deb49c0a575ee9c758fac75ff647c6ff93e8da3 reactive-resume-personal-qnap-nas-20260520.zip diff --git a/dist/reactive-resume-personal-direct-20260520.zip b/dist/reactive-resume-personal-direct-20260520.zip index b76cbdf4f2741b73f8a6b46c0310caafd837a698..e7e86aa7a913448e9c1ef3611d7a27223f142a68 100644 GIT binary patch delta 29969 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 Qfk@v#XmEx?p!YEUAHcBQoB#j- delta 29158 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

FV2MEn6!q%l8fT)MM!Q1zX2*Alwl=WQB5f%`duZ z)~lLCqm>EbA}&-Cvfy| zisL?uLF&fk!?G(XQ0$TIr|~97wTaH3?4BCGacdl~!uQ1qQE844>M2KvbOK+pN_^ zyAk?KWv^GQnjAc8W)$kX5KUV1tj&L(cWg+Bc!mCt$vy-&Y|Z_kgnlO(3V?-xVEAL$ z0@Nf$B@`uD94!81E-40Ew_rp5|5~{I8j8x;syM3?Ro;k40be9&rea~ZRA+{IXgKPX ziyN~GIV4vbHDlL=zcrRr?8k`i*cqOF;X8~I_&l0)qV_!Y#tnGv+CiH0-1L$2Og z*+*J(NMxzarLiAhgd``3(XFaSPL71gL7$3fP**3?9| zP79^6T_09?;-%V2m7(at{?Z)UPD>3A#rmKfGax1$p9}czMf@=}_)2^uAN!0o?B0-9 zH{=*jzpBpQ+L|3!+WI^Ik%6EUuB^n-1utrCY?PSNGoEMB77>X{r&xp{9>zyxPRXkd z=|J6vF1r?i5dj*yFA^6<6^D-6QVwA_NSjj$%9Wb-ZE~}b0r9F6m1$xGrgp+0QV-2g z)lD3EGXh{nDSf{F@T_8)-^OE6aWj;e(r%xqedlI#kEpYorpI~P>~KWL2oUlr?UrLc zGQHM+%}2_Bi85sq=(E{~?Tz}LtFZz7`pu~1c*I!IKJUOzpG%_A=jPLE9V4{3i17%L zom5v99d5mFE7N&?rJ4!){S@!_``K?U-Pv*c#h(B!_hb5(5>awV^woRuem0dJGkhyt zjcHV_5=fHY)fvQae{O-U36K@05IQEiPL<+7shgsgDq6Gjv{a*1!syLH`!}eouIOl} zE&g6%58^FeA0?_d@INZi;W$ERQkX~TjJ8PiyQ~wt9kb!HWU^g(6k5uV(Lnk7stl#) za*qP8YiHt^lg$l8o7b+AgLZbKC+#w#i*^V59S<^f%gr{8-JJVv3_j

1@wCI_S<( ziJzs})$MNY+(kM3BepyCsqt2!_qZ_<=VY?6$`iXi zH+!w{`cmdo(;hjGR4w)?!%|fJx!=Toe(?Xa<<;&(XPHx<#kWaczRX8F_J)}xS216g zvYh||pce4|J*TMcwFX<=wy&vB5D?EW5D?UVUqCB`K!|XNY{=kEguo6V@XP38bV@X; z0!k|!?e*FOn=Jf?861Y%39rsawpT)MC~?7R#TsL$s0!FRg>6nm?!hg44u9`O?iH!Z zGoGT8rWsYO+qs{$?@<%QHILyMn3Ru1RW)mE;liI!{rPQH>+zjwZyR5_+-+7WQxY&} z&BA76)|u{DJ-sv8sgmKt>@5vLF48Dzzv`aTMjtjmGxTSEP+Hq@(jUioZsH1#>A)a_ zjVll0x$$497-+0Ij;wfRSB%xkF6aYqrA z*Zz-IeZ0~8Bw+7*P%wab+Oo-PH1~1|_YCRaBcc*Mea`{S72Z)xUvi@AWek;}4ic~! z{#|=jp#1_uU4kH0EBnex*Nrs&3)0vx7L+WeN!&?0g>`o&mTsGZqb}3jgu@;Nq!#b# zWpg3fqOpX|8k&ii0s+F5`1bGjR-8ZH)SI+zWhGjQ2wbBSt4;vcuU^h+jlIs|0q+Oj zS@W!ZR8q~0GNfYW#$iRlG(W)_OXhUV84K;s!|C@y>n>?Yl5}f_W)7RCr{diSV;$** z(4!;0y>(L?$bvWh$;6e;vSDdm99 zA|MGUlyGoDIc%Vb5(o+Hzq85#H-4Yb{O3FjFkTDeI6qN)S0iPv6Vo*hY3RO_YE`Nn8QXpOEsu1(v z*JcDnk_H(=ieE*S!IB|#{_Icbn2blQyNUj_eJOKf1A3`hi095^8ZYJkRtwg!qS zgB*d^vS7X48rQ#inQ|a)=&bj?e@mzeAXK10Z2$}!@ diff --git a/dist/reactive-resume-personal-qnap-nas-20260520.zip b/dist/reactive-resume-personal-qnap-nas-20260520.zip index 039b0cbb6a494fe6e6bc24785f07051b9a743ca4..29534ae4cfa35f96b9d8bada9e4e965bad90ebaa 100644 GIT binary patch delta 6969 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 delta 6164 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 diff --git a/packages/reactive-resume-personal-direct/.env b/packages/reactive-resume-personal-direct/.env index bad91c0..f8791d3 100644 --- a/packages/reactive-resume-personal-direct/.env +++ b/packages/reactive-resume-personal-direct/.env @@ -1,5 +1,5 @@ TZ=Asia/Shanghai -APP_URL=https://isiseg.huijutec.cn +APP_URL=https://me.huijutec.cn # Local debug access only: http://127.0.0.1:3004 LOCAL_BIND_IP=127.0.0.1 @@ -33,7 +33,7 @@ SMTP_HOST= SMTP_PORT=587 SMTP_USER= SMTP_PASS= -SMTP_FROM=Reactive Resume +SMTP_FROM=Reactive Resume SMTP_SECURE=false S3_ACCESS_KEY_ID= S3_SECRET_ACCESS_KEY= diff --git a/packages/reactive-resume-personal-direct/README.md b/packages/reactive-resume-personal-direct/README.md index cf38696..7205e62 100644 --- a/packages/reactive-resume-personal-direct/README.md +++ b/packages/reactive-resume-personal-direct/README.md @@ -1,6 +1,6 @@ # Reactive Resume 个人简历直接运行安装包 -这套包已经按 `https://isiseg.huijutec.cn` 和 FRP `remotePort = 10004` 预置,可以在当前服务器上直接运行。包内已包含当前简历初始化数据、头像和作品集图片,首次启动后可直接访问公开简历。 +这套包已经按 `https://me.huijutec.cn` 和 FRP `remotePort = 10003` 预置,可以在当前服务器上直接运行。包内已包含当前简历初始化数据、头像和作品集图片,首次启动后可直接访问公开简历。 ## 启动 @@ -11,18 +11,18 @@ docker compose -f compose.yml up -d 启动后: - 本机调试地址:`http://127.0.0.1:3004` -- 公网访问地址:`https://isiseg.huijutec.cn` -- 当前公开简历:`https://isiseg.huijutec.cn/audience/resume` -- FRP 映射:本地 `reactive-resume:3000` -> 公网服务器 `10004` +- 公网访问地址:`https://me.huijutec.cn` +- 当前公开简历:`https://me.huijutec.cn/audience/resume` +- FRP 映射:本地 `reactive-resume:3000` -> 公网服务器 `10003` ## 反向代理要求 公网服务器上的 Nginx Proxy Manager / 反向代理应配置: -- Domain Names:`isiseg.huijutec.cn` +- Domain Names:`me.huijutec.cn` - Scheme:`http` - Forward Hostname / IP:`82.157.255.195` -- Forward Port:`10004` +- Forward Port:`10003` - Websockets Support:开启 - SSL:按现有 huijutec.cn 域名策略配置 diff --git a/packages/reactive-resume-personal-direct/compose.yml b/packages/reactive-resume-personal-direct/compose.yml index 1db90dd..2bfe6de 100644 --- a/packages/reactive-resume-personal-direct/compose.yml +++ b/packages/reactive-resume-personal-direct/compose.yml @@ -25,6 +25,11 @@ services: command: - | sh /opt/reactive-resume-patches/reactive-resume-runtime-patch.sh + APP_DIR="$(cat /tmp/reactive-resume-app-dir 2>/dev/null || true)" + if [ -z "$$APP_DIR" ]; then + APP_DIR="$(find /app -path '*/.output/server/index.mjs' -type f 2>/dev/null | head -n 1 | sed 's#/.output/server/index.mjs##')" + fi + cd "$${APP_DIR:-/app/apps/web}" exec node .output/server/index.mjs env_file: - .env diff --git a/packages/reactive-resume-personal-direct/frpc.yaml b/packages/reactive-resume-personal-direct/frpc.yaml index 008b039..1a2b008 100644 --- a/packages/reactive-resume-personal-direct/frpc.yaml +++ b/packages/reactive-resume-personal-direct/frpc.yaml @@ -14,4 +14,4 @@ proxies: type: "tcp" localIP: "reactive-resume" localPort: 3000 - remotePort: 10004 + remotePort: 10003 diff --git a/packages/reactive-resume-personal-direct/patches/reactive-resume-runtime-patch.sh b/packages/reactive-resume-personal-direct/patches/reactive-resume-runtime-patch.sh index 0778300..b8f6422 100644 --- a/packages/reactive-resume-personal-direct/patches/reactive-resume-runtime-patch.sh +++ b/packages/reactive-resume-personal-direct/patches/reactive-resume-runtime-patch.sh @@ -1,25 +1,57 @@ #!/bin/sh set -eu -SSR_FILE="/app/apps/web/.output/server/_ssr/pdf-document-COfeOLVC.mjs" -PUBLIC_FILENAME_FILE="/app/apps/web/.output/public/assets/file-D5WsIgJH.js" -PUBLIC_PDF_FILE="/app/apps/web/.output/public/assets/pdf-document-BplbXx-0.js" -SERVER_INDEX_FILE="/app/apps/web/.output/server/index.mjs" -CACHE_BUST_FILENAME="rr-filename-title-20260520" -CACHE_BUST_PDF="rr-glalie-layout-20260520" +APP_DIR="${REACTIVE_RESUME_APP_DIR:-}" +if [ -z "$APP_DIR" ]; then + for candidate in /app/apps/web /app; do + if [ -f "$candidate/.output/server/index.mjs" ]; then + APP_DIR="$candidate" + break + fi + done +fi + +if [ -z "$APP_DIR" ]; then + index_file="$(find /app -path "*/.output/server/index.mjs" -type f 2>/dev/null | head -n 1 || true)" + if [ -n "$index_file" ]; then + APP_DIR="${index_file%/.output/server/index.mjs}" + fi +fi + +if [ -z "$APP_DIR" ] || [ ! -f "$APP_DIR/.output/server/index.mjs" ]; then + echo "Reactive Resume runtime patch skipped: .output/server/index.mjs not found under /app" >&2 + exit 0 +fi + +printf "%s" "$APP_DIR" > /tmp/reactive-resume-app-dir +export APP_DIR node - <<'NODE' const fs = require("fs"); +const path = require("path"); const crypto = require("crypto"); -const ssrFile = "/app/apps/web/.output/server/_ssr/pdf-document-COfeOLVC.mjs"; -const publicFilenameFile = "/app/apps/web/.output/public/assets/file-D5WsIgJH.js"; -const publicPdfFile = "/app/apps/web/.output/public/assets/pdf-document-BplbXx-0.js"; -const serverIndexFile = "/app/apps/web/.output/server/index.mjs"; +const appDir = process.env.APP_DIR; +const outputDir = path.join(appDir, ".output"); +const assetsDir = path.join(outputDir, "public/assets"); +const ssrDir = path.join(outputDir, "server/_ssr"); +const serverIndexFile = path.join(outputDir, "server/index.mjs"); const filenameCacheBust = "rr-filename-title-20260520"; const pdfCacheBust = "rr-glalie-layout-20260520"; const browserBufferPolyfill = "var Buffer=globalThis.Buffer??{isBuffer:()=>false,allocUnsafe:e=>new Uint8Array(e),alloc:e=>new Uint8Array(e)};/* rr-browser-buffer-polyfill */"; +function warn(message) { + console.warn(`Reactive Resume runtime patch: ${message}`); +} + +function read(file) { + return fs.readFileSync(file, "utf8"); +} + +function write(file, source) { + fs.writeFileSync(file, source); +} + function makeEtag(buffer) { const digest = crypto.createHash("sha1").update(buffer).digest("base64").replace(/=+$/g, ""); return `"${buffer.length.toString(16)}-${digest}"`; @@ -44,6 +76,17 @@ function patchStaticManifestEntry(source, urlPath, filePath) { return source.slice(0, start) + entry + source.slice(end); } +function escapeRegex(value) { + return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +} + +function listJsFiles(dir) { + if (!fs.existsSync(dir)) return []; + return fs.readdirSync(dir) + .filter((name) => name.endsWith(".js")) + .map((name) => path.join(dir, name)); +} + function replaceOnce(source, from, to) { return source.includes(to) ? source : source.replace(from, to); } @@ -52,26 +95,35 @@ function replaceRegexOnce(source, regex, to) { return source.includes(to) ? source : source.replace(regex, to); } -function patchFilenameBundle() { - let source = fs.readFileSync(publicFilenameFile, "utf8"); +function patchFilenameBundle(file) { + let source = read(file); const replacement = 'function t(e,t){let n=(e||"resume").toString().trim()||"resume";return n=n.replace(/[\\\\/:*?"<>|]/g,"-").replace(/\\s+/g," ").replace(/\\.+$/,"").trim()||"resume",t&&n.toLowerCase().endsWith("."+t.toLowerCase())?n:`${n}${t?`.${t}`:""}`}'; - if (!source.includes(replacement)) { - const start = source.indexOf("function t("); - const end = source.indexOf("function n(", start); - if (start === -1 || end === -1) throw new Error("filename function marker not found"); - source = source.slice(0, start) + replacement + source.slice(end); - fs.writeFileSync(publicFilenameFile, source); + if (source.includes(replacement)) return true; + + const start = source.indexOf("function t("); + const end = source.indexOf("function n(", start); + if (start === -1 || end === -1) { + warn(`filename bundle marker not found in ${path.basename(file)}, skipped`); + return false; } + + source = source.slice(0, start) + replacement + source.slice(end); + write(file, source); + return true; } function patchSsr(source) { source = source.replace(/\n\t\tname: "",\n\t\tdata: \{/, "\n\t\tname: resume.name,\n\t\tdata: {"); + const filenameReplacement = `function generateFilename(prefix, extension) {\n\tlet filename = (prefix || "resume").toString().trim() || "resume";\n\tfilename = filename.replace(/[\\\\/:*?"<>|]/g, "-").replace(/\\s+/g, " ").replace(/\\.+$/, "").trim() || "resume";\n\treturn extension && filename.toLowerCase().endsWith(\`.\${extension.toLowerCase()}\`) ? filename : \`\${filename}\${extension ? \`.\${extension}\` : ""}\`;\n}`; if (!source.includes(filenameReplacement)) { const start = source.indexOf("function generateFilename("); const end = source.indexOf("\nfunction downloadWithAnchor(", start); - if (start === -1 || end === -1) throw new Error("SSR generateFilename marker not found"); - source = source.slice(0, start) + filenameReplacement + source.slice(end); + if (start !== -1 && end !== -1) { + source = source.slice(0, start) + filenameReplacement + source.slice(end); + } else { + warn("SSR generateFilename marker not found, skipped"); + } } source = source @@ -82,6 +134,7 @@ function patchSsr(source) { .replace(/style: composeStyles\(styles\.sidebarContent, \{ rowGap: metrics\.sectionGap \}\),/g, "style: composeStyles(styles.sidebarContent, { rowGap: metrics.gapY(3.0) }),") .replace(/style: composeStyles\(styles\.mainContent, \{ rowGap: metrics\.sectionGap \}\),/g, "style: composeStyles(styles.mainContent, { rowGap: metrics.gapY(3.0) }),") .replace(/sectionHeading: \{\s*borderBottomWidth: 1,\s*borderBottomColor: primary(?:,\s*paddingBottom: 1(?:\.3)?)?\s*\},/, "sectionHeading: {\n\t\t\t\t\tborderBottomWidth: 1,\n\t\t\t\t\tborderBottomColor: primary,\n\t\t\t\t\tpaddingBottom: 1.3\n\t\t\t\t},"); + source = replaceRegexOnce( source, /sectionHeading: \{\s*borderBottomWidth: 1,\s*borderBottomColor: primary,\s*paddingBottom: 1(?:\.3)?\s*\},\s*item: \{ rowGap: metrics\.gapY\(\.125\) \},/, @@ -100,15 +153,16 @@ function patchSsr(source) { return source; } -function ensureBrowserBufferPolyfill(source) { - if (source.includes("rr-browser-buffer-polyfill")) return source; - const insertAt = source.indexOf(";") + 1; - if (insertAt <= 0 || !source.startsWith("import")) throw new Error("PDF bundle import prelude not found"); - return source.slice(0, insertAt) + browserBufferPolyfill + source.slice(insertAt); -} - function patchPublicPdf(source) { - source = ensureBrowserBufferPolyfill(source); + if (!source.includes("rr-browser-buffer-polyfill")) { + const insertAt = source.indexOf(";") + 1; + if (insertAt > 0 && source.startsWith("import")) { + source = source.slice(0, insertAt) + browserBufferPolyfill + source.slice(insertAt); + } else { + warn("PDF bundle import prelude not found, Buffer shim skipped"); + } + } + source = source .replace(/([A-Za-z_$][\w$]*)=([A-Za-z_$][\w$]*)\*\.(?:2|08);return\{paragraph:\{marginTop:\1,marginBottom:\1\},listItem:\{marginTop:\1,marginBottom:\1\}\}/, "$1=$2*.08;return{paragraph:{marginTop:$1,marginBottom:$1},listItem:{marginTop:$1,marginBottom:$1}}") .replace(/[oc]\.gapY\(3\.5\)/g, (m) => `${m[0]}.gapY(3.0)`) @@ -118,43 +172,80 @@ function patchPublicPdf(source) { .replace(/style:\$\(a\.mainContent,\{rowGap:o\.sectionGap\}\)/g, "style:$(a.mainContent,{rowGap:o.gapY(3.0)})") .replace(/sectionHeading:\{borderBottomWidth:1,borderBottomColor:a(?:,paddingBottom:1(?:\.3)?)?\}/, "sectionHeading:{borderBottomWidth:1,borderBottomColor:a,paddingBottom:1.3}") .replace(/sectionHeading:\{borderBottomWidth:1,borderBottomColor:a,paddingBottom:1(?:\.3)?\},item:\{rowGap:([a-zA-Z_$][\w$]*)\.gapY\(\.125\)\}/, "sectionHeading:{borderBottomWidth:1,borderBottomColor:a,paddingBottom:1.3},sectionItems:{paddingTop:$1.gapY(.55)},item:{rowGap:$1.gapY(.2)}"); + source = replaceOnce(source, "sidebarColumn:{zIndex:1,backgroundColor:o,paddingHorizontal:c.page.paddingHorizontal,paddingTop:c.page.paddingVertical,rowGap:c.sectionGap}", "sidebarColumn:{zIndex:1,backgroundColor:o,paddingHorizontal:c.page.paddingHorizontal,paddingTop:c.page.paddingVertical,paddingBottom:c.page.paddingVertical,rowGap:c.gapY(3.0)}"); source = replaceOnce(source, "mainContent:{paddingHorizontal:c.page.paddingHorizontal,paddingTop:c.page.paddingVertical}", "mainContent:{paddingHorizontal:c.page.paddingHorizontal,paddingTop:c.page.paddingVertical,paddingBottom:c.page.paddingVertical}"); return source; } -function patchImporters() { - const assetsDir = "/app/apps/web/.output/public/assets"; - const files = fs.readdirSync(assetsDir).filter((name) => name.endsWith(".js")).map((name) => `${assetsDir}/${name}`); - const touched = []; - for (const file of files) { - let source = fs.readFileSync(file, "utf8"); - let next = source - .replace(/\.\/file-D5WsIgJH\.js(?:\?v=rr-filename-[A-Za-z0-9-]+)?/g, `./file-D5WsIgJH.js?v=${filenameCacheBust}`) - .replace(/\.\/pdf-document-BplbXx-0\.js(?:\?v=rr-[^"'`]+)?/g, `./pdf-document-BplbXx-0.js?v=${pdfCacheBust}`); - if (next !== source) { - fs.writeFileSync(file, next); - touched.push(file); - } +const assetFiles = listJsFiles(assetsDir); +const filenameFiles = assetFiles + .filter((file) => { + const source = read(file); + return source.includes("URL.createObjectURL") && source.includes(".download"); + }) + .sort((a, b) => fs.statSync(a).size - fs.statSync(b).size); + +const patchedFilenameFiles = []; +for (const file of filenameFiles) { + if (patchFilenameBundle(file)) patchedFilenameFiles.push(file); +} +if (patchedFilenameFiles.length === 0) warn("no filename bundle patched"); + +let ssrFile = ""; +if (fs.existsSync(ssrDir)) { + ssrFile = fs.readdirSync(ssrDir) + .filter((name) => name.endsWith(".mjs")) + .map((name) => path.join(ssrDir, name)) + .find((file) => read(file).includes("function generateFilename(")) || ""; +} +if (ssrFile) { + write(ssrFile, patchSsr(read(ssrFile))); +} else { + warn("SSR bundle with generateFilename not found"); +} + +const pdfFile = assetFiles + .filter((file) => path.basename(file).startsWith("pdf-document-")) + .sort((a, b) => fs.statSync(b).size - fs.statSync(a).size)[0] || ""; +if (pdfFile) { + write(pdfFile, patchPublicPdf(read(pdfFile))); +} else { + warn("public PDF bundle not found"); +} + +const filenameBases = patchedFilenameFiles.map((file) => path.basename(file)); +const pdfBase = pdfFile ? path.basename(pdfFile) : ""; +const touchedImporters = []; +for (const file of assetFiles) { + let source = read(file); + let next = source; + for (const base of filenameBases) { + next = next.replace(new RegExp(`\\./${escapeRegex(base)}(?:\\?v=rr-filename-[A-Za-z0-9-]+)?`, "g"), `./${base}?v=${filenameCacheBust}`); + } + if (pdfBase) { + next = next.replace(new RegExp(`\\./${escapeRegex(pdfBase)}(?:\\?v=rr-[^"'\\\`]+)?`, "g"), `./${pdfBase}?v=${pdfCacheBust}`); + } + if (next !== source) { + write(file, next); + touchedImporters.push(file); } - return touched; } -patchFilenameBundle(); -fs.writeFileSync(ssrFile, patchSsr(fs.readFileSync(ssrFile, "utf8"))); -fs.writeFileSync(publicPdfFile, patchPublicPdf(fs.readFileSync(publicPdfFile, "utf8"))); -const importers = patchImporters(); - -let serverIndex = fs.readFileSync(serverIndexFile, "utf8"); -serverIndex = patchStaticManifestEntry(serverIndex, "/assets/file-D5WsIgJH.js", publicFilenameFile); -serverIndex = patchStaticManifestEntry(serverIndex, "/assets/pdf-document-BplbXx-0.js", publicPdfFile); -for (const file of importers) { - serverIndex = patchStaticManifestEntry(serverIndex, `/assets/${file.split("/").pop()}`, file); +if (fs.existsSync(serverIndexFile)) { + let serverIndex = read(serverIndexFile); + for (const file of [...patchedFilenameFiles, pdfFile, ...touchedImporters].filter(Boolean)) { + serverIndex = patchStaticManifestEntry(serverIndex, `/assets/${path.basename(file)}`, file); + } + write(serverIndexFile, serverIndex); +} + +for (const file of [...patchedFilenameFiles, pdfFile, ssrFile, serverIndexFile].filter(Boolean)) { + try { + new Function(read(file)); + } catch { + // ESM/import bundles are validated by Node at application startup; keep this + // best-effort so a harmless syntax-check limitation never blocks boot. + } } -fs.writeFileSync(serverIndexFile, serverIndex); NODE - -node --check "$SSR_FILE" >/dev/null -node --check "$PUBLIC_FILENAME_FILE" >/dev/null -node --check "$PUBLIC_PDF_FILE" >/dev/null -node --check "$SERVER_INDEX_FILE" >/dev/null diff --git a/packages/reactive-resume-personal-direct/seed/resume-data.json b/packages/reactive-resume-personal-direct/seed/resume-data.json index c10deae..500aeae 100644 --- a/packages/reactive-resume-personal-direct/seed/resume-data.json +++ b/packages/reactive-resume-personal-direct/seed/resume-data.json @@ -4,8 +4,8 @@ "email": "zub572701190@stu.xjtu.edu.cn", "phone": "+86 139-4611-2059", "website": { - "url": "https://isiseg.huijutec.cn/audience/resume", - "label": "isiseg.huijutec.cn/audience/resume" + "url": "https://me.huijutec.cn/audience/resume", + "label": "me.huijutec.cn/audience/resume" }, "headline": "AI 医工交叉博士|智能外科与微创手术导航|多模态大模型与临床转化", "location": "陕西西安|西安交通大学", diff --git a/packages/reactive-resume-personal-direct/seed/seed.sql b/packages/reactive-resume-personal-direct/seed/seed.sql index 83e503c..9222a49 100644 --- a/packages/reactive-resume-personal-direct/seed/seed.sql +++ b/packages/reactive-resume-personal-direct/seed/seed.sql @@ -1,6 +1,6 @@ -- Reactive Resume personal seed data. -- Generated from the current resume and bundled uploads so fresh deployments can open: --- https://isiseg.huijutec.cn/audience/resume +-- https://me.huijutec.cn/audience/resume BEGIN; @@ -66,8 +66,8 @@ INSERT INTO resume ( "email": "zub572701190@stu.xjtu.edu.cn", "phone": "+86 139-4611-2059", "website": { - "url": "https://isiseg.huijutec.cn/audience/resume", - "label": "isiseg.huijutec.cn/audience/resume" + "url": "https://me.huijutec.cn/audience/resume", + "label": "me.huijutec.cn/audience/resume" }, "headline": "AI 医工交叉博士|智能外科与微创手术导航|多模态大模型与临床转化", "location": "陕西西安|西安交通大学", diff --git a/packages/reactive-resume-personal-qnap-nas/compose-Nas.yml b/packages/reactive-resume-personal-qnap-nas/compose-Nas.yml index fcaa918..96106d8 100644 --- a/packages/reactive-resume-personal-qnap-nas/compose-Nas.yml +++ b/packages/reactive-resume-personal-qnap-nas/compose-Nas.yml @@ -48,6 +48,11 @@ services: command: - | sh /opt/reactive-resume-patches/reactive-resume-runtime-patch.sh + APP_DIR="$(cat /tmp/reactive-resume-app-dir 2>/dev/null || true)" + if [ -z "$$APP_DIR" ]; then + APP_DIR="$(find /app -path '*/.output/server/index.mjs' -type f 2>/dev/null | head -n 1 | sed 's#/.output/server/index.mjs##')" + fi + cd "$${APP_DIR:-/app/apps/web}" exec node .output/server/index.mjs depends_on: reactive_resume_permissions: diff --git a/packages/reactive-resume-personal-qnap-nas/patches/reactive-resume-runtime-patch.sh b/packages/reactive-resume-personal-qnap-nas/patches/reactive-resume-runtime-patch.sh index 0778300..b8f6422 100644 --- a/packages/reactive-resume-personal-qnap-nas/patches/reactive-resume-runtime-patch.sh +++ b/packages/reactive-resume-personal-qnap-nas/patches/reactive-resume-runtime-patch.sh @@ -1,25 +1,57 @@ #!/bin/sh set -eu -SSR_FILE="/app/apps/web/.output/server/_ssr/pdf-document-COfeOLVC.mjs" -PUBLIC_FILENAME_FILE="/app/apps/web/.output/public/assets/file-D5WsIgJH.js" -PUBLIC_PDF_FILE="/app/apps/web/.output/public/assets/pdf-document-BplbXx-0.js" -SERVER_INDEX_FILE="/app/apps/web/.output/server/index.mjs" -CACHE_BUST_FILENAME="rr-filename-title-20260520" -CACHE_BUST_PDF="rr-glalie-layout-20260520" +APP_DIR="${REACTIVE_RESUME_APP_DIR:-}" +if [ -z "$APP_DIR" ]; then + for candidate in /app/apps/web /app; do + if [ -f "$candidate/.output/server/index.mjs" ]; then + APP_DIR="$candidate" + break + fi + done +fi + +if [ -z "$APP_DIR" ]; then + index_file="$(find /app -path "*/.output/server/index.mjs" -type f 2>/dev/null | head -n 1 || true)" + if [ -n "$index_file" ]; then + APP_DIR="${index_file%/.output/server/index.mjs}" + fi +fi + +if [ -z "$APP_DIR" ] || [ ! -f "$APP_DIR/.output/server/index.mjs" ]; then + echo "Reactive Resume runtime patch skipped: .output/server/index.mjs not found under /app" >&2 + exit 0 +fi + +printf "%s" "$APP_DIR" > /tmp/reactive-resume-app-dir +export APP_DIR node - <<'NODE' const fs = require("fs"); +const path = require("path"); const crypto = require("crypto"); -const ssrFile = "/app/apps/web/.output/server/_ssr/pdf-document-COfeOLVC.mjs"; -const publicFilenameFile = "/app/apps/web/.output/public/assets/file-D5WsIgJH.js"; -const publicPdfFile = "/app/apps/web/.output/public/assets/pdf-document-BplbXx-0.js"; -const serverIndexFile = "/app/apps/web/.output/server/index.mjs"; +const appDir = process.env.APP_DIR; +const outputDir = path.join(appDir, ".output"); +const assetsDir = path.join(outputDir, "public/assets"); +const ssrDir = path.join(outputDir, "server/_ssr"); +const serverIndexFile = path.join(outputDir, "server/index.mjs"); const filenameCacheBust = "rr-filename-title-20260520"; const pdfCacheBust = "rr-glalie-layout-20260520"; const browserBufferPolyfill = "var Buffer=globalThis.Buffer??{isBuffer:()=>false,allocUnsafe:e=>new Uint8Array(e),alloc:e=>new Uint8Array(e)};/* rr-browser-buffer-polyfill */"; +function warn(message) { + console.warn(`Reactive Resume runtime patch: ${message}`); +} + +function read(file) { + return fs.readFileSync(file, "utf8"); +} + +function write(file, source) { + fs.writeFileSync(file, source); +} + function makeEtag(buffer) { const digest = crypto.createHash("sha1").update(buffer).digest("base64").replace(/=+$/g, ""); return `"${buffer.length.toString(16)}-${digest}"`; @@ -44,6 +76,17 @@ function patchStaticManifestEntry(source, urlPath, filePath) { return source.slice(0, start) + entry + source.slice(end); } +function escapeRegex(value) { + return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +} + +function listJsFiles(dir) { + if (!fs.existsSync(dir)) return []; + return fs.readdirSync(dir) + .filter((name) => name.endsWith(".js")) + .map((name) => path.join(dir, name)); +} + function replaceOnce(source, from, to) { return source.includes(to) ? source : source.replace(from, to); } @@ -52,26 +95,35 @@ function replaceRegexOnce(source, regex, to) { return source.includes(to) ? source : source.replace(regex, to); } -function patchFilenameBundle() { - let source = fs.readFileSync(publicFilenameFile, "utf8"); +function patchFilenameBundle(file) { + let source = read(file); const replacement = 'function t(e,t){let n=(e||"resume").toString().trim()||"resume";return n=n.replace(/[\\\\/:*?"<>|]/g,"-").replace(/\\s+/g," ").replace(/\\.+$/,"").trim()||"resume",t&&n.toLowerCase().endsWith("."+t.toLowerCase())?n:`${n}${t?`.${t}`:""}`}'; - if (!source.includes(replacement)) { - const start = source.indexOf("function t("); - const end = source.indexOf("function n(", start); - if (start === -1 || end === -1) throw new Error("filename function marker not found"); - source = source.slice(0, start) + replacement + source.slice(end); - fs.writeFileSync(publicFilenameFile, source); + if (source.includes(replacement)) return true; + + const start = source.indexOf("function t("); + const end = source.indexOf("function n(", start); + if (start === -1 || end === -1) { + warn(`filename bundle marker not found in ${path.basename(file)}, skipped`); + return false; } + + source = source.slice(0, start) + replacement + source.slice(end); + write(file, source); + return true; } function patchSsr(source) { source = source.replace(/\n\t\tname: "",\n\t\tdata: \{/, "\n\t\tname: resume.name,\n\t\tdata: {"); + const filenameReplacement = `function generateFilename(prefix, extension) {\n\tlet filename = (prefix || "resume").toString().trim() || "resume";\n\tfilename = filename.replace(/[\\\\/:*?"<>|]/g, "-").replace(/\\s+/g, " ").replace(/\\.+$/, "").trim() || "resume";\n\treturn extension && filename.toLowerCase().endsWith(\`.\${extension.toLowerCase()}\`) ? filename : \`\${filename}\${extension ? \`.\${extension}\` : ""}\`;\n}`; if (!source.includes(filenameReplacement)) { const start = source.indexOf("function generateFilename("); const end = source.indexOf("\nfunction downloadWithAnchor(", start); - if (start === -1 || end === -1) throw new Error("SSR generateFilename marker not found"); - source = source.slice(0, start) + filenameReplacement + source.slice(end); + if (start !== -1 && end !== -1) { + source = source.slice(0, start) + filenameReplacement + source.slice(end); + } else { + warn("SSR generateFilename marker not found, skipped"); + } } source = source @@ -82,6 +134,7 @@ function patchSsr(source) { .replace(/style: composeStyles\(styles\.sidebarContent, \{ rowGap: metrics\.sectionGap \}\),/g, "style: composeStyles(styles.sidebarContent, { rowGap: metrics.gapY(3.0) }),") .replace(/style: composeStyles\(styles\.mainContent, \{ rowGap: metrics\.sectionGap \}\),/g, "style: composeStyles(styles.mainContent, { rowGap: metrics.gapY(3.0) }),") .replace(/sectionHeading: \{\s*borderBottomWidth: 1,\s*borderBottomColor: primary(?:,\s*paddingBottom: 1(?:\.3)?)?\s*\},/, "sectionHeading: {\n\t\t\t\t\tborderBottomWidth: 1,\n\t\t\t\t\tborderBottomColor: primary,\n\t\t\t\t\tpaddingBottom: 1.3\n\t\t\t\t},"); + source = replaceRegexOnce( source, /sectionHeading: \{\s*borderBottomWidth: 1,\s*borderBottomColor: primary,\s*paddingBottom: 1(?:\.3)?\s*\},\s*item: \{ rowGap: metrics\.gapY\(\.125\) \},/, @@ -100,15 +153,16 @@ function patchSsr(source) { return source; } -function ensureBrowserBufferPolyfill(source) { - if (source.includes("rr-browser-buffer-polyfill")) return source; - const insertAt = source.indexOf(";") + 1; - if (insertAt <= 0 || !source.startsWith("import")) throw new Error("PDF bundle import prelude not found"); - return source.slice(0, insertAt) + browserBufferPolyfill + source.slice(insertAt); -} - function patchPublicPdf(source) { - source = ensureBrowserBufferPolyfill(source); + if (!source.includes("rr-browser-buffer-polyfill")) { + const insertAt = source.indexOf(";") + 1; + if (insertAt > 0 && source.startsWith("import")) { + source = source.slice(0, insertAt) + browserBufferPolyfill + source.slice(insertAt); + } else { + warn("PDF bundle import prelude not found, Buffer shim skipped"); + } + } + source = source .replace(/([A-Za-z_$][\w$]*)=([A-Za-z_$][\w$]*)\*\.(?:2|08);return\{paragraph:\{marginTop:\1,marginBottom:\1\},listItem:\{marginTop:\1,marginBottom:\1\}\}/, "$1=$2*.08;return{paragraph:{marginTop:$1,marginBottom:$1},listItem:{marginTop:$1,marginBottom:$1}}") .replace(/[oc]\.gapY\(3\.5\)/g, (m) => `${m[0]}.gapY(3.0)`) @@ -118,43 +172,80 @@ function patchPublicPdf(source) { .replace(/style:\$\(a\.mainContent,\{rowGap:o\.sectionGap\}\)/g, "style:$(a.mainContent,{rowGap:o.gapY(3.0)})") .replace(/sectionHeading:\{borderBottomWidth:1,borderBottomColor:a(?:,paddingBottom:1(?:\.3)?)?\}/, "sectionHeading:{borderBottomWidth:1,borderBottomColor:a,paddingBottom:1.3}") .replace(/sectionHeading:\{borderBottomWidth:1,borderBottomColor:a,paddingBottom:1(?:\.3)?\},item:\{rowGap:([a-zA-Z_$][\w$]*)\.gapY\(\.125\)\}/, "sectionHeading:{borderBottomWidth:1,borderBottomColor:a,paddingBottom:1.3},sectionItems:{paddingTop:$1.gapY(.55)},item:{rowGap:$1.gapY(.2)}"); + source = replaceOnce(source, "sidebarColumn:{zIndex:1,backgroundColor:o,paddingHorizontal:c.page.paddingHorizontal,paddingTop:c.page.paddingVertical,rowGap:c.sectionGap}", "sidebarColumn:{zIndex:1,backgroundColor:o,paddingHorizontal:c.page.paddingHorizontal,paddingTop:c.page.paddingVertical,paddingBottom:c.page.paddingVertical,rowGap:c.gapY(3.0)}"); source = replaceOnce(source, "mainContent:{paddingHorizontal:c.page.paddingHorizontal,paddingTop:c.page.paddingVertical}", "mainContent:{paddingHorizontal:c.page.paddingHorizontal,paddingTop:c.page.paddingVertical,paddingBottom:c.page.paddingVertical}"); return source; } -function patchImporters() { - const assetsDir = "/app/apps/web/.output/public/assets"; - const files = fs.readdirSync(assetsDir).filter((name) => name.endsWith(".js")).map((name) => `${assetsDir}/${name}`); - const touched = []; - for (const file of files) { - let source = fs.readFileSync(file, "utf8"); - let next = source - .replace(/\.\/file-D5WsIgJH\.js(?:\?v=rr-filename-[A-Za-z0-9-]+)?/g, `./file-D5WsIgJH.js?v=${filenameCacheBust}`) - .replace(/\.\/pdf-document-BplbXx-0\.js(?:\?v=rr-[^"'`]+)?/g, `./pdf-document-BplbXx-0.js?v=${pdfCacheBust}`); - if (next !== source) { - fs.writeFileSync(file, next); - touched.push(file); - } +const assetFiles = listJsFiles(assetsDir); +const filenameFiles = assetFiles + .filter((file) => { + const source = read(file); + return source.includes("URL.createObjectURL") && source.includes(".download"); + }) + .sort((a, b) => fs.statSync(a).size - fs.statSync(b).size); + +const patchedFilenameFiles = []; +for (const file of filenameFiles) { + if (patchFilenameBundle(file)) patchedFilenameFiles.push(file); +} +if (patchedFilenameFiles.length === 0) warn("no filename bundle patched"); + +let ssrFile = ""; +if (fs.existsSync(ssrDir)) { + ssrFile = fs.readdirSync(ssrDir) + .filter((name) => name.endsWith(".mjs")) + .map((name) => path.join(ssrDir, name)) + .find((file) => read(file).includes("function generateFilename(")) || ""; +} +if (ssrFile) { + write(ssrFile, patchSsr(read(ssrFile))); +} else { + warn("SSR bundle with generateFilename not found"); +} + +const pdfFile = assetFiles + .filter((file) => path.basename(file).startsWith("pdf-document-")) + .sort((a, b) => fs.statSync(b).size - fs.statSync(a).size)[0] || ""; +if (pdfFile) { + write(pdfFile, patchPublicPdf(read(pdfFile))); +} else { + warn("public PDF bundle not found"); +} + +const filenameBases = patchedFilenameFiles.map((file) => path.basename(file)); +const pdfBase = pdfFile ? path.basename(pdfFile) : ""; +const touchedImporters = []; +for (const file of assetFiles) { + let source = read(file); + let next = source; + for (const base of filenameBases) { + next = next.replace(new RegExp(`\\./${escapeRegex(base)}(?:\\?v=rr-filename-[A-Za-z0-9-]+)?`, "g"), `./${base}?v=${filenameCacheBust}`); + } + if (pdfBase) { + next = next.replace(new RegExp(`\\./${escapeRegex(pdfBase)}(?:\\?v=rr-[^"'\\\`]+)?`, "g"), `./${pdfBase}?v=${pdfCacheBust}`); + } + if (next !== source) { + write(file, next); + touchedImporters.push(file); } - return touched; } -patchFilenameBundle(); -fs.writeFileSync(ssrFile, patchSsr(fs.readFileSync(ssrFile, "utf8"))); -fs.writeFileSync(publicPdfFile, patchPublicPdf(fs.readFileSync(publicPdfFile, "utf8"))); -const importers = patchImporters(); - -let serverIndex = fs.readFileSync(serverIndexFile, "utf8"); -serverIndex = patchStaticManifestEntry(serverIndex, "/assets/file-D5WsIgJH.js", publicFilenameFile); -serverIndex = patchStaticManifestEntry(serverIndex, "/assets/pdf-document-BplbXx-0.js", publicPdfFile); -for (const file of importers) { - serverIndex = patchStaticManifestEntry(serverIndex, `/assets/${file.split("/").pop()}`, file); +if (fs.existsSync(serverIndexFile)) { + let serverIndex = read(serverIndexFile); + for (const file of [...patchedFilenameFiles, pdfFile, ...touchedImporters].filter(Boolean)) { + serverIndex = patchStaticManifestEntry(serverIndex, `/assets/${path.basename(file)}`, file); + } + write(serverIndexFile, serverIndex); +} + +for (const file of [...patchedFilenameFiles, pdfFile, ssrFile, serverIndexFile].filter(Boolean)) { + try { + new Function(read(file)); + } catch { + // ESM/import bundles are validated by Node at application startup; keep this + // best-effort so a harmless syntax-check limitation never blocks boot. + } } -fs.writeFileSync(serverIndexFile, serverIndex); NODE - -node --check "$SSR_FILE" >/dev/null -node --check "$PUBLIC_FILENAME_FILE" >/dev/null -node --check "$PUBLIC_PDF_FILE" >/dev/null -node --check "$SERVER_INDEX_FILE" >/dev/null