@nanyujun/rum-vite-plugin-sourcemap 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.
Potentially problematic release.
This version of @nanyujun/rum-vite-plugin-sourcemap might be problematic. Click here for more details.
- package/dist/index.cjs +198 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +173 -0
- package/dist/index.js.map +1 -0
- package/package.json +37 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
rumSourcemap: () => rumSourcemap
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
var import_node_path = require("path");
|
|
27
|
+
|
|
28
|
+
// ../sourcemap-cli/dist/index.js
|
|
29
|
+
var import_promises = require("fs/promises");
|
|
30
|
+
var import_path = require("path");
|
|
31
|
+
var SourceMapUploadError = class extends Error {
|
|
32
|
+
constructor(message, status) {
|
|
33
|
+
super(message);
|
|
34
|
+
this.name = "SourceMapUploadError";
|
|
35
|
+
this.status = status;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var DEFAULT_RETRIES = 3;
|
|
39
|
+
var DEFAULT_RETRY_DELAY_MS = 1e3;
|
|
40
|
+
var DEFAULT_CONCURRENCY = 4;
|
|
41
|
+
function sourceMapUrl(endpoint) {
|
|
42
|
+
return `${endpoint.replace(/\/+$/, "")}/admin/sourcemaps`;
|
|
43
|
+
}
|
|
44
|
+
function sleep(ms) {
|
|
45
|
+
if (ms <= 0) return Promise.resolve();
|
|
46
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
47
|
+
}
|
|
48
|
+
function retryDelay(baseMs, retryIndex) {
|
|
49
|
+
return baseMs * 2 ** retryIndex;
|
|
50
|
+
}
|
|
51
|
+
async function responseMessage(response) {
|
|
52
|
+
try {
|
|
53
|
+
const body = await response.json();
|
|
54
|
+
if (typeof body.error === "string" && body.error.length > 0) return body.error;
|
|
55
|
+
} catch {
|
|
56
|
+
}
|
|
57
|
+
return response.statusText || `HTTP ${response.status}`;
|
|
58
|
+
}
|
|
59
|
+
function isRetryable(status) {
|
|
60
|
+
return status >= 500 || status === 408 || status === 429;
|
|
61
|
+
}
|
|
62
|
+
async function readUploadResult(response) {
|
|
63
|
+
const body = await response.json();
|
|
64
|
+
return {
|
|
65
|
+
id: Number(body.id),
|
|
66
|
+
sha256: String(body.sha256),
|
|
67
|
+
sizeBytes: Number(body.sizeBytes)
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
async function uploadFile(options) {
|
|
71
|
+
const fetcher = options.fetchImpl ?? fetch;
|
|
72
|
+
const retries = options.retries ?? DEFAULT_RETRIES;
|
|
73
|
+
const retryDelayMs = options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;
|
|
74
|
+
let lastError;
|
|
75
|
+
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
76
|
+
try {
|
|
77
|
+
const content = await (0, import_promises.readFile)(options.mapPath);
|
|
78
|
+
const form = new FormData();
|
|
79
|
+
form.set("appId", options.appId);
|
|
80
|
+
form.set("release", options.release);
|
|
81
|
+
form.set("file", options.file);
|
|
82
|
+
form.set("map", new Blob([new Uint8Array(content)]), (0, import_path.basename)(options.mapPath));
|
|
83
|
+
const response = await fetcher(sourceMapUrl(options.endpoint), {
|
|
84
|
+
method: "POST",
|
|
85
|
+
headers: { Authorization: `Bearer ${options.token}` },
|
|
86
|
+
body: form
|
|
87
|
+
});
|
|
88
|
+
if (response.ok) return readUploadResult(response);
|
|
89
|
+
const message = await responseMessage(response);
|
|
90
|
+
if (!isRetryable(response.status) || attempt >= retries) {
|
|
91
|
+
throw new SourceMapUploadError(message, response.status);
|
|
92
|
+
}
|
|
93
|
+
lastError = new SourceMapUploadError(message, response.status);
|
|
94
|
+
} catch (err) {
|
|
95
|
+
if (err instanceof SourceMapUploadError && !isRetryable(err.status ?? 0)) throw err;
|
|
96
|
+
lastError = err;
|
|
97
|
+
if (attempt >= retries) break;
|
|
98
|
+
}
|
|
99
|
+
await sleep(retryDelay(retryDelayMs, attempt));
|
|
100
|
+
}
|
|
101
|
+
if (lastError instanceof Error) throw lastError;
|
|
102
|
+
throw new SourceMapUploadError("source map upload failed");
|
|
103
|
+
}
|
|
104
|
+
async function collectMapFiles(dir) {
|
|
105
|
+
const files = [];
|
|
106
|
+
const entries = await (0, import_promises.opendir)(dir);
|
|
107
|
+
for await (const entry of entries) {
|
|
108
|
+
const path = (0, import_path.join)(dir, entry.name);
|
|
109
|
+
if (entry.isDirectory()) {
|
|
110
|
+
files.push(...await collectMapFiles(path));
|
|
111
|
+
} else if (entry.isFile() && entry.name.endsWith(".map")) {
|
|
112
|
+
files.push(path);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return files.sort();
|
|
116
|
+
}
|
|
117
|
+
function toSourceFile(distDir, mapPath) {
|
|
118
|
+
return (0, import_path.relative)(distDir, mapPath).split("\\").join("/").replace(/\.map$/, "");
|
|
119
|
+
}
|
|
120
|
+
async function runPool(items, concurrency, worker) {
|
|
121
|
+
const results = [];
|
|
122
|
+
let cursor = 0;
|
|
123
|
+
const workerCount = Math.max(1, Math.min(concurrency, items.length));
|
|
124
|
+
await Promise.all(
|
|
125
|
+
Array.from({ length: workerCount }, async () => {
|
|
126
|
+
for (; ; ) {
|
|
127
|
+
const index = cursor++;
|
|
128
|
+
const item = items[index];
|
|
129
|
+
if (item === void 0) break;
|
|
130
|
+
results[index] = await worker(item);
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
);
|
|
134
|
+
return results;
|
|
135
|
+
}
|
|
136
|
+
async function uploadDir(options) {
|
|
137
|
+
const mapPaths = await collectMapFiles(options.distDir);
|
|
138
|
+
const concurrency = options.concurrency ?? DEFAULT_CONCURRENCY;
|
|
139
|
+
const uploaded = await runPool(mapPaths, concurrency, async (mapPath) => {
|
|
140
|
+
const file = toSourceFile(options.distDir, mapPath);
|
|
141
|
+
const result = await uploadFile({
|
|
142
|
+
appId: options.appId,
|
|
143
|
+
release: options.release,
|
|
144
|
+
endpoint: options.endpoint,
|
|
145
|
+
token: options.token,
|
|
146
|
+
file,
|
|
147
|
+
mapPath,
|
|
148
|
+
retries: options.retries,
|
|
149
|
+
retryDelayMs: options.retryDelayMs,
|
|
150
|
+
fetchImpl: options.fetchImpl
|
|
151
|
+
});
|
|
152
|
+
return { ...result, file, mapPath };
|
|
153
|
+
});
|
|
154
|
+
return { uploaded };
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// src/index.ts
|
|
158
|
+
function isEnabled(options) {
|
|
159
|
+
if (options.disabled !== void 0) return !options.disabled;
|
|
160
|
+
return process.env.NODE_ENV === "production";
|
|
161
|
+
}
|
|
162
|
+
function resolveDistDir(config, distDir) {
|
|
163
|
+
const dir = distDir ?? config.build.outDir;
|
|
164
|
+
return (0, import_node_path.isAbsolute)(dir) ? dir : (0, import_node_path.resolve)(config.root, dir);
|
|
165
|
+
}
|
|
166
|
+
function rumSourcemap(options) {
|
|
167
|
+
let config;
|
|
168
|
+
return {
|
|
169
|
+
name: "rum-sourcemap",
|
|
170
|
+
apply: "build",
|
|
171
|
+
configResolved(resolved) {
|
|
172
|
+
config = resolved;
|
|
173
|
+
if (isEnabled(options) && resolved.build.sourcemap !== "hidden") {
|
|
174
|
+
resolved.logger.warn("[rum-sourcemap] build.sourcemap should be 'hidden' to avoid publishing .map files.");
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
async closeBundle() {
|
|
178
|
+
if (!config || config.command !== "build" || !isEnabled(options)) return;
|
|
179
|
+
if (!options.token) {
|
|
180
|
+
config.logger.warn("[rum-sourcemap] token is missing; skip source map upload.");
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
await uploadDir({
|
|
184
|
+
appId: options.app,
|
|
185
|
+
release: options.release,
|
|
186
|
+
endpoint: options.endpoint,
|
|
187
|
+
token: options.token,
|
|
188
|
+
distDir: resolveDistDir(config, options.distDir),
|
|
189
|
+
...options.concurrency !== void 0 && { concurrency: options.concurrency }
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
195
|
+
0 && (module.exports = {
|
|
196
|
+
rumSourcemap
|
|
197
|
+
});
|
|
198
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../../sourcemap-cli/src/index.ts"],"sourcesContent":["import { isAbsolute, resolve } from 'node:path';\nimport type { Plugin, ResolvedConfig } from 'vite';\nimport { uploadDir } from '@rum/sourcemap-cli';\n\nexport interface RumSourcemapPluginOptions {\n app: string;\n release: string;\n endpoint: string;\n token?: string;\n distDir?: string;\n concurrency?: number;\n disabled?: boolean;\n}\n\nfunction isEnabled(options: RumSourcemapPluginOptions): boolean {\n if (options.disabled !== undefined) return !options.disabled;\n return process.env.NODE_ENV === 'production';\n}\n\nfunction resolveDistDir(config: ResolvedConfig, distDir: string | undefined): string {\n const dir = distDir ?? config.build.outDir;\n return isAbsolute(dir) ? dir : resolve(config.root, dir);\n}\n\nexport function rumSourcemap(options: RumSourcemapPluginOptions): Plugin {\n let config: ResolvedConfig | undefined;\n\n return {\n name: 'rum-sourcemap',\n apply: 'build',\n\n configResolved(resolved) {\n config = resolved;\n if (isEnabled(options) && resolved.build.sourcemap !== 'hidden') {\n resolved.logger.warn(\"[rum-sourcemap] build.sourcemap should be 'hidden' to avoid publishing .map files.\");\n }\n },\n\n async closeBundle() {\n if (!config || config.command !== 'build' || !isEnabled(options)) return;\n if (!options.token) {\n config.logger.warn('[rum-sourcemap] token is missing; skip source map upload.');\n return;\n }\n\n await uploadDir({\n appId: options.app,\n release: options.release,\n endpoint: options.endpoint,\n token: options.token,\n distDir: resolveDistDir(config, options.distDir),\n ...(options.concurrency !== undefined && { concurrency: options.concurrency }),\n });\n },\n };\n}\n","import { opendir, readFile } from 'node:fs/promises';\nimport { basename, join, relative } from 'node:path';\n\nexport interface UploadFileResult {\n id: number;\n sha256: string;\n sizeBytes: number;\n}\n\nexport interface UploadFileOptions {\n appId: string;\n release: string;\n endpoint: string;\n token: string;\n file: string;\n mapPath: string;\n retries?: number;\n retryDelayMs?: number;\n fetchImpl?: typeof fetch;\n}\n\nexport interface UploadDirOptions {\n appId: string;\n release: string;\n endpoint: string;\n token: string;\n distDir: string;\n concurrency?: number;\n retries?: number;\n retryDelayMs?: number;\n fetchImpl?: typeof fetch;\n}\n\nexport interface UploadedSourceMap extends UploadFileResult {\n file: string;\n mapPath: string;\n}\n\nexport interface UploadDirResult {\n uploaded: UploadedSourceMap[];\n}\n\nexport interface ParsedUploadCommand {\n command: 'upload';\n appId: string;\n release: string;\n distDir: string;\n endpoint: string;\n token: string;\n concurrency?: number;\n}\n\nexport class SourceMapUploadError extends Error {\n status?: number;\n\n constructor(message: string, status?: number) {\n super(message);\n this.name = 'SourceMapUploadError';\n this.status = status;\n }\n}\n\nexport class SourceMapCliUsageError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'SourceMapCliUsageError';\n }\n}\n\nconst DEFAULT_RETRIES = 3;\nconst DEFAULT_RETRY_DELAY_MS = 1000;\nconst DEFAULT_CONCURRENCY = 4;\n\nfunction sourceMapUrl(endpoint: string): string {\n return `${endpoint.replace(/\\/+$/, '')}/admin/sourcemaps`;\n}\n\nfunction sleep(ms: number): Promise<void> {\n if (ms <= 0) return Promise.resolve();\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction retryDelay(baseMs: number, retryIndex: number): number {\n return baseMs * 2 ** retryIndex;\n}\n\nasync function responseMessage(response: Response): Promise<string> {\n try {\n const body = (await response.json()) as { error?: unknown };\n if (typeof body.error === 'string' && body.error.length > 0) return body.error;\n } catch {\n // Ignore malformed error bodies; status text is enough for CLI output.\n }\n return response.statusText || `HTTP ${response.status}`;\n}\n\nfunction isRetryable(status: number): boolean {\n return status >= 500 || status === 408 || status === 429;\n}\n\nasync function readUploadResult(response: Response): Promise<UploadFileResult> {\n const body = (await response.json()) as Partial<UploadFileResult>;\n return {\n id: Number(body.id),\n sha256: String(body.sha256),\n sizeBytes: Number(body.sizeBytes),\n };\n}\n\nexport async function uploadFile(options: UploadFileOptions): Promise<UploadFileResult> {\n const fetcher = options.fetchImpl ?? fetch;\n const retries = options.retries ?? DEFAULT_RETRIES;\n const retryDelayMs = options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n const content = await readFile(options.mapPath);\n const form = new FormData();\n form.set('appId', options.appId);\n form.set('release', options.release);\n form.set('file', options.file);\n form.set('map', new Blob([new Uint8Array(content)]), basename(options.mapPath));\n\n const response = await fetcher(sourceMapUrl(options.endpoint), {\n method: 'POST',\n headers: { Authorization: `Bearer ${options.token}` },\n body: form,\n });\n\n if (response.ok) return readUploadResult(response);\n const message = await responseMessage(response);\n if (!isRetryable(response.status) || attempt >= retries) {\n throw new SourceMapUploadError(message, response.status);\n }\n lastError = new SourceMapUploadError(message, response.status);\n } catch (err) {\n if (err instanceof SourceMapUploadError && !isRetryable(err.status ?? 0)) throw err;\n lastError = err;\n if (attempt >= retries) break;\n }\n\n await sleep(retryDelay(retryDelayMs, attempt));\n }\n\n if (lastError instanceof Error) throw lastError;\n throw new SourceMapUploadError('source map upload failed');\n}\n\nasync function collectMapFiles(dir: string): Promise<string[]> {\n const files: string[] = [];\n const entries = await opendir(dir);\n for await (const entry of entries) {\n const path = join(dir, entry.name);\n if (entry.isDirectory()) {\n files.push(...(await collectMapFiles(path)));\n } else if (entry.isFile() && entry.name.endsWith('.map')) {\n files.push(path);\n }\n }\n return files.sort();\n}\n\nfunction toSourceFile(distDir: string, mapPath: string): string {\n return relative(distDir, mapPath).split('\\\\').join('/').replace(/\\.map$/, '');\n}\n\nasync function runPool<T, R>(\n items: T[],\n concurrency: number,\n worker: (item: T) => Promise<R>,\n): Promise<R[]> {\n const results: R[] = [];\n let cursor = 0;\n const workerCount = Math.max(1, Math.min(concurrency, items.length));\n\n await Promise.all(\n Array.from({ length: workerCount }, async () => {\n for (;;) {\n const index = cursor++;\n const item = items[index];\n if (item === undefined) break;\n results[index] = await worker(item);\n }\n }),\n );\n\n return results;\n}\n\nexport async function uploadDir(options: UploadDirOptions): Promise<UploadDirResult> {\n const mapPaths = await collectMapFiles(options.distDir);\n const concurrency = options.concurrency ?? DEFAULT_CONCURRENCY;\n const uploaded = await runPool(mapPaths, concurrency, async (mapPath) => {\n const file = toSourceFile(options.distDir, mapPath);\n const result = await uploadFile({\n appId: options.appId,\n release: options.release,\n endpoint: options.endpoint,\n token: options.token,\n file,\n mapPath,\n retries: options.retries,\n retryDelayMs: options.retryDelayMs,\n fetchImpl: options.fetchImpl,\n });\n return { ...result, file, mapPath };\n });\n return { uploaded };\n}\n\nfunction readFlag(argv: string[], flag: string): string | undefined {\n const index = argv.indexOf(flag);\n if (index === -1) return undefined;\n return argv[index + 1];\n}\n\nfunction required(value: string | undefined, flag: string): string {\n if (!value) throw new SourceMapCliUsageError(`missing ${flag}`);\n return value;\n}\n\nexport function parseCliArgs(argv: string[]): ParsedUploadCommand {\n const command = argv[0];\n if (command !== 'upload') {\n throw new SourceMapCliUsageError('usage: rum-sourcemap upload --app <appId> --release <release> --dist <dir> --endpoint <url> --token <token>');\n }\n\n const concurrencyRaw = readFlag(argv, '--concurrency');\n return {\n command: 'upload',\n appId: required(readFlag(argv, '--app') ?? readFlag(argv, '--app-id'), '--app'),\n release: required(readFlag(argv, '--release'), '--release'),\n distDir: required(readFlag(argv, '--dist'), '--dist'),\n endpoint: required(readFlag(argv, '--endpoint'), '--endpoint'),\n token: required(readFlag(argv, '--token'), '--token'),\n ...(concurrencyRaw !== undefined && { concurrency: Number(concurrencyRaw) }),\n };\n}\n\nexport async function runCli(argv: string[], log: (message: string) => void = console.warn) {\n const command = parseCliArgs(argv);\n const result = await uploadDir(command);\n log(`uploaded ${result.uploaded.length} source maps`);\n return result;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAAoC;;;ACApC,sBAAkC;AAClC,kBAAyC;AAmDlC,IAAM,uBAAN,cAAmC,MAAM;EAG9C,YAAY,SAAiB,QAAiB;AAC5C,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;EAChB;AACF;AASA,IAAM,kBAAkB;AACxB,IAAM,yBAAyB;AAC/B,IAAM,sBAAsB;AAE5B,SAAS,aAAa,UAA0B;AAC9C,SAAO,GAAG,SAAS,QAAQ,QAAQ,EAAE,CAAC;AACxC;AAEA,SAAS,MAAM,IAA2B;AACxC,MAAI,MAAM,EAAG,QAAO,QAAQ,QAAQ;AACpC,SAAO,IAAI,QAAQ,CAACA,aAAY,WAAWA,UAAS,EAAE,CAAC;AACzD;AAEA,SAAS,WAAW,QAAgB,YAA4B;AAC9D,SAAO,SAAS,KAAK;AACvB;AAEA,eAAe,gBAAgB,UAAqC;AAClE,MAAI;AACF,UAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,QAAI,OAAO,KAAK,UAAU,YAAY,KAAK,MAAM,SAAS,EAAG,QAAO,KAAK;EAC3E,QAAQ;EAER;AACA,SAAO,SAAS,cAAc,QAAQ,SAAS,MAAM;AACvD;AAEA,SAAS,YAAY,QAAyB;AAC5C,SAAO,UAAU,OAAO,WAAW,OAAO,WAAW;AACvD;AAEA,eAAe,iBAAiB,UAA+C;AAC7E,QAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,SAAO;IACL,IAAI,OAAO,KAAK,EAAE;IAClB,QAAQ,OAAO,KAAK,MAAM;IAC1B,WAAW,OAAO,KAAK,SAAS;EAClC;AACF;AAEA,eAAsB,WAAW,SAAuD;AACtF,QAAM,UAAU,QAAQ,aAAa;AACrC,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,eAAe,QAAQ,gBAAgB;AAC7C,MAAI;AAEJ,WAAS,UAAU,GAAG,WAAW,SAAS,WAAW;AACnD,QAAI;AACF,YAAM,UAAU,UAAM,0BAAS,QAAQ,OAAO;AAC9C,YAAM,OAAO,IAAI,SAAS;AAC1B,WAAK,IAAI,SAAS,QAAQ,KAAK;AAC/B,WAAK,IAAI,WAAW,QAAQ,OAAO;AACnC,WAAK,IAAI,QAAQ,QAAQ,IAAI;AAC7B,WAAK,IAAI,OAAO,IAAI,KAAK,CAAC,IAAI,WAAW,OAAO,CAAC,CAAC,OAAG,sBAAS,QAAQ,OAAO,CAAC;AAE9E,YAAM,WAAW,MAAM,QAAQ,aAAa,QAAQ,QAAQ,GAAG;QAC7D,QAAQ;QACR,SAAS,EAAE,eAAe,UAAU,QAAQ,KAAK,GAAG;QACpD,MAAM;MACR,CAAC;AAED,UAAI,SAAS,GAAI,QAAO,iBAAiB,QAAQ;AACjD,YAAM,UAAU,MAAM,gBAAgB,QAAQ;AAC9C,UAAI,CAAC,YAAY,SAAS,MAAM,KAAK,WAAW,SAAS;AACvD,cAAM,IAAI,qBAAqB,SAAS,SAAS,MAAM;MACzD;AACA,kBAAY,IAAI,qBAAqB,SAAS,SAAS,MAAM;IAC/D,SAAS,KAAK;AACZ,UAAI,eAAe,wBAAwB,CAAC,YAAY,IAAI,UAAU,CAAC,EAAG,OAAM;AAChF,kBAAY;AACZ,UAAI,WAAW,QAAS;IAC1B;AAEA,UAAM,MAAM,WAAW,cAAc,OAAO,CAAC;EAC/C;AAEA,MAAI,qBAAqB,MAAO,OAAM;AACtC,QAAM,IAAI,qBAAqB,0BAA0B;AAC3D;AAEA,eAAe,gBAAgB,KAAgC;AAC7D,QAAM,QAAkB,CAAC;AACzB,QAAM,UAAU,UAAM,yBAAQ,GAAG;AACjC,mBAAiB,SAAS,SAAS;AACjC,UAAM,WAAO,kBAAK,KAAK,MAAM,IAAI;AACjC,QAAI,MAAM,YAAY,GAAG;AACvB,YAAM,KAAK,GAAI,MAAM,gBAAgB,IAAI,CAAE;IAC7C,WAAW,MAAM,OAAO,KAAK,MAAM,KAAK,SAAS,MAAM,GAAG;AACxD,YAAM,KAAK,IAAI;IACjB;EACF;AACA,SAAO,MAAM,KAAK;AACpB;AAEA,SAAS,aAAa,SAAiB,SAAyB;AAC9D,aAAO,sBAAS,SAAS,OAAO,EAAE,MAAM,IAAI,EAAE,KAAK,GAAG,EAAE,QAAQ,UAAU,EAAE;AAC9E;AAEA,eAAe,QACb,OACA,aACA,QACc;AACd,QAAM,UAAe,CAAC;AACtB,MAAI,SAAS;AACb,QAAM,cAAc,KAAK,IAAI,GAAG,KAAK,IAAI,aAAa,MAAM,MAAM,CAAC;AAEnE,QAAM,QAAQ;IACZ,MAAM,KAAK,EAAE,QAAQ,YAAY,GAAG,YAAY;AAC9C,iBAAS;AACP,cAAM,QAAQ;AACd,cAAM,OAAO,MAAM,KAAK;AACxB,YAAI,SAAS,OAAW;AACxB,gBAAQ,KAAK,IAAI,MAAM,OAAO,IAAI;MACpC;IACF,CAAC;EACH;AAEA,SAAO;AACT;AAEA,eAAsB,UAAU,SAAqD;AACnF,QAAM,WAAW,MAAM,gBAAgB,QAAQ,OAAO;AACtD,QAAM,cAAc,QAAQ,eAAe;AAC3C,QAAM,WAAW,MAAM,QAAQ,UAAU,aAAa,OAAO,YAAY;AACvE,UAAM,OAAO,aAAa,QAAQ,SAAS,OAAO;AAClD,UAAM,SAAS,MAAM,WAAW;MAC9B,OAAO,QAAQ;MACf,SAAS,QAAQ;MACjB,UAAU,QAAQ;MAClB,OAAO,QAAQ;MACf;MACA;MACA,SAAS,QAAQ;MACjB,cAAc,QAAQ;MACtB,WAAW,QAAQ;IACrB,CAAC;AACD,WAAO,EAAE,GAAG,QAAQ,MAAM,QAAQ;EACpC,CAAC;AACD,SAAO,EAAE,SAAS;AACpB;;;ADnMA,SAAS,UAAU,SAA6C;AAC9D,MAAI,QAAQ,aAAa,OAAW,QAAO,CAAC,QAAQ;AACpD,SAAO,QAAQ,IAAI,aAAa;AAClC;AAEA,SAAS,eAAe,QAAwB,SAAqC;AACnF,QAAM,MAAM,WAAW,OAAO,MAAM;AACpC,aAAO,6BAAW,GAAG,IAAI,UAAM,0BAAQ,OAAO,MAAM,GAAG;AACzD;AAEO,SAAS,aAAa,SAA4C;AACvE,MAAI;AAEJ,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IAEP,eAAe,UAAU;AACvB,eAAS;AACT,UAAI,UAAU,OAAO,KAAK,SAAS,MAAM,cAAc,UAAU;AAC/D,iBAAS,OAAO,KAAK,oFAAoF;AAAA,MAC3G;AAAA,IACF;AAAA,IAEA,MAAM,cAAc;AAClB,UAAI,CAAC,UAAU,OAAO,YAAY,WAAW,CAAC,UAAU,OAAO,EAAG;AAClE,UAAI,CAAC,QAAQ,OAAO;AAClB,eAAO,OAAO,KAAK,2DAA2D;AAC9E;AAAA,MACF;AAEA,YAAM,UAAU;AAAA,QACd,OAAO,QAAQ;AAAA,QACf,SAAS,QAAQ;AAAA,QACjB,UAAU,QAAQ;AAAA,QAClB,OAAO,QAAQ;AAAA,QACf,SAAS,eAAe,QAAQ,QAAQ,OAAO;AAAA,QAC/C,GAAI,QAAQ,gBAAgB,UAAa,EAAE,aAAa,QAAQ,YAAY;AAAA,MAC9E,CAAC;AAAA,IACH;AAAA,EACF;AACF;","names":["resolve"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Plugin } from 'vite';
|
|
2
|
+
|
|
3
|
+
interface RumSourcemapPluginOptions {
|
|
4
|
+
app: string;
|
|
5
|
+
release: string;
|
|
6
|
+
endpoint: string;
|
|
7
|
+
token?: string;
|
|
8
|
+
distDir?: string;
|
|
9
|
+
concurrency?: number;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
}
|
|
12
|
+
declare function rumSourcemap(options: RumSourcemapPluginOptions): Plugin;
|
|
13
|
+
|
|
14
|
+
export { type RumSourcemapPluginOptions, rumSourcemap };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Plugin } from 'vite';
|
|
2
|
+
|
|
3
|
+
interface RumSourcemapPluginOptions {
|
|
4
|
+
app: string;
|
|
5
|
+
release: string;
|
|
6
|
+
endpoint: string;
|
|
7
|
+
token?: string;
|
|
8
|
+
distDir?: string;
|
|
9
|
+
concurrency?: number;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
}
|
|
12
|
+
declare function rumSourcemap(options: RumSourcemapPluginOptions): Plugin;
|
|
13
|
+
|
|
14
|
+
export { type RumSourcemapPluginOptions, rumSourcemap };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { isAbsolute, resolve } from "path";
|
|
3
|
+
|
|
4
|
+
// ../sourcemap-cli/dist/index.js
|
|
5
|
+
import { opendir, readFile } from "fs/promises";
|
|
6
|
+
import { basename, join, relative } from "path";
|
|
7
|
+
var SourceMapUploadError = class extends Error {
|
|
8
|
+
constructor(message, status) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "SourceMapUploadError";
|
|
11
|
+
this.status = status;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
var DEFAULT_RETRIES = 3;
|
|
15
|
+
var DEFAULT_RETRY_DELAY_MS = 1e3;
|
|
16
|
+
var DEFAULT_CONCURRENCY = 4;
|
|
17
|
+
function sourceMapUrl(endpoint) {
|
|
18
|
+
return `${endpoint.replace(/\/+$/, "")}/admin/sourcemaps`;
|
|
19
|
+
}
|
|
20
|
+
function sleep(ms) {
|
|
21
|
+
if (ms <= 0) return Promise.resolve();
|
|
22
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
23
|
+
}
|
|
24
|
+
function retryDelay(baseMs, retryIndex) {
|
|
25
|
+
return baseMs * 2 ** retryIndex;
|
|
26
|
+
}
|
|
27
|
+
async function responseMessage(response) {
|
|
28
|
+
try {
|
|
29
|
+
const body = await response.json();
|
|
30
|
+
if (typeof body.error === "string" && body.error.length > 0) return body.error;
|
|
31
|
+
} catch {
|
|
32
|
+
}
|
|
33
|
+
return response.statusText || `HTTP ${response.status}`;
|
|
34
|
+
}
|
|
35
|
+
function isRetryable(status) {
|
|
36
|
+
return status >= 500 || status === 408 || status === 429;
|
|
37
|
+
}
|
|
38
|
+
async function readUploadResult(response) {
|
|
39
|
+
const body = await response.json();
|
|
40
|
+
return {
|
|
41
|
+
id: Number(body.id),
|
|
42
|
+
sha256: String(body.sha256),
|
|
43
|
+
sizeBytes: Number(body.sizeBytes)
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async function uploadFile(options) {
|
|
47
|
+
const fetcher = options.fetchImpl ?? fetch;
|
|
48
|
+
const retries = options.retries ?? DEFAULT_RETRIES;
|
|
49
|
+
const retryDelayMs = options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;
|
|
50
|
+
let lastError;
|
|
51
|
+
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
52
|
+
try {
|
|
53
|
+
const content = await readFile(options.mapPath);
|
|
54
|
+
const form = new FormData();
|
|
55
|
+
form.set("appId", options.appId);
|
|
56
|
+
form.set("release", options.release);
|
|
57
|
+
form.set("file", options.file);
|
|
58
|
+
form.set("map", new Blob([new Uint8Array(content)]), basename(options.mapPath));
|
|
59
|
+
const response = await fetcher(sourceMapUrl(options.endpoint), {
|
|
60
|
+
method: "POST",
|
|
61
|
+
headers: { Authorization: `Bearer ${options.token}` },
|
|
62
|
+
body: form
|
|
63
|
+
});
|
|
64
|
+
if (response.ok) return readUploadResult(response);
|
|
65
|
+
const message = await responseMessage(response);
|
|
66
|
+
if (!isRetryable(response.status) || attempt >= retries) {
|
|
67
|
+
throw new SourceMapUploadError(message, response.status);
|
|
68
|
+
}
|
|
69
|
+
lastError = new SourceMapUploadError(message, response.status);
|
|
70
|
+
} catch (err) {
|
|
71
|
+
if (err instanceof SourceMapUploadError && !isRetryable(err.status ?? 0)) throw err;
|
|
72
|
+
lastError = err;
|
|
73
|
+
if (attempt >= retries) break;
|
|
74
|
+
}
|
|
75
|
+
await sleep(retryDelay(retryDelayMs, attempt));
|
|
76
|
+
}
|
|
77
|
+
if (lastError instanceof Error) throw lastError;
|
|
78
|
+
throw new SourceMapUploadError("source map upload failed");
|
|
79
|
+
}
|
|
80
|
+
async function collectMapFiles(dir) {
|
|
81
|
+
const files = [];
|
|
82
|
+
const entries = await opendir(dir);
|
|
83
|
+
for await (const entry of entries) {
|
|
84
|
+
const path = join(dir, entry.name);
|
|
85
|
+
if (entry.isDirectory()) {
|
|
86
|
+
files.push(...await collectMapFiles(path));
|
|
87
|
+
} else if (entry.isFile() && entry.name.endsWith(".map")) {
|
|
88
|
+
files.push(path);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return files.sort();
|
|
92
|
+
}
|
|
93
|
+
function toSourceFile(distDir, mapPath) {
|
|
94
|
+
return relative(distDir, mapPath).split("\\").join("/").replace(/\.map$/, "");
|
|
95
|
+
}
|
|
96
|
+
async function runPool(items, concurrency, worker) {
|
|
97
|
+
const results = [];
|
|
98
|
+
let cursor = 0;
|
|
99
|
+
const workerCount = Math.max(1, Math.min(concurrency, items.length));
|
|
100
|
+
await Promise.all(
|
|
101
|
+
Array.from({ length: workerCount }, async () => {
|
|
102
|
+
for (; ; ) {
|
|
103
|
+
const index = cursor++;
|
|
104
|
+
const item = items[index];
|
|
105
|
+
if (item === void 0) break;
|
|
106
|
+
results[index] = await worker(item);
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
);
|
|
110
|
+
return results;
|
|
111
|
+
}
|
|
112
|
+
async function uploadDir(options) {
|
|
113
|
+
const mapPaths = await collectMapFiles(options.distDir);
|
|
114
|
+
const concurrency = options.concurrency ?? DEFAULT_CONCURRENCY;
|
|
115
|
+
const uploaded = await runPool(mapPaths, concurrency, async (mapPath) => {
|
|
116
|
+
const file = toSourceFile(options.distDir, mapPath);
|
|
117
|
+
const result = await uploadFile({
|
|
118
|
+
appId: options.appId,
|
|
119
|
+
release: options.release,
|
|
120
|
+
endpoint: options.endpoint,
|
|
121
|
+
token: options.token,
|
|
122
|
+
file,
|
|
123
|
+
mapPath,
|
|
124
|
+
retries: options.retries,
|
|
125
|
+
retryDelayMs: options.retryDelayMs,
|
|
126
|
+
fetchImpl: options.fetchImpl
|
|
127
|
+
});
|
|
128
|
+
return { ...result, file, mapPath };
|
|
129
|
+
});
|
|
130
|
+
return { uploaded };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// src/index.ts
|
|
134
|
+
function isEnabled(options) {
|
|
135
|
+
if (options.disabled !== void 0) return !options.disabled;
|
|
136
|
+
return process.env.NODE_ENV === "production";
|
|
137
|
+
}
|
|
138
|
+
function resolveDistDir(config, distDir) {
|
|
139
|
+
const dir = distDir ?? config.build.outDir;
|
|
140
|
+
return isAbsolute(dir) ? dir : resolve(config.root, dir);
|
|
141
|
+
}
|
|
142
|
+
function rumSourcemap(options) {
|
|
143
|
+
let config;
|
|
144
|
+
return {
|
|
145
|
+
name: "rum-sourcemap",
|
|
146
|
+
apply: "build",
|
|
147
|
+
configResolved(resolved) {
|
|
148
|
+
config = resolved;
|
|
149
|
+
if (isEnabled(options) && resolved.build.sourcemap !== "hidden") {
|
|
150
|
+
resolved.logger.warn("[rum-sourcemap] build.sourcemap should be 'hidden' to avoid publishing .map files.");
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
async closeBundle() {
|
|
154
|
+
if (!config || config.command !== "build" || !isEnabled(options)) return;
|
|
155
|
+
if (!options.token) {
|
|
156
|
+
config.logger.warn("[rum-sourcemap] token is missing; skip source map upload.");
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
await uploadDir({
|
|
160
|
+
appId: options.app,
|
|
161
|
+
release: options.release,
|
|
162
|
+
endpoint: options.endpoint,
|
|
163
|
+
token: options.token,
|
|
164
|
+
distDir: resolveDistDir(config, options.distDir),
|
|
165
|
+
...options.concurrency !== void 0 && { concurrency: options.concurrency }
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
export {
|
|
171
|
+
rumSourcemap
|
|
172
|
+
};
|
|
173
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../../sourcemap-cli/src/index.ts"],"sourcesContent":["import { isAbsolute, resolve } from 'node:path';\nimport type { Plugin, ResolvedConfig } from 'vite';\nimport { uploadDir } from '@rum/sourcemap-cli';\n\nexport interface RumSourcemapPluginOptions {\n app: string;\n release: string;\n endpoint: string;\n token?: string;\n distDir?: string;\n concurrency?: number;\n disabled?: boolean;\n}\n\nfunction isEnabled(options: RumSourcemapPluginOptions): boolean {\n if (options.disabled !== undefined) return !options.disabled;\n return process.env.NODE_ENV === 'production';\n}\n\nfunction resolveDistDir(config: ResolvedConfig, distDir: string | undefined): string {\n const dir = distDir ?? config.build.outDir;\n return isAbsolute(dir) ? dir : resolve(config.root, dir);\n}\n\nexport function rumSourcemap(options: RumSourcemapPluginOptions): Plugin {\n let config: ResolvedConfig | undefined;\n\n return {\n name: 'rum-sourcemap',\n apply: 'build',\n\n configResolved(resolved) {\n config = resolved;\n if (isEnabled(options) && resolved.build.sourcemap !== 'hidden') {\n resolved.logger.warn(\"[rum-sourcemap] build.sourcemap should be 'hidden' to avoid publishing .map files.\");\n }\n },\n\n async closeBundle() {\n if (!config || config.command !== 'build' || !isEnabled(options)) return;\n if (!options.token) {\n config.logger.warn('[rum-sourcemap] token is missing; skip source map upload.');\n return;\n }\n\n await uploadDir({\n appId: options.app,\n release: options.release,\n endpoint: options.endpoint,\n token: options.token,\n distDir: resolveDistDir(config, options.distDir),\n ...(options.concurrency !== undefined && { concurrency: options.concurrency }),\n });\n },\n };\n}\n","import { opendir, readFile } from 'node:fs/promises';\nimport { basename, join, relative } from 'node:path';\n\nexport interface UploadFileResult {\n id: number;\n sha256: string;\n sizeBytes: number;\n}\n\nexport interface UploadFileOptions {\n appId: string;\n release: string;\n endpoint: string;\n token: string;\n file: string;\n mapPath: string;\n retries?: number;\n retryDelayMs?: number;\n fetchImpl?: typeof fetch;\n}\n\nexport interface UploadDirOptions {\n appId: string;\n release: string;\n endpoint: string;\n token: string;\n distDir: string;\n concurrency?: number;\n retries?: number;\n retryDelayMs?: number;\n fetchImpl?: typeof fetch;\n}\n\nexport interface UploadedSourceMap extends UploadFileResult {\n file: string;\n mapPath: string;\n}\n\nexport interface UploadDirResult {\n uploaded: UploadedSourceMap[];\n}\n\nexport interface ParsedUploadCommand {\n command: 'upload';\n appId: string;\n release: string;\n distDir: string;\n endpoint: string;\n token: string;\n concurrency?: number;\n}\n\nexport class SourceMapUploadError extends Error {\n status?: number;\n\n constructor(message: string, status?: number) {\n super(message);\n this.name = 'SourceMapUploadError';\n this.status = status;\n }\n}\n\nexport class SourceMapCliUsageError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'SourceMapCliUsageError';\n }\n}\n\nconst DEFAULT_RETRIES = 3;\nconst DEFAULT_RETRY_DELAY_MS = 1000;\nconst DEFAULT_CONCURRENCY = 4;\n\nfunction sourceMapUrl(endpoint: string): string {\n return `${endpoint.replace(/\\/+$/, '')}/admin/sourcemaps`;\n}\n\nfunction sleep(ms: number): Promise<void> {\n if (ms <= 0) return Promise.resolve();\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction retryDelay(baseMs: number, retryIndex: number): number {\n return baseMs * 2 ** retryIndex;\n}\n\nasync function responseMessage(response: Response): Promise<string> {\n try {\n const body = (await response.json()) as { error?: unknown };\n if (typeof body.error === 'string' && body.error.length > 0) return body.error;\n } catch {\n // Ignore malformed error bodies; status text is enough for CLI output.\n }\n return response.statusText || `HTTP ${response.status}`;\n}\n\nfunction isRetryable(status: number): boolean {\n return status >= 500 || status === 408 || status === 429;\n}\n\nasync function readUploadResult(response: Response): Promise<UploadFileResult> {\n const body = (await response.json()) as Partial<UploadFileResult>;\n return {\n id: Number(body.id),\n sha256: String(body.sha256),\n sizeBytes: Number(body.sizeBytes),\n };\n}\n\nexport async function uploadFile(options: UploadFileOptions): Promise<UploadFileResult> {\n const fetcher = options.fetchImpl ?? fetch;\n const retries = options.retries ?? DEFAULT_RETRIES;\n const retryDelayMs = options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n const content = await readFile(options.mapPath);\n const form = new FormData();\n form.set('appId', options.appId);\n form.set('release', options.release);\n form.set('file', options.file);\n form.set('map', new Blob([new Uint8Array(content)]), basename(options.mapPath));\n\n const response = await fetcher(sourceMapUrl(options.endpoint), {\n method: 'POST',\n headers: { Authorization: `Bearer ${options.token}` },\n body: form,\n });\n\n if (response.ok) return readUploadResult(response);\n const message = await responseMessage(response);\n if (!isRetryable(response.status) || attempt >= retries) {\n throw new SourceMapUploadError(message, response.status);\n }\n lastError = new SourceMapUploadError(message, response.status);\n } catch (err) {\n if (err instanceof SourceMapUploadError && !isRetryable(err.status ?? 0)) throw err;\n lastError = err;\n if (attempt >= retries) break;\n }\n\n await sleep(retryDelay(retryDelayMs, attempt));\n }\n\n if (lastError instanceof Error) throw lastError;\n throw new SourceMapUploadError('source map upload failed');\n}\n\nasync function collectMapFiles(dir: string): Promise<string[]> {\n const files: string[] = [];\n const entries = await opendir(dir);\n for await (const entry of entries) {\n const path = join(dir, entry.name);\n if (entry.isDirectory()) {\n files.push(...(await collectMapFiles(path)));\n } else if (entry.isFile() && entry.name.endsWith('.map')) {\n files.push(path);\n }\n }\n return files.sort();\n}\n\nfunction toSourceFile(distDir: string, mapPath: string): string {\n return relative(distDir, mapPath).split('\\\\').join('/').replace(/\\.map$/, '');\n}\n\nasync function runPool<T, R>(\n items: T[],\n concurrency: number,\n worker: (item: T) => Promise<R>,\n): Promise<R[]> {\n const results: R[] = [];\n let cursor = 0;\n const workerCount = Math.max(1, Math.min(concurrency, items.length));\n\n await Promise.all(\n Array.from({ length: workerCount }, async () => {\n for (;;) {\n const index = cursor++;\n const item = items[index];\n if (item === undefined) break;\n results[index] = await worker(item);\n }\n }),\n );\n\n return results;\n}\n\nexport async function uploadDir(options: UploadDirOptions): Promise<UploadDirResult> {\n const mapPaths = await collectMapFiles(options.distDir);\n const concurrency = options.concurrency ?? DEFAULT_CONCURRENCY;\n const uploaded = await runPool(mapPaths, concurrency, async (mapPath) => {\n const file = toSourceFile(options.distDir, mapPath);\n const result = await uploadFile({\n appId: options.appId,\n release: options.release,\n endpoint: options.endpoint,\n token: options.token,\n file,\n mapPath,\n retries: options.retries,\n retryDelayMs: options.retryDelayMs,\n fetchImpl: options.fetchImpl,\n });\n return { ...result, file, mapPath };\n });\n return { uploaded };\n}\n\nfunction readFlag(argv: string[], flag: string): string | undefined {\n const index = argv.indexOf(flag);\n if (index === -1) return undefined;\n return argv[index + 1];\n}\n\nfunction required(value: string | undefined, flag: string): string {\n if (!value) throw new SourceMapCliUsageError(`missing ${flag}`);\n return value;\n}\n\nexport function parseCliArgs(argv: string[]): ParsedUploadCommand {\n const command = argv[0];\n if (command !== 'upload') {\n throw new SourceMapCliUsageError('usage: rum-sourcemap upload --app <appId> --release <release> --dist <dir> --endpoint <url> --token <token>');\n }\n\n const concurrencyRaw = readFlag(argv, '--concurrency');\n return {\n command: 'upload',\n appId: required(readFlag(argv, '--app') ?? readFlag(argv, '--app-id'), '--app'),\n release: required(readFlag(argv, '--release'), '--release'),\n distDir: required(readFlag(argv, '--dist'), '--dist'),\n endpoint: required(readFlag(argv, '--endpoint'), '--endpoint'),\n token: required(readFlag(argv, '--token'), '--token'),\n ...(concurrencyRaw !== undefined && { concurrency: Number(concurrencyRaw) }),\n };\n}\n\nexport async function runCli(argv: string[], log: (message: string) => void = console.warn) {\n const command = parseCliArgs(argv);\n const result = await uploadDir(command);\n log(`uploaded ${result.uploaded.length} source maps`);\n return result;\n}\n"],"mappings":"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","names":["resolve"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nanyujun/rum-vite-plugin-sourcemap",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"main": "./dist/index.cjs",
|
|
9
|
+
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"require": "./dist/index.cjs"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsup",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"test": "tsc --noEmit && vitest run",
|
|
25
|
+
"lint": "eslint src tests",
|
|
26
|
+
"clean": "rm -rf dist .turbo"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"vite": "^5.0.0 || ^6.0.0"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@nanyujun/rum-sourcemap-cli": "^0.1.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"vite": "^5.4.0"
|
|
36
|
+
}
|
|
37
|
+
}
|