@frontend-monitor/upload-sourcemaps 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,37 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@frontend-monitor/upload-sourcemaps` are documented here.
4
+
5
+ ---
6
+
7
+ ## [0.1.0] (2025-03-13)
8
+
9
+ ### 版本升级说明 / Release Notes
10
+
11
+ #### 行为变更 / Behavior Changes
12
+
13
+ - **移除 `uploadMode: 'all'`**
14
+ 仅保留 `mapOnly`(默认)与 `backup`。若配置或参数中使用了 `all`,将自动按 `backup` 处理。
15
+ - **backup 模式与项目配置联动**
16
+ 备份 tar 是否包含 .map 由项目打包配置(如 Vite/Webpack 的 sourcemap、是否保留 .map 等)推断的 `keepMapInOutput` 决定:
17
+ - 项目**保留** .map 时:备份包包含 `project-code.tar.gz` + 所有 .map;
18
+ - 项目**不保留** .map 时:备份包仅包含 `project-code.tar.gz`(便于仅做部署包备份)。
19
+
20
+ #### 修复 / Fixes
21
+
22
+ - **backup 时未传入 `keepMapInOutput`**
23
+ 修复 `upload.js` 中 `uploadArchiveThenDelete` / `uploadArchiveChunkedThenDelete` 未将 `keepMapInOutput` 传给 `uploadArchive`、`uploadArchiveChunked` 的问题,确保 backup 打包与删除行为与配置一致。
24
+ - **backup 仅上传部署包时的提示**
25
+ 当 backup 模式且项目配置不保留 .map 时,服务端会保存 0 个 .map;现区分提示为「Backup uploaded (deploy package only; no .map in tar per project config).」,避免与「构建未产出 .map」混淆。
26
+
27
+ #### 使用建议
28
+
29
+ - 使用 **mapOnly**:只上传 .map,不打包代码(默认)。
30
+ - 使用 **backup**:上传部署包(及按项目配置可选的 .map),便于服务端保留版本与还原。
31
+ - 若此前使用 `--upload-mode all`,可改为 `--upload-mode backup`(或直接省略,脚本会对 `all` 自动按 backup 处理)。
32
+
33
+ ---
34
+
35
+ ## [0.0.3] and earlier
36
+
37
+ Initial releases: upload single .map files or archive (tar.gz), build subcommand, chunked upload, certificate auth.
package/README.md CHANGED
@@ -161,6 +161,7 @@ Priority: **CLI > env > config**.
161
161
  | `--release` | `RELEASE` | Version (must match SDK) | From package.json |
162
162
  | `--build-id` | `BUILD_ID` | Build serial number | Auto-generated |
163
163
  | `--archive` | — | Pack as tar.gz and upload encrypted (recommended) | — |
164
+ | `--upload-mode` | `UPLOAD_MODE` | `mapOnly` (default) / `backup` (code tar; .map included only if project keeps sourcemap) | `mapOnly` |
164
165
  | `--chunk-size` | `UPLOAD_SOURCEMAPS_CHUNK_SIZE` | Chunk size with --archive (e.g. 1M) | 1MB |
165
166
  | `--auth-cert` | `MONITOR_AUTH_CERT` | Certificate content (alternative to project-id + secret-key) | — |
166
167
  | `-d` / `--delete-after-upload` | — | Delete local .map after upload | Inferred from bundler |
@@ -175,9 +176,16 @@ Priority: **CLI > env > config**.
175
176
 
176
177
  Links errors to the right Source Map when the same version is built multiple times. With the **build** subcommand, buildId is generated and injected automatically; the SDK reads it — no manual setup. For manual builds, inject `MONITOR_BUILD_ID` in your bundler and pass the same `--build-id` when uploading.
177
178
 
179
+ ### Upload mode (--upload-mode)
180
+
181
+ - **mapOnly** (default): Upload only `.map` files for stack resolution.
182
+ - **backup**: Pack **non-.map resources** into `project-code.tar.gz`. Whether the backup tar also includes `.map` files is determined by your **project bundler config** (e.g. Vite/Webpack sourcemap setting): if the project is configured to keep separate .map files, the backup tar contains `project-code.tar.gz` and all `.map` files at the same level; otherwise the backup tar contains only `project-code.tar.gz`. Server extracts and saves .map (if any) and the code package. Use with `--archive`.
183
+
184
+ Config: `"uploadMode": "backup"` or CLI: `--upload-mode backup`.
185
+
178
186
  ### Archive upload (--archive)
179
187
 
180
- Packs the output as `.tar.gz` and uploads it. The server decrypts and extracts only `.map` files. Default is encrypted. Use when you have many .map files to reduce requests.
188
+ Packs the output as `.tar.gz` and uploads it. Server decrypts and extracts .map (if any) and backup `project-code.tar.gz`. Default is encrypted. With `--upload-mode backup`, the archive is a single tar: `project-code.tar.gz` plus (per project config) `.map` files at the same level.
181
189
 
182
190
  ### Chunked upload (--chunk-size)
183
191
 
@@ -302,6 +310,24 @@ Recommended: `npx upload-sourcemaps build --archive` and wire up the SDK as in i
302
310
 
303
311
  ---
304
312
 
313
+ ## Changelog
314
+
315
+ ### 0.0.3 (2026-03-10)
316
+
317
+ **Current stable release**
318
+ - Support `build` subcommand to auto-inject buildId and upload Source Maps
319
+ - Support `--archive` mode to pack as tar.gz before upload
320
+ - Support certificate authentication (`--auth-cert`)
321
+ - Compatible with Vite / Webpack / Rollup and other bundlers
322
+
323
+ ### 0.0.2 (withdrawn)
324
+
325
+ - Added archive mode, certificate authentication support
326
+
327
+ ### 0.0.1 / 0.0.1-beta.1 (withdrawn)
328
+
329
+ - Initial version with basic Source Map upload functionality
330
+
305
331
  ## License
306
332
 
307
333
  MIT
package/README.zh-CN.md CHANGED
@@ -135,11 +135,14 @@ npx upload-sourcemaps
135
135
  "endpoint": "https://monitor.example.com/monitorApi",
136
136
  "dir": "./dist",
137
137
  "uploadAsArchive": true,
138
+ "uploadMode": "mapOnly",
138
139
  "buildCommand": "npm run build",
139
140
  "buildOutputDir": "./dist"
140
141
  }
141
142
  ```
142
143
 
144
+ `uploadMode` 可选 `mapOnly`(默认,仅 .map)或 `backup`(代码包打 tar;是否含 .map 由项目打包配置「是否保留 sourcemap」决定,便于回退)。
145
+
143
146
  ### 鉴权与证书
144
147
 
145
148
  - **方式一**:Project ID + Secret Key(表单或请求头 `X-Project-Id`、`X-Secret-Key`)。
@@ -161,6 +164,7 @@ npx upload-sourcemaps
161
164
  | `--release` | `RELEASE` | 版本号(需与 SDK 一致) | 读 package.json |
162
165
  | `--build-id` | `BUILD_ID` | 构建序列号 | 自动生成 |
163
166
  | `--archive` | — | 打 tar.gz 并加密上传(推荐) | — |
167
+ | `--upload-mode` | `UPLOAD_MODE` | 上传范围:`mapOnly` 仅 .map(默认)/ `backup` 代码包 tar(.map 依项目是否保留 sourcemap 配置) | `mapOnly` |
164
168
  | `--chunk-size` | `UPLOAD_SOURCEMAPS_CHUNK_SIZE` | 分片大小(如 1M),与 --archive 同用 | 1MB |
165
169
  | `--auth-cert` | `MONITOR_AUTH_CERT` | 证书内容(与 project-id+secret-key 二选一) | — |
166
170
  | `-d` / `--delete-after-upload` | — | 上传后删除本地 .map | 按打包配置推断 |
@@ -175,13 +179,20 @@ npx upload-sourcemaps
175
179
 
176
180
  同一版本可能构建多次,`buildId` 用于精确关联错误与 Source Map。使用 **`build` 子命令**时自动生成并注入构建环境,SDK 自动读取,无需手动配置。手动构建时需在打包配置中注入 `MONITOR_BUILD_ID`,上传时传相同 `--build-id`。
177
181
 
182
+ ### 上传模式(--upload-mode)
183
+
184
+ - **mapOnly**(默认):仅上传 `.map` 文件,供监控端堆栈还原使用。
185
+ - **backup**:将**除 .map 外的资源**打成 `project-code.tar.gz`,再根据**项目打包配置是否保留 sourcemap**(Vite/Webpack 等的 sourcemap 配置)决定备份 tar 是否包含 .map:若配置为保留独立 .map,则备份 tar 内为 `project-code.tar.gz` 与各 `.map` 同级;若不保留,则备份 tar 内仅 `project-code.tar.gz`。服务端解压后保存 .map(若有)与代码包。需与 `--archive` 一起使用。
186
+
187
+ 配置文件示例:`"uploadMode": "backup"`,或命令行:`--upload-mode backup`。
188
+
178
189
  ### 压缩包上传(--archive)
179
190
 
180
- 将产物打成 `.tar.gz` 上传,服务端解压后只保留 `.map`。默认加密,服务端解密后保存。适合 .map 较多时减少请求次数。
191
+ 将产物打成 `.tar.gz` 上传,服务端解压后保存 .map(若有)及 backup 模式下的 `project-code.tar.gz`。默认加密。当 `--upload-mode backup` 时,压缩包内为 `project-code.tar.gz` 与(依项目配置)各 `.map` 文件同级,再整体打成一个 tar 传输。
181
192
 
182
193
  ### 分片上传(--chunk-size)
183
194
 
184
- 与 `--archive` 同用时,可加 `--chunk-size 1M` 启用分片上传、断点续传与重试,适合 Nginx 限制 body 或大压缩包。
195
+ 与 `--archive` 同用时,可加 `--chunk-size 1M` 启用分片上传、断点续传与重试,适合 Nginx 限制 body 或大压缩包。init、每个分片、complete 请求均带自动重试(指数退避),同次运行内会先查已上传分片再补传,减少失败重跑成本。
185
196
 
186
197
  ### build 子命令:强制生成 Source Map
187
198
 
@@ -302,6 +313,24 @@ const { ok, fail } = await uploadAll({
302
313
 
303
314
  ---
304
315
 
316
+ ## 版本记录
317
+
318
+ ### 0.0.3(2026-03-10)
319
+
320
+ **当前稳定版本**
321
+ - 支持 `build` 子命令自动注入 buildId 并上传 Source Map
322
+ - 支持 `--archive` 模式打包为 tar.gz 后上传
323
+ - 支持证书认证(`--auth-cert`)
324
+ - 兼容 Vite / Webpack / Rollup 等主流打包工具
325
+
326
+ ### 0.0.2(已撤回)
327
+
328
+ - 新增 archive 模式、证书认证支持
329
+
330
+ ### 0.0.1 / 0.0.1-beta.1(已撤回)
331
+
332
+ - 初始版本,基础 Source Map 上传功能
333
+
305
334
  ## License
306
335
 
307
336
  MIT
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- var He=Object.defineProperty;var K=(t,e)=>()=>(t&&(e=t(t=0)),e);var _=(t,e)=>{for(var o in e)He(t,o,{get:e[o],enumerable:!0})};var z={};_(z,{extractProjectIdFromCert:()=>Ge,extractUploadKeyFromCert:()=>qe});function Ge(t){if(typeof t!="string")return"";let e=t.trim();if(e.startsWith(Ve+"$"))return e.split("$")[1]||"";if(e.includes(de)){let o=e.match(/Project:\s*(\S+)/);return o?o[1]:""}return""}function qe(t){if(typeof t!="string"||!t.includes(de))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 Ve,de,J=K(()=>{Ve="MC1",de="-----BEGIN MONITOR CERT-----"});var L={};_(L,{decryptArchive:()=>rt,encryptArchive:()=>tt,encryptArchiveWithKey:()=>he});import{createCipheriv as Ye,createDecipheriv as Ze,createHash as Qe,randomBytes as et}from"crypto";function me(t,e){let o=`${t}:${e}`;return Qe("sha256").update(o,"utf8").digest()}function tt(t,e,o){let r=me(e,o);return he(t,r)}function he(t,e){if(!Buffer.isBuffer(e)||e.length!==32)throw new Error("Invalid key: must be 32-byte Buffer");let o=et(X),r=Ye(fe,e,o,{authTagLength:B}),a=Buffer.concat([r.update(t),r.final()]),n=r.getAuthTag();return Buffer.concat([o,a,n])}function rt(t,e,o){if(t.length<X+B)throw new Error("Invalid encrypted archive: too short");let r=me(e,o),a=t.subarray(0,X),n=t.subarray(t.length-B),s=t.subarray(X,t.length-B),c=Ze(fe,r,a,{authTagLength:B});return c.setAuthTag(n),Buffer.concat([c.update(s),c.final()])}var fe,X,B,$=K(()=>{fe="aes-256-gcm",X=12,B=16});var te={};_(te,{DEFAULT_EXCLUDE_EXT:()=>V,collectFiles:()=>ee,createArchive:()=>G,deleteMapFiles:()=>ye,uploadArchive:()=>ft});import{createRequire as ot}from"module";import{readdir as we,unlink as nt,readFile as at,mkdtemp as st,rm as ct}from"fs/promises";import{join as H,relative as it}from"path";import{createWriteStream as ut}from"fs";import{tmpdir as lt}from"os";async function ee(t,e=t,o=V){let r=await we(t,{withFileTypes:!0}),a=[];for(let n of r){let s=H(t,n.name),c=it(e,s).replace(/\\/g,"/");if(n.isDirectory()){let p=await ee(s,e,o);a.push(...p)}else{let p=(n.name.includes(".")?"."+n.name.split(".").pop():"").toLowerCase();if(o.has(p))continue;a.push({relativePath:c,fullPath:s})}}return a}async function G(t,e,o=V,r=!0){let a=await ee(t,t,o),n=a.map(s=>s.relativePath);return n.length===0?0:new Promise((s,c)=>{let p=dt.create({gzip:r,cwd:t},n);p.on("error",c),p.pipe(ut(e)).on("close",()=>s(a.length)).on("error",c)})}async function ft(t,e=console){let{dir:o,endpoint:r,projectId:a,secretKey:n,authCert:s,release:c,buildId:p,excludeExt:f,noEncrypt:i}=t,d=!!s,{extractProjectIdFromCert:u,extractUploadKeyFromCert:m}=await Promise.resolve().then(()=>(J(),z)),l=a||(d?u(s):""),h=d?m(s):null,y=await st(H(lt(),"upload-sourcemaps-")),g=H(y,"archive.tar.gz");try{let k=await G(o,g,f||V,!0);if(k===0)return e.log("No files to pack (directory empty or only excluded). Skip upload."),{ok:!0,uploaded:0};let S=await at(g),x=!i&&(d?h!==null:!!(l&&n));if(x)if(h){let{encryptArchiveWithKey:D}=await Promise.resolve().then(()=>($(),L));S=D(S,h),e.log("Created tar.gz with",k,"file(s), encrypted with cert Upload-Key, uploading...")}else{let{encryptArchive:D}=await Promise.resolve().then(()=>($(),L));S=D(S,l,n),e.log("Created tar.gz with",k,"file(s), encrypted, uploading...")}else e.log("Created tar.gz with",k,"file(s), uploading...");let R="/sourcemaps/upload-archive",T=r.replace(/\/$/,""),C=T.endsWith(R)?T:T+R,I=new FormData;I.append("projectId",l),d||I.append("secretKey",n||""),I.append("release",c),p&&I.append("buildId",p),x&&I.append("encrypted","1"),I.append("file",new Blob([S]),x?"archive.tar.gz.enc":"archive.tar.gz");let M={"X-Project-Id":l};d?M["X-Auth-Cert"]=s:M["X-Secret-Key"]=n||"";let P=await fetch(C,{method:"POST",headers:M,body:I}),Z=await P.text();if(!P.ok)throw new Error(`${P.status} ${Z}`);let A=JSON.parse(Z||"{}");return e.log("Upload archive OK, server extracted and saved",A.uploaded,".map file(s)"),{ok:!0,uploaded:A.uploaded||0}}finally{await ct(y,{recursive:!0,force:!0})}}async function ye(t,e=[]){let o=await we(t,{withFileTypes:!0});for(let r of o){let a=H(t,r.name);r.isDirectory()?await ye(a,e):r.name.endsWith(".map")&&(await nt(a),e.push(a))}return e}var pt,dt,V,q=K(()=>{pt=ot(import.meta.url),dt=pt("tar"),V=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"])});var ge={};_(ge,{uploadArchiveChunked:()=>xt});import{readFile as mt,mkdtemp as ht,rm as wt}from"fs/promises";import{join as be}from"path";import{tmpdir as yt}from"os";function It(t){return t.replace(/\/$/,"")}function Y(t,e){let o=It(t),r=e.startsWith("/")?e:`/${e}`;return o.endsWith(r)?o:o+r}async function kt(t){return new Promise(e=>setTimeout(e,t))}async function St(t,e,o,r=gt){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=vt*Math.pow(2,n);o.log?.(` Retry ${n+1}/${r} after ${c}ms: ${s.message}`),await kt(c)}}throw a}async function xt(t,e=console){let{dir:o,endpoint:r,projectId:a,secretKey:n,authCert:s,release:c,buildId:p,noEncrypt:f,chunkSizeBytes:i=bt,excludeExt:d}=t,u=!!s,{extractProjectIdFromCert:m,extractUploadKeyFromCert:l}=await Promise.resolve().then(()=>(J(),z)),h=a||(u?m(s):""),y=u?l(s):null,g=await ht(be(yt(),"upload-sourcemaps-chunked-")),k=be(g,"archive.tar.gz");try{let S=await G(o,k,d||void 0,!0);if(S===0)return e.log?.("No files to pack. Skip upload."),{ok:!0,uploaded:0};let x=await mt(k),R=!f&&(u?y!==null:!!(h&&n));if(R){if(y){let{encryptArchiveWithKey:b}=await Promise.resolve().then(()=>($(),L));x=b(x,y)}else{let{encryptArchive:b}=await Promise.resolve().then(()=>($(),L));x=b(x,h,n)}e.log?.(`Created tar.gz with ${S} file(s), encrypted, uploading in chunks...`)}else e.log?.(`Created tar.gz with ${S} file(s), uploading in chunks...`);let T=x.length,C=Math.ceil(T/i),I={"Content-Type":"application/json"};u?I["X-Auth-Cert"]=s:(I["X-Project-Id"]=h,I["X-Secret-Key"]=n||"");let M=await fetch(Y(r,"/sourcemaps/upload-archive-multipart/init"),{method:"POST",headers:{...I,"Content-Type":"application/json"},body:JSON.stringify({projectId:h,secretKey:u?"":n||"",release:c,buildId:p||void 0,totalChunks:C,chunkSizeBytes:i,encrypted:R})}),P=await M.text();if(!M.ok)throw new Error(`${M.status} ${P}`);let A=JSON.parse(P||"{}").uploadId;if(!A)throw new Error("Init did not return uploadId");let D=new Set;for(let b=0;b<C;b++)D.add(b);try{let b=await fetch(Y(r,"/sourcemaps/upload-archive-multipart/status")+`?uploadId=${encodeURIComponent(A)}`,{method:"GET",headers:I}),F=await b.text();if(b.ok&&F){let N=JSON.parse(F).receivedChunks||[];N.forEach(U=>D.delete(U)),N.length>0&&e.log?.(`Resume: ${N.length}/${C} chunks already uploaded`)}}catch{}for(let b=0;b<C;b++){if(!D.has(b))continue;let F=b*i,pe=Math.min(F+i,T),N=x.subarray(F,pe),U=new FormData;U.append("uploadId",A),U.append("index",String(b)),U.append("totalChunks",String(C)),U.append("chunk",new Blob([N]),`chunk-${b}`);let Xe=Y(r,"/sourcemaps/upload-archive-multipart/chunk");await St(Xe,{method:"POST",headers:u?{"X-Auth-Cert":s}:{"X-Project-Id":h,"X-Secret-Key":n||""},body:U},e),e.log?.(` Chunk ${b+1}/${C} OK`)}let Q=await fetch(Y(r,"/sourcemaps/upload-archive-multipart/complete"),{method:"POST",headers:{...I,"Content-Type":"application/json"},body:JSON.stringify({uploadId:A})}),ue=await Q.text();if(!Q.ok)throw new Error(`${Q.status} ${ue}`);let le=JSON.parse(ue||"{}").uploaded??0;return e.log?.("Chunked upload OK, server extracted and saved",le,".map file(s)"),{ok:!0,uploaded:le}}finally{await wt(g,{recursive:!0,force:!0})}}var bt,gt,vt,ve=K(()=>{q();bt=1*1024*1024,gt=3,vt=1e3});var Be={};_(Be,{loadMonitorConfig:()=>Ke,loadUploadSourcemapsJson:()=>_e,resolveUploadConfig:()=>Rt});import{readFile as Pe}from"fs/promises";import{join as Re,resolve as Pt}from"path";import{pathToFileURL as Fe}from"url";function Ne(){try{return process.env.UPLOAD_ENV||process.env.NODE_ENV||"production"}catch{return"production"}}async function Ke(t){let e=["monitor.config.js","monitor.config.cjs","monitor.config.mjs"];for(let o of e){let r=Re(t,o),a;try{a=await import(Fe(r).href)}catch{continue}let n=a.default;if(!n||typeof n!="object")return null;let s=Ne(),c=n.common||{},p=n[s]||{},f={...c,...p},i=(f.endpoint||"").trim(),d=(f.apiPrefix||"").trim(),u=i+(d.startsWith("/")?d:d?"/"+d:"");return{projectId:f.projectId,secretKey:f.secretKey,authCert:f.authCert,endpoint:u||void 0,release:f.release||n.version,version:n.version}}return null}async function _e(t){try{let e=await Pe(Re(t,".upload-sourcemaps.json"),"utf-8");return JSON.parse(e)}catch{return{}}}async function Rt(t,e){let o=null,r=null;if(e){let a=Pt(t,e);if(e.endsWith(".json"))try{r=JSON.parse(await Pe(a,"utf-8"))}catch{r={}}else try{let s=(await import(Fe(a).href)).default;if(s&&typeof s=="object"&&(s.common||s.production||s.development)){let c=Ne(),p=s.common||{},f=s[c]||{},i={...p,...f},d=(i.endpoint||"").trim(),u=(i.apiPrefix||"").trim();o={projectId:i.projectId,secretKey:i.secretKey,authCert:i.authCert,endpoint:d+(u.startsWith("/")?u:u?"/"+u:""),release:i.release||s.version}}else r=s||{}}catch{r={}}}else o=await Ke(t),r=await _e(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}}var Le=K(()=>{});import{readFile as Ft}from"fs/promises";import{resolve as Nt,dirname as Kt,join as _t}from"path";import{fileURLToPath as Bt}from"url";import{randomUUID as $e}from"crypto";import{spawn as Lt}from"child_process";import{readdir as jt,readFile as Ct,unlink as Et}from"fs/promises";import{join as Ot,basename as W}from"path";async function ke(t,e=[]){let o;try{o=await jt(t,{withFileTypes:!0})}catch(r){if(r?.code==="ENOENT")return e;throw r}for(let r of o){let a=Ot(t,r.name);r.isDirectory()?await ke(a,e):r.name.endsWith(".map")&&e.push(a)}return e}var Ie="/sourcemaps/upload";function Mt(t){let e=t.replace(/\/$/,"");return e.endsWith(Ie)?e:e+Ie}async function At(t){let{endpoint:e,projectId:o,secretKey:r,authCert:a,release:n,buildId:s,filePath:c}=t,p=!!a,f=o||(p?(await Promise.resolve().then(()=>(J(),z))).extractProjectIdFromCert(a):""),i=W(c,".map"),d=await Ct(c),u=Mt(e),m=new FormData;m.append("projectId",f),p||m.append("secretKey",r||""),m.append("release",n),s&&m.append("buildId",s),m.append("filename",i),m.append("file",new Blob([d]),W(c));let h=await fetch(u,{method:"POST",headers:p?{"X-Project-Id":f,"X-Auth-Cert":a}:{"X-Project-Id":f,"X-Secret-Key":r||""},body:m}),y=await h.text();if(!h.ok)throw new Error(`${h.status} ${y}`);return JSON.parse(y||"{}")}async function re(t,e=console){let{dir:o,endpoint:r,projectId:a,secretKey:n,authCert:s,release:c,buildId:p,deleteAfterUpload:f=!1,deleteEvenOnFailure:i=!1}=t,d=await ke(o);if(d.length===0)return e.log("No .map files found in",o),{ok:0,fail:0,deleted:0};let u=f&&i;e.log("Uploading",d.length,"source map(s) to",r,"release=",c,f?u?"(will delete local .map even on failure)":"(will delete local .map only after all succeed)":"");let m=0,l=0;for(let g of d)try{await At({endpoint:r,projectId:a,secretKey:n,authCert:s,release:c,buildId:p,filePath:g}),e.log(" OK",W(g)),m++}catch(k){e.error(" FAIL",W(g),k.message),l++}let h=f&&(l===0||i),y=0;if(h&&d.length>0){for(let g of d)try{await Et(g),y++,e.log(" Deleted",W(g))}catch(k){e.error(" Delete failed",g,k.message)}l>0&&i&&e.log("Deleted .map files despite upload failures. Fix errors and re-run to re-upload.")}else l>0&&!i&&e.log("Upload had failures. Local .map files were NOT deleted. Fix errors and re-run.");return{ok:m,fail:l,deleted:y}}async function oe(t,e=console){let{uploadArchive:o,deleteMapFiles:r}=await Promise.resolve().then(()=>(q(),te)),{dir:a,endpoint:n,projectId:s,secretKey:c,authCert:p,release:f,buildId:i,deleteEvenOnFailure:d=!1,noEncrypt:u}=t;try{let{uploaded:m}=await o({dir:a,endpoint:n,projectId:s,secretKey:c,authCert:p,release:f,buildId:i,noEncrypt:u},e);if(m===0)return{uploaded:0,deleted:0};let l=await r(a,[]);return e.log("Deleted",l.length,"local .map file(s)."),{uploaded:m,deleted:l.length}}catch(m){if(d)try{let l=await r(a,[]);e.log("Deleted",l.length,"local .map file(s) despite upload failure.")}catch(l){e.error("Delete .map after upload failure failed:",l.message)}else e.error("Upload failed. Local .map files were NOT deleted.",m.message);throw m}}async function ne(t,e=console){let{uploadArchiveChunked:o}=await Promise.resolve().then(()=>(ve(),ge)),{deleteMapFiles:r}=await Promise.resolve().then(()=>(q(),te)),{dir:a,endpoint:n,projectId:s,secretKey:c,authCert:p,release:f,buildId:i,deleteEvenOnFailure:d=!1,noEncrypt:u,chunkSizeBytes:m}=t;try{let{uploaded:l}=await o({dir:a,endpoint:n,projectId:s,secretKey:c,authCert:p,release:f,buildId:i,noEncrypt:u,chunkSizeBytes:m},e);if(l===0)return{uploaded:0,deleted:0};let h=await r(a,[]);return e.log("Deleted",h.length,"local .map file(s)."),{uploaded:l,deleted:h.length}}catch(l){if(d)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.",l.message);throw l}}import{readFile as ae}from"fs/promises";import{join as j,resolve as Se}from"path";async function se(t){let e=[t,Se(t,".."),Se(t,"..",".."),process.cwd()];for(let o of e)try{return await ae(j(o,"package.json"),"utf-8"),o}catch{continue}return null}async function E(t){try{return await ae(t,"utf-8")}catch{return""}}async function xe(t){let e=["vite.config.js","vite.config.mjs","vite.config.cjs","vite.config.ts"];for(let o of e){let r=await E(j(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 je(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 E(j(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 Ce(t){let e=await E(j(t,"vue.config.js"))||await E(j(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 Ee(t){let e=["rollup.config.js","rollup.config.mjs","rollup.config.cjs"];for(let o of e){let r=await E(j(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 Oe(t){let e=["next.config.js","next.config.mjs","next.config.cjs","next.config.ts"];for(let o of e){let r=await E(j(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 Me(t){let e=await E(j(t,"nuxt.config.js"))||await E(j(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 Dt(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 ce(t){let e=await se(t);if(!e)return{emitsSourceMap:!0,keepMapInOutput:!1};let o={};try{let n=await ae(j(e,"package.json"),"utf-8");o=JSON.parse(n)}catch{return{emitsSourceMap:!0,keepMapInOutput:!1}}let r=Dt(o),a=[()=>r==="vite"?xe(e):null,()=>r==="next"?Oe(e):null,()=>r==="nuxt"?Me(e):null,()=>r==="vue-cli"?Ce(e):null,()=>r==="webpack"?je(e):null,()=>r==="rollup"?Ee(e):null,()=>xe(e),()=>Oe(e),()=>Ce(e),()=>je(e),()=>Ee(e),()=>Me(e)];for(let n of a){let s=await n();if(s)return s}return{emitsSourceMap:!0,keepMapInOutput:!1}}import{readFile as Ue,writeFile as Ae}from"fs/promises";import{join as De}from"path";async function Ut(t){try{return await Ue(t,"utf-8")}catch{return""}}function Tt(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 ie=[{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 Te(t){let e=await se(t);if(!e)return{restore:async()=>{}};let o={};try{let n=await Ue(De(e,"package.json"),"utf-8");o=JSON.parse(n)}catch{return{restore:async()=>{}}}let r=Tt(o),a=r?[...ie.filter(n=>n.name===r),...ie.filter(n=>n.name!==r)]:ie;for(let n of a)for(let s of n.configNames){let c=De(e,s),p=await Ut(c);if(!p||!n.needPatch(p))continue;let f=n.patch(p);return await Ae(c,f,"utf-8"),{restore:async()=>{try{await Ae(c,p,"utf-8")}catch(i){console.error(`Restore ${n.name} config failed:`,i?.message||i)}}}}return{restore:async()=>{}}}var Er=Kt(Bt(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 O(t){return process.argv.includes(t)}function $t(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 We(t={}){let e=v("--chunk-size","UPLOAD_SOURCEMAPS_CHUNK_SIZE")||t.chunkSize;return $t(e)}async function Wt(){let{resolveUploadConfig:t}=await Promise.resolve().then(()=>(Le(),Be));return t(process.cwd(),v("--config","UPLOAD_SOURCEMAPS_CONFIG")||void 0)}async function zt(t){let e=[t,Nt(t,".."),process.cwd()];for(let o of e)try{let r=await Ft(_t(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 ze(t,e){return t&&t!=="default"?t:await zt(e)||"default"}var w=await Wt(),Jt=process.argv[2]==="build";function Je(t,e){return t||e===!0}async function Xt(){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=O("--archive")||w.uploadAsArchive===!0,c=Je(O("--no-encrypt"),w.noEncrypt),f=!(await ce(n)).keepMapInOutput||O("--delete-after-upload")||O("-d")||w.deleteAfterUpload===!0,i=v("--build-id","BUILD_ID")||w.buildId||$e(),d=await Te(n);try{console.log("Step 1: Running build (forcing source map generation):",a),console.log("Build ID:",i);let[u,...m]=a.split(/\s+/);await new Promise((y,g)=>{Lt(u,m,{stdio:"inherit",shell:!0,env:{...process.env,BUILD_SOURCEMAP:"1",SOURCEMAP:"1",MONITOR_BUILD_ID:i,VITE_MONITOR_BUILD_ID:i}}).on("exit",S=>S===0?y():g(new Error(`Build exited ${S}`)))}),console.log("Step 2: Uploading source maps...");let l=await ze(v("--release","RELEASE")||w.release,n);l!=="default"&&console.log("Release (from package.json or config):",l);let h=We(w);if(s){let y={dir:n,endpoint:r,projectId:t,secretKey:e,authCert:o,release:l,buildId:i,deleteEvenOnFailure:!1,noEncrypt:c};(h?await ne({...y,chunkSizeBytes:h},console):await oe(y,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:y,fail:g}=await re({endpoint:r,projectId:t,secretKey:e,authCert:o,release:l,buildId:i,dir:n,deleteAfterUpload:f,deleteEvenOnFailure:!1},console);if(g>0)throw new Error("Upload had failures. Local .map files were NOT deleted. Fix errors and re-run.");y===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(u){throw console.error("Error:",u.message),console.error(f?"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."),u}finally{await d.restore()}}if(Jt)try{await Xt()}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 ze(v("--release","RELEASE")||w.release,a),s=v("--build-id","BUILD_ID")||w.buildId||$e(),c=O("--archive")||w.uploadAsArchive===!0,p=Je(O("--no-encrypt"),w.noEncrypt),f=We(w),d=!(await ce(a)).keepMapInOutput||O("--delete-after-upload")||O("-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(" --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 u={dir:a,endpoint:r,projectId:t,secretKey:e,authCert:o,release:n,buildId:s,deleteEvenOnFailure:!1,noEncrypt:p};f?await ne({...u,chunkSizeBytes:f},console):await oe(u,console)}else{let{ok:u,fail:m,deleted:l}=await re({endpoint:r,projectId:t,secretKey:e,authCert:o,release:n,buildId:s,dir:a,deleteAfterUpload:d,deleteEvenOnFailure:d},console);l>0&&console.log("Deleted",l,"local .map file(s) from output."),m>0&&(console.error(d?"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(u){console.error("Error:",u.message),console.error(d?"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 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}}}
package/dist/upload.js CHANGED
@@ -1 +1 @@
1
- var ue=Object.defineProperty;var U=(t,e)=>()=>(t&&(e=t(t=0)),e);var L=(t,e)=>{for(var a in e)ue(t,a,{get:e[a],enumerable:!0})};var R={};L(R,{extractProjectIdFromCert:()=>he,extractUploadKeyFromCert:()=>me});function he(t){if(typeof t!="string")return"";let e=t.trim();if(e.startsWith(fe+"$"))return e.split("$")[1]||"";if(e.includes(ee)){let a=e.match(/Project:\s*(\S+)/);return a?a[1]:""}return""}function me(t){if(typeof t!="string"||!t.includes(ee))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 fe,ee,X=U(()=>{fe="MC1",ee="-----BEGIN MONITOR CERT-----"});var O={};L(O,{decryptArchive:()=>Ie,encryptArchive:()=>Ce,encryptArchiveWithKey:()=>ae});import{createCipheriv as we,createDecipheriv as ye,createHash as ve,randomBytes as xe}from"crypto";function re(t,e){let a=`${t}:${e}`;return ve("sha256").update(a,"utf8").digest()}function Ce(t,e,a){let r=re(e,a);return ae(t,r)}function ae(t,e){if(!Buffer.isBuffer(e)||e.length!==32)throw new Error("Invalid key: must be 32-byte Buffer");let a=xe(B),r=we(te,e,a,{authTagLength:K}),o=Buffer.concat([r.update(t),r.final()]),n=r.getAuthTag();return Buffer.concat([a,o,n])}function Ie(t,e,a){if(t.length<B+K)throw new Error("Invalid encrypted archive: too short");let r=re(e,a),o=t.subarray(0,B),n=t.subarray(t.length-K),i=t.subarray(B,t.length-K),c=ye(te,r,o,{authTagLength:K});return c.setAuthTag(n),Buffer.concat([c.update(i),c.final()])}var te,B,K,P=U(()=>{te="aes-256-gcm",B=12,K=16});var Y={};L(Y,{DEFAULT_EXCLUDE_EXT:()=>z,collectFiles:()=>q,createArchive:()=>M,deleteMapFiles:()=>ne,uploadArchive:()=>je});import{createRequire as ke}from"module";import{readdir as oe,unlink as Ee,readFile as ge,mkdtemp as be,rm as Te}from"fs/promises";import{join as _,relative as Ae}from"path";import{createWriteStream as De}from"fs";import{tmpdir as Fe}from"os";async function q(t,e=t,a=z){let r=await oe(t,{withFileTypes:!0}),o=[];for(let n of r){let i=_(t,n.name),c=Ae(e,i).replace(/\\/g,"/");if(n.isDirectory()){let p=await q(i,e,a);o.push(...p)}else{let p=(n.name.includes(".")?"."+n.name.split(".").pop():"").toLowerCase();if(a.has(p))continue;o.push({relativePath:c,fullPath:i})}}return o}async function M(t,e,a=z,r=!0){let o=await q(t,t,a),n=o.map(i=>i.relativePath);return n.length===0?0:new Promise((i,c)=>{let p=$e.create({gzip:r,cwd:t},n);p.on("error",c),p.pipe(De(e)).on("close",()=>i(o.length)).on("error",c)})}async function je(t,e=console){let{dir:a,endpoint:r,projectId:o,secretKey:n,authCert:i,release:c,buildId:p,excludeExt:w,noEncrypt:h}=t,u=!!i,{extractProjectIdFromCert:m,extractUploadKeyFromCert:l}=await Promise.resolve().then(()=>(X(),R)),s=o||(u?m(i):""),d=u?l(i):null,x=await be(_(Fe(),"upload-sourcemaps-")),v=_(x,"archive.tar.gz");try{let C=await M(a,v,w||z,!0);if(C===0)return e.log("No files to pack (directory empty or only excluded). Skip upload."),{ok:!0,uploaded:0};let k=await ge(v),I=!h&&(u?d!==null:!!(s&&n));if(I)if(d){let{encryptArchiveWithKey:T}=await Promise.resolve().then(()=>(P(),O));k=T(k,d),e.log("Created tar.gz with",C,"file(s), encrypted with cert Upload-Key, uploading...")}else{let{encryptArchive:T}=await Promise.resolve().then(()=>(P(),O));k=T(k,s,n),e.log("Created tar.gz with",C,"file(s), encrypted, uploading...")}else e.log("Created tar.gz with",C,"file(s), uploading...");let S="/sourcemaps/upload-archive",D=r.replace(/\/$/,""),E=D.endsWith(S)?D:D+S,y=new FormData;y.append("projectId",s),u||y.append("secretKey",n||""),y.append("release",c),p&&y.append("buildId",p),I&&y.append("encrypted","1"),y.append("file",new Blob([k]),I?"archive.tar.gz.enc":"archive.tar.gz");let g={"X-Project-Id":s};u?g["X-Auth-Cert"]=i:g["X-Secret-Key"]=n||"";let F=await fetch(E,{method:"POST",headers:g,body:y}),G=await F.text();if(!F.ok)throw new Error(`${F.status} ${G}`);let b=JSON.parse(G||"{}");return e.log("Upload archive OK, server extracted and saved",b.uploaded,".map file(s)"),{ok:!0,uploaded:b.uploaded||0}}finally{await Te(x,{recursive:!0,force:!0})}}async function ne(t,e=[]){let a=await oe(t,{withFileTypes:!0});for(let r of a){let o=_(t,r.name);r.isDirectory()?await ne(o,e):r.name.endsWith(".map")&&(await Ee(o),e.push(o))}return e}var Se,$e,z,W=U(()=>{Se=ke(import.meta.url),$e=Se("tar"),z=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"])});var ce={};L(ce,{uploadArchiveChunked:()=>ze});import{readFile as Ke,mkdtemp as Oe,rm as Pe}from"fs/promises";import{join as ie}from"path";import{tmpdir as Ne}from"os";function Xe(t){return t.replace(/\/$/,"")}function J(t,e){let a=Xe(t),r=e.startsWith("/")?e:`/${e}`;return a.endsWith(r)?a:a+r}async function Be(t){return new Promise(e=>setTimeout(e,t))}async function _e(t,e,a,r=Le){let o;for(let n=0;n<=r;n++)try{let i=await fetch(t,e),c=await i.text();if(!i.ok)throw new Error(`${i.status} ${c}`);return c?JSON.parse(c):{}}catch(i){if(o=i,n<r){let c=Re*Math.pow(2,n);a.log?.(` Retry ${n+1}/${r} after ${c}ms: ${i.message}`),await Be(c)}}throw o}async function ze(t,e=console){let{dir:a,endpoint:r,projectId:o,secretKey:n,authCert:i,release:c,buildId:p,noEncrypt:w,chunkSizeBytes:h=Ue,excludeExt:u}=t,m=!!i,{extractProjectIdFromCert:l,extractUploadKeyFromCert:s}=await Promise.resolve().then(()=>(X(),R)),d=o||(m?l(i):""),x=m?s(i):null,v=await Oe(ie(Ne(),"upload-sourcemaps-chunked-")),C=ie(v,"archive.tar.gz");try{let k=await M(a,C,u||void 0,!0);if(k===0)return e.log?.("No files to pack. Skip upload."),{ok:!0,uploaded:0};let I=await Ke(C),S=!w&&(m?x!==null:!!(d&&n));if(S){if(x){let{encryptArchiveWithKey:f}=await Promise.resolve().then(()=>(P(),O));I=f(I,x)}else{let{encryptArchive:f}=await Promise.resolve().then(()=>(P(),O));I=f(I,d,n)}e.log?.(`Created tar.gz with ${k} file(s), encrypted, uploading in chunks...`)}else e.log?.(`Created tar.gz with ${k} file(s), uploading in chunks...`);let D=I.length,E=Math.ceil(D/h),y={"Content-Type":"application/json"};m?y["X-Auth-Cert"]=i:(y["X-Project-Id"]=d,y["X-Secret-Key"]=n||"");let g=await fetch(J(r,"/sourcemaps/upload-archive-multipart/init"),{method:"POST",headers:{...y,"Content-Type":"application/json"},body:JSON.stringify({projectId:d,secretKey:m?"":n||"",release:c,buildId:p||void 0,totalChunks:E,chunkSizeBytes:h,encrypted:S})}),F=await g.text();if(!g.ok)throw new Error(`${g.status} ${F}`);let b=JSON.parse(F||"{}").uploadId;if(!b)throw new Error("Init did not return uploadId");let T=new Set;for(let f=0;f<E;f++)T.add(f);try{let f=await fetch(J(r,"/sourcemaps/upload-archive-multipart/status")+`?uploadId=${encodeURIComponent(b)}`,{method:"GET",headers:y}),$=await f.text();if(f.ok&&$){let j=JSON.parse($).receivedChunks||[];j.forEach(A=>T.delete(A)),j.length>0&&e.log?.(`Resume: ${j.length}/${E} chunks already uploaded`)}}catch{}for(let f=0;f<E;f++){if(!T.has(f))continue;let $=f*h,Q=Math.min($+h,D),j=I.subarray($,Q),A=new FormData;A.append("uploadId",b),A.append("index",String(f)),A.append("totalChunks",String(E)),A.append("chunk",new Blob([j]),`chunk-${f}`);let pe=J(r,"/sourcemaps/upload-archive-multipart/chunk");await _e(pe,{method:"POST",headers:m?{"X-Auth-Cert":i}:{"X-Project-Id":d,"X-Secret-Key":n||""},body:A},e),e.log?.(` Chunk ${f+1}/${E} OK`)}let H=await fetch(J(r,"/sourcemaps/upload-archive-multipart/complete"),{method:"POST",headers:{...y,"Content-Type":"application/json"},body:JSON.stringify({uploadId:b})}),V=await H.text();if(!H.ok)throw new Error(`${H.status} ${V}`);let Z=JSON.parse(V||"{}").uploaded??0;return e.log?.("Chunked upload OK, server extracted and saved",Z,".map file(s)"),{ok:!0,uploaded:Z}}finally{await Pe(v,{recursive:!0,force:!0})}}var Ue,Le,Re,se=U(()=>{W();Ue=1*1024*1024,Le=3,Re=1e3});import{readdir as Me,readFile as We,unlink as Je}from"fs/promises";import{join as Ge,basename as N}from"path";async function de(t,e=[]){let a;try{a=await Me(t,{withFileTypes:!0})}catch(r){if(r?.code==="ENOENT")return e;throw r}for(let r of a){let o=Ge(t,r.name);r.isDirectory()?await de(o,e):r.name.endsWith(".map")&&e.push(o)}return e}var le="/sourcemaps/upload";function He(t){let e=t.replace(/\/$/,"");return e.endsWith(le)?e:e+le}async function qe(t){let{endpoint:e,projectId:a,secretKey:r,authCert:o,release:n,buildId:i,filePath:c}=t,p=!!o,w=a||(p?(await Promise.resolve().then(()=>(X(),R))).extractProjectIdFromCert(o):""),h=N(c,".map"),u=await We(c),m=He(e),l=new FormData;l.append("projectId",w),p||l.append("secretKey",r||""),l.append("release",n),i&&l.append("buildId",i),l.append("filename",h),l.append("file",new Blob([u]),N(c));let d=await fetch(m,{method:"POST",headers:p?{"X-Project-Id":w,"X-Auth-Cert":o}:{"X-Project-Id":w,"X-Secret-Key":r||""},body:l}),x=await d.text();if(!d.ok)throw new Error(`${d.status} ${x}`);return JSON.parse(x||"{}")}async function pt(t,e=console){let{dir:a,endpoint:r,projectId:o,secretKey:n,authCert:i,release:c,buildId:p,deleteAfterUpload:w=!1,deleteEvenOnFailure:h=!1}=t,u=await de(a);if(u.length===0)return e.log("No .map files found in",a),{ok:0,fail:0,deleted:0};let m=w&&h;e.log("Uploading",u.length,"source map(s) to",r,"release=",c,w?m?"(will delete local .map even on failure)":"(will delete local .map only after all succeed)":"");let l=0,s=0;for(let v of u)try{await qe({endpoint:r,projectId:o,secretKey:n,authCert:i,release:c,buildId:p,filePath:v}),e.log(" OK",N(v)),l++}catch(C){e.error(" FAIL",N(v),C.message),s++}let d=w&&(s===0||h),x=0;if(d&&u.length>0){for(let v of u)try{await Je(v),x++,e.log(" Deleted",N(v))}catch(C){e.error(" Delete failed",v,C.message)}s>0&&h&&e.log("Deleted .map files despite upload failures. Fix errors and re-run to re-upload.")}else s>0&&!h&&e.log("Upload had failures. Local .map files were NOT deleted. Fix errors and re-run.");return{ok:l,fail:s,deleted:x}}async function ut(t,e=console){let{uploadArchive:a,deleteMapFiles:r}=await Promise.resolve().then(()=>(W(),Y)),{dir:o,endpoint:n,projectId:i,secretKey:c,authCert:p,release:w,buildId:h,deleteEvenOnFailure:u=!1,noEncrypt:m}=t;try{let{uploaded:l}=await a({dir:o,endpoint:n,projectId:i,secretKey:c,authCert:p,release:w,buildId:h,noEncrypt:m},e);if(l===0)return{uploaded:0,deleted:0};let s=await r(o,[]);return e.log("Deleted",s.length,"local .map file(s)."),{uploaded:l,deleted:s.length}}catch(l){if(u)try{let s=await r(o,[]);e.log("Deleted",s.length,"local .map file(s) despite upload failure.")}catch(s){e.error("Delete .map after upload failure failed:",s.message)}else e.error("Upload failed. Local .map files were NOT deleted.",l.message);throw l}}async function ft(t,e=console){let{uploadArchiveChunked:a}=await Promise.resolve().then(()=>(se(),ce)),{deleteMapFiles:r}=await Promise.resolve().then(()=>(W(),Y)),{dir:o,endpoint:n,projectId:i,secretKey:c,authCert:p,release:w,buildId:h,deleteEvenOnFailure:u=!1,noEncrypt:m,chunkSizeBytes:l}=t;try{let{uploaded:s}=await a({dir:o,endpoint:n,projectId:i,secretKey:c,authCert:p,release:w,buildId:h,noEncrypt:m,chunkSizeBytes:l},e);if(s===0)return{uploaded:0,deleted:0};let d=await r(o,[]);return e.log("Deleted",d.length,"local .map file(s)."),{uploaded:s,deleted:d.length}}catch(s){if(u)try{let d=await r(o,[]);e.log("Deleted",d.length,"local .map file(s) despite upload failure.")}catch(d){e.error("Delete .map after upload failure failed:",d.message)}else e.error("Upload failed. Local .map files were NOT deleted.",s.message);throw s}}export{de as findMapFiles,pt as uploadAll,ft as uploadArchiveChunkedThenDelete,ut as uploadArchiveThenDelete,qe as uploadOne};
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};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontend-monitor/upload-sourcemaps",
3
- "version": "0.0.2",
3
+ "version": "0.1.0",
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",
@@ -11,12 +11,13 @@
11
11
  "build": "node build.js",
12
12
  "prepublishOnly": "npm run build",
13
13
  "publish:dry": "npm run build && npm publish --dry-run",
14
- "publish:public": "npm run build && npm publish --access public --tag release"
14
+ "publish:public": "npm run build && npm publish --access public --tag latest"
15
15
  },
16
16
  "files": [
17
17
  "dist",
18
18
  "README.md",
19
- "README.zh-CN.md"
19
+ "README.zh-CN.md",
20
+ "CHANGELOG.md"
20
21
  ],
21
22
  "devDependencies": {
22
23
  "esbuild": "^0.24.2"