@frontend-monitor/upload-sourcemaps 0.1.0 → 0.2.1

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/CHANGELOG.md CHANGED
@@ -4,6 +4,43 @@ All notable changes to `@frontend-monitor/upload-sourcemaps` are documented here
4
4
 
5
5
  ---
6
6
 
7
+ ## [0.2.0] (Unreleased)
8
+
9
+ ### 版本升级说明 / Release Notes
10
+
11
+ #### 新增 / Added
12
+
13
+ - **`init` 子命令**
14
+ 在项目根目录执行 `npx @frontend-monitor/upload-sourcemaps init`,自动在 `package.json` 中写入推荐脚本:`build:upload`(构建并上传)、`build:upload:archive`(构建并打包上传)。无需记忆 CLI 参数,配置好凭证后直接使用 `npm run build:upload` 或 `npm run build:upload:archive`。
15
+ - **上传进度提示**
16
+ 三种上传方式均会输出实时进度,避免用户误以为卡死:
17
+ - **多文件上传**:按「已上传文件总大小 / 总大小」显示 `上传进度 X.XX/Y.YY MB (百分比%)`,每 3 秒刷新一次。
18
+ - **单次归档上传**:按已发送字节显示 `上传进度 归档 X.XX/Y.YY MB (百分比%)`,最多每 3 秒刷新一次。
19
+ - **分片上传**:按已上传分片字节显示 `上传进度 分片 X.XX/Y.YY MB (百分比%)`,每 3 秒刷新一次。
20
+ 进度统一写入 stderr,使用 `\r` 单行刷新。
21
+
22
+ #### 变更 / Changed
23
+
24
+ - **打包脚本性能**
25
+ 本包自身构建(`build.js`)改为并行执行两个 esbuild 入口,缩短构建时间。
26
+ - **单次归档上传实现**
27
+ 归档上传改为手动构建 multipart body 并以流式发送,便于按字节统计并输出上传进度(百分比基于已发送字节 / 总字节)。
28
+
29
+ #### 文档 / Documentation
30
+
31
+ - **SDK 配套说明**
32
+ `@frontend-monitor/sdk` 的 README(中英文)中「配套包:upload-sourcemaps」一节增加「一键写入推荐脚本」:推荐先执行 `npx @frontend-monitor/upload-sourcemaps init`,再使用 `npm run build:upload` / `build:upload:archive`。
33
+ - **本包 README**
34
+ - 快速开始中增加 Step 1b:执行 `init` 写入推荐脚本。
35
+ - 参数速查中增加「子命令」表格,说明 `init`、`build`、`patch`、`restore`。
36
+
37
+ #### 使用建议
38
+
39
+ - 新项目建议执行一次 `npx @frontend-monitor/upload-sourcemaps init`,之后在 CI 或本地使用 `npm run build:upload` 或 `npm run build:upload:archive`。
40
+ - 上传过程中关注终端中的「上传进度 … MB (…%)」即可判断是否在正常上传。
41
+
42
+ ---
43
+
7
44
  ## [0.1.0] (2025-03-13)
8
45
 
9
46
  ### 版本升级说明 / Release Notes
package/README.md CHANGED
@@ -16,6 +16,16 @@ npm install @frontend-monitor/upload-sourcemaps
16
16
 
17
17
  Or run without installing: `npx @frontend-monitor/upload-sourcemaps`
18
18
 
19
+ ### Step 1b: Add scripts to package.json (recommended)
20
+
21
+ From your project root, run:
22
+
23
+ ```bash
24
+ npx @frontend-monitor/upload-sourcemaps init
25
+ ```
26
+
27
+ This adds `build:upload` and `build:upload:archive` to your `package.json`. After configuring credentials (Step 2), you can run `npm run build:upload` or `npm run build:upload:archive` instead of remembering CLI options.
28
+
19
29
  ### Step 2: Configure credentials
20
30
 
21
31
  Create `.upload-sourcemaps.json` at your **project root** (do not commit to public repos):
@@ -158,6 +168,7 @@ Priority: **CLI > env > config**.
158
168
  | `--secret-key` | `SECRET_KEY` | Project secret | — |
159
169
  | `--endpoint` | `ENDPOINT` | API URL | — |
160
170
  | `--dir` | `DIR` | Directory with .map files | Current dir |
171
+ | `--concurrency` | `CONCURRENCY` | Max parallel uploads (when not using --archive) | 12 |
161
172
  | `--release` | `RELEASE` | Version (must match SDK) | From package.json |
162
173
  | `--build-id` | `BUILD_ID` | Build serial number | Auto-generated |
163
174
  | `--archive` | — | Pack as tar.gz and upload encrypted (recommended) | — |
@@ -168,6 +179,15 @@ Priority: **CLI > env > config**.
168
179
  | `--no-encrypt` | — | With --archive: upload plain tar.gz (older servers) | — |
169
180
  | `--config` | `UPLOAD_SOURCEMAPS_CONFIG` | Config file path | — |
170
181
 
182
+ ### Subcommands
183
+
184
+ | Subcommand | Description |
185
+ |------------|-------------|
186
+ | **init** | Add recommended scripts to `package.json` (`build:upload`, `build:upload:archive`). Run from project root. No credentials needed. |
187
+ | **build** | One-step: run build (with Source Maps forced), then upload .map files. Uses `buildCommand` / `buildOutputDir` from config. |
188
+ | **patch** | Temporarily enable Source Map in bundler config; then run your build and `upload-sourcemaps` (no subcommand). |
189
+ | **restore** | Restore bundler config from a previous `patch` (from `.upload-sourcemaps.patch-backup.json`). |
190
+
171
191
  ---
172
192
 
173
193
  ## Advanced
@@ -298,11 +318,32 @@ Recommended: `npx upload-sourcemaps build --archive` and wire up the SDK as in i
298
318
 
299
319
  ---
300
320
 
321
+ ## Nuxt (2 & 3)
322
+
323
+ - **Output directory**: Client assets and their `.map` files are under **`.output/public/_nuxt/`**. Set `dir` to that path so the CLI finds and uploads them:
324
+ - In `.upload-sourcemaps.json`: `"dir": ".output/public/_nuxt"`
325
+ - Or: `npx upload-sourcemaps --dir .output/public/_nuxt`
326
+ - **Generate .map (SSR-friendly)**:
327
+ - **Nuxt 3**: For SSR you need source maps for both server and browser. In `nuxt.config.ts` set **both** `server` and `client`: `sourcemap: { server: true, client: true }`.
328
+ - Or use **one-step** `npx upload-sourcemaps build --dir .output/public/_nuxt`: the tool will temporarily enable **both** server and client source maps, run `npm run build`, then upload from `.output/public/_nuxt`.
329
+ - **Suggested scripts** (project root):
330
+
331
+ ```json
332
+ "scripts": {
333
+ "build": "nuxt build",
334
+ "upload-sourcemaps": "upload-sourcemaps --dir .output/public/_nuxt"
335
+ }
336
+ ```
337
+
338
+ Then: `npm run build && npx upload-sourcemaps` or use `npx upload-sourcemaps build --dir .output/public/_nuxt` (with endpoint/projectId/secretKey in config or env).
339
+
340
+ ---
341
+
301
342
  ## FAQ
302
343
 
303
344
  **Stack still shows minified locations?** Ensure SDK `release` matches upload version; stack script names match uploaded .map basenames; correct project is selected in the admin.
304
345
 
305
- **No .map after build subcommand?** Vite usually works as-is; other bundlers may need to enable Source Maps when `BUILD_SOURCEMAP=1`.
346
+ **No .map after build subcommand?** Vite usually works as-is; for Nuxt set `dir` to `.output/public/_nuxt` and enable `sourcemap: { client: true }` (Nuxt 3) or use the build subcommand. Other bundlers may need to enable Source Maps when `BUILD_SOURCEMAP=1`.
306
347
 
307
348
  **Where to get Project ID / Secret Key?** Admin console → Project settings.
308
349
 
package/README.zh-CN.md CHANGED
@@ -16,6 +16,16 @@ npm install @frontend-monitor/upload-sourcemaps
16
16
 
17
17
  或直接使用(不安装):`npx @frontend-monitor/upload-sourcemaps`
18
18
 
19
+ ### 第一步补充:写入推荐脚本(推荐)
20
+
21
+ 在项目根目录执行:
22
+
23
+ ```bash
24
+ npx @frontend-monitor/upload-sourcemaps init
25
+ ```
26
+
27
+ 会在 `package.json` 中增加 `build:upload` 与 `build:upload:archive` 脚本。配置好凭证(第二步)后,可直接使用 `npm run build:upload` 或 `npm run build:upload:archive`,无需记忆 CLI 参数。
28
+
19
29
  ### 第二步:配置凭证
20
30
 
21
31
  在**项目根目录**创建 `.upload-sourcemaps.json`(不要提交到公开仓库):
@@ -161,6 +171,7 @@ npx upload-sourcemaps
161
171
  | `--secret-key` | `SECRET_KEY` | 项目密钥 | — |
162
172
  | `--endpoint` | `ENDPOINT` | API 地址 | — |
163
173
  | `--dir` | `DIR` | 包含 .map 的目录 | 当前目录 |
174
+ | `--concurrency` | `CONCURRENCY` | 最大并发上传数(未使用 --archive 时) | 12 |
164
175
  | `--release` | `RELEASE` | 版本号(需与 SDK 一致) | 读 package.json |
165
176
  | `--build-id` | `BUILD_ID` | 构建序列号 | 自动生成 |
166
177
  | `--archive` | — | 打 tar.gz 并加密上传(推荐) | — |
@@ -171,6 +182,15 @@ npx upload-sourcemaps
171
182
  | `--no-encrypt` | — | 与 --archive 同用时明文上传(兼容旧服务端) | — |
172
183
  | `--config` | `UPLOAD_SOURCEMAPS_CONFIG` | 配置文件路径 | — |
173
184
 
185
+ ### 子命令
186
+
187
+ | 子命令 | 说明 |
188
+ |--------|------|
189
+ | **init** | 在 `package.json` 中写入推荐脚本(`build:upload`、`build:upload:archive`)。在项目根目录执行,无需配置凭证。 |
190
+ | **build** | 一键:执行构建(强制生成 Source Map)并上传 .map,使用配置中的 `buildCommand` / `buildOutputDir`。 |
191
+ | **patch** | 临时开启打包工具的 Source Map 配置;之后自行构建并执行 `upload-sourcemaps`(无子命令)。 |
192
+ | **restore** | 从之前的 `patch` 备份(`.upload-sourcemaps.patch-backup.json`)恢复打包配置。 |
193
+
174
194
  ---
175
195
 
176
196
  ## 进阶
@@ -301,11 +321,32 @@ const { ok, fail } = await uploadAll({
301
321
 
302
322
  ---
303
323
 
324
+ ## Nuxt(2 与 3)
325
+
326
+ - **输出目录**:客户端资源及 `.map` 在 **`.output/public/_nuxt/`**。需把 `dir` 指向该目录,上传脚本才会扫描并上传:
327
+ - 在 `.upload-sourcemaps.json` 中:`"dir": ".output/public/_nuxt"`
328
+ - 或:`npx upload-sourcemaps --dir .output/public/_nuxt`
329
+ - **生成 .map(兼容 SSR)**:
330
+ - **Nuxt 3**:服务端渲染需同时兼容服务端与浏览器端,请在 `nuxt.config.ts` 中同时开启 **server 与 client**:`sourcemap: { server: true, client: true }`。
331
+ - 或使用**一键** `npx upload-sourcemaps build --dir .output/public/_nuxt`:工具会临时同时开启 **服务端与客户端** source map、执行 `npm run build`,再从 `.output/public/_nuxt` 上传。
332
+ - **推荐脚本**(项目根目录):
333
+
334
+ ```json
335
+ "scripts": {
336
+ "build": "nuxt build",
337
+ "upload-sourcemaps": "upload-sourcemaps --dir .output/public/_nuxt"
338
+ }
339
+ ```
340
+
341
+ 然后执行:`npm run build && npx upload-sourcemaps`,或使用 `npx upload-sourcemaps build --dir .output/public/_nuxt`(endpoint/projectId/secretKey 写在配置或环境变量中)。
342
+
343
+ ---
344
+
304
345
  ## 常见问题
305
346
 
306
347
  **堆栈仍显示压缩后位置?** 确认 SDK 的 `release` 与上传版本一致;堆栈中的脚本名与上传的 .map 文件名对应;管理端选择了正确项目。
307
348
 
308
- **build 子命令后没有 .map?** Vite 一般自动生效;其他打包工具需在配置中根据 `BUILD_SOURCEMAP=1` 开启 Source Map。
349
+ **build 子命令后没有 .map?** Vite 一般自动生效;Nuxt 需将 `dir` 设为 `.output/public/_nuxt`,并在 Nuxt 3 中开启 `sourcemap: { client: true }` 或使用 build 子命令。其他打包工具需在配置中根据 `BUILD_SOURCEMAP=1` 开启 Source Map。
309
350
 
310
351
  **Project ID / Secret Key 在哪?** 登录管理端 → 项目设置。
311
352
 
@@ -1,2 +1,8 @@
1
1
  #!/usr/bin/env node
2
- var at=Object.defineProperty;var W=(t,e)=>()=>(t&&(e=t(t=0)),e);var X=(t,e)=>{for(var o in e)at(t,o,{get:e[o],enumerable:!0})};var Y={};X(Y,{extractProjectIdFromCert:()=>ct,extractUploadKeyFromCert:()=>it});function ct(t){if(typeof t!="string")return"";let e=t.trim();if(e.startsWith(st+"$"))return e.split("$")[1]||"";if(e.includes(we)){let o=e.match(/Project:\s*(\S+)/);return o?o[1]:""}return""}function it(t){if(typeof t!="string"||!t.includes(we))return null;let e=t.match(/Upload-Key:\s*([0-9a-fA-F]{64})/);if(!e)return null;try{return Buffer.from(e[1],"hex")}catch{return null}}var st,we,Z=W(()=>{st="MC1",we="-----BEGIN MONITOR CERT-----"});var H={};X(H,{decryptArchive:()=>mt,encryptArchive:()=>ft,encryptArchiveWithKey:()=>ge});import{createCipheriv as ut,createDecipheriv as lt,createHash as pt,randomBytes as dt}from"crypto";function be(t,e){let o=`${t}:${e}`;return pt("sha256").update(o,"utf8").digest()}function ft(t,e,o){let r=be(e,o);return ge(t,r)}function ge(t,e){if(!Buffer.isBuffer(e)||e.length!==32)throw new Error("Invalid key: must be 32-byte Buffer");let o=dt(Q),r=ut(ye,e,o,{authTagLength:J}),a=Buffer.concat([r.update(t),r.final()]),n=r.getAuthTag();return Buffer.concat([o,a,n])}function mt(t,e,o){if(t.length<Q+J)throw new Error("Invalid encrypted archive: too short");let r=be(e,o),a=t.subarray(0,Q),n=t.subarray(t.length-J),s=t.subarray(Q,t.length-J),c=lt(ye,r,a,{authTagLength:J});return c.setAuthTag(n),Buffer.concat([c.update(s),c.final()])}var ye,Q,J,V=W(()=>{ye="aes-256-gcm",Q=12,J=16});var se={};X(se,{DEFAULT_EXCLUDE_EXT:()=>S,UPLOAD_MODE_BACKUP:()=>ee,UPLOAD_MODE_MAP_ONLY:()=>kt,collectFiles:()=>te,createArchive:()=>B,createBackupArchive:()=>re,deleteMapFiles:()=>Se,uploadArchive:()=>Ot});import{createRequire as ht}from"module";import{readdir as xe,unlink as Oe,readFile as wt,mkdtemp as Ie,rm as Me,mkdir as yt,copyFile as ve,writeFile as bt}from"fs/promises";import{join as j,relative as gt,dirname as ke}from"path";import{createWriteStream as Ee}from"fs";import{tmpdir as Ce}from"os";async function te(t,e=t,o={}){let{excludeExt:r=S,mapOnly:a=!1,excludeMap:n=!1}=typeof o=="object"&&o!==null?o:{},s=await xe(t,{withFileTypes:!0}),c=[];for(let u of s){let i=j(t,u.name),l=gt(e,i).replace(/\\/g,"/");if(u.isDirectory()){let p=await te(i,e,o);c.push(...p)}else{if(a&&!u.name.endsWith(".map")||!a&&n&&u.name.endsWith(".map"))continue;if(!a&&r&&r.size>0){let p=(u.name.includes(".")?"."+u.name.split(".").pop():"").toLowerCase();if(r.has(p))continue}c.push({relativePath:l,fullPath:i})}}return c}async function B(t,e,o={},r=!0){let a={};o instanceof Set?(a={excludeExt:o,mapOnly:!1},r=arguments[3]!==void 0?arguments[3]:!0):typeof o=="object"&&o!==null&&(a=o);let n=await te(t,t,a),s=n.map(c=>c.relativePath);return s.length===0?0:new Promise((c,u)=>{let i=je.create({gzip:r,cwd:t},s);i.on("error",u),i.pipe(Ee(e)).on("close",()=>c(n.length)).on("error",u)})}async function re(t,e,o={}){let{excludeExt:r=S,includeMapInOutput:a=!0}=typeof o=="object"&&o!==null?o:{},n=await Ie(j(Ce(),"upload-sourcemaps-backup-")),s=ke(e),c=j(s,"project-code.tar.gz"),u=j(n,"project-code.tar.gz");try{let i=await B(t,u,{excludeExt:r||S,mapOnly:!1,excludeMap:!0},!0);if(i===0){let f=j(n,".keep");await bt(f,""),await B(n,u,{excludeExt:new Set,mapOnly:!1},!0),await Oe(f).catch(()=>{})}else await ve(u,c);let l=[];if(a){l=await te(t,t,{mapOnly:!0});for(let f of l){let d=j(n,f.relativePath);await yt(ke(d),{recursive:!0}),await ve(f.fullPath,d)}}let p=["project-code.tar.gz",...l.map(f=>f.relativePath)];return await xt(n,e,p,!0),{codeFileCount:i,mapFileCount:l.length,codeTarPath:i>0?c:void 0}}finally{await Me(n,{recursive:!0,force:!0})}}function xt(t,e,o,r=!0){return o.length===0?Promise.resolve(0):new Promise((a,n)=>{let s=je.create({gzip:r,cwd:t},o);s.on("error",n),s.pipe(Ee(e)).on("close",()=>a(o.length)).on("error",n)})}async function Ot(t,e=console){let{dir:o,endpoint:r,projectId:a,secretKey:n,authCert:s,release:c,buildId:u,excludeExt:i,noEncrypt:l,uploadMode:p,keepMapInOutput:f}=t,d=!!s,{extractProjectIdFromCert:g,extractUploadKeyFromCert:y}=await Promise.resolve().then(()=>(Z(),Y)),h=a||(d?g(s):""),m=d?y(s):null,k=await Ie(j(Ce(),"upload-sourcemaps-")),_=j(k,"archive.tar.gz"),O=p===ee,N=O?null:{excludeExt:i||S,mapOnly:!0};try{let D;if(O){let{codeFileCount:C,mapFileCount:b}=await re(o,_,{excludeExt:i||S,includeMapInOutput:f!==!1});D=Math.max(1,b),f!==!1?e.log("Created backup archive: project-code.tar.gz (",C," files for rollback) + ",b," .map file(s), uploading..."):e.log("Created backup archive: project-code.tar.gz (",C," files for rollback, no .map per project config), uploading...")}else D=await B(o,_,N,!0);if(D===0)return e.log("No files to pack (directory empty or only excluded). Skip upload."),{ok:!0,uploaded:0};let I=await wt(_),M=!l&&(d?m!==null:!!(h&&n));if(M)if(m){let{encryptArchiveWithKey:C}=await Promise.resolve().then(()=>(V(),H));I=C(I,m),O||e.log("Created tar.gz with",D,"file(s), encrypted with cert Upload-Key, uploading...")}else{let{encryptArchive:C}=await Promise.resolve().then(()=>(V(),H));I=C(I,h,n),O||e.log("Created tar.gz with",D,"file(s), encrypted, uploading...")}else O||e.log("Created tar.gz with",D,"file(s), uploading...");let $="/sourcemaps/upload-archive",K=r.replace(/\/$/,""),A=K.endsWith($)?K:K+$,x=new FormData;x.append("projectId",h),d||x.append("secretKey",n||""),x.append("release",c),u&&x.append("buildId",u),M&&x.append("encrypted","1"),p&&x.append("uploadMode",p),x.append("file",new Blob([I]),M?"archive.tar.gz.enc":"archive.tar.gz");let q={"X-Project-Id":h};d?q["X-Auth-Cert"]=s:q["X-Secret-Key"]=n||"";let P=await fetch(A,{method:"POST",headers:q,body:x}),L=await P.text();if(!P.ok)throw new Error(`${P.status} ${L}`);let ae=JSON.parse(L||"{}");return e.log("Upload archive OK, server extracted and saved",ae.uploaded,".map file(s)"),{ok:!0,uploaded:ae.uploaded||0}}finally{await Me(k,{recursive:!0,force:!0})}}async function Se(t,e=[]){let o=await xe(t,{withFileTypes:!0});for(let r of o){let a=j(t,r.name);r.isDirectory()?await Se(a,e):r.name.endsWith(".map")&&(await Oe(a),e.push(a))}return e}var vt,je,S,kt,ee,oe=W(()=>{vt=ht(import.meta.url),je=vt("tar"),S=new Set([".png",".jpg",".jpeg",".gif",".svg",".webp",".ico",".bmp",".avif",".woff",".woff2",".ttf",".eot",".otf",".mp4",".webm",".ogg",".mp3",".wav",".m4a",".aac",".pdf",".doc",".docx",".xls",".xlsx"]),kt="mapOnly",ee="backup"});var Ae={};X(Ae,{uploadArchiveChunked:()=>Ut});import{readFile as It,mkdtemp as Mt,rm as Et}from"fs/promises";import{join as De}from"path";import{tmpdir as Ct}from"os";function At(t){return t.replace(/\/$/,"")}function ne(t,e){let o=At(t),r=e.startsWith("/")?e:`/${e}`;return o.endsWith(r)?o:o+r}async function Pt(t){return new Promise(e=>setTimeout(e,t))}async function ce(t,e,o,r=St){let a;for(let n=0;n<=r;n++)try{let s=await fetch(t,e),c=await s.text();if(!s.ok)throw new Error(`${s.status} ${c}`);return c?JSON.parse(c):{}}catch(s){if(a=s,n<r){let c=Dt*Math.pow(2,n);o.log?.(` Retry ${n+1}/${r} after ${c}ms: ${s.message}`),await Pt(c)}}throw a}async function Ut(t,e=console){let{dir:o,endpoint:r,projectId:a,secretKey:n,authCert:s,release:c,buildId:u,noEncrypt:i,chunkSizeBytes:l=jt,excludeExt:p,uploadMode:f,keepMapInOutput:d}=t,g=!!s,{extractProjectIdFromCert:y,extractUploadKeyFromCert:h}=await Promise.resolve().then(()=>(Z(),Y)),m=a||(g?y(s):""),k=g?h(s):null,_=await Mt(De(Ct(),"upload-sourcemaps-chunked-")),O=De(_,"archive.tar.gz"),N=f===ee,D=N?null:{excludeExt:p||S,mapOnly:!0};try{let I;if(N){let{codeFileCount:b,mapFileCount:U}=await re(o,O,{excludeExt:p||S,includeMapInOutput:d!==!1});I=Math.max(1,U),d!==!1?e.log?.("Created backup archive: project-code.tar.gz (",b," files for rollback) + ",U," .map file(s), uploading in chunks..."):e.log?.("Created backup archive: project-code.tar.gz (",b," files for rollback, no .map per project config), uploading in chunks...")}else I=await B(o,O,D,!0);if(I===0)return e.log?.("No files to pack. Skip upload."),{ok:!0,uploaded:0};let M=await It(O),$=!i&&(g?k!==null:!!(m&&n));if($){if(k){let{encryptArchiveWithKey:b}=await Promise.resolve().then(()=>(V(),H));M=b(M,k)}else{let{encryptArchive:b}=await Promise.resolve().then(()=>(V(),H));M=b(M,m,n)}N||e.log?.(`Created tar.gz with ${I} file(s), encrypted, uploading in chunks...`)}else N||e.log?.(`Created tar.gz with ${I} file(s), uploading in chunks...`);let K=M.length,A=Math.ceil(K/l),x={"Content-Type":"application/json"};g?x["X-Auth-Cert"]=s:(x["X-Project-Id"]=m,x["X-Secret-Key"]=n||"");let P=(await ce(ne(r,"/sourcemaps/upload-archive-multipart/init"),{method:"POST",headers:{...x,"Content-Type":"application/json"},body:JSON.stringify({projectId:m,secretKey:g?"":n||"",release:c,buildId:u||void 0,totalChunks:A,chunkSizeBytes:l,encrypted:$,uploadMode:f||void 0})},e)).uploadId;if(!P)throw new Error("Init did not return uploadId");let L=new Set;for(let b=0;b<A;b++)L.add(b);try{let b=await fetch(ne(r,"/sourcemaps/upload-archive-multipart/status")+`?uploadId=${encodeURIComponent(P)}`,{method:"GET",headers:x}),U=await b.text();if(b.ok&&U){let z=JSON.parse(U).receivedChunks||[];z.forEach(R=>L.delete(R)),z.length>0&&e.log?.(`Resume: ${z.length}/${A} chunks already uploaded`)}}catch{}for(let b=0;b<A;b++){if(!L.has(b))continue;let U=b*l,he=Math.min(U+l,K),z=M.subarray(U,he),R=new FormData;R.append("uploadId",P),R.append("index",String(b)),R.append("totalChunks",String(A)),R.append("chunk",new Blob([z]),`chunk-${b}`);let nt=ne(r,"/sourcemaps/upload-archive-multipart/chunk");await ce(nt,{method:"POST",headers:g?{"X-Auth-Cert":s}:{"X-Project-Id":m,"X-Secret-Key":n||""},body:R},e),e.log?.(` Chunk ${b+1}/${A} OK`)}let C=(await ce(ne(r,"/sourcemaps/upload-archive-multipart/complete"),{method:"POST",headers:{...x,"Content-Type":"application/json"},body:JSON.stringify({uploadId:P})},e)).uploaded??0;return e.log?.("Chunked upload OK, server extracted and saved",C,".map file(s)"),{ok:!0,uploaded:C}}finally{await Et(_,{recursive:!0,force:!0})}}var jt,St,Dt,Pe=W(()=>{oe();jt=1*1024*1024,St=3,Dt=1e3});var Ze={};X(Ze,{loadMonitorConfig:()=>qe,loadUploadSourcemapsJson:()=>Ye,resolveUploadConfig:()=>Wt});import{readFile as Je}from"fs/promises";import{join as He,resolve as zt}from"path";import{pathToFileURL as Ve}from"url";function Ge(){try{return process.env.UPLOAD_ENV||process.env.NODE_ENV||"production"}catch{return"production"}}async function qe(t){let e=["monitor.config.js","monitor.config.cjs","monitor.config.mjs"];for(let o of e){let r=He(t,o),a;try{a=await import(Ve(r).href)}catch{continue}let n=a.default;if(!n||typeof n!="object")return null;let s=Ge(),c=n.common||{},u=n[s]||{},i={...c,...u},l=(i.endpoint||"").trim(),p=(i.apiPrefix||"").trim(),f=l+(p.startsWith("/")?p:p?"/"+p:"");return{projectId:i.projectId,secretKey:i.secretKey,authCert:i.authCert,endpoint:f||void 0,release:i.release||n.version,version:n.version}}return null}async function Ye(t){try{let e=await Je(He(t,".upload-sourcemaps.json"),"utf-8");return JSON.parse(e)}catch{return{}}}async function Wt(t,e){let o=null,r=null;if(e){let a=zt(t,e);if(e.endsWith(".json"))try{r=JSON.parse(await Je(a,"utf-8"))}catch{r={}}else try{let s=(await import(Ve(a).href)).default;if(s&&typeof s=="object"&&(s.common||s.production||s.development)){let c=Ge(),u=s.common||{},i=s[c]||{},l={...u,...i},p=(l.endpoint||"").trim(),f=(l.apiPrefix||"").trim();o={projectId:l.projectId,secretKey:l.secretKey,authCert:l.authCert,endpoint:p+(f.startsWith("/")?f:f?"/"+f:""),release:l.release||s.version}}else r=s||{}}catch{r={}}}else o=await qe(t),r=await Ye(t);return{projectId:r.projectId??o?.projectId,secretKey:r.secretKey??o?.secretKey,authCert:r.authCert??o?.authCert,endpoint:r.endpoint??o?.endpoint,release:r.release??o?.release??o?.version,dir:r.dir,chunkSize:r.chunkSize,uploadAsArchive:r.uploadAsArchive,noEncrypt:r.noEncrypt,buildCommand:r.buildCommand,buildOutputDir:r.buildOutputDir,uploadMode:r.uploadMode==="backup"?"backup":"mapOnly"}}var Qe=W(()=>{});import{readFile as Xt}from"fs/promises";import{resolve as Jt,dirname as Ht,join as Vt}from"path";import{fileURLToPath as Gt}from"url";import{randomUUID as et}from"crypto";import{spawn as qt}from"child_process";import{readdir as Ft,readFile as Tt,unlink as _t}from"fs/promises";import{join as Rt,basename as G}from"path";async function Fe(t,e=[]){let o;try{o=await Ft(t,{withFileTypes:!0})}catch(r){if(r?.code==="ENOENT")return e;throw r}for(let r of o){let a=Rt(t,r.name);r.isDirectory()?await Fe(a,e):r.name.endsWith(".map")&&e.push(a)}return e}var Ue="/sourcemaps/upload";function Nt(t){let e=t.replace(/\/$/,"");return e.endsWith(Ue)?e:e+Ue}async function Kt(t){let{endpoint:e,projectId:o,secretKey:r,authCert:a,release:n,buildId:s,filePath:c}=t,u=!!a,i=o||(u?(await Promise.resolve().then(()=>(Z(),Y))).extractProjectIdFromCert(a):""),l=G(c,".map"),p=await Tt(c),f=Nt(e),d=new FormData;d.append("projectId",i),u||d.append("secretKey",r||""),d.append("release",n),s&&d.append("buildId",s),d.append("filename",l),d.append("file",new Blob([p]),G(c));let y=await fetch(f,{method:"POST",headers:u?{"X-Project-Id":i,"X-Auth-Cert":a}:{"X-Project-Id":i,"X-Secret-Key":r||""},body:d}),h=await y.text();if(!y.ok)throw new Error(`${y.status} ${h}`);return JSON.parse(h||"{}")}async function ie(t,e=console){let{dir:o,endpoint:r,projectId:a,secretKey:n,authCert:s,release:c,buildId:u,deleteAfterUpload:i=!1,deleteEvenOnFailure:l=!1}=t,p=await Fe(o);if(p.length===0)return e.log("No .map files found in",o),{ok:0,fail:0,deleted:0};let f=i&&l;e.log("Uploading",p.length,"source map(s) to",r,"release=",c,i?f?"(will delete local .map even on failure)":"(will delete local .map only after all succeed)":"");let d=0,g=0;for(let m of p)try{await Kt({endpoint:r,projectId:a,secretKey:n,authCert:s,release:c,buildId:u,filePath:m}),e.log(" OK",G(m)),d++}catch(k){e.error(" FAIL",G(m),k.message),g++}let y=i&&(g===0||l),h=0;if(y&&p.length>0){for(let m of p)try{await _t(m),h++,e.log(" Deleted",G(m))}catch(k){e.error(" Delete failed",m,k.message)}g>0&&l&&e.log("Deleted .map files despite upload failures. Fix errors and re-run to re-upload.")}else g>0&&!l&&e.log("Upload had failures. Local .map files were NOT deleted. Fix errors and re-run.");return{ok:d,fail:g,deleted:h}}async function ue(t,e=console){let{uploadArchive:o,deleteMapFiles:r}=await Promise.resolve().then(()=>(oe(),se)),{dir:a,endpoint:n,projectId:s,secretKey:c,authCert:u,release:i,buildId:l,deleteEvenOnFailure:p=!1,noEncrypt:f,uploadMode:d,excludeExt:g}=t;try{let{uploaded:y}=await o({dir:a,endpoint:n,projectId:s,secretKey:c,authCert:u,release:i,buildId:l,noEncrypt:f,uploadMode:d,excludeExt:g},e);if(y===0)return{uploaded:0,deleted:0};let h=await r(a,[]);return e.log("Deleted",h.length,"local .map file(s)."),{uploaded:y,deleted:h.length}}catch(y){if(p)try{let h=await r(a,[]);e.log("Deleted",h.length,"local .map file(s) despite upload failure.")}catch(h){e.error("Delete .map after upload failure failed:",h.message)}else e.error("Upload failed. Local .map files were NOT deleted.",y.message);throw y}}async function le(t,e=console){let{uploadArchiveChunked:o}=await Promise.resolve().then(()=>(Pe(),Ae)),{deleteMapFiles:r}=await Promise.resolve().then(()=>(oe(),se)),{dir:a,endpoint:n,projectId:s,secretKey:c,authCert:u,release:i,buildId:l,deleteEvenOnFailure:p=!1,noEncrypt:f,chunkSizeBytes:d,uploadMode:g,excludeExt:y}=t;try{let{uploaded:h}=await o({dir:a,endpoint:n,projectId:s,secretKey:c,authCert:u,release:i,buildId:l,noEncrypt:f,chunkSizeBytes:d,uploadMode:g,excludeExt:y},e);if(h===0)return{uploaded:0,deleted:0};let m=await r(a,[]);return e.log("Deleted",m.length,"local .map file(s)."),{uploaded:h,deleted:m.length}}catch(h){if(p)try{let m=await r(a,[]);e.log("Deleted",m.length,"local .map file(s) despite upload failure.")}catch(m){e.error("Delete .map after upload failure failed:",m.message)}else e.error("Upload failed. Local .map files were NOT deleted.",h.message);throw h}}import{readFile as pe}from"fs/promises";import{join as E,resolve as Te}from"path";async function de(t){let e=[t,Te(t,".."),Te(t,"..",".."),process.cwd()];for(let o of e)try{return await pe(E(o,"package.json"),"utf-8"),o}catch{continue}return null}async function F(t){try{return await pe(t,"utf-8")}catch{return""}}async function _e(t){let e=["vite.config.js","vite.config.mjs","vite.config.cjs","vite.config.ts"];for(let o of e){let r=await F(E(t,o));if(r){if(/\bsourcemap\s*:\s*false\b/.test(r)||/build\s*:\s*\{[^}]*sourcemap\s*:\s*false/.test(r))return{emitsSourceMap:!1,bundler:"vite",keepMapInOutput:!1};if(/\bsourcemap\s*:\s*['"]inline['"]/.test(r)||/build\s*:\s*\{[\s\S]*?sourcemap\s*:\s*['"]inline['"]/.test(r))return{emitsSourceMap:!0,bundler:"vite",keepMapInOutput:!1};if(/\bsourcemap\s*:\s*true\b/.test(r)||/\bsourcemap\s*:\s*['"]hidden['"]/.test(r))return{emitsSourceMap:!0,bundler:"vite",keepMapInOutput:!0};if(/build\s*:\s*\{[\s\S]*?sourcemap\s*:\s*true/.test(r))return{emitsSourceMap:!0,bundler:"vite",keepMapInOutput:!0};if(/build\s*:\s*\{[\s\S]*?sourcemap\s*:\s*['"]hidden['"]/.test(r))return{emitsSourceMap:!0,bundler:"vite",keepMapInOutput:!0};if(/BUILD_SOURCEMAP|SOURCEMAP/.test(r)&&/build\s*:\s*\{[\s\S]*?sourcemap\s*:/.test(r))return{emitsSourceMap:!0,bundler:"vite",keepMapInOutput:!0};if(/build\s*:|\bdefineConfig\s*\(/.test(r))return{emitsSourceMap:!1,bundler:"vite",keepMapInOutput:!1}}}return null}async function Re(t){let e=["webpack.config.js","webpack.config.cjs","webpack.config.mjs","webpack.config.ts","webpack.common.js","webpack.prod.js"];for(let o of e){let r=await F(E(t,o));if(r){if(/\bdevtool\s*:\s*false\b/.test(r))return{emitsSourceMap:!1,bundler:"webpack",keepMapInOutput:!1};if(/\bdevtool\s*:\s*['"]source-map['"]/.test(r)||/\bdevtool\s*:\s*['"]hidden-source-map['"]/.test(r))return{emitsSourceMap:!0,bundler:"webpack",keepMapInOutput:!0};if(/\bdevtool\s*:\s*true\b/.test(r))return{emitsSourceMap:!0,bundler:"webpack",keepMapInOutput:!0}}}return null}async function Ne(t){let e=await F(E(t,"vue.config.js"))||await F(E(t,"vue.config.cjs"));return e?/\bproductionSourceMap\s*:\s*false\b/.test(e)?{emitsSourceMap:!1,bundler:"vue-cli",keepMapInOutput:!1}:/\bproductionSourceMap\s*:\s*true\b/.test(e)?{emitsSourceMap:!0,bundler:"vue-cli",keepMapInOutput:!0}:/\.devtool\s*\(\s*['"]source-map['"]\s*\)/.test(e)?{emitsSourceMap:!0,bundler:"vue-cli",keepMapInOutput:!0}:null:null}async function Ke(t){let e=["rollup.config.js","rollup.config.mjs","rollup.config.cjs"];for(let o of e){let r=await F(E(t,o));if(r){if(/\bsourcemap\s*:\s*false\b/.test(r))return{emitsSourceMap:!1,bundler:"rollup",keepMapInOutput:!1};if(/\bsourcemap\s*:\s*['"]inline['"]/.test(r))return{emitsSourceMap:!0,bundler:"rollup",keepMapInOutput:!1};if(/\bsourcemap\s*:\s*true\b/.test(r))return{emitsSourceMap:!0,bundler:"rollup",keepMapInOutput:!0}}}return null}async function Le(t){let e=["next.config.js","next.config.mjs","next.config.cjs","next.config.ts"];for(let o of e){let r=await F(E(t,o));if(r){if(/\bproductionBrowserSourceMaps\s*:\s*true\b/.test(r))return{emitsSourceMap:!0,bundler:"next",keepMapInOutput:!0};if(/\bproductionBrowserSourceMaps\s*:\s*false\b/.test(r))return{emitsSourceMap:!1,bundler:"next",keepMapInOutput:!1};if(/module\.exports|next\s*\(/.test(r))return{emitsSourceMap:!1,bundler:"next",keepMapInOutput:!1}}}return null}async function Be(t){let e=await F(E(t,"nuxt.config.js"))||await F(E(t,"nuxt.config.ts"));return e?/\bsourcemap\s*:\s*false\b/.test(e)?{emitsSourceMap:!1,bundler:"nuxt",keepMapInOutput:!1}:/\bsourcemap\s*:\s*true\b/.test(e)?{emitsSourceMap:!0,bundler:"nuxt",keepMapInOutput:!0}:null:null}function Lt(t){let e={...t.dependencies,...t.devDependencies};return!e||typeof e!="object"?null:e.vite||e.vite?"vite":e.next?"next":e.nuxt||e.nuxt3?"nuxt":e.vue&&(e["@vue/cli-service"]||e["vue-cli-service"])?"vue-cli":e.webpack||e["react-scripts"]||e["@angular/cli"]?"webpack":e.rollup?"rollup":e.parcel?"parcel":null}async function fe(t){let e=await de(t);if(!e)return{emitsSourceMap:!0,keepMapInOutput:!1};let o={};try{let n=await pe(E(e,"package.json"),"utf-8");o=JSON.parse(n)}catch{return{emitsSourceMap:!0,keepMapInOutput:!1}}let r=Lt(o),a=[()=>r==="vite"?_e(e):null,()=>r==="next"?Le(e):null,()=>r==="nuxt"?Be(e):null,()=>r==="vue-cli"?Ne(e):null,()=>r==="webpack"?Re(e):null,()=>r==="rollup"?Ke(e):null,()=>_e(e),()=>Le(e),()=>Ne(e),()=>Re(e),()=>Ke(e),()=>Be(e)];for(let n of a){let s=await n();if(s)return s}return{emitsSourceMap:!0,keepMapInOutput:!1}}import{readFile as We,writeFile as $e}from"fs/promises";import{join as ze}from"path";async function Bt(t){try{return await We(t,"utf-8")}catch{return""}}function $t(t){let e={...t?.dependencies||{},...t?.devDependencies||{}};return e.vite||e.vite?"vite":e.next?"next":e.nuxt||e.nuxt3?"nuxt":e.vue&&(e["@vue/cli-service"]||e["vue-cli-service"])?"vue-cli":e.webpack||e["react-scripts"]||e["@angular/cli"]?"webpack":e.rollup?"rollup":null}var me=[{name:"vite",configNames:["vite.config.js","vite.config.mjs","vite.config.cjs","vite.config.ts"],needPatch:t=>/\bsourcemap\s*:\s*false\b/.test(t),patch:t=>t.replace(/(sourcemap\s*:\s*)false\b/,"$1true")},{name:"webpack",configNames:["webpack.config.js","webpack.config.cjs","webpack.config.mjs","webpack.config.ts","webpack.common.js","webpack.prod.js"],needPatch:t=>/\bdevtool\s*:\s*false\b/.test(t),patch:t=>t.replace(/(devtool\s*:\s*)false\b/,(e,o)=>`${o}'source-map'`)},{name:"vue-cli",configNames:["vue.config.js","vue.config.cjs"],needPatch:t=>/\bproductionSourceMap\s*:\s*false\b/.test(t),patch:t=>t.replace(/(productionSourceMap\s*:\s*)false\b/,"$1true")},{name:"rollup",configNames:["rollup.config.js","rollup.config.mjs","rollup.config.cjs"],needPatch:t=>/\bsourcemap\s*:\s*false\b/.test(t),patch:t=>t.replace(/(sourcemap\s*:\s*)false\b/,"$1true")},{name:"next",configNames:["next.config.js","next.config.mjs","next.config.cjs","next.config.ts"],needPatch:t=>/\bproductionBrowserSourceMaps\s*:\s*false\b/.test(t),patch:t=>t.replace(/(productionBrowserSourceMaps\s*:\s*)false\b/,"$1true")},{name:"nuxt",configNames:["nuxt.config.js","nuxt.config.ts"],needPatch:t=>/\bsourcemap\s*:\s*false\b/.test(t),patch:t=>t.replace(/(sourcemap\s*:\s*)false\b/,"$1true")}];async function Xe(t){let e=await de(t);if(!e)return{restore:async()=>{}};let o={};try{let n=await We(ze(e,"package.json"),"utf-8");o=JSON.parse(n)}catch{return{restore:async()=>{}}}let r=$t(o),a=r?[...me.filter(n=>n.name===r),...me.filter(n=>n.name!==r)]:me;for(let n of a)for(let s of n.configNames){let c=ze(e,s),u=await Bt(c);if(!u||!n.needPatch(u))continue;let i=n.patch(u);return await $e(c,i,"utf-8"),{restore:async()=>{try{await $e(c,u,"utf-8")}catch(l){console.error(`Restore ${n.name} config failed:`,l?.message||l)}}}}return{restore:async()=>{}}}var Tr=Ht(Gt(import.meta.url));function v(t,e){let o=process.env[e];if(o)return o;let r=process.argv.indexOf(t);return r!==-1&&process.argv[r+1]?process.argv[r+1]:null}function T(t){return process.argv.includes(t)}function Yt(t){if(t==null||t==="")return null;let e=String(t).trim().toUpperCase(),o=parseInt(e.replace(/[^0-9]/g,""),10)||0;return e.endsWith("G")?o*1024*1024*1024:e.endsWith("MB")||e.endsWith("M")?o*1024*1024:e.endsWith("KB")||e.endsWith("K")?o*1024:/^\d+$/.test(String(t).trim())?parseInt(String(t).trim(),10)||null:o>0?o*1024*1024:null}function tt(t={}){let e=v("--chunk-size","UPLOAD_SOURCEMAPS_CHUNK_SIZE")||t.chunkSize;return Yt(e)}async function Zt(){let{resolveUploadConfig:t}=await Promise.resolve().then(()=>(Qe(),Ze));return t(process.cwd(),v("--config","UPLOAD_SOURCEMAPS_CONFIG")||void 0)}async function Qt(t){let e=[t,Jt(t,".."),process.cwd()];for(let o of e)try{let r=await Xt(Vt(o,"package.json"),"utf-8"),a=JSON.parse(r);if(a.version&&typeof a.version=="string")return a.version.trim()}catch{continue}return null}async function rt(t,e){return t&&t!=="default"?t:await Qt(e)||"default"}var w=await Zt(),er=process.argv[2]==="build";function ot(t,e){return t||e===!0}async function tr(){let t=v("--project-id","PROJECT_ID")||w.projectId,e=v("--secret-key","SECRET_KEY")||w.secretKey,o=v("--auth-cert","MONITOR_AUTH_CERT")||w.authCert,r=(v("--endpoint","ENDPOINT")||w.endpoint||"").replace(/\/$/,"");if(!r)throw new Error("build subcommand requires endpoint (config file or env/args).");if(!o&&(!t||!e))throw new Error("build subcommand requires projectId+secretKey or authCert (config file or env/args).");let a=w.buildCommand||process.env.UPLOAD_SOURCEMAPS_BUILD_CMD||"npm run build",n=w.buildOutputDir||w.dir||v("--dir","DIR")||process.cwd(),s=T("--archive")||w.uploadAsArchive===!0,c=ot(T("--no-encrypt"),w.noEncrypt),u=v("--upload-mode","UPLOAD_MODE")||w.uploadMode||"mapOnly";u==="all"&&(u="backup");let i=await fe(n),l=!i.keepMapInOutput||T("--delete-after-upload")||T("-d")||w.deleteAfterUpload===!0,p=v("--build-id","BUILD_ID")||w.buildId||et(),f=await Xe(n);try{console.log("Step 1: Running build (forcing source map generation):",a),console.log("Build ID:",p);let[d,...g]=a.split(/\s+/);await new Promise((m,k)=>{qt(d,g,{stdio:"inherit",shell:!0,env:{...process.env,BUILD_SOURCEMAP:"1",SOURCEMAP:"1",MONITOR_BUILD_ID:p,VITE_MONITOR_BUILD_ID:p}}).on("exit",O=>O===0?m():k(new Error(`Build exited ${O}`)))}),console.log("Step 2: Uploading source maps...");let y=await rt(v("--release","RELEASE")||w.release,n);y!=="default"&&console.log("Release (from package.json or config):",y);let h=tt(w);if(s){let m={dir:n,endpoint:r,projectId:t,secretKey:e,authCert:o,release:y,buildId:p,deleteEvenOnFailure:!1,noEncrypt:c,uploadMode:u,keepMapInOutput:i.keepMapInOutput};(h?await le({...m,chunkSizeBytes:h},console):await ue(m,console)).uploaded===0&&console.log("No .map files in output. For Vite we patch config to force source map; check build output dir and README.")}else{let{ok:m,fail:k}=await ie({endpoint:r,projectId:t,secretKey:e,authCert:o,release:y,buildId:p,dir:n,deleteAfterUpload:l,deleteEvenOnFailure:!1},console);if(k>0)throw new Error("Upload had failures. Local .map files were NOT deleted. Fix errors and re-run.");m===0&&console.log("No .map files in output. For Vite we patch config to force source map; check build output dir and README.")}console.log("Done. Output dir:",n)}catch(d){throw console.error("Error:",d.message),console.error(l?"If the failure was during upload, local .map files may have been removed. Fix the issue and re-run.":"Local files were not modified. Fix the issue and re-run."),d}finally{await f.restore()}}if(er)try{await tr()}catch{process.exitCode=1}else{let t=v("--project-id","PROJECT_ID")||w.projectId,e=v("--secret-key","SECRET_KEY")||w.secretKey,o=v("--auth-cert","MONITOR_AUTH_CERT")||w.authCert,r=(v("--endpoint","ENDPOINT")||w.endpoint||"").replace(/\/$/,""),a=v("--dir","DIR")||w.dir||process.cwd(),n=await rt(v("--release","RELEASE")||w.release,a),s=v("--build-id","BUILD_ID")||w.buildId||et(),c=T("--archive")||w.uploadAsArchive===!0,u=ot(T("--no-encrypt"),w.noEncrypt),i=tt(w),l=v("--upload-mode","UPLOAD_MODE")||w.uploadMode||"mapOnly";l==="all"&&(l="backup");let p=await fe(a),f=!p.keepMapInOutput||T("--delete-after-upload")||T("-d")||w.deleteAfterUpload===!0;if(!r)console.error("Usage: ENDPOINT is required.");else if(!o&&(!t||!e))console.error("Usage: PROJECT_ID and SECRET_KEY are required, or use AUTH_CERT (certificate auth)."),console.error(""),console.error(" Arguments:"),console.error(" --project-id <id> Project ID"),console.error(" --secret-key <key> Secret Key"),console.error(" --endpoint <url> API base URL (e.g. https://api.example.com/monitorApi)"),console.error(" --auth-cert <cert> Certificate content (or MONITOR_AUTH_CERT); use with monitor.config.js, no secretKey needed"),console.error(" --release <tag> Release version (default: read from package.json)"),console.error(" --build-id <id> Build ID (default: auto-generated UUID)"),console.error(" --dir <path> Directory (default: cwd)"),console.error(" --delete-after-upload, -d Delete local .map after upload (from deployment output)"),console.error(" --archive Pack as .tar.gz (encrypted by default) \u2192 upload \u2192 server decrypts and extracts"),console.error(" --upload-mode <mode> mapOnly (default) | backup (code tar, .map \u4F9D\u9879\u76EE\u914D\u7F6E\u662F\u5426\u4FDD\u7559)"),console.error(" --chunk-size <size> With --archive: chunked upload (e.g. 1M, 5M), default 1MB, enables resumable and retry"),console.error(" --no-encrypt With --archive: upload plain tar.gz (certificate auth implies no-encrypt)"),console.error(" --config <path> Config file (default: monitor.config.js + .upload-sourcemaps.json)"),console.error(""),console.error(" Whether to delete .map after upload: inferred from project bundler config (Vite/Webpack etc.). Use -d to force delete."),process.exitCode=1;else{n!=="default"&&console.log("Release:",n),console.log("Build ID:",s);try{if(c){let d={dir:a,endpoint:r,projectId:t,secretKey:e,authCert:o,release:n,buildId:s,deleteEvenOnFailure:!1,noEncrypt:u,uploadMode:l,keepMapInOutput:p.keepMapInOutput};i?await le({...d,chunkSizeBytes:i},console):await ue(d,console)}else{let{ok:d,fail:g,deleted:y}=await ie({endpoint:r,projectId:t,secretKey:e,authCert:o,release:n,buildId:s,dir:a,deleteAfterUpload:f,deleteEvenOnFailure:f},console);y>0&&console.log("Deleted",y,"local .map file(s) from output."),g>0&&(console.error(f?"Upload had failures. Local .map files were still deleted (per project config). Fix errors and re-run to re-upload.":"Upload had failures. Local .map files were NOT deleted. Fix errors and re-run."),process.exitCode=1)}}catch(d){console.error("Error:",d.message),console.error(f?"Local .map files were still deleted. Fix the issue and re-run.":"Local files were not modified. Fix the issue and re-run."),process.exitCode=1}}}
2
+ var vt=Object.defineProperty;var te=(t,e)=>()=>(t&&(e=t(t=0)),e);var re=(t,e)=>{for(var o in e)vt(t,o,{get:e[o],enumerable:!0})};var de={};re(de,{extractProjectIdFromCert:()=>Mt,extractUploadKeyFromCert:()=>xt});function Mt(t){if(typeof t!="string")return"";let e=t.trim();if(e.startsWith(kt+"$"))return e.split("$")[1]||"";if(e.includes(Ue)){let o=e.match(/Project:\s*(\S+)/);return o?o[1]:""}return""}function xt(t){if(typeof t!="string"||!t.includes(Ue))return null;let e=t.match(/Upload-Key:\s*([0-9a-fA-F]{64})/);if(!e)return null;try{return Buffer.from(e[1],"hex")}catch{return null}}var kt,Ue,fe=te(()=>{kt="MC1",Ue="-----BEGIN MONITOR CERT-----"});var ne={};re(ne,{decryptArchive:()=>jt,encryptArchive:()=>Et,encryptArchiveWithKey:()=>Re});import{createCipheriv as Ct,createDecipheriv as St,createHash as It,randomBytes as Ot}from"crypto";function Fe(t,e){let o=`${t}:${e}`;return It("sha256").update(o,"utf8").digest()}function Et(t,e,o){let r=Fe(e,o);return Re(t,r)}function Re(t,e){if(!Buffer.isBuffer(e)||e.length!==32)throw new Error("Invalid key: must be 32-byte Buffer");let o=Ot(me),r=Ct(Te,e,o,{authTagLength:oe}),s=Buffer.concat([r.update(t),r.final()]),n=r.getAuthTag();return Buffer.concat([o,s,n])}function jt(t,e,o){if(t.length<me+oe)throw new Error("Invalid encrypted archive: too short");let r=Fe(e,o),s=t.subarray(0,me),n=t.subarray(t.length-oe),a=t.subarray(me,t.length-oe),c=St(Te,r,s,{authTagLength:oe});return c.setAuthTag(n),Buffer.concat([c.update(a),c.final()])}var Te,me,oe,se=te(()=>{Te="aes-256-gcm",me=12,oe=16});var ke={};re(ke,{DEFAULT_EXCLUDE_EXT:()=>_,UPLOAD_MODE_BACKUP:()=>he,UPLOAD_MODE_MAP_ONLY:()=>Rt,collectFiles:()=>be,createArchive:()=>H,createBackupArchive:()=>we,deleteMapFiles:()=>Xe,uploadArchive:()=>Nt});import{createRequire as At}from"module";import{readdir as _e,unlink as Be,readFile as Pt,mkdtemp as Le,rm as Ke,mkdir as Dt,copyFile as $e,writeFile as Ut}from"fs/promises";import{join as N,relative as Tt,dirname as Ne}from"path";import{createWriteStream as ze}from"fs";import{tmpdir as We}from"os";async function be(t,e=t,o={}){let{excludeExt:r=_,mapOnly:s=!1,excludeMap:n=!1}=typeof o=="object"&&o!==null?o:{},a=await _e(t,{withFileTypes:!0}),c=[];for(let u of a){let i=N(t,u.name),p=Tt(e,i).replace(/\\/g,"/");if(u.isDirectory()){let d=await be(i,e,o);c.push(...d)}else{if(s&&!u.name.endsWith(".map")||!s&&n&&u.name.endsWith(".map"))continue;if(!s&&r&&r.size>0){let d=(u.name.includes(".")?"."+u.name.split(".").pop():"").toLowerCase();if(r.has(d))continue}c.push({relativePath:p,fullPath:i})}}return c}async function H(t,e,o={},r=!0){let s={};o instanceof Set?(s={excludeExt:o,mapOnly:!1},r=arguments[3]!==void 0?arguments[3]:!0):typeof o=="object"&&o!==null&&(s=o);let n=await be(t,t,s),a=n.map(c=>c.relativePath);return a.length===0?0:new Promise((c,u)=>{let i=Je.create({gzip:r,cwd:t},a);i.on("error",u),i.pipe(ze(e)).on("close",()=>c(n.length)).on("error",u)})}async function we(t,e,o={}){let{excludeExt:r=_,includeMapInOutput:s=!0}=typeof o=="object"&&o!==null?o:{},n=await Le(N(We(),"upload-sourcemaps-backup-")),a=Ne(e),c=N(a,"project-code.tar.gz"),u=N(n,"project-code.tar.gz");try{let i=await H(t,u,{excludeExt:r||_,mapOnly:!1,excludeMap:!0},!0);if(i===0){let f=N(n,".keep");await Ut(f,""),await H(n,u,{excludeExt:new Set,mapOnly:!1},!0),await Be(f).catch(()=>{})}else await $e(u,c);let p=[];if(s){p=await be(t,t,{mapOnly:!0});for(let f of p){let m=N(n,f.relativePath);await Dt(Ne(m),{recursive:!0}),await $e(f.fullPath,m)}}let d=["project-code.tar.gz",...p.map(f=>f.relativePath)];return await $t(n,e,d,!0),{codeFileCount:i,mapFileCount:p.length,codeTarPath:i>0?c:void 0}}finally{await Ke(n,{recursive:!0,force:!0})}}function $t(t,e,o,r=!0){return o.length===0?Promise.resolve(0):new Promise((s,n)=>{let a=Je.create({gzip:r,cwd:t},o);a.on("error",n),a.pipe(ze(e)).on("close",()=>s(o.length)).on("error",n)})}async function Nt(t,e=console){let{dir:o,endpoint:r,projectId:s,secretKey:n,authCert:a,release:c,buildId:u,excludeExt:i,noEncrypt:p,uploadMode:d,keepMapInOutput:f}=t,m=!!a,{extractProjectIdFromCert:k,extractUploadKeyFromCert:v}=await Promise.resolve().then(()=>(fe(),de)),b=s||(m?k(a):""),g=m?v(a):null,A=await Le(N(We(),"upload-sourcemaps-")),j=N(A,"archive.tar.gz"),I=d===he,B=I?null:{excludeExt:i||_,mapOnly:!0};try{let R;if(I){let{codeFileCount:C,mapFileCount:E}=await we(o,j,{excludeExt:i||_,includeMapInOutput:f!==!1});R=Math.max(1,E),f!==!1?e.log("Created backup archive: project-code.tar.gz (",C," files for rollback) + ",E," .map file(s), uploading..."):e.log("Created backup archive: project-code.tar.gz (",C," files for rollback, no .map per project config), uploading...")}else R=await H(o,j,B,!0);if(R===0)return e.log("No files to pack (directory empty or only excluded). Skip upload."),{ok:!0,uploaded:0};let O=await Pt(j),P=!p&&(m?g!==null:!!(b&&n));if(P)if(g){let{encryptArchiveWithKey:C}=await Promise.resolve().then(()=>(se(),ne));O=C(O,g),I||e.log("Created tar.gz with",R,"file(s), encrypted with cert Upload-Key, uploading...")}else{let{encryptArchive:C}=await Promise.resolve().then(()=>(se(),ne));O=C(O,b,n),I||e.log("Created tar.gz with",R,"file(s), encrypted, uploading...")}else I||e.log("Created tar.gz with",R,"file(s), uploading...");let U="/sourcemaps/upload-archive",D=r.replace(/\/$/,""),T=D.endsWith(U)?D:D+U,h="----UploadSourceMaps"+Date.now().toString(36)+Math.random().toString(36).slice(2),l=`\r
3
+ `,F=Buffer.isBuffer(O)?O:Buffer.from(O),W=P?"archive.tar.gz.enc":"archive.tar.gz",J=Buffer.from([`--${h}${l}`,`Content-Disposition: form-data; name="projectId"${l}${l}`,b+l,`--${h}${l}`,`Content-Disposition: form-data; name="secretKey"${l}${l}`,(m?"":n||"")+l,`--${h}${l}`,`Content-Disposition: form-data; name="release"${l}${l}`,c+l,`--${h}${l}`,`Content-Disposition: form-data; name="buildId"${l}${l}`,(u||"")+l,`--${h}${l}`,`Content-Disposition: form-data; name="encrypted"${l}${l}`,(P?"1":"")+l,`--${h}${l}`,`Content-Disposition: form-data; name="uploadMode"${l}${l}`,(d||"")+l,`--${h}${l}`,`Content-Disposition: form-data; name="file"; filename="${W}"${l}`,`Content-Type: application/octet-stream${l}${l}`].join(""),"utf-8"),Y=Buffer.from(l+`--${h}--${l}`,"utf-8"),q=J.length+F.length+Y.length,Z=(q/1024/1024).toFixed(2),L=64*1024,ue=3e3,Q=0,ee=0,le=C=>{if(typeof process<"u"&&process.stderr&&process.stderr.write){let E=(Q/1024/1024).toFixed(2);process.stderr.write(`\r \u4E0A\u4F20\u8FDB\u5EA6 \u5F52\u6863 ${E}/${Z} MB (${C}%) `)}},pe=()=>{let C=q?Math.min(100,Math.round(Q/q*100)):0,E=Date.now();(C>=100||E-ee>=ue)&&(ee=E,le(C))},De=new ReadableStream({start(C){let E=M=>{C.enqueue(M),Q+=M.length,pe()};for(let M=0;M<J.length;M+=L)E(J.subarray(M,Math.min(M+L,J.length)));for(let M=0;M<F.length;M+=L)E(F.subarray(M,Math.min(M+L,F.length)));for(let M=0;M<Y.length;M+=L)E(Y.subarray(M,Math.min(M+L,Y.length)));C.close()}}),X={"X-Project-Id":b,"Content-Type":`multipart/form-data; boundary=${h}`,"Content-Length":String(q)};m?X["X-Auth-Cert"]=a:X["X-Secret-Key"]=n||"";let w=await fetch(T,{method:"POST",headers:X,body:De,duplex:"half"}),S=await w.text();if(!w.ok)throw new Error(`${w.status} ${S}`);typeof process<"u"&&process.stderr&&process.stderr.write&&(le(100),process.stderr.write(`
4
+ `));let V=JSON.parse(S||"{}");return e.log("Upload archive OK, server extracted and saved",V.uploaded,".map file(s)"),{ok:!0,uploaded:V.uploaded||0}}finally{await Ke(A,{recursive:!0,force:!0})}}async function Xe(t,e=[]){let o=await _e(t,{withFileTypes:!0});for(let r of o){let s=N(t,r.name);r.isDirectory()?await Xe(s,e):r.name.endsWith(".map")&&(await Be(s),e.push(s))}return e}var Ft,Je,_,Rt,he,ye=te(()=>{Ft=At(import.meta.url),Je=Ft("tar"),_=new Set([".png",".jpg",".jpeg",".gif",".svg",".webp",".ico",".bmp",".avif",".woff",".woff2",".ttf",".eot",".otf",".mp4",".webm",".ogg",".mp3",".wav",".m4a",".aac",".pdf",".doc",".docx",".xls",".xlsx"]),Rt="mapOnly",he="backup"});var He={};re(He,{uploadArchiveChunked:()=>Ht});import{readFile as _t,mkdtemp as Bt,rm as Lt}from"fs/promises";import{join as Ve}from"path";import{tmpdir as Kt}from"os";function Xt(t){return t.replace(/\/$/,"")}function ge(t,e){let o=Xt(t),r=e.startsWith("/")?e:`/${e}`;return o.endsWith(r)?o:o+r}async function Vt(t){return new Promise(e=>setTimeout(e,t))}async function Me(t,e,o,r=Wt){let s;for(let n=0;n<=r;n++)try{let a=await fetch(t,e),c=await a.text();if(!a.ok)throw new Error(`${a.status} ${c}`);return c?JSON.parse(c):{}}catch(a){if(s=a,n<r){let c=Jt*Math.pow(2,n);o.log?.(` Retry ${n+1}/${r} after ${c}ms: ${a.message}`),await Vt(c)}}throw s}async function Ht(t,e=console){let{dir:o,endpoint:r,projectId:s,secretKey:n,authCert:a,release:c,buildId:u,noEncrypt:i,chunkSizeBytes:p=zt,excludeExt:d,uploadMode:f,keepMapInOutput:m}=t,k=!!a,{extractProjectIdFromCert:v,extractUploadKeyFromCert:b}=await Promise.resolve().then(()=>(fe(),de)),g=s||(k?v(a):""),A=k?b(a):null,j=await Bt(Ve(Kt(),"upload-sourcemaps-chunked-")),I=Ve(j,"archive.tar.gz"),B=f===he,R=B?null:{excludeExt:d||_,mapOnly:!0};try{let O;if(B){let{codeFileCount:w,mapFileCount:S}=await we(o,I,{excludeExt:d||_,includeMapInOutput:m!==!1});O=Math.max(1,S),m!==!1?e.log?.("Created backup archive: project-code.tar.gz (",w," files for rollback) + ",S," .map file(s), uploading in chunks..."):e.log?.("Created backup archive: project-code.tar.gz (",w," files for rollback, no .map per project config), uploading in chunks...")}else O=await H(o,I,R,!0);if(O===0)return e.log?.("No files to pack. Skip upload."),{ok:!0,uploaded:0};let P=await _t(I),U=!i&&(k?A!==null:!!(g&&n));if(U){if(A){let{encryptArchiveWithKey:w}=await Promise.resolve().then(()=>(se(),ne));P=w(P,A)}else{let{encryptArchive:w}=await Promise.resolve().then(()=>(se(),ne));P=w(P,g,n)}B||e.log?.(`Created tar.gz with ${O} file(s), encrypted, uploading in chunks...`)}else B||e.log?.(`Created tar.gz with ${O} file(s), uploading in chunks...`);let D=P.length,T=Math.ceil(D/p),h={"Content-Type":"application/json"};k?h["X-Auth-Cert"]=a:(h["X-Project-Id"]=g,h["X-Secret-Key"]=n||"");let F=(await Me(ge(r,"/sourcemaps/upload-archive-multipart/init"),{method:"POST",headers:{...h,"Content-Type":"application/json"},body:JSON.stringify({projectId:g,secretKey:k?"":n||"",release:c,buildId:u||void 0,totalChunks:T,chunkSizeBytes:p,encrypted:U,uploadMode:f||void 0})},e)).uploadId;if(!F)throw new Error("Init did not return uploadId");let W=new Set;for(let w=0;w<T;w++)W.add(w);try{let w=await fetch(ge(r,"/sourcemaps/upload-archive-multipart/status")+`?uploadId=${encodeURIComponent(F)}`,{method:"GET",headers:h}),S=await w.text();if(w.ok&&S){let C=JSON.parse(S).receivedChunks||[];C.forEach(E=>W.delete(E)),C.length>0&&e.log?.(`Resume: ${C.length}/${T} chunks already uploaded`)}}catch{}let J=3e3,Z=(T-W.size)*p,L=(D/1024/1024).toFixed(2),ue=()=>{let w=D?Math.min(100,Math.round(Z/D*100)):0,S=(Z/1024/1024).toFixed(2);typeof process<"u"&&process.stderr&&process.stderr.write&&process.stderr.write(`\r \u4E0A\u4F20\u8FDB\u5EA6 \u5206\u7247 ${S}/${L} MB (${w}%) `)},Q=setInterval(ue,J),ee=Math.min(8,T),le=async w=>{let S=w*p,V=Math.min(S+p,D),C=V-S,E=P.subarray(S,V),M=new FormData;M.append("uploadId",F),M.append("index",String(w)),M.append("totalChunks",String(T)),M.append("chunk",new Blob([E]),`chunk-${w}`);let gt=ge(r,"/sourcemaps/upload-archive-multipart/chunk");await Me(gt,{method:"POST",headers:k?{"X-Auth-Cert":a}:{"X-Project-Id":g,"X-Secret-Key":n||""},body:M},e),Z+=C},pe=[...W].sort((w,S)=>w-S);for(let w=0;w<pe.length;w+=ee){let S=pe.slice(w,w+ee);await Promise.all(S.map(le))}clearInterval(Q),D>0&&typeof process<"u"&&process.stderr&&process.stderr.write&&(ue(),process.stderr.write(`
5
+ `));let X=(await Me(ge(r,"/sourcemaps/upload-archive-multipart/complete"),{method:"POST",headers:{...h,"Content-Type":"application/json"},body:JSON.stringify({uploadId:F})},e)).uploaded??0;return e.log?.("Chunked upload OK, server extracted and saved",X,".map file(s)"),{ok:!0,uploaded:X}}finally{await Lt(j,{recursive:!0,force:!0})}}var zt,Wt,Jt,Ge=te(()=>{ye();zt=1*1024*1024,Wt=3,Jt=1e3});var dt={};re(dt,{loadMonitorConfig:()=>lt,loadUploadSourcemapsJson:()=>pt,resolveUploadConfig:()=>lr});import{readFile as at}from"fs/promises";import{join as ct,resolve as ur}from"path";import{pathToFileURL as it}from"url";function ut(){try{return process.env.UPLOAD_ENV||process.env.NODE_ENV||"production"}catch{return"production"}}async function lt(t){let e=["monitor.config.js","monitor.config.cjs","monitor.config.mjs"];for(let o of e){let r=ct(t,o),s;try{s=await import(it(r).href)}catch{continue}let n=s.default;if(!n||typeof n!="object")return null;let a=ut(),c=n.common||{},u=n[a]||{},i={...c,...u},p=(i.endpoint||"").trim(),d=(i.apiPrefix||"").trim(),f=p+(d.startsWith("/")?d:d?"/"+d:"");return{projectId:i.projectId,secretKey:i.secretKey,authCert:i.authCert,endpoint:f||void 0,release:i.release||n.version,version:n.version}}return null}async function pt(t){try{let e=await at(ct(t,".upload-sourcemaps.json"),"utf-8");return JSON.parse(e)}catch{return{}}}async function lr(t,e){let o=null,r=null;if(e){let s=ur(t,e);if(e.endsWith(".json"))try{r=JSON.parse(await at(s,"utf-8"))}catch{r={}}else try{let a=(await import(it(s).href)).default;if(a&&typeof a=="object"&&(a.common||a.production||a.development)){let c=ut(),u=a.common||{},i=a[c]||{},p={...u,...i},d=(p.endpoint||"").trim(),f=(p.apiPrefix||"").trim();o={projectId:p.projectId,secretKey:p.secretKey,authCert:p.authCert,endpoint:d+(f.startsWith("/")?f:f?"/"+f:""),release:p.release||a.version}}else r=a||{}}catch{r={}}}else o=await lt(t),r=await pt(t);return{projectId:r.projectId??o?.projectId,secretKey:r.secretKey??o?.secretKey,authCert:r.authCert??o?.authCert,endpoint:r.endpoint??o?.endpoint,release:r.release??o?.release??o?.version,dir:r.dir,chunkSize:r.chunkSize,concurrency:r.concurrency,uploadAsArchive:r.uploadAsArchive,noEncrypt:r.noEncrypt,buildCommand:r.buildCommand,buildOutputDir:r.buildOutputDir,uploadMode:r.uploadMode==="backup"?"backup":"mapOnly"}}var ft=te(()=>{});import{readFile as mt,writeFile as pr,access as dr}from"fs/promises";import{resolve as fr,dirname as mr,join as ie}from"path";import{fileURLToPath as hr}from"url";import{randomUUID as ht}from"crypto";import{spawn as br}from"child_process";import{readdir as Gt,readFile as Yt,unlink as qt,stat as Zt}from"fs/promises";import{join as Qt,basename as ae}from"path";var er=3e3;async function tr(t,e=12){let o=[],r=0;async function s(){for(;r<t.length;){let a=r++;try{o[a]=await t[a]()}catch(c){o[a]=Promise.reject(c)}}}let n=Array.from({length:Math.min(e,t.length)},()=>s());return await Promise.all(n),o}async function qe(t,e=[]){let o;try{o=await Gt(t,{withFileTypes:!0})}catch(r){if(r?.code==="ENOENT")return e;throw r}for(let r of o){let s=Qt(t,r.name);r.isDirectory()?await qe(s,e):r.name.endsWith(".map")&&e.push(s)}return e}var Ye="/sourcemaps/upload";function rr(t){let e=t.replace(/\/$/,"");return e.endsWith(Ye)?e:e+Ye}async function or(t){let{endpoint:e,projectId:o,secretKey:r,authCert:s,release:n,buildId:a,filePath:c}=t,u=!!s,i=o||(u?(await Promise.resolve().then(()=>(fe(),de))).extractProjectIdFromCert(s):""),p=ae(c,".map"),d=await Yt(c),f=rr(e),m=new FormData;m.append("projectId",i),u||m.append("secretKey",r||""),m.append("release",n),a&&m.append("buildId",a),m.append("filename",p),m.append("file",new Blob([d]),ae(c));let v=await fetch(f,{method:"POST",headers:u?{"X-Project-Id":i,"X-Auth-Cert":s}:{"X-Project-Id":i,"X-Secret-Key":r||""},body:m}),b=await v.text();if(!v.ok)throw new Error(`${v.status} ${b}`);return JSON.parse(b||"{}")}async function xe(t,e=console){let{dir:o,endpoint:r,projectId:s,secretKey:n,authCert:a,release:c,buildId:u,deleteAfterUpload:i=!1,deleteEvenOnFailure:p=!1,concurrency:d=12}=t,f=await qe(o);if(f.length===0)return e.log("No .map files found in",o),{ok:0,fail:0,deleted:0};let m=Math.max(1,Math.min(64,Number(d)||12)),k=i&&p,v=f.length,b=await Promise.all(f.map(h=>Zt(h).then(l=>l.size))),g=b.reduce((h,l)=>h+l,0),A=(g/1024/1024).toFixed(2);e.log("Uploading",v,"source map(s) to",r,"release=",c,"concurrency=",m,i?k?"(will delete local .map even on failure)":"(will delete local .map only after all succeed)":"");let j=0,I=()=>{let h=g?Math.min(100,Math.round(j/g*100)):0,l=(j/1024/1024).toFixed(2);typeof process<"u"&&process.stderr&&process.stderr.write&&process.stderr.write(`\r \u4E0A\u4F20\u8FDB\u5EA6 ${l}/${A} MB (${h}%) `)},B=setInterval(I,er),R=f.map((h,l)=>()=>or({endpoint:r,projectId:s,secretKey:n,authCert:a,release:c,buildId:u,filePath:h}).then(()=>(j+=b[l],{ok:!0,name:ae(h)})).catch(F=>(j+=b[l],{ok:!1,name:ae(h),err:F}))),O=await tr(R,m);clearInterval(B),g>0&&process.stderr&&process.stderr.write&&(I(),process.stderr.write(`
6
+ `));let P=0,U=0;for(let h of O)h.ok?(e.log(" OK",h.name),P++):(e.error(" FAIL",h.name,h.err?.message||h.err),U++);let D=i&&(U===0||p),T=0;if(D&&f.length>0){for(let h of f)try{await qt(h),T++,e.log(" Deleted",ae(h))}catch(l){e.error(" Delete failed",h,l.message)}U>0&&p&&e.log("Deleted .map files despite upload failures. Fix errors and re-run to re-upload.")}else U>0&&!p&&e.log("Upload had failures. Local .map files were NOT deleted. Fix errors and re-run.");return{ok:P,fail:U,deleted:T}}async function Ce(t,e=console){let{uploadArchive:o,deleteMapFiles:r}=await Promise.resolve().then(()=>(ye(),ke)),{dir:s,endpoint:n,projectId:a,secretKey:c,authCert:u,release:i,buildId:p,deleteEvenOnFailure:d=!1,noEncrypt:f,uploadMode:m,excludeExt:k}=t;try{let{uploaded:v}=await o({dir:s,endpoint:n,projectId:a,secretKey:c,authCert:u,release:i,buildId:p,noEncrypt:f,uploadMode:m,excludeExt:k},e);if(v===0)return{uploaded:0,deleted:0};let b=await r(s,[]);return e.log("Deleted",b.length,"local .map file(s)."),{uploaded:v,deleted:b.length}}catch(v){if(d)try{let b=await r(s,[]);e.log("Deleted",b.length,"local .map file(s) despite upload failure.")}catch(b){e.error("Delete .map after upload failure failed:",b.message)}else e.error("Upload failed. Local .map files were NOT deleted.",v.message);throw v}}async function Se(t,e=console){let{uploadArchiveChunked:o}=await Promise.resolve().then(()=>(Ge(),He)),{deleteMapFiles:r}=await Promise.resolve().then(()=>(ye(),ke)),{dir:s,endpoint:n,projectId:a,secretKey:c,authCert:u,release:i,buildId:p,deleteEvenOnFailure:d=!1,noEncrypt:f,chunkSizeBytes:m,uploadMode:k,excludeExt:v}=t;try{let{uploaded:b}=await o({dir:s,endpoint:n,projectId:a,secretKey:c,authCert:u,release:i,buildId:p,noEncrypt:f,chunkSizeBytes:m,uploadMode:k,excludeExt:v},e);if(b===0)return{uploaded:0,deleted:0};let g=await r(s,[]);return e.log("Deleted",g.length,"local .map file(s)."),{uploaded:b,deleted:g.length}}catch(b){if(d)try{let g=await r(s,[]);e.log("Deleted",g.length,"local .map file(s) despite upload failure.")}catch(g){e.error("Delete .map after upload failure failed:",g.message)}else e.error("Upload failed. Local .map files were NOT deleted.",b.message);throw b}}import{readFile as Ie}from"fs/promises";import{join as $,resolve as ce}from"path";async function G(t){let e=t?ce(process.cwd(),t):process.cwd(),o=[process.cwd(),e,ce(e,".."),ce(e,"..",".."),ce(e,"..","..","..")],r=new Set;for(let s of o){let n=s&&ce(s);if(!(!n||r.has(n))){r.add(n);try{return await Ie($(n,"package.json"),"utf-8"),n}catch{continue}}}return null}async function K(t){try{return await Ie(t,"utf-8")}catch{return""}}async function Ze(t){let e=["vite.config.js","vite.config.mjs","vite.config.cjs","vite.config.ts"];for(let o of e){let r=await K($(t,o));if(r){if(/\bsourcemap\s*:\s*false\b/.test(r)||/build\s*:\s*\{[^}]*sourcemap\s*:\s*false/.test(r))return{emitsSourceMap:!1,bundler:"vite",keepMapInOutput:!1};if(/\bsourcemap\s*:\s*['"]inline['"]/.test(r)||/build\s*:\s*\{[\s\S]*?sourcemap\s*:\s*['"]inline['"]/.test(r))return{emitsSourceMap:!0,bundler:"vite",keepMapInOutput:!1};if(/\bsourcemap\s*:\s*true\b/.test(r)||/\bsourcemap\s*:\s*['"]hidden['"]/.test(r))return{emitsSourceMap:!0,bundler:"vite",keepMapInOutput:!0};if(/build\s*:\s*\{[\s\S]*?sourcemap\s*:\s*true/.test(r))return{emitsSourceMap:!0,bundler:"vite",keepMapInOutput:!0};if(/build\s*:\s*\{[\s\S]*?sourcemap\s*:\s*['"]hidden['"]/.test(r))return{emitsSourceMap:!0,bundler:"vite",keepMapInOutput:!0};if(/BUILD_SOURCEMAP|SOURCEMAP/.test(r)&&/build\s*:\s*\{[\s\S]*?sourcemap\s*:/.test(r))return{emitsSourceMap:!0,bundler:"vite",keepMapInOutput:!0};if(/build\s*:|\bdefineConfig\s*\(/.test(r))return{emitsSourceMap:!1,bundler:"vite",keepMapInOutput:!1}}}return null}async function Qe(t){let e=["webpack.config.js","webpack.config.cjs","webpack.config.mjs","webpack.config.ts","webpack.common.js","webpack.prod.js"];for(let o of e){let r=await K($(t,o));if(r){if(/\bdevtool\s*:\s*false\b/.test(r))return{emitsSourceMap:!1,bundler:"webpack",keepMapInOutput:!1};if(/\bdevtool\s*:\s*['"]source-map['"]/.test(r)||/\bdevtool\s*:\s*['"]hidden-source-map['"]/.test(r))return{emitsSourceMap:!0,bundler:"webpack",keepMapInOutput:!0};if(/\bdevtool\s*:\s*true\b/.test(r))return{emitsSourceMap:!0,bundler:"webpack",keepMapInOutput:!0}}}return null}async function et(t){let e=await K($(t,"vue.config.js"))||await K($(t,"vue.config.cjs"));return e?/\bproductionSourceMap\s*:\s*false\b/.test(e)?{emitsSourceMap:!1,bundler:"vue-cli",keepMapInOutput:!1}:/\bproductionSourceMap\s*:\s*true\b/.test(e)?{emitsSourceMap:!0,bundler:"vue-cli",keepMapInOutput:!0}:/\.devtool\s*\(\s*['"]source-map['"]\s*\)/.test(e)?{emitsSourceMap:!0,bundler:"vue-cli",keepMapInOutput:!0}:null:null}async function tt(t){let e=["rollup.config.js","rollup.config.mjs","rollup.config.cjs"];for(let o of e){let r=await K($(t,o));if(r){if(/\bsourcemap\s*:\s*false\b/.test(r))return{emitsSourceMap:!1,bundler:"rollup",keepMapInOutput:!1};if(/\bsourcemap\s*:\s*['"]inline['"]/.test(r))return{emitsSourceMap:!0,bundler:"rollup",keepMapInOutput:!1};if(/\bsourcemap\s*:\s*true\b/.test(r))return{emitsSourceMap:!0,bundler:"rollup",keepMapInOutput:!0}}}return null}async function rt(t){let e=["next.config.js","next.config.mjs","next.config.cjs","next.config.ts"];for(let o of e){let r=await K($(t,o));if(r){if(/\bproductionBrowserSourceMaps\s*:\s*true\b/.test(r))return{emitsSourceMap:!0,bundler:"next",keepMapInOutput:!0};if(/\bproductionBrowserSourceMaps\s*:\s*false\b/.test(r))return{emitsSourceMap:!1,bundler:"next",keepMapInOutput:!1};if(/module\.exports|next\s*\(/.test(r))return{emitsSourceMap:!1,bundler:"next",keepMapInOutput:!1}}}return null}async function ot(t){let e=await K($(t,"nuxt.config.js"))||await K($(t,"nuxt.config.ts"));return e?/\bsourcemap\s*:\s*false\b/.test(e)?{emitsSourceMap:!1,bundler:"nuxt",keepMapInOutput:!1}:/\bsourcemap\s*:\s*true\b/.test(e)?{emitsSourceMap:!0,bundler:"nuxt",keepMapInOutput:!0}:/\bsourcemap\s*:\s*\{[\s\S]*?\bclient\s*:\s*false\b/.test(e)||/\bsourcemap\s*:\s*\{[\s\S]*?\bserver\s*:\s*false\b/.test(e)?{emitsSourceMap:!1,bundler:"nuxt",keepMapInOutput:!1}:/\bsourcemap\s*:\s*\{[\s\S]*?\bclient\s*:\s*true\b/.test(e)?{emitsSourceMap:!0,bundler:"nuxt",keepMapInOutput:!0}:/\bsourcemap\s*:\s*\{[\s\S]*?\bserver\s*:\s*true[\s\S]*?\bclient\s*:\s*true\b/.test(e)?{emitsSourceMap:!0,bundler:"nuxt",keepMapInOutput:!0}:null:null}function nr(t){let e={...t.dependencies,...t.devDependencies};return!e||typeof e!="object"?null:e.vite||e.vite?"vite":e.next?"next":e.nuxt||e.nuxt3?"nuxt":e.vue&&(e["@vue/cli-service"]||e["vue-cli-service"])?"vue-cli":e.webpack||e["react-scripts"]||e["@angular/cli"]?"webpack":e.rollup?"rollup":e.parcel?"parcel":null}async function Oe(t){let e=await G(t);if(!e)return{emitsSourceMap:!0,keepMapInOutput:!1};let o={};try{let n=await Ie($(e,"package.json"),"utf-8");o=JSON.parse(n)}catch{return{emitsSourceMap:!0,keepMapInOutput:!1}}let r=nr(o),s=[()=>r==="vite"?Ze(e):null,()=>r==="next"?rt(e):null,()=>r==="nuxt"?ot(e):null,()=>r==="vue-cli"?et(e):null,()=>r==="webpack"?Qe(e):null,()=>r==="rollup"?tt(e):null,()=>Ze(e),()=>rt(e),()=>et(e),()=>Qe(e),()=>tt(e),()=>ot(e)];for(let n of s){let a=await n();if(a)return a}return{emitsSourceMap:!0,keepMapInOutput:!1}}import{readFile as je,writeFile as ve,unlink as sr}from"fs/promises";import{join as nt,resolve as ar}from"path";var Ae=".upload-sourcemaps.patch-backup.json";async function cr(t){try{return await je(t,"utf-8")}catch{return""}}function ir(t){let e={...t?.dependencies||{},...t?.devDependencies||{}};return e.vite||e.vite?"vite":e.next?"next":e.nuxt||e.nuxt3?"nuxt":e.vue&&(e["@vue/cli-service"]||e["vue-cli-service"])?"vue-cli":e.webpack||e["react-scripts"]||e["@angular/cli"]?"webpack":e.rollup?"rollup":null}var Ee=[{name:"vite",configNames:["vite.config.js","vite.config.mjs","vite.config.cjs","vite.config.ts"],needPatch:t=>/\bsourcemap\s*:\s*false\b/.test(t),patch:t=>t.replace(/(sourcemap\s*:\s*)false\b/,"$1true")},{name:"webpack",configNames:["webpack.config.js","webpack.config.cjs","webpack.config.mjs","webpack.config.ts","webpack.common.js","webpack.prod.js"],needPatch:t=>/\bdevtool\s*:\s*false\b/.test(t),patch:t=>t.replace(/(devtool\s*:\s*)false\b/,(e,o)=>`${o}'source-map'`)},{name:"vue-cli",configNames:["vue.config.js","vue.config.cjs"],needPatch:t=>/\bproductionSourceMap\s*:\s*false\b/.test(t),patch:t=>t.replace(/(productionSourceMap\s*:\s*)false\b/,"$1true")},{name:"rollup",configNames:["rollup.config.js","rollup.config.mjs","rollup.config.cjs"],needPatch:t=>/\bsourcemap\s*:\s*false\b/.test(t),patch:t=>t.replace(/(sourcemap\s*:\s*)false\b/,"$1true")},{name:"next",configNames:["next.config.js","next.config.mjs","next.config.cjs","next.config.ts"],needPatch:t=>/\bproductionBrowserSourceMaps\s*:\s*false\b/.test(t),patch:t=>t.replace(/(productionBrowserSourceMaps\s*:\s*)false\b/,"$1true")},{name:"nuxt",configNames:["nuxt.config.js","nuxt.config.ts"],needPatch:t=>!!(!/\bsourcemap\s*:/.test(t)||/\bsourcemap\s*:\s*false\b/.test(t)||/\bsourcemap\s*:\s*\{/.test(t)&&(/\bclient\s*:\s*false\b/.test(t)||/\bserver\s*:\s*false\b/.test(t)||!/\bclient\s*:\s*true\b/.test(t)||!/\bserver\s*:\s*true\b/.test(t))),patch:t=>{let e=t;if(!/\bsourcemap\s*:\s*\{[\s\S]*?\b(server|client)\s*:/.test(e)){let r=e.match(/(defineNuxtConfig\s*\(\s*)\{/);r&&(e=e.replace(/(defineNuxtConfig\s*\(\s*)\{/,`${r[1]}{
7
+ sourcemap: { server: true, client: true },`))}return/\bsourcemap\s*:\s*false\b/.test(e)&&(e=e.replace(/(sourcemap\s*:\s*)false\b/g,"$1true")),/\bclient\s*:\s*false\b/.test(e)&&(e=e.replace(/(\bclient\s*:\s*)false\b/g,"$1true")),/\bserver\s*:\s*false\b/.test(e)&&(e=e.replace(/(\bserver\s*:\s*)false\b/g,"$1true")),/\bsourcemap\s*:\s*\{[\s\S]*?\bserver\s*:\s*true\b/.test(e)&&!/\bclient\s*:/.test(e)&&(e=e.replace(/(\bserver\s*:\s*true)\b/,"$1, client: true")),/\bsourcemap\s*:\s*\{[\s\S]*?\bclient\s*:\s*true\b/.test(e)&&!/\bserver\s*:/.test(e)&&(e=e.replace(/(\bsourcemap\s*:\s*\{)/,"$1 server: true, ")),/\bsourcemap\s*:\s*\{\s*\}/.test(e)&&(e=e.replace(/\bsourcemap\s*:\s*\{\s*\}/,"sourcemap: { server: true, client: true }")),/\bsourcemap\s*:\s*\{/.test(e)&&(!/\bclient\s*:\s*true\b/.test(e)||!/\bserver\s*:\s*true\b/.test(e))&&(e=e.replace(/(\bsourcemap\s*:\s*\{)/,"$1 server: true, client: true, ")),e}}];async function Pe(t,e={}){let o=await G(t);if(!o)return{restore:async()=>{}};let r={};try{let a=await je(nt(o,"package.json"),"utf-8");r=JSON.parse(a)}catch{return{restore:async()=>{}}}let s=ir(r),n=s?[...Ee.filter(a=>a.name===s),...Ee.filter(a=>a.name!==s)]:Ee;for(let a of n)for(let c of a.configNames){let u=nt(o,c),i=await cr(u);if(!i||!a.needPatch(i))continue;let p=a.patch(i);if(await ve(u,p,"utf-8"),e.writeBackupTo){let d={configPath:ar(u),content:i};await ve(e.writeBackupTo,JSON.stringify(d),"utf-8")}return console.log("[upload-sourcemaps] Patched %s to enable source map (%s)",u,a.name),{patchedFile:u,restore:async()=>{try{await ve(u,i,"utf-8")}catch(d){console.error(`Restore ${a.name} config failed:`,d?.message||d)}}}}return{restore:async()=>{}}}async function st(t){try{let e=await je(t,"utf-8"),{configPath:o,content:r}=JSON.parse(e);return!o||r===void 0?!1:(await ve(o,r,"utf-8"),await sr(t),console.log("[upload-sourcemaps] Restored %s",o),!0)}catch{return!1}}var ao=mr(hr(import.meta.url));function x(t,e){let o=process.env[e];if(o)return o;let r=process.argv.indexOf(t);return r!==-1&&process.argv[r+1]?process.argv[r+1]:null}function z(t){return process.argv.includes(t)}function wr(t){if(t==null||t==="")return null;let e=String(t).trim().toUpperCase(),o=parseInt(e.replace(/[^0-9]/g,""),10)||0;return e.endsWith("G")?o*1024*1024*1024:e.endsWith("MB")||e.endsWith("M")?o*1024*1024:e.endsWith("KB")||e.endsWith("K")?o*1024:/^\d+$/.test(String(t).trim())?parseInt(String(t).trim(),10)||null:o>0?o*1024*1024:null}function bt(t={}){let e=x("--chunk-size","UPLOAD_SOURCEMAPS_CHUNK_SIZE")||t.chunkSize;return wr(e)}async function yr(){let{resolveUploadConfig:t}=await Promise.resolve().then(()=>(ft(),dt));return t(process.cwd(),x("--config","UPLOAD_SOURCEMAPS_CONFIG")||void 0)}async function gr(t){let e=[t,fr(t,".."),process.cwd()];for(let o of e)try{let r=await mt(ie(o,"package.json"),"utf-8"),s=JSON.parse(r);if(s.version&&typeof s.version=="string")return s.version.trim()}catch{continue}return null}async function wt(t,e){return t&&t!=="default"?t:await gr(e)||"default"}var y={};try{y=await yr()}catch{y={}}var vr=process.argv[2]==="build",kr=process.argv[2]==="patch",Mr=process.argv[2]==="restore",xr=process.argv[2]==="init";function yt(t,e){return t||e===!0}async function Cr(){let t=x("--project-id","PROJECT_ID")||y.projectId,e=x("--secret-key","SECRET_KEY")||y.secretKey,o=x("--auth-cert","MONITOR_AUTH_CERT")||y.authCert,r=(x("--endpoint","ENDPOINT")||y.endpoint||"").replace(/\/$/,"");if(!r)throw new Error("build subcommand requires endpoint (config file or env/args).");if(!o&&(!t||!e))throw new Error("build subcommand requires projectId+secretKey or authCert (config file or env/args).");let s=y.buildCommand||process.env.UPLOAD_SOURCEMAPS_BUILD_CMD||"npm run build",n=y.buildOutputDir||y.dir||x("--dir","DIR")||process.cwd(),a=z("--archive")||y.uploadAsArchive===!0,c=yt(z("--no-encrypt"),y.noEncrypt),u=x("--upload-mode","UPLOAD_MODE")||y.uploadMode||"mapOnly";u==="all"&&(u="backup");let i=await Oe(n),p=!i.keepMapInOutput||z("--delete-after-upload")||z("-d")||y.deleteAfterUpload===!0,d=x("--build-id","BUILD_ID")||y.buildId||ht(),f=await Pe(n);try{console.log("Step 1: Running build (forcing source map generation):",s),console.log("Build ID:",d);let[m,...k]=s.split(/\s+/);await new Promise((g,A)=>{br(m,k,{stdio:"inherit",shell:!0,env:{...process.env,BUILD_SOURCEMAP:"1",SOURCEMAP:"1",MONITOR_BUILD_ID:d,VITE_MONITOR_BUILD_ID:d}}).on("exit",I=>I===0?g():A(new Error(`Build exited ${I}`)))}),console.log("Step 2: Uploading source maps...");let v=await wt(x("--release","RELEASE")||y.release,n);v!=="default"&&console.log("Release (from package.json or config):",v);let b=bt(y);if(a){let g={dir:n,endpoint:r,projectId:t,secretKey:e,authCert:o,release:v,buildId:d,deleteEvenOnFailure:!1,noEncrypt:c,uploadMode:u,keepMapInOutput:i.keepMapInOutput};(b?await Se({...g,chunkSizeBytes:b},console):await Ce(g,console)).uploaded===0&&console.log("No .map files in output. For Vite we patch config to force source map; check build output dir and README.")}else{let g=Math.max(1,Math.min(64,parseInt(x("--concurrency","CONCURRENCY")||y.concurrency||"12",10)||12)),{ok:A,fail:j}=await xe({endpoint:r,projectId:t,secretKey:e,authCert:o,release:v,buildId:d,dir:n,deleteAfterUpload:p,deleteEvenOnFailure:!1,concurrency:g},console);if(j>0)throw new Error("Upload had failures. Local .map files were NOT deleted. Fix errors and re-run.");A===0&&console.log("No .map files in output. For Vite we patch config to force source map; check build output dir and README.")}console.log("Done. Output dir:",n)}catch(m){throw console.error("Error:",m.message),console.error(p?"If the failure was during upload, local .map files may have been removed. Fix the issue and re-run.":"Local files were not modified. Fix the issue and re-run."),m}finally{await f.restore()}}var Sr={"build:upload":"upload-sourcemaps build","build:upload:archive":"upload-sourcemaps build --archive"};async function Ir(){let t=process.cwd(),e=await G(t);if(!e){console.error("[upload-sourcemaps] Cannot find project root (no package.json from:",t,"). Run from project root."),process.exitCode=1;return}let o=ie(e,"package.json"),r;try{let c=await mt(o,"utf-8");r=JSON.parse(c)}catch(c){console.error("[upload-sourcemaps] Failed to read package.json:",c.message),process.exitCode=1;return}let s=r.scripts||{},n=0;for(let[c,u]of Object.entries(Sr))s[c]||(s[c]=u,n++);r.scripts=s;try{await pr(o,JSON.stringify(r,null,2)+`
8
+ `,"utf-8")}catch(c){console.error("[upload-sourcemaps] Failed to write package.json:",c.message),process.exitCode=1;return}let a=!1;try{await dr(ie(e,".upload-sourcemaps.json")),a=!0}catch{}console.log("[upload-sourcemaps] init ok. Added",n,"script(s) to package.json."),n>0&&(console.log(" Use: npm run build:upload (build + upload .map)"),console.log(" Or: npm run build:upload:archive (build + pack & upload, recommended)")),a||console.log(" Config: add monitor.config.js or .upload-sourcemaps.json (see README).")}if(xr)await Ir();else if(kr){let t=x("--dir","DIR")||y.dir||process.cwd(),e=await G(t);if(!e)console.error("[upload-sourcemaps] Could not find project root (no package.json from dir:",t,"). Fix --dir or run from project root."),process.exitCode=1;else{let o=ie(e,Ae),r=await Pe(t,{writeBackupTo:o});if(r.patchedFile){try{let{readFile:s}=await import("fs/promises"),n=await s(r.patchedFile,"utf-8"),a=/sourcemap\s*:\s*\{\s*[\s\S]*?server\s*:\s*true[\s\S]*?client\s*:\s*true/.test(n)||/sourcemap\s*:\s*\{\s*[\s\S]*?client\s*:\s*true[\s\S]*?server\s*:\s*true/.test(n),c=/sourcemap\s*:\s*true/.test(n);console.log("[upload-sourcemaps] Verified:",a?"top-level sourcemap":"(no top-level)",c?"vite.build.sourcemap=true":"")}catch{}console.log("Run your build, then run: upload-sourcemaps restore")}else console.log("No config needed patching (source map already enabled or unsupported bundler).")}}else if(Mr){let t=x("--backup","UPLOAD_SOURCEMAPS_PATCH_BACKUP")||ie(process.cwd(),Ae);await st(t)||(console.error("Restore failed or no backup file found at",t),process.exitCode=1)}else if(vr)try{await Cr()}catch{process.exitCode=1}else{let t=x("--project-id","PROJECT_ID")||y.projectId,e=x("--secret-key","SECRET_KEY")||y.secretKey,o=x("--auth-cert","MONITOR_AUTH_CERT")||y.authCert,r=(x("--endpoint","ENDPOINT")||y.endpoint||"").replace(/\/$/,""),s=x("--dir","DIR")||y.dir||process.cwd(),n=await wt(x("--release","RELEASE")||y.release,s),a=x("--build-id","BUILD_ID")||y.buildId||ht(),c=z("--archive")||y.uploadAsArchive===!0,u=yt(z("--no-encrypt"),y.noEncrypt),i=bt(y),p=Math.max(1,Math.min(64,parseInt(x("--concurrency","CONCURRENCY")||y.concurrency||"12",10)||12)),d=x("--upload-mode","UPLOAD_MODE")||y.uploadMode||"mapOnly";d==="all"&&(d="backup");let f=await Oe(s),m=!f.keepMapInOutput||z("--delete-after-upload")||z("-d")||y.deleteAfterUpload===!0;if(!r)console.error("Usage: ENDPOINT is required.");else if(!o&&(!t||!e))console.error("Usage: PROJECT_ID and SECRET_KEY are required, or use AUTH_CERT (certificate auth)."),console.error(""),console.error(" Arguments:"),console.error(" --project-id <id> Project ID"),console.error(" --secret-key <key> Secret Key"),console.error(" --endpoint <url> API base URL (e.g. https://api.example.com/monitorApi)"),console.error(" --auth-cert <cert> Certificate content (or MONITOR_AUTH_CERT); use with monitor.config.js, no secretKey needed"),console.error(" --release <tag> Release version (default: read from package.json)"),console.error(" --build-id <id> Build ID (default: auto-generated UUID)"),console.error(" --dir <path> Directory (default: cwd)"),console.error(" --concurrency <n> Max parallel uploads when not using --archive (default: 12)"),console.error(" --delete-after-upload, -d Delete local .map after upload (from deployment output)"),console.error(" --archive Pack as .tar.gz (encrypted by default) \u2192 upload \u2192 server decrypts and extracts"),console.error(" --upload-mode <mode> mapOnly (default) | backup (code tar, .map \u4F9D\u9879\u76EE\u914D\u7F6E\u662F\u5426\u4FDD\u7559)"),console.error(" --chunk-size <size> With --archive: chunked upload (e.g. 1M, 5M), default 1MB, enables resumable and retry"),console.error(" --no-encrypt With --archive: upload plain tar.gz (certificate auth implies no-encrypt)"),console.error(" --config <path> Config file (default: monitor.config.js + .upload-sourcemaps.json)"),console.error(""),console.error(" Subcommands:"),console.error(" init Add recommended scripts to package.json (build:upload, build:upload:archive)"),console.error(" build One-step: run build then upload source maps"),console.error(" patch / restore Temporarily enable source map in bundler config, then restore"),console.error(""),console.error(" Whether to delete .map after upload: inferred from project bundler config (Vite/Webpack etc.). Use -d to force delete."),process.exitCode=1;else{n!=="default"&&console.log("Release:",n),console.log("Build ID:",a);try{if(c){let k={dir:s,endpoint:r,projectId:t,secretKey:e,authCert:o,release:n,buildId:a,deleteEvenOnFailure:!1,noEncrypt:u,uploadMode:d,keepMapInOutput:f.keepMapInOutput};i?await Se({...k,chunkSizeBytes:i},console):await Ce(k,console)}else{let{ok:k,fail:v,deleted:b}=await xe({endpoint:r,projectId:t,secretKey:e,authCert:o,release:n,buildId:a,dir:s,deleteAfterUpload:m,deleteEvenOnFailure:m,concurrency:p},console);b>0&&console.log("Deleted",b,"local .map file(s) from output."),v>0&&(console.error(m?"Upload had failures. Local .map files were still deleted (per project config). Fix errors and re-run to re-upload.":"Upload had failures. Local .map files were NOT deleted. Fix errors and re-run."),process.exitCode=1)}}catch(k){console.error("Error:",k.message),console.error(m?"Local .map files were still deleted. Fix the issue and re-run.":"Local files were not modified. Fix the issue and re-run."),process.exitCode=1}}}
package/dist/upload.js CHANGED
@@ -1 +1,5 @@
1
- var ge=Object.defineProperty;var W=(t,e)=>()=>(t&&(e=t(t=0)),e);var R=(t,e)=>{for(var a in e)ge(t,a,{get:e[a],enumerable:!0})};var G={};R(G,{extractProjectIdFromCert:()=>Oe,extractUploadKeyFromCert:()=>Ae});function Oe(t){if(typeof t!="string")return"";let e=t.trim();if(e.startsWith(Ie+"$"))return e.split("$")[1]||"";if(e.includes(oe)){let a=e.match(/Project:\s*(\S+)/);return a?a[1]:""}return""}function Ae(t){if(typeof t!="string"||!t.includes(oe))return null;let e=t.match(/Upload-Key:\s*([0-9a-fA-F]{64})/);if(!e)return null;try{return Buffer.from(e[1],"hex")}catch{return null}}var Ie,oe,H=W(()=>{Ie="MC1",oe="-----BEGIN MONITOR CERT-----"});var B={};R(B,{decryptArchive:()=>Me,encryptArchive:()=>Te,encryptArchiveWithKey:()=>ie});import{createCipheriv as De,createDecipheriv as Fe,createHash as je,randomBytes as Pe}from"crypto";function ce(t,e){let a=`${t}:${e}`;return je("sha256").update(a,"utf8").digest()}function Te(t,e,a){let r=ce(e,a);return ie(t,r)}function ie(t,e){if(!Buffer.isBuffer(e)||e.length!==32)throw new Error("Invalid key: must be 32-byte Buffer");let a=Pe(J),r=De(ne,e,a,{authTagLength:_}),o=Buffer.concat([r.update(t),r.final()]),n=r.getAuthTag();return Buffer.concat([a,o,n])}function Me(t,e,a){if(t.length<J+_)throw new Error("Invalid encrypted archive: too short");let r=ce(e,a),o=t.subarray(0,J),n=t.subarray(t.length-_),c=t.subarray(J,t.length-_),i=Fe(ne,r,o,{authTagLength:_});return i.setAuthTag(n),Buffer.concat([i.update(c),i.final()])}var ne,J,_,N=W(()=>{ne="aes-256-gcm",J=12,_=16});var te={};R(te,{DEFAULT_EXCLUDE_EXT:()=>O,UPLOAD_MODE_BACKUP:()=>Y,UPLOAD_MODE_MAP_ONLY:()=>Be,collectFiles:()=>q,createArchive:()=>U,createBackupArchive:()=>V,deleteMapFiles:()=>we,uploadArchive:()=>ze});import{createRequire as Ke}from"module";import{readdir as de,unlink as ue,readFile as Se,mkdtemp as pe,rm as fe,mkdir as Ue,copyFile as le,writeFile as $e}from"fs/promises";import{join as I,relative as Le,dirname as se}from"path";import{createWriteStream as he}from"fs";import{tmpdir as me}from"os";async function q(t,e=t,a={}){let{excludeExt:r=O,mapOnly:o=!1,excludeMap:n=!1}=typeof a=="object"&&a!==null?a:{},c=await de(t,{withFileTypes:!0}),i=[];for(let l of c){let s=I(t,l.name),f=Le(e,s).replace(/\\/g,"/");if(l.isDirectory()){let h=await q(s,e,a);i.push(...h)}else{if(o&&!l.name.endsWith(".map")||!o&&n&&l.name.endsWith(".map"))continue;if(!o&&r&&r.size>0){let h=(l.name.includes(".")?"."+l.name.split(".").pop():"").toLowerCase();if(r.has(h))continue}i.push({relativePath:f,fullPath:s})}}return i}async function U(t,e,a={},r=!0){let o={};a instanceof Set?(o={excludeExt:a,mapOnly:!1},r=arguments[3]!==void 0?arguments[3]:!0):typeof a=="object"&&a!==null&&(o=a);let n=await q(t,t,o),c=n.map(i=>i.relativePath);return c.length===0?0:new Promise((i,l)=>{let s=ye.create({gzip:r,cwd:t},c);s.on("error",l),s.pipe(he(e)).on("close",()=>i(n.length)).on("error",l)})}async function V(t,e,a={}){let{excludeExt:r=O,includeMapInOutput:o=!0}=typeof a=="object"&&a!==null?a:{},n=await pe(I(me(),"upload-sourcemaps-backup-")),c=se(e),i=I(c,"project-code.tar.gz"),l=I(n,"project-code.tar.gz");try{let s=await U(t,l,{excludeExt:r||O,mapOnly:!1,excludeMap:!0},!0);if(s===0){let y=I(n,".keep");await $e(y,""),await U(n,l,{excludeExt:new Set,mapOnly:!1},!0),await ue(y).catch(()=>{})}else await le(l,i);let f=[];if(o){f=await q(t,t,{mapOnly:!0});for(let y of f){let d=I(n,y.relativePath);await Ue(se(d),{recursive:!0}),await le(y.fullPath,d)}}let h=["project-code.tar.gz",...f.map(y=>y.relativePath)];return await Ne(n,e,h,!0),{codeFileCount:s,mapFileCount:f.length,codeTarPath:s>0?i:void 0}}finally{await fe(n,{recursive:!0,force:!0})}}function Ne(t,e,a,r=!0){return a.length===0?Promise.resolve(0):new Promise((o,n)=>{let c=ye.create({gzip:r,cwd:t},a);c.on("error",n),c.pipe(he(e)).on("close",()=>o(a.length)).on("error",n)})}async function ze(t,e=console){let{dir:a,endpoint:r,projectId:o,secretKey:n,authCert:c,release:i,buildId:l,excludeExt:s,noEncrypt:f,uploadMode:h,keepMapInOutput:y}=t,d=!!c,{extractProjectIdFromCert:w,extractUploadKeyFromCert:x}=await Promise.resolve().then(()=>(H(),G)),u=o||(d?w(c):""),m=d?x(c):null,C=await pe(I(me(),"upload-sourcemaps-")),T=I(C,"archive.tar.gz"),b=h===Y,M=b?null:{excludeExt:s||O,mapOnly:!0};try{let A;if(b){let{codeFileCount:g,mapFileCount:p}=await V(a,T,{excludeExt:s||O,includeMapInOutput:y!==!1});A=Math.max(1,p),y!==!1?e.log("Created backup archive: project-code.tar.gz (",g," files for rollback) + ",p," .map file(s), uploading..."):e.log("Created backup archive: project-code.tar.gz (",g," files for rollback, no .map per project config), uploading...")}else A=await U(a,T,M,!0);if(A===0)return e.log("No files to pack (directory empty or only excluded). Skip upload."),{ok:!0,uploaded:0};let k=await Se(T),E=!f&&(d?m!==null:!!(u&&n));if(E)if(m){let{encryptArchiveWithKey:g}=await Promise.resolve().then(()=>(N(),B));k=g(k,m),b||e.log("Created tar.gz with",A,"file(s), encrypted with cert Upload-Key, uploading...")}else{let{encryptArchive:g}=await Promise.resolve().then(()=>(N(),B));k=g(k,u,n),b||e.log("Created tar.gz with",A,"file(s), encrypted, uploading...")}else b||e.log("Created tar.gz with",A,"file(s), uploading...");let $="/sourcemaps/upload-archive",K=r.replace(/\/$/,""),D=K.endsWith($)?K:K+$,v=new FormData;v.append("projectId",u),d||v.append("secretKey",n||""),v.append("release",i),l&&v.append("buildId",l),E&&v.append("encrypted","1"),h&&v.append("uploadMode",h),v.append("file",new Blob([k]),E?"archive.tar.gz.enc":"archive.tar.gz");let X={"X-Project-Id":u};d?X["X-Auth-Cert"]=c:X["X-Secret-Key"]=n||"";let F=await fetch(D,{method:"POST",headers:X,body:v}),S=await F.text();if(!F.ok)throw new Error(`${F.status} ${S}`);let ee=JSON.parse(S||"{}");return e.log("Upload archive OK, server extracted and saved",ee.uploaded,".map file(s)"),{ok:!0,uploaded:ee.uploaded||0}}finally{await fe(C,{recursive:!0,force:!0})}}async function we(t,e=[]){let a=await de(t,{withFileTypes:!0});for(let r of a){let o=I(t,r.name);r.isDirectory()?await we(o,e):r.name.endsWith(".map")&&(await ue(o),e.push(o))}return e}var _e,ye,O,Be,Y,Z=W(()=>{_e=Ke(import.meta.url),ye=_e("tar"),O=new Set([".png",".jpg",".jpeg",".gif",".svg",".webp",".ico",".bmp",".avif",".woff",".woff2",".ttf",".eot",".otf",".mp4",".webm",".ogg",".mp3",".wav",".m4a",".aac",".pdf",".doc",".docx",".xls",".xlsx"]),Be="mapOnly",Y="backup"});var ve={};R(ve,{uploadArchiveChunked:()=>Ze});import{readFile as Xe,mkdtemp as We,rm as Re}from"fs/promises";import{join as xe}from"path";import{tmpdir as Ge}from"os";function qe(t){return t.replace(/\/$/,"")}function Q(t,e){let a=qe(t),r=e.startsWith("/")?e:`/${e}`;return a.endsWith(r)?a:a+r}async function Ve(t){return new Promise(e=>setTimeout(e,t))}async function ae(t,e,a,r=Je){let o;for(let n=0;n<=r;n++)try{let c=await fetch(t,e),i=await c.text();if(!c.ok)throw new Error(`${c.status} ${i}`);return i?JSON.parse(i):{}}catch(c){if(o=c,n<r){let i=Ye*Math.pow(2,n);a.log?.(` Retry ${n+1}/${r} after ${i}ms: ${c.message}`),await Ve(i)}}throw o}async function Ze(t,e=console){let{dir:a,endpoint:r,projectId:o,secretKey:n,authCert:c,release:i,buildId:l,noEncrypt:s,chunkSizeBytes:f=He,excludeExt:h,uploadMode:y,keepMapInOutput:d}=t,w=!!c,{extractProjectIdFromCert:x,extractUploadKeyFromCert:u}=await Promise.resolve().then(()=>(H(),G)),m=o||(w?x(c):""),C=w?u(c):null,T=await We(xe(Ge(),"upload-sourcemaps-chunked-")),b=xe(T,"archive.tar.gz"),M=y===Y,A=M?null:{excludeExt:h||O,mapOnly:!0};try{let k;if(M){let{codeFileCount:p,mapFileCount:j}=await V(a,b,{excludeExt:h||O,includeMapInOutput:d!==!1});k=Math.max(1,j),d!==!1?e.log?.("Created backup archive: project-code.tar.gz (",p," files for rollback) + ",j," .map file(s), uploading in chunks..."):e.log?.("Created backup archive: project-code.tar.gz (",p," files for rollback, no .map per project config), uploading in chunks...")}else k=await U(a,b,A,!0);if(k===0)return e.log?.("No files to pack. Skip upload."),{ok:!0,uploaded:0};let E=await Xe(b),$=!s&&(w?C!==null:!!(m&&n));if($){if(C){let{encryptArchiveWithKey:p}=await Promise.resolve().then(()=>(N(),B));E=p(E,C)}else{let{encryptArchive:p}=await Promise.resolve().then(()=>(N(),B));E=p(E,m,n)}M||e.log?.(`Created tar.gz with ${k} file(s), encrypted, uploading in chunks...`)}else M||e.log?.(`Created tar.gz with ${k} file(s), uploading in chunks...`);let K=E.length,D=Math.ceil(K/f),v={"Content-Type":"application/json"};w?v["X-Auth-Cert"]=c:(v["X-Project-Id"]=m,v["X-Secret-Key"]=n||"");let F=(await ae(Q(r,"/sourcemaps/upload-archive-multipart/init"),{method:"POST",headers:{...v,"Content-Type":"application/json"},body:JSON.stringify({projectId:m,secretKey:w?"":n||"",release:i,buildId:l||void 0,totalChunks:D,chunkSizeBytes:f,encrypted:$,uploadMode:y||void 0})},e)).uploadId;if(!F)throw new Error("Init did not return uploadId");let S=new Set;for(let p=0;p<D;p++)S.add(p);try{let p=await fetch(Q(r,"/sourcemaps/upload-archive-multipart/status")+`?uploadId=${encodeURIComponent(F)}`,{method:"GET",headers:v}),j=await p.text();if(p.ok&&j){let L=JSON.parse(j).receivedChunks||[];L.forEach(P=>S.delete(P)),L.length>0&&e.log?.(`Resume: ${L.length}/${D} chunks already uploaded`)}}catch{}for(let p=0;p<D;p++){if(!S.has(p))continue;let j=p*f,re=Math.min(j+f,K),L=E.subarray(j,re),P=new FormData;P.append("uploadId",F),P.append("index",String(p)),P.append("totalChunks",String(D)),P.append("chunk",new Blob([L]),`chunk-${p}`);let be=Q(r,"/sourcemaps/upload-archive-multipart/chunk");await ae(be,{method:"POST",headers:w?{"X-Auth-Cert":c}:{"X-Project-Id":m,"X-Secret-Key":n||""},body:P},e),e.log?.(` Chunk ${p+1}/${D} OK`)}let g=(await ae(Q(r,"/sourcemaps/upload-archive-multipart/complete"),{method:"POST",headers:{...v,"Content-Type":"application/json"},body:JSON.stringify({uploadId:F})},e)).uploaded??0;return e.log?.("Chunked upload OK, server extracted and saved",g,".map file(s)"),{ok:!0,uploaded:g}}finally{await Re(T,{recursive:!0,force:!0})}}var He,Je,Ye,ke=W(()=>{Z();He=1*1024*1024,Je=3,Ye=1e3});import{readdir as Qe,readFile as et,unlink as tt}from"fs/promises";import{join as at,basename as z}from"path";async function Ee(t,e=[]){let a;try{a=await Qe(t,{withFileTypes:!0})}catch(r){if(r?.code==="ENOENT")return e;throw r}for(let r of a){let o=at(t,r.name);r.isDirectory()?await Ee(o,e):r.name.endsWith(".map")&&e.push(o)}return e}var Ce="/sourcemaps/upload";function rt(t){let e=t.replace(/\/$/,"");return e.endsWith(Ce)?e:e+Ce}async function ot(t){let{endpoint:e,projectId:a,secretKey:r,authCert:o,release:n,buildId:c,filePath:i}=t,l=!!o,s=a||(l?(await Promise.resolve().then(()=>(H(),G))).extractProjectIdFromCert(o):""),f=z(i,".map"),h=await et(i),y=rt(e),d=new FormData;d.append("projectId",s),l||d.append("secretKey",r||""),d.append("release",n),c&&d.append("buildId",c),d.append("filename",f),d.append("file",new Blob([h]),z(i));let x=await fetch(y,{method:"POST",headers:l?{"X-Project-Id":s,"X-Auth-Cert":o}:{"X-Project-Id":s,"X-Secret-Key":r||""},body:d}),u=await x.text();if(!x.ok)throw new Error(`${x.status} ${u}`);return JSON.parse(u||"{}")}async function vt(t,e=console){let{dir:a,endpoint:r,projectId:o,secretKey:n,authCert:c,release:i,buildId:l,deleteAfterUpload:s=!1,deleteEvenOnFailure:f=!1}=t,h=await Ee(a);if(h.length===0)return e.log("No .map files found in",a),{ok:0,fail:0,deleted:0};let y=s&&f;e.log("Uploading",h.length,"source map(s) to",r,"release=",i,s?y?"(will delete local .map even on failure)":"(will delete local .map only after all succeed)":"");let d=0,w=0;for(let m of h)try{await ot({endpoint:r,projectId:o,secretKey:n,authCert:c,release:i,buildId:l,filePath:m}),e.log(" OK",z(m)),d++}catch(C){e.error(" FAIL",z(m),C.message),w++}let x=s&&(w===0||f),u=0;if(x&&h.length>0){for(let m of h)try{await tt(m),u++,e.log(" Deleted",z(m))}catch(C){e.error(" Delete failed",m,C.message)}w>0&&f&&e.log("Deleted .map files despite upload failures. Fix errors and re-run to re-upload.")}else w>0&&!f&&e.log("Upload had failures. Local .map files were NOT deleted. Fix errors and re-run.");return{ok:d,fail:w,deleted:u}}async function kt(t,e=console){let{uploadArchive:a,deleteMapFiles:r}=await Promise.resolve().then(()=>(Z(),te)),{dir:o,endpoint:n,projectId:c,secretKey:i,authCert:l,release:s,buildId:f,deleteEvenOnFailure:h=!1,noEncrypt:y,uploadMode:d,excludeExt:w}=t;try{let{uploaded:x}=await a({dir:o,endpoint:n,projectId:c,secretKey:i,authCert:l,release:s,buildId:f,noEncrypt:y,uploadMode:d,excludeExt:w},e);if(x===0)return{uploaded:0,deleted:0};let u=await r(o,[]);return e.log("Deleted",u.length,"local .map file(s)."),{uploaded:x,deleted:u.length}}catch(x){if(h)try{let u=await r(o,[]);e.log("Deleted",u.length,"local .map file(s) despite upload failure.")}catch(u){e.error("Delete .map after upload failure failed:",u.message)}else e.error("Upload failed. Local .map files were NOT deleted.",x.message);throw x}}async function Ct(t,e=console){let{uploadArchiveChunked:a}=await Promise.resolve().then(()=>(ke(),ve)),{deleteMapFiles:r}=await Promise.resolve().then(()=>(Z(),te)),{dir:o,endpoint:n,projectId:c,secretKey:i,authCert:l,release:s,buildId:f,deleteEvenOnFailure:h=!1,noEncrypt:y,chunkSizeBytes:d,uploadMode:w,excludeExt:x}=t;try{let{uploaded:u}=await a({dir:o,endpoint:n,projectId:c,secretKey:i,authCert:l,release:s,buildId:f,noEncrypt:y,chunkSizeBytes:d,uploadMode:w,excludeExt:x},e);if(u===0)return{uploaded:0,deleted:0};let m=await r(o,[]);return e.log("Deleted",m.length,"local .map file(s)."),{uploaded:u,deleted:m.length}}catch(u){if(h)try{let m=await r(o,[]);e.log("Deleted",m.length,"local .map file(s) despite upload failure.")}catch(m){e.error("Delete .map after upload failure failed:",m.message)}else e.error("Upload failed. Local .map files were NOT deleted.",u.message);throw u}}export{Ee as findMapFiles,vt as uploadAll,Ct as uploadArchiveChunkedThenDelete,kt as uploadArchiveThenDelete,ot as uploadOne};
1
+ var je=Object.defineProperty;var re=(t,e)=>()=>(t&&(e=t(t=0)),e);var oe=(t,e)=>{for(var r in e)je(t,r,{get:e[r],enumerable:!0})};var ae={};oe(ae,{extractProjectIdFromCert:()=>Ue,extractUploadKeyFromCert:()=>Le});function Ue(t){if(typeof t!="string")return"";let e=t.trim();if(e.startsWith(Be+"$"))return e.split("$")[1]||"";if(e.includes(me)){let r=e.match(/Project:\s*(\S+)/);return r?r[1]:""}return""}function Le(t){if(typeof t!="string"||!t.includes(me))return null;let e=t.match(/Upload-Key:\s*([0-9a-fA-F]{64})/);if(!e)return null;try{return Buffer.from(e[1],"hex")}catch{return null}}var Be,me,ne=re(()=>{Be="MC1",me="-----BEGIN MONITOR CERT-----"});var q={};oe(q,{decryptArchive:()=>Xe,encryptArchive:()=>Ne,encryptArchiveWithKey:()=>xe});import{createCipheriv as Ke,createDecipheriv as _e,createHash as ze,randomBytes as Re}from"crypto";function we(t,e){let r=`${t}:${e}`;return ze("sha256").update(r,"utf8").digest()}function Ne(t,e,r){let o=we(e,r);return xe(t,o)}function xe(t,e){if(!Buffer.isBuffer(e)||e.length!==32)throw new Error("Invalid key: must be 32-byte Buffer");let r=Re(se),o=Ke(ye,e,r,{authTagLength:V}),a=Buffer.concat([o.update(t),o.final()]),n=o.getAuthTag();return Buffer.concat([r,a,n])}function Xe(t,e,r){if(t.length<se+V)throw new Error("Invalid encrypted archive: too short");let o=we(e,r),a=t.subarray(0,se),n=t.subarray(t.length-V),s=t.subarray(se,t.length-V),i=_e(ye,o,a,{authTagLength:V});return i.setAuthTag(n),Buffer.concat([i.update(s),i.final()])}var ye,se,V,Y=re(()=>{ye="aes-256-gcm",se=12,V=16});var pe={};oe(pe,{DEFAULT_EXCLUDE_EXT:()=>j,UPLOAD_MODE_BACKUP:()=>ce,UPLOAD_MODE_MAP_ONLY:()=>Ye,collectFiles:()=>ie,createArchive:()=>N,createBackupArchive:()=>le,deleteMapFiles:()=>Oe,uploadArchive:()=>Qe});import{createRequire as We}from"module";import{readdir as Ce,unlink as ke,readFile as Ge,mkdtemp as $e,rm as be,mkdir as He,copyFile as ve,writeFile as Je}from"fs/promises";import{join as T,relative as Ve,dirname as ge}from"path";import{createWriteStream as Ee}from"fs";import{tmpdir as Me}from"os";async function ie(t,e=t,r={}){let{excludeExt:o=j,mapOnly:a=!1,excludeMap:n=!1}=typeof r=="object"&&r!==null?r:{},s=await Ce(t,{withFileTypes:!0}),i=[];for(let u of s){let p=T(t,u.name),y=Ve(e,p).replace(/\\/g,"/");if(u.isDirectory()){let g=await ie(p,e,r);i.push(...g)}else{if(a&&!u.name.endsWith(".map")||!a&&n&&u.name.endsWith(".map"))continue;if(!a&&o&&o.size>0){let g=(u.name.includes(".")?"."+u.name.split(".").pop():"").toLowerCase();if(o.has(g))continue}i.push({relativePath:y,fullPath:p})}}return i}async function N(t,e,r={},o=!0){let a={};r instanceof Set?(a={excludeExt:r,mapOnly:!1},o=arguments[3]!==void 0?arguments[3]:!0):typeof r=="object"&&r!==null&&(a=r);let n=await ie(t,t,a),s=n.map(i=>i.relativePath);return s.length===0?0:new Promise((i,u)=>{let p=Ie.create({gzip:o,cwd:t},s);p.on("error",u),p.pipe(Ee(e)).on("close",()=>i(n.length)).on("error",u)})}async function le(t,e,r={}){let{excludeExt:o=j,includeMapInOutput:a=!0}=typeof r=="object"&&r!==null?r:{},n=await $e(T(Me(),"upload-sourcemaps-backup-")),s=ge(e),i=T(s,"project-code.tar.gz"),u=T(n,"project-code.tar.gz");try{let p=await N(t,u,{excludeExt:o||j,mapOnly:!1,excludeMap:!0},!0);if(p===0){let f=T(n,".keep");await Je(f,""),await N(n,u,{excludeExt:new Set,mapOnly:!1},!0),await ke(f).catch(()=>{})}else await ve(u,i);let y=[];if(a){y=await ie(t,t,{mapOnly:!0});for(let f of y){let h=T(n,f.relativePath);await He(ge(h),{recursive:!0}),await ve(f.fullPath,h)}}let g=["project-code.tar.gz",...y.map(f=>f.relativePath)];return await Ze(n,e,g,!0),{codeFileCount:p,mapFileCount:y.length,codeTarPath:p>0?i:void 0}}finally{await be(n,{recursive:!0,force:!0})}}function Ze(t,e,r,o=!0){return r.length===0?Promise.resolve(0):new Promise((a,n)=>{let s=Ie.create({gzip:o,cwd:t},r);s.on("error",n),s.pipe(Ee(e)).on("close",()=>a(r.length)).on("error",n)})}async function Qe(t,e=console){let{dir:r,endpoint:o,projectId:a,secretKey:n,authCert:s,release:i,buildId:u,excludeExt:p,noEncrypt:y,uploadMode:g,keepMapInOutput:f}=t,h=!!s,{extractProjectIdFromCert:$,extractUploadKeyFromCert:k}=await Promise.resolve().then(()=>(ne(),ae)),m=a||(h?$(s):""),x=h?k(s):null,B=await $e(T(Me(),"upload-sourcemaps-")),S=T(B,"archive.tar.gz"),I=g===ce,U=I?null:{excludeExt:p||j,mapOnly:!0};try{let F;if(I){let{codeFileCount:v,mapFileCount:E}=await le(r,S,{excludeExt:p||j,includeMapInOutput:f!==!1});F=Math.max(1,E),f!==!1?e.log("Created backup archive: project-code.tar.gz (",v," files for rollback) + ",E," .map file(s), uploading..."):e.log("Created backup archive: project-code.tar.gz (",v," files for rollback, no .map per project config), uploading...")}else F=await N(r,S,U,!0);if(F===0)return e.log("No files to pack (directory empty or only excluded). Skip upload."),{ok:!0,uploaded:0};let b=await Ge(S),M=!y&&(h?x!==null:!!(m&&n));if(M)if(x){let{encryptArchiveWithKey:v}=await Promise.resolve().then(()=>(Y(),q));b=v(b,x),I||e.log("Created tar.gz with",F,"file(s), encrypted with cert Upload-Key, uploading...")}else{let{encryptArchive:v}=await Promise.resolve().then(()=>(Y(),q));b=v(b,m,n),I||e.log("Created tar.gz with",F,"file(s), encrypted, uploading...")}else I||e.log("Created tar.gz with",F,"file(s), uploading...");let D="/sourcemaps/upload-archive",O=o.replace(/\/$/,""),P=O.endsWith(D)?O:O+D,l="----UploadSourceMaps"+Date.now().toString(36)+Math.random().toString(36).slice(2),c=`\r
2
+ `,A=Buffer.isBuffer(b)?b:Buffer.from(b),K=M?"archive.tar.gz.enc":"archive.tar.gz",_=Buffer.from([`--${l}${c}`,`Content-Disposition: form-data; name="projectId"${c}${c}`,m+c,`--${l}${c}`,`Content-Disposition: form-data; name="secretKey"${c}${c}`,(h?"":n||"")+c,`--${l}${c}`,`Content-Disposition: form-data; name="release"${c}${c}`,i+c,`--${l}${c}`,`Content-Disposition: form-data; name="buildId"${c}${c}`,(u||"")+c,`--${l}${c}`,`Content-Disposition: form-data; name="encrypted"${c}${c}`,(M?"1":"")+c,`--${l}${c}`,`Content-Disposition: form-data; name="uploadMode"${c}${c}`,(g||"")+c,`--${l}${c}`,`Content-Disposition: form-data; name="file"; filename="${K}"${c}`,`Content-Type: application/octet-stream${c}${c}`].join(""),"utf-8"),X=Buffer.from(c+`--${l}--${c}`,"utf-8"),W=_.length+A.length+X.length,G=(W/1024/1024).toFixed(2),L=64*1024,Q=3e3,H=0,J=0,ee=v=>{if(typeof process<"u"&&process.stderr&&process.stderr.write){let E=(H/1024/1024).toFixed(2);process.stderr.write(`\r \u4E0A\u4F20\u8FDB\u5EA6 \u5F52\u6863 ${E}/${G} MB (${v}%) `)}},te=()=>{let v=W?Math.min(100,Math.round(H/W*100)):0,E=Date.now();(v>=100||E-J>=Q)&&(J=E,ee(v))},he=new ReadableStream({start(v){let E=w=>{v.enqueue(w),H+=w.length,te()};for(let w=0;w<_.length;w+=L)E(_.subarray(w,Math.min(w+L,_.length)));for(let w=0;w<A.length;w+=L)E(A.subarray(w,Math.min(w+L,A.length)));for(let w=0;w<X.length;w+=L)E(X.subarray(w,Math.min(w+L,X.length)));v.close()}}),z={"X-Project-Id":m,"Content-Type":`multipart/form-data; boundary=${l}`,"Content-Length":String(W)};h?z["X-Auth-Cert"]=s:z["X-Secret-Key"]=n||"";let d=await fetch(P,{method:"POST",headers:z,body:he,duplex:"half"}),C=await d.text();if(!d.ok)throw new Error(`${d.status} ${C}`);typeof process<"u"&&process.stderr&&process.stderr.write&&(ee(100),process.stderr.write(`
3
+ `));let R=JSON.parse(C||"{}");return e.log("Upload archive OK, server extracted and saved",R.uploaded,".map file(s)"),{ok:!0,uploaded:R.uploaded||0}}finally{await be(B,{recursive:!0,force:!0})}}async function Oe(t,e=[]){let r=await Ce(t,{withFileTypes:!0});for(let o of r){let a=T(t,o.name);o.isDirectory()?await Oe(a,e):o.name.endsWith(".map")&&(await ke(a),e.push(a))}return e}var qe,Ie,j,Ye,ce,de=re(()=>{qe=We(import.meta.url),Ie=qe("tar"),j=new Set([".png",".jpg",".jpeg",".gif",".svg",".webp",".ico",".bmp",".avif",".woff",".woff2",".ttf",".eot",".otf",".mp4",".webm",".ogg",".mp3",".wav",".m4a",".aac",".pdf",".doc",".docx",".xls",".xlsx"]),Ye="mapOnly",ce="backup"});var De={};oe(De,{uploadArchiveChunked:()=>lt});import{readFile as et,mkdtemp as tt,rm as rt}from"fs/promises";import{join as Se}from"path";import{tmpdir as ot}from"os";function ct(t){return t.replace(/\/$/,"")}function ue(t,e){let r=ct(t),o=e.startsWith("/")?e:`/${e}`;return r.endsWith(o)?r:r+o}async function it(t){return new Promise(e=>setTimeout(e,t))}async function fe(t,e,r,o=nt){let a;for(let n=0;n<=o;n++)try{let s=await fetch(t,e),i=await s.text();if(!s.ok)throw new Error(`${s.status} ${i}`);return i?JSON.parse(i):{}}catch(s){if(a=s,n<o){let i=st*Math.pow(2,n);r.log?.(` Retry ${n+1}/${o} after ${i}ms: ${s.message}`),await it(i)}}throw a}async function lt(t,e=console){let{dir:r,endpoint:o,projectId:a,secretKey:n,authCert:s,release:i,buildId:u,noEncrypt:p,chunkSizeBytes:y=at,excludeExt:g,uploadMode:f,keepMapInOutput:h}=t,$=!!s,{extractProjectIdFromCert:k,extractUploadKeyFromCert:m}=await Promise.resolve().then(()=>(ne(),ae)),x=a||($?k(s):""),B=$?m(s):null,S=await tt(Se(ot(),"upload-sourcemaps-chunked-")),I=Se(S,"archive.tar.gz"),U=f===ce,F=U?null:{excludeExt:g||j,mapOnly:!0};try{let b;if(U){let{codeFileCount:d,mapFileCount:C}=await le(r,I,{excludeExt:g||j,includeMapInOutput:h!==!1});b=Math.max(1,C),h!==!1?e.log?.("Created backup archive: project-code.tar.gz (",d," files for rollback) + ",C," .map file(s), uploading in chunks..."):e.log?.("Created backup archive: project-code.tar.gz (",d," files for rollback, no .map per project config), uploading in chunks...")}else b=await N(r,I,F,!0);if(b===0)return e.log?.("No files to pack. Skip upload."),{ok:!0,uploaded:0};let M=await et(I),D=!p&&($?B!==null:!!(x&&n));if(D){if(B){let{encryptArchiveWithKey:d}=await Promise.resolve().then(()=>(Y(),q));M=d(M,B)}else{let{encryptArchive:d}=await Promise.resolve().then(()=>(Y(),q));M=d(M,x,n)}U||e.log?.(`Created tar.gz with ${b} file(s), encrypted, uploading in chunks...`)}else U||e.log?.(`Created tar.gz with ${b} file(s), uploading in chunks...`);let O=M.length,P=Math.ceil(O/y),l={"Content-Type":"application/json"};$?l["X-Auth-Cert"]=s:(l["X-Project-Id"]=x,l["X-Secret-Key"]=n||"");let A=(await fe(ue(o,"/sourcemaps/upload-archive-multipart/init"),{method:"POST",headers:{...l,"Content-Type":"application/json"},body:JSON.stringify({projectId:x,secretKey:$?"":n||"",release:i,buildId:u||void 0,totalChunks:P,chunkSizeBytes:y,encrypted:D,uploadMode:f||void 0})},e)).uploadId;if(!A)throw new Error("Init did not return uploadId");let K=new Set;for(let d=0;d<P;d++)K.add(d);try{let d=await fetch(ue(o,"/sourcemaps/upload-archive-multipart/status")+`?uploadId=${encodeURIComponent(A)}`,{method:"GET",headers:l}),C=await d.text();if(d.ok&&C){let v=JSON.parse(C).receivedChunks||[];v.forEach(E=>K.delete(E)),v.length>0&&e.log?.(`Resume: ${v.length}/${P} chunks already uploaded`)}}catch{}let _=3e3,G=(P-K.size)*y,L=(O/1024/1024).toFixed(2),Q=()=>{let d=O?Math.min(100,Math.round(G/O*100)):0,C=(G/1024/1024).toFixed(2);typeof process<"u"&&process.stderr&&process.stderr.write&&process.stderr.write(`\r \u4E0A\u4F20\u8FDB\u5EA6 \u5206\u7247 ${C}/${L} MB (${d}%) `)},H=setInterval(Q,_),J=Math.min(8,P),ee=async d=>{let C=d*y,R=Math.min(C+y,O),v=R-C,E=M.subarray(C,R),w=new FormData;w.append("uploadId",A),w.append("index",String(d)),w.append("totalChunks",String(P)),w.append("chunk",new Blob([E]),`chunk-${d}`);let Te=ue(o,"/sourcemaps/upload-archive-multipart/chunk");await fe(Te,{method:"POST",headers:$?{"X-Auth-Cert":s}:{"X-Project-Id":x,"X-Secret-Key":n||""},body:w},e),G+=v},te=[...K].sort((d,C)=>d-C);for(let d=0;d<te.length;d+=J){let C=te.slice(d,d+J);await Promise.all(C.map(ee))}clearInterval(H),O>0&&typeof process<"u"&&process.stderr&&process.stderr.write&&(Q(),process.stderr.write(`
4
+ `));let z=(await fe(ue(o,"/sourcemaps/upload-archive-multipart/complete"),{method:"POST",headers:{...l,"Content-Type":"application/json"},body:JSON.stringify({uploadId:A})},e)).uploaded??0;return e.log?.("Chunked upload OK, server extracted and saved",z,".map file(s)"),{ok:!0,uploaded:z}}finally{await rt(S,{recursive:!0,force:!0})}}var at,nt,st,Pe=re(()=>{de();at=1*1024*1024,nt=3,st=1e3});import{readdir as dt,readFile as ut,unlink as pt,stat as ft}from"fs/promises";import{join as ht,basename as Z}from"path";var mt=3e3;async function yt(t,e=12){let r=[],o=0;async function a(){for(;o<t.length;){let s=o++;try{r[s]=await t[s]()}catch(i){r[s]=Promise.reject(i)}}}let n=Array.from({length:Math.min(e,t.length)},()=>a());return await Promise.all(n),r}async function Fe(t,e=[]){let r;try{r=await dt(t,{withFileTypes:!0})}catch(o){if(o?.code==="ENOENT")return e;throw o}for(let o of r){let a=ht(t,o.name);o.isDirectory()?await Fe(a,e):o.name.endsWith(".map")&&e.push(a)}return e}var Ae="/sourcemaps/upload";function wt(t){let e=t.replace(/\/$/,"");return e.endsWith(Ae)?e:e+Ae}async function xt(t){let{endpoint:e,projectId:r,secretKey:o,authCert:a,release:n,buildId:s,filePath:i}=t,u=!!a,p=r||(u?(await Promise.resolve().then(()=>(ne(),ae))).extractProjectIdFromCert(a):""),y=Z(i,".map"),g=await ut(i),f=wt(e),h=new FormData;h.append("projectId",p),u||h.append("secretKey",o||""),h.append("release",n),s&&h.append("buildId",s),h.append("filename",y),h.append("file",new Blob([g]),Z(i));let k=await fetch(f,{method:"POST",headers:u?{"X-Project-Id":p,"X-Auth-Cert":a}:{"X-Project-Id":p,"X-Secret-Key":o||""},body:h}),m=await k.text();if(!k.ok)throw new Error(`${k.status} ${m}`);return JSON.parse(m||"{}")}async function Ft(t,e=console){let{dir:r,endpoint:o,projectId:a,secretKey:n,authCert:s,release:i,buildId:u,deleteAfterUpload:p=!1,deleteEvenOnFailure:y=!1,concurrency:g=12}=t,f=await Fe(r);if(f.length===0)return e.log("No .map files found in",r),{ok:0,fail:0,deleted:0};let h=Math.max(1,Math.min(64,Number(g)||12)),$=p&&y,k=f.length,m=await Promise.all(f.map(l=>ft(l).then(c=>c.size))),x=m.reduce((l,c)=>l+c,0),B=(x/1024/1024).toFixed(2);e.log("Uploading",k,"source map(s) to",o,"release=",i,"concurrency=",h,p?$?"(will delete local .map even on failure)":"(will delete local .map only after all succeed)":"");let S=0,I=()=>{let l=x?Math.min(100,Math.round(S/x*100)):0,c=(S/1024/1024).toFixed(2);typeof process<"u"&&process.stderr&&process.stderr.write&&process.stderr.write(`\r \u4E0A\u4F20\u8FDB\u5EA6 ${c}/${B} MB (${l}%) `)},U=setInterval(I,mt),F=f.map((l,c)=>()=>xt({endpoint:o,projectId:a,secretKey:n,authCert:s,release:i,buildId:u,filePath:l}).then(()=>(S+=m[c],{ok:!0,name:Z(l)})).catch(A=>(S+=m[c],{ok:!1,name:Z(l),err:A}))),b=await yt(F,h);clearInterval(U),x>0&&process.stderr&&process.stderr.write&&(I(),process.stderr.write(`
5
+ `));let M=0,D=0;for(let l of b)l.ok?(e.log(" OK",l.name),M++):(e.error(" FAIL",l.name,l.err?.message||l.err),D++);let O=p&&(D===0||y),P=0;if(O&&f.length>0){for(let l of f)try{await pt(l),P++,e.log(" Deleted",Z(l))}catch(c){e.error(" Delete failed",l,c.message)}D>0&&y&&e.log("Deleted .map files despite upload failures. Fix errors and re-run to re-upload.")}else D>0&&!y&&e.log("Upload had failures. Local .map files were NOT deleted. Fix errors and re-run.");return{ok:M,fail:D,deleted:P}}async function Tt(t,e=console){let{uploadArchive:r,deleteMapFiles:o}=await Promise.resolve().then(()=>(de(),pe)),{dir:a,endpoint:n,projectId:s,secretKey:i,authCert:u,release:p,buildId:y,deleteEvenOnFailure:g=!1,noEncrypt:f,uploadMode:h,excludeExt:$}=t;try{let{uploaded:k}=await r({dir:a,endpoint:n,projectId:s,secretKey:i,authCert:u,release:p,buildId:y,noEncrypt:f,uploadMode:h,excludeExt:$},e);if(k===0)return{uploaded:0,deleted:0};let m=await o(a,[]);return e.log("Deleted",m.length,"local .map file(s)."),{uploaded:k,deleted:m.length}}catch(k){if(g)try{let m=await o(a,[]);e.log("Deleted",m.length,"local .map file(s) despite upload failure.")}catch(m){e.error("Delete .map after upload failure failed:",m.message)}else e.error("Upload failed. Local .map files were NOT deleted.",k.message);throw k}}async function jt(t,e=console){let{uploadArchiveChunked:r}=await Promise.resolve().then(()=>(Pe(),De)),{deleteMapFiles:o}=await Promise.resolve().then(()=>(de(),pe)),{dir:a,endpoint:n,projectId:s,secretKey:i,authCert:u,release:p,buildId:y,deleteEvenOnFailure:g=!1,noEncrypt:f,chunkSizeBytes:h,uploadMode:$,excludeExt:k}=t;try{let{uploaded:m}=await r({dir:a,endpoint:n,projectId:s,secretKey:i,authCert:u,release:p,buildId:y,noEncrypt:f,chunkSizeBytes:h,uploadMode:$,excludeExt:k},e);if(m===0)return{uploaded:0,deleted:0};let x=await o(a,[]);return e.log("Deleted",x.length,"local .map file(s)."),{uploaded:m,deleted:x.length}}catch(m){if(g)try{let x=await o(a,[]);e.log("Deleted",x.length,"local .map file(s) despite upload failure.")}catch(x){e.error("Delete .map after upload failure failed:",x.message)}else e.error("Upload failed. Local .map files were NOT deleted.",m.message);throw m}}export{Fe as findMapFiles,Ft as uploadAll,jt as uploadArchiveChunkedThenDelete,Tt as uploadArchiveThenDelete,xt as uploadOne};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontend-monitor/upload-sourcemaps",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "CLI to upload Source Map files to frontend-monitor API (for CI/CD)",
5
5
  "type": "module",
6
6
  "main": "dist/upload.js",