@frontend-monitor/upload-sourcemaps 0.0.3 → 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 +37 -0
- package/README.md +27 -1
- package/README.zh-CN.md +30 -1
- package/dist/upload-sourcemaps.js +1 -1
- package/dist/upload.js +1 -1
- package/package.json +3 -2
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.
|
|
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,9 +179,16 @@ 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`
|
|
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
|
|
|
@@ -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 Je=Object.defineProperty;var N=(t,e)=>()=>(t&&(e=t(t=0)),e);var K=(t,e)=>{for(var o in e)Je(t,o,{get:e[o],enumerable:!0})};var z={};K(z,{extractProjectIdFromCert:()=>He,extractUploadKeyFromCert:()=>Ve});function He(t){if(typeof t!="string")return"";let e=t.trim();if(e.startsWith(Xe+"$"))return e.split("$")[1]||"";if(e.includes(le)){let o=e.match(/Project:\s*(\S+)/);return o?o[1]:""}return""}function Ve(t){if(typeof t!="string"||!t.includes(le))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 Xe,le,J=N(()=>{Xe="MC1",le="-----BEGIN MONITOR CERT-----"});var B={};K(B,{decryptArchive:()=>et,encryptArchive:()=>Qe,encryptArchiveWithKey:()=>fe});import{createCipheriv as Ge,createDecipheriv as qe,createHash as Ye,randomBytes as Ze}from"crypto";function de(t,e){let o=`${t}:${e}`;return Ye("sha256").update(o,"utf8").digest()}function Qe(t,e,o){let r=de(e,o);return fe(t,r)}function fe(t,e){if(!Buffer.isBuffer(e)||e.length!==32)throw new Error("Invalid key: must be 32-byte Buffer");let o=Ze(X),r=Ge(pe,e,o,{authTagLength:_}),a=Buffer.concat([r.update(t),r.final()]),n=r.getAuthTag();return Buffer.concat([o,a,n])}function et(t,e,o){if(t.length<X+_)throw new Error("Invalid encrypted archive: too short");let r=de(e,o),a=t.subarray(0,X),n=t.subarray(t.length-_),s=t.subarray(X,t.length-_),c=qe(pe,r,a,{authTagLength:_});return c.setAuthTag(n),Buffer.concat([c.update(s),c.final()])}var pe,X,_,L=N(()=>{pe="aes-256-gcm",X=12,_=16});var ee={};K(ee,{DEFAULT_EXCLUDE_EXT:()=>V,collectFiles:()=>Q,createArchive:()=>G,deleteMapFiles:()=>he,uploadArchive:()=>pt});import{createRequire as tt}from"module";import{readdir as me,unlink as rt,readFile as ot,mkdtemp as nt,rm as at}from"fs/promises";import{join as H,relative as st}from"path";import{createWriteStream as ct}from"fs";import{tmpdir as it}from"os";async function Q(t,e=t,o=V){let r=await me(t,{withFileTypes:!0}),a=[];for(let n of r){let s=H(t,n.name),c=st(e,s).replace(/\\/g,"/");if(n.isDirectory()){let p=await Q(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 Q(t,t,o),n=a.map(s=>s.relativePath);return n.length===0?0:new Promise((s,c)=>{let p=lt.create({gzip:r,cwd:t},n);p.on("error",c),p.pipe(ct(e)).on("close",()=>s(a.length)).on("error",c)})}async function pt(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 nt(H(it(),"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 ot(g),j=!i&&(d?h!==null:!!(l&&n));if(j)if(h){let{encryptArchiveWithKey:T}=await Promise.resolve().then(()=>(L(),B));S=T(S,h),e.log("Created tar.gz with",k,"file(s), encrypted with cert Upload-Key, uploading...")}else{let{encryptArchive:T}=await Promise.resolve().then(()=>(L(),B));S=T(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 P="/sourcemaps/upload-archive",D=r.replace(/\/$/,""),C=D.endsWith(P)?D:D+P,I=new FormData;I.append("projectId",l),d||I.append("secretKey",n||""),I.append("release",c),p&&I.append("buildId",p),j&&I.append("encrypted","1"),I.append("file",new Blob([S]),j?"archive.tar.gz.enc":"archive.tar.gz");let W={"X-Project-Id":l};d?W["X-Auth-Cert"]=s:W["X-Secret-Key"]=n||"";let E=await fetch(C,{method:"POST",headers:W,body:I}),U=await E.text();if(!E.ok)throw new Error(`${E.status} ${U}`);let Z=JSON.parse(U||"{}");return e.log("Upload archive OK, server extracted and saved",Z.uploaded,".map file(s)"),{ok:!0,uploaded:Z.uploaded||0}}finally{await at(y,{recursive:!0,force:!0})}}async function he(t,e=[]){let o=await me(t,{withFileTypes:!0});for(let r of o){let a=H(t,r.name);r.isDirectory()?await he(a,e):r.name.endsWith(".map")&&(await rt(a),e.push(a))}return e}var ut,lt,V,q=N(()=>{ut=tt(import.meta.url),lt=ut("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 ye={};K(ye,{uploadArchiveChunked:()=>It});import{readFile as dt,mkdtemp as ft,rm as mt}from"fs/promises";import{join as we}from"path";import{tmpdir as ht}from"os";function gt(t){return t.replace(/\/$/,"")}function Y(t,e){let o=gt(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 te(t,e,o,r=yt){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=bt*Math.pow(2,n);o.log?.(` Retry ${n+1}/${r} after ${c}ms: ${s.message}`),await vt(c)}}throw a}async function It(t,e=console){let{dir:o,endpoint:r,projectId:a,secretKey:n,authCert:s,release:c,buildId:p,noEncrypt:f,chunkSizeBytes:i=wt,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 ft(we(ht(),"upload-sourcemaps-chunked-")),k=we(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 j=await dt(k),P=!f&&(u?y!==null:!!(h&&n));if(P){if(y){let{encryptArchiveWithKey:b}=await Promise.resolve().then(()=>(L(),B));j=b(j,y)}else{let{encryptArchive:b}=await Promise.resolve().then(()=>(L(),B));j=b(j,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 D=j.length,C=Math.ceil(D/i),I={"Content-Type":"application/json"};u?I["X-Auth-Cert"]=s:(I["X-Project-Id"]=h,I["X-Secret-Key"]=n||"");let E=(await te(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:P})},e)).uploadId;if(!E)throw new Error("Init did not return uploadId");let U=new Set;for(let b=0;b<C;b++)U.add(b);try{let b=await fetch(Y(r,"/sourcemaps/upload-archive-multipart/status")+`?uploadId=${encodeURIComponent(E)}`,{method:"GET",headers:I}),F=await b.text();if(b.ok&&F){let R=JSON.parse(F).receivedChunks||[];R.forEach(A=>U.delete(A)),R.length>0&&e.log?.(`Resume: ${R.length}/${C} chunks already uploaded`)}}catch{}for(let b=0;b<C;b++){if(!U.has(b))continue;let F=b*i,ue=Math.min(F+i,D),R=j.subarray(F,ue),A=new FormData;A.append("uploadId",E),A.append("index",String(b)),A.append("totalChunks",String(C)),A.append("chunk",new Blob([R]),`chunk-${b}`);let ze=Y(r,"/sourcemaps/upload-archive-multipart/chunk");await te(ze,{method:"POST",headers:u?{"X-Auth-Cert":s}:{"X-Project-Id":h,"X-Secret-Key":n||""},body:A},e),e.log?.(` Chunk ${b+1}/${C} OK`)}let T=(await te(Y(r,"/sourcemaps/upload-archive-multipart/complete"),{method:"POST",headers:{...I,"Content-Type":"application/json"},body:JSON.stringify({uploadId:E})},e)).uploaded??0;return e.log?.("Chunked upload OK, server extracted and saved",T,".map file(s)"),{ok:!0,uploaded:T}}finally{await mt(g,{recursive:!0,force:!0})}}var wt,yt,bt,be=N(()=>{q();wt=1*1024*1024,yt=3,bt=1e3});var Ke={};K(Ke,{loadMonitorConfig:()=>Re,loadUploadSourcemapsJson:()=>Ne,resolveUploadConfig:()=>Ut});import{readFile as Ue}from"fs/promises";import{join as Te,resolve as Dt}from"path";import{pathToFileURL as Pe}from"url";function Fe(){try{return process.env.UPLOAD_ENV||process.env.NODE_ENV||"production"}catch{return"production"}}async function Re(t){let e=["monitor.config.js","monitor.config.cjs","monitor.config.mjs"];for(let o of e){let r=Te(t,o),a;try{a=await import(Pe(r).href)}catch{continue}let n=a.default;if(!n||typeof n!="object")return null;let s=Fe(),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 Ne(t){try{let e=await Ue(Te(t,".upload-sourcemaps.json"),"utf-8");return JSON.parse(e)}catch{return{}}}async function Ut(t,e){let o=null,r=null;if(e){let a=Dt(t,e);if(e.endsWith(".json"))try{r=JSON.parse(await Ue(a,"utf-8"))}catch{r={}}else try{let s=(await import(Pe(a).href)).default;if(s&&typeof s=="object"&&(s.common||s.production||s.development)){let c=Fe(),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 Re(t),r=await Ne(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 _e=N(()=>{});import{readFile as Tt}from"fs/promises";import{resolve as Pt,dirname as Ft,join as Rt}from"path";import{fileURLToPath as Nt}from"url";import{randomUUID as Be}from"crypto";import{spawn as Kt}from"child_process";import{readdir as kt,readFile as St,unlink as jt}from"fs/promises";import{join as xt,basename as $}from"path";async function ve(t,e=[]){let o;try{o=await kt(t,{withFileTypes:!0})}catch(r){if(r?.code==="ENOENT")return e;throw r}for(let r of o){let a=xt(t,r.name);r.isDirectory()?await ve(a,e):r.name.endsWith(".map")&&e.push(a)}return e}var ge="/sourcemaps/upload";function Ct(t){let e=t.replace(/\/$/,"");return e.endsWith(ge)?e:e+ge}async function Et(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=$(c,".map"),d=await St(c),u=Ct(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]),$(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 ve(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 Et({endpoint:r,projectId:a,secretKey:n,authCert:s,release:c,buildId:p,filePath:g}),e.log(" OK",$(g)),m++}catch(k){e.error(" FAIL",$(g),k.message),l++}let h=f&&(l===0||i),y=0;if(h&&d.length>0){for(let g of d)try{await jt(g),y++,e.log(" Deleted",$(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(),ee)),{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(()=>(be(),ye)),{deleteMapFiles:r}=await Promise.resolve().then(()=>(q(),ee)),{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 x,resolve as Ie}from"path";async function se(t){let e=[t,Ie(t,".."),Ie(t,"..",".."),process.cwd()];for(let o of e)try{return await ae(x(o,"package.json"),"utf-8"),o}catch{continue}return null}async function O(t){try{return await ae(t,"utf-8")}catch{return""}}async function ke(t){let e=["vite.config.js","vite.config.mjs","vite.config.cjs","vite.config.ts"];for(let o of e){let r=await O(x(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 Se(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 O(x(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 je(t){let e=await O(x(t,"vue.config.js"))||await O(x(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 xe(t){let e=["rollup.config.js","rollup.config.mjs","rollup.config.cjs"];for(let o of e){let r=await O(x(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 Ce(t){let e=["next.config.js","next.config.mjs","next.config.cjs","next.config.ts"];for(let o of e){let r=await O(x(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 Ee(t){let e=await O(x(t,"nuxt.config.js"))||await O(x(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 Ot(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(x(e,"package.json"),"utf-8");o=JSON.parse(n)}catch{return{emitsSourceMap:!0,keepMapInOutput:!1}}let r=Ot(o),a=[()=>r==="vite"?ke(e):null,()=>r==="next"?Ce(e):null,()=>r==="nuxt"?Ee(e):null,()=>r==="vue-cli"?je(e):null,()=>r==="webpack"?Se(e):null,()=>r==="rollup"?xe(e):null,()=>ke(e),()=>Ce(e),()=>je(e),()=>Se(e),()=>xe(e),()=>Ee(e)];for(let n of a){let s=await n();if(s)return s}return{emitsSourceMap:!0,keepMapInOutput:!1}}import{readFile as Ae,writeFile as Oe}from"fs/promises";import{join as Me}from"path";async function Mt(t){try{return await Ae(t,"utf-8")}catch{return""}}function At(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 De(t){let e=await se(t);if(!e)return{restore:async()=>{}};let o={};try{let n=await Ae(Me(e,"package.json"),"utf-8");o=JSON.parse(n)}catch{return{restore:async()=>{}}}let r=At(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=Me(e,s),p=await Mt(c);if(!p||!n.needPatch(p))continue;let f=n.patch(p);return await Oe(c,f,"utf-8"),{restore:async()=>{try{await Oe(c,p,"utf-8")}catch(i){console.error(`Restore ${n.name} config failed:`,i?.message||i)}}}}return{restore:async()=>{}}}var Sr=Ft(Nt(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 M(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 Le(t={}){let e=v("--chunk-size","UPLOAD_SOURCEMAPS_CHUNK_SIZE")||t.chunkSize;return _t(e)}async function Bt(){let{resolveUploadConfig:t}=await Promise.resolve().then(()=>(_e(),Ke));return t(process.cwd(),v("--config","UPLOAD_SOURCEMAPS_CONFIG")||void 0)}async function Lt(t){let e=[t,Pt(t,".."),process.cwd()];for(let o of e)try{let r=await Tt(Rt(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 $e(t,e){return t&&t!=="default"?t:await Lt(e)||"default"}var w=await Bt(),$t=process.argv[2]==="build";function We(t,e){return t||e===!0}async function Wt(){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=M("--archive")||w.uploadAsArchive===!0,c=We(M("--no-encrypt"),w.noEncrypt),f=!(await ce(n)).keepMapInOutput||M("--delete-after-upload")||M("-d")||w.deleteAfterUpload===!0,i=v("--build-id","BUILD_ID")||w.buildId||Be(),d=await De(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)=>{Kt(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 $e(v("--release","RELEASE")||w.release,n);l!=="default"&&console.log("Release (from package.json or config):",l);let h=Le(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($t)try{await Wt()}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 $e(v("--release","RELEASE")||w.release,a),s=v("--build-id","BUILD_ID")||w.buildId||Be(),c=M("--archive")||w.uploadAsArchive===!0,p=We(M("--no-encrypt"),w.noEncrypt),f=Le(w),d=!(await ce(a)).keepMapInOutput||M("--delete-after-upload")||M("-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 de=Object.defineProperty;var N=(t,e)=>()=>(t&&(e=t(t=0)),e);var L=(t,e)=>{for(var a in e)de(t,a,{get:e[a],enumerable:!0})};var X={};L(X,{extractProjectIdFromCert:()=>ue,extractUploadKeyFromCert:()=>fe});function ue(t){if(typeof t!="string")return"";let e=t.trim();if(e.startsWith(pe+"$"))return e.split("$")[1]||"";if(e.includes(Z)){let a=e.match(/Project:\s*(\S+)/);return a?a[1]:""}return""}function fe(t){if(typeof t!="string"||!t.includes(Z))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 pe,Z,B=N(()=>{pe="MC1",Z="-----BEGIN MONITOR CERT-----"});var O={};L(O,{decryptArchive:()=>xe,encryptArchive:()=>ve,encryptArchiveWithKey:()=>te});import{createCipheriv as he,createDecipheriv as me,createHash as ye,randomBytes as we}from"crypto";function ee(t,e){let a=`${t}:${e}`;return ye("sha256").update(a,"utf8").digest()}function ve(t,e,a){let r=ee(e,a);return te(t,r)}function te(t,e){if(!Buffer.isBuffer(e)||e.length!==32)throw new Error("Invalid key: must be 32-byte Buffer");let a=we(R),r=he(Q,e,a,{authTagLength:S}),o=Buffer.concat([r.update(t),r.final()]),n=r.getAuthTag();return Buffer.concat([a,o,n])}function xe(t,e,a){if(t.length<R+S)throw new Error("Invalid encrypted archive: too short");let r=ee(e,a),o=t.subarray(0,R),n=t.subarray(t.length-S),i=t.subarray(R,t.length-S),c=me(Q,r,o,{authTagLength:S});return c.setAuthTag(n),Buffer.concat([c.update(i),c.final()])}var Q,R,S,$=N(()=>{Q="aes-256-gcm",R=12,S=16});var q={};L(q,{DEFAULT_EXCLUDE_EXT:()=>z,collectFiles:()=>J,createArchive:()=>M,deleteMapFiles:()=>ae,uploadArchive:()=>je});import{createRequire as Ce}from"module";import{readdir as re,unlink as Ie,readFile as ke,mkdtemp as Ee,rm as be}from"fs/promises";import{join as _,relative as Ae}from"path";import{createWriteStream as ge}from"fs";import{tmpdir as Te}from"os";async function J(t,e=t,a=z){let r=await re(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 J(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 J(t,t,a),n=o.map(i=>i.relativePath);return n.length===0?0:new Promise((i,c)=>{let p=Fe.create({gzip:r,cwd:t},n);p.on("error",c),p.pipe(ge(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:y,noEncrypt:h}=t,u=!!i,{extractProjectIdFromCert:m,extractUploadKeyFromCert:l}=await Promise.resolve().then(()=>(B(),X)),s=o||(u?m(i):""),d=u?l(i):null,x=await Ee(_(Te(),"upload-sourcemaps-")),v=_(x,"archive.tar.gz");try{let C=await M(a,v,y||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 ke(v),I=!h&&(u?d!==null:!!(s&&n));if(I)if(d){let{encryptArchiveWithKey:D}=await Promise.resolve().then(()=>($(),O));k=D(k,d),e.log("Created tar.gz with",C,"file(s), encrypted with cert Upload-Key, uploading...")}else{let{encryptArchive:D}=await Promise.resolve().then(()=>($(),O));k=D(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 F="/sourcemaps/upload-archive",g=r.replace(/\/$/,""),E=g.endsWith(F)?g:g+F,w=new FormData;w.append("projectId",s),u||w.append("secretKey",n||""),w.append("release",c),p&&w.append("buildId",p),I&&w.append("encrypted","1"),w.append("file",new Blob([k]),I?"archive.tar.gz.enc":"archive.tar.gz");let U={"X-Project-Id":s};u?U["X-Auth-Cert"]=i:U["X-Secret-Key"]=n||"";let b=await fetch(E,{method:"POST",headers:U,body:w}),T=await b.text();if(!b.ok)throw new Error(`${b.status} ${T}`);let H=JSON.parse(T||"{}");return e.log("Upload archive OK, server extracted and saved",H.uploaded,".map file(s)"),{ok:!0,uploaded:H.uploaded||0}}finally{await be(x,{recursive:!0,force:!0})}}async function ae(t,e=[]){let a=await re(t,{withFileTypes:!0});for(let r of a){let o=_(t,r.name);r.isDirectory()?await ae(o,e):r.name.endsWith(".map")&&(await Ie(o),e.push(o))}return e}var De,Fe,z,W=N(()=>{De=Ce(import.meta.url),Fe=De("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 ne={};L(ne,{uploadArchiveChunked:()=>Be});import{readFile as Ke,mkdtemp as Se,rm as Oe}from"fs/promises";import{join as oe}from"path";import{tmpdir as $e}from"os";function Le(t){return t.replace(/\/$/,"")}function G(t,e){let a=Le(t),r=e.startsWith("/")?e:`/${e}`;return a.endsWith(r)?a:a+r}async function Xe(t){return new Promise(e=>setTimeout(e,t))}async function Y(t,e,a,r=Ue){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=Ne*Math.pow(2,n);a.log?.(` Retry ${n+1}/${r} after ${c}ms: ${i.message}`),await Xe(c)}}throw o}async function Be(t,e=console){let{dir:a,endpoint:r,projectId:o,secretKey:n,authCert:i,release:c,buildId:p,noEncrypt:y,chunkSizeBytes:h=Pe,excludeExt:u}=t,m=!!i,{extractProjectIdFromCert:l,extractUploadKeyFromCert:s}=await Promise.resolve().then(()=>(B(),X)),d=o||(m?l(i):""),x=m?s(i):null,v=await Se(oe($e(),"upload-sourcemaps-chunked-")),C=oe(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),F=!y&&(m?x!==null:!!(d&&n));if(F){if(x){let{encryptArchiveWithKey:f}=await Promise.resolve().then(()=>($(),O));I=f(I,x)}else{let{encryptArchive:f}=await Promise.resolve().then(()=>($(),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 g=I.length,E=Math.ceil(g/h),w={"Content-Type":"application/json"};m?w["X-Auth-Cert"]=i:(w["X-Project-Id"]=d,w["X-Secret-Key"]=n||"");let b=(await Y(G(r,"/sourcemaps/upload-archive-multipart/init"),{method:"POST",headers:{...w,"Content-Type":"application/json"},body:JSON.stringify({projectId:d,secretKey:m?"":n||"",release:c,buildId:p||void 0,totalChunks:E,chunkSizeBytes:h,encrypted:F})},e)).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(G(r,"/sourcemaps/upload-archive-multipart/status")+`?uploadId=${encodeURIComponent(b)}`,{method:"GET",headers:w}),j=await f.text();if(f.ok&&j){let K=JSON.parse(j).receivedChunks||[];K.forEach(A=>T.delete(A)),K.length>0&&e.log?.(`Resume: ${K.length}/${E} chunks already uploaded`)}}catch{}for(let f=0;f<E;f++){if(!T.has(f))continue;let j=f*h,V=Math.min(j+h,g),K=I.subarray(j,V),A=new FormData;A.append("uploadId",b),A.append("index",String(f)),A.append("totalChunks",String(E)),A.append("chunk",new Blob([K]),`chunk-${f}`);let le=G(r,"/sourcemaps/upload-archive-multipart/chunk");await Y(le,{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 D=(await Y(G(r,"/sourcemaps/upload-archive-multipart/complete"),{method:"POST",headers:{...w,"Content-Type":"application/json"},body:JSON.stringify({uploadId:b})},e)).uploaded??0;return e.log?.("Chunked upload OK, server extracted and saved",D,".map file(s)"),{ok:!0,uploaded:D}}finally{await Oe(v,{recursive:!0,force:!0})}}var Pe,Ue,Ne,ie=N(()=>{W();Pe=1*1024*1024,Ue=3,Ne=1e3});import{readdir as Re,readFile as _e,unlink as ze}from"fs/promises";import{join as Me,basename as P}from"path";async function se(t,e=[]){let a;try{a=await Re(t,{withFileTypes:!0})}catch(r){if(r?.code==="ENOENT")return e;throw r}for(let r of a){let o=Me(t,r.name);r.isDirectory()?await se(o,e):r.name.endsWith(".map")&&e.push(o)}return e}var ce="/sourcemaps/upload";function We(t){let e=t.replace(/\/$/,"");return e.endsWith(ce)?e:e+ce}async function Ge(t){let{endpoint:e,projectId:a,secretKey:r,authCert:o,release:n,buildId:i,filePath:c}=t,p=!!o,y=a||(p?(await Promise.resolve().then(()=>(B(),X))).extractProjectIdFromCert(o):""),h=P(c,".map"),u=await _e(c),m=We(e),l=new FormData;l.append("projectId",y),p||l.append("secretKey",r||""),l.append("release",n),i&&l.append("buildId",i),l.append("filename",h),l.append("file",new Blob([u]),P(c));let d=await fetch(m,{method:"POST",headers:p?{"X-Project-Id":y,"X-Auth-Cert":o}:{"X-Project-Id":y,"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 ct(t,e=console){let{dir:a,endpoint:r,projectId:o,secretKey:n,authCert:i,release:c,buildId:p,deleteAfterUpload:y=!1,deleteEvenOnFailure:h=!1}=t,u=await se(a);if(u.length===0)return e.log("No .map files found in",a),{ok:0,fail:0,deleted:0};let m=y&&h;e.log("Uploading",u.length,"source map(s) to",r,"release=",c,y?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 Ge({endpoint:r,projectId:o,secretKey:n,authCert:i,release:c,buildId:p,filePath:v}),e.log(" OK",P(v)),l++}catch(C){e.error(" FAIL",P(v),C.message),s++}let d=y&&(s===0||h),x=0;if(d&&u.length>0){for(let v of u)try{await ze(v),x++,e.log(" Deleted",P(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 st(t,e=console){let{uploadArchive:a,deleteMapFiles:r}=await Promise.resolve().then(()=>(W(),q)),{dir:o,endpoint:n,projectId:i,secretKey:c,authCert:p,release:y,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:y,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 lt(t,e=console){let{uploadArchiveChunked:a}=await Promise.resolve().then(()=>(ie(),ne)),{deleteMapFiles:r}=await Promise.resolve().then(()=>(W(),q)),{dir:o,endpoint:n,projectId:i,secretKey:c,authCert:p,release:y,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:y,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{se as findMapFiles,ct as uploadAll,lt as uploadArchiveChunkedThenDelete,st as uploadArchiveThenDelete,Ge 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
|
|
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",
|
|
@@ -16,7 +16,8 @@
|
|
|
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"
|