@proliferate_ai/rollup-plugin 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/dist/index.d.mts +76 -0
- package/dist/index.d.ts +76 -0
- package/dist/index.js +240 -0
- package/dist/index.mjs +204 -0
- package/package.json +60 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Plugin } from 'rollup';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Rollup plugin for Proliferate.
|
|
5
|
+
*
|
|
6
|
+
* Injects release metadata and uploads source maps on build.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
interface ProliferatePluginOptions {
|
|
10
|
+
/**
|
|
11
|
+
* API endpoint for uploading sourcemaps.
|
|
12
|
+
* Can also be set via PROLIFERATE_ENDPOINT env var.
|
|
13
|
+
*/
|
|
14
|
+
endpoint?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Project API key (starts with pk_).
|
|
17
|
+
* Can also be set via PROLIFERATE_API_KEY env var.
|
|
18
|
+
*/
|
|
19
|
+
apiKey?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Release version. If not specified, auto-detected from git/environment.
|
|
22
|
+
* Can also be set via PROLIFERATE_RELEASE env var.
|
|
23
|
+
*/
|
|
24
|
+
release?: string;
|
|
25
|
+
/**
|
|
26
|
+
* URL prefix for source map URLs. Defaults to '~/'.
|
|
27
|
+
*/
|
|
28
|
+
urlPrefix?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Whether to upload sourcemaps. Defaults to true.
|
|
31
|
+
*/
|
|
32
|
+
uploadSourceMaps?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Delete source maps after upload. Defaults to false.
|
|
35
|
+
*/
|
|
36
|
+
deleteAfterUpload?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Suppress log output.
|
|
39
|
+
*/
|
|
40
|
+
silent?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Dry run mode - log what would be uploaded without actually uploading.
|
|
43
|
+
*/
|
|
44
|
+
dryRun?: boolean;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Detect release version from various CI/CD environment variables.
|
|
48
|
+
*/
|
|
49
|
+
declare function detectRelease(): string;
|
|
50
|
+
/**
|
|
51
|
+
* Create the Proliferate Rollup plugin.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* // rollup.config.js
|
|
56
|
+
* import { proliferate } from '@proliferate/rollup-plugin';
|
|
57
|
+
*
|
|
58
|
+
* export default {
|
|
59
|
+
* input: 'src/index.js',
|
|
60
|
+
* output: {
|
|
61
|
+
* file: 'dist/bundle.js',
|
|
62
|
+
* format: 'esm',
|
|
63
|
+
* sourcemap: true,
|
|
64
|
+
* },
|
|
65
|
+
* plugins: [
|
|
66
|
+
* proliferate({
|
|
67
|
+
* endpoint: 'https://api.example.com/api/v1',
|
|
68
|
+
* apiKey: process.env.PROLIFERATE_API_KEY,
|
|
69
|
+
* })
|
|
70
|
+
* ]
|
|
71
|
+
* };
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
declare function proliferate(options?: ProliferatePluginOptions): Plugin;
|
|
75
|
+
|
|
76
|
+
export { type ProliferatePluginOptions, proliferate as default, detectRelease, proliferate };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Plugin } from 'rollup';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Rollup plugin for Proliferate.
|
|
5
|
+
*
|
|
6
|
+
* Injects release metadata and uploads source maps on build.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
interface ProliferatePluginOptions {
|
|
10
|
+
/**
|
|
11
|
+
* API endpoint for uploading sourcemaps.
|
|
12
|
+
* Can also be set via PROLIFERATE_ENDPOINT env var.
|
|
13
|
+
*/
|
|
14
|
+
endpoint?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Project API key (starts with pk_).
|
|
17
|
+
* Can also be set via PROLIFERATE_API_KEY env var.
|
|
18
|
+
*/
|
|
19
|
+
apiKey?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Release version. If not specified, auto-detected from git/environment.
|
|
22
|
+
* Can also be set via PROLIFERATE_RELEASE env var.
|
|
23
|
+
*/
|
|
24
|
+
release?: string;
|
|
25
|
+
/**
|
|
26
|
+
* URL prefix for source map URLs. Defaults to '~/'.
|
|
27
|
+
*/
|
|
28
|
+
urlPrefix?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Whether to upload sourcemaps. Defaults to true.
|
|
31
|
+
*/
|
|
32
|
+
uploadSourceMaps?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Delete source maps after upload. Defaults to false.
|
|
35
|
+
*/
|
|
36
|
+
deleteAfterUpload?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Suppress log output.
|
|
39
|
+
*/
|
|
40
|
+
silent?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Dry run mode - log what would be uploaded without actually uploading.
|
|
43
|
+
*/
|
|
44
|
+
dryRun?: boolean;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Detect release version from various CI/CD environment variables.
|
|
48
|
+
*/
|
|
49
|
+
declare function detectRelease(): string;
|
|
50
|
+
/**
|
|
51
|
+
* Create the Proliferate Rollup plugin.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* // rollup.config.js
|
|
56
|
+
* import { proliferate } from '@proliferate/rollup-plugin';
|
|
57
|
+
*
|
|
58
|
+
* export default {
|
|
59
|
+
* input: 'src/index.js',
|
|
60
|
+
* output: {
|
|
61
|
+
* file: 'dist/bundle.js',
|
|
62
|
+
* format: 'esm',
|
|
63
|
+
* sourcemap: true,
|
|
64
|
+
* },
|
|
65
|
+
* plugins: [
|
|
66
|
+
* proliferate({
|
|
67
|
+
* endpoint: 'https://api.example.com/api/v1',
|
|
68
|
+
* apiKey: process.env.PROLIFERATE_API_KEY,
|
|
69
|
+
* })
|
|
70
|
+
* ]
|
|
71
|
+
* };
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
declare function proliferate(options?: ProliferatePluginOptions): Plugin;
|
|
75
|
+
|
|
76
|
+
export { type ProliferatePluginOptions, proliferate as default, detectRelease, proliferate };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
default: () => index_default,
|
|
34
|
+
detectRelease: () => detectRelease,
|
|
35
|
+
proliferate: () => proliferate
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(index_exports);
|
|
38
|
+
var fs = __toESM(require("fs"));
|
|
39
|
+
var path = __toESM(require("path"));
|
|
40
|
+
var import_child_process = require("child_process");
|
|
41
|
+
var import_form_data = __toESM(require("form-data"));
|
|
42
|
+
function log(options, message) {
|
|
43
|
+
if (!options.silent) {
|
|
44
|
+
console.log(`[Proliferate] ${message}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function warn(options, message) {
|
|
48
|
+
if (!options.silent) {
|
|
49
|
+
console.warn(`[Proliferate] Warning: ${message}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function error(options, message) {
|
|
53
|
+
if (!options.silent) {
|
|
54
|
+
console.error(`[Proliferate] Error: ${message}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function detectRelease() {
|
|
58
|
+
const envVars = [
|
|
59
|
+
"PROLIFERATE_RELEASE",
|
|
60
|
+
"GITHUB_SHA",
|
|
61
|
+
"VERCEL_GIT_COMMIT_SHA",
|
|
62
|
+
"CF_PAGES_COMMIT_SHA",
|
|
63
|
+
"RENDER_GIT_COMMIT",
|
|
64
|
+
"RAILWAY_GIT_COMMIT_SHA",
|
|
65
|
+
"GITLAB_CI_COMMIT_SHA",
|
|
66
|
+
"CIRCLE_SHA1",
|
|
67
|
+
"COMMIT_SHA",
|
|
68
|
+
"GIT_COMMIT",
|
|
69
|
+
"BITBUCKET_COMMIT",
|
|
70
|
+
"DRONE_COMMIT_SHA",
|
|
71
|
+
"TRAVIS_COMMIT"
|
|
72
|
+
];
|
|
73
|
+
for (const envVar of envVars) {
|
|
74
|
+
const value = process.env[envVar];
|
|
75
|
+
if (value) {
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const sha = (0, import_child_process.execSync)("git rev-parse HEAD", {
|
|
81
|
+
encoding: "utf8",
|
|
82
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
83
|
+
}).trim();
|
|
84
|
+
return sha;
|
|
85
|
+
} catch {
|
|
86
|
+
}
|
|
87
|
+
return `build-${Date.now()}`;
|
|
88
|
+
}
|
|
89
|
+
async function createRelease(options) {
|
|
90
|
+
const form = new import_form_data.default();
|
|
91
|
+
form.append("version", options.release);
|
|
92
|
+
form.append("url_prefix", options.urlPrefix);
|
|
93
|
+
const response = await fetch(`${options.endpoint}/releases`, {
|
|
94
|
+
method: "POST",
|
|
95
|
+
headers: {
|
|
96
|
+
Authorization: `Bearer ${options.apiKey}`
|
|
97
|
+
},
|
|
98
|
+
body: form
|
|
99
|
+
});
|
|
100
|
+
if (!response.ok) {
|
|
101
|
+
const text = await response.text();
|
|
102
|
+
throw new Error(`Failed to create release: ${response.status} ${text}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async function uploadSourceMap(options, url, content) {
|
|
106
|
+
const form = new import_form_data.default();
|
|
107
|
+
form.append("release", options.release);
|
|
108
|
+
form.append("url", url);
|
|
109
|
+
form.append("url_prefix", options.urlPrefix);
|
|
110
|
+
form.append("sourcemap", Buffer.from(content), {
|
|
111
|
+
filename: "sourcemap.map",
|
|
112
|
+
contentType: "application/json"
|
|
113
|
+
});
|
|
114
|
+
const response = await fetch(`${options.endpoint}/sourcemaps`, {
|
|
115
|
+
method: "POST",
|
|
116
|
+
headers: {
|
|
117
|
+
Authorization: `Bearer ${options.apiKey}`
|
|
118
|
+
},
|
|
119
|
+
body: form
|
|
120
|
+
});
|
|
121
|
+
if (!response.ok) {
|
|
122
|
+
const text = await response.text();
|
|
123
|
+
throw new Error(`${response.status} ${text}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async function finalizeRelease(options) {
|
|
127
|
+
const response = await fetch(
|
|
128
|
+
`${options.endpoint}/releases/${encodeURIComponent(options.release)}/finalize`,
|
|
129
|
+
{
|
|
130
|
+
method: "POST",
|
|
131
|
+
headers: {
|
|
132
|
+
Authorization: `Bearer ${options.apiKey}`
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
);
|
|
136
|
+
if (!response.ok) {
|
|
137
|
+
const text = await response.text();
|
|
138
|
+
warn(options, `Failed to finalize release: ${response.status} ${text}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function proliferate(options = {}) {
|
|
142
|
+
const release = options.release || detectRelease();
|
|
143
|
+
const apiKey = options.apiKey || process.env.PROLIFERATE_API_KEY;
|
|
144
|
+
const endpoint = options.endpoint || process.env.PROLIFERATE_ENDPOINT;
|
|
145
|
+
const resolvedOptions = {
|
|
146
|
+
endpoint: endpoint || "",
|
|
147
|
+
apiKey: apiKey || "",
|
|
148
|
+
release,
|
|
149
|
+
urlPrefix: options.urlPrefix || "~/",
|
|
150
|
+
uploadSourceMaps: options.uploadSourceMaps ?? true,
|
|
151
|
+
deleteAfterUpload: options.deleteAfterUpload ?? false,
|
|
152
|
+
silent: options.silent ?? false,
|
|
153
|
+
dryRun: options.dryRun ?? false
|
|
154
|
+
};
|
|
155
|
+
return {
|
|
156
|
+
name: "proliferate",
|
|
157
|
+
// Inject __PROLIFERATE_RELEASE__ at the start of each bundle
|
|
158
|
+
banner() {
|
|
159
|
+
return `var __PROLIFERATE_RELEASE__ = ${JSON.stringify(release)};`;
|
|
160
|
+
},
|
|
161
|
+
async writeBundle(outputOptions, bundle) {
|
|
162
|
+
if (!resolvedOptions.uploadSourceMaps) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (!resolvedOptions.apiKey || !resolvedOptions.endpoint) {
|
|
166
|
+
warn(
|
|
167
|
+
resolvedOptions,
|
|
168
|
+
"Skipping source map upload: missing apiKey or endpoint"
|
|
169
|
+
);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const sourceMaps = [];
|
|
173
|
+
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
174
|
+
if (fileName.endsWith(".map") && "source" in chunk) {
|
|
175
|
+
sourceMaps.push({
|
|
176
|
+
fileName,
|
|
177
|
+
source: chunk.source
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (sourceMaps.length === 0) {
|
|
182
|
+
warn(resolvedOptions, "No source maps found in bundle");
|
|
183
|
+
warn(resolvedOptions, "Make sure sourcemap: true is set in output options");
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
log(resolvedOptions, `Found ${sourceMaps.length} source map(s) to upload`);
|
|
187
|
+
log(resolvedOptions, `Release: ${release}`);
|
|
188
|
+
if (!resolvedOptions.dryRun) {
|
|
189
|
+
try {
|
|
190
|
+
await createRelease(resolvedOptions);
|
|
191
|
+
log(resolvedOptions, "Created release");
|
|
192
|
+
} catch (err) {
|
|
193
|
+
error(resolvedOptions, `Failed to create release: ${err}`);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
let uploaded = 0;
|
|
198
|
+
let failed = 0;
|
|
199
|
+
const outputDir = outputOptions.dir || (outputOptions.file ? path.dirname(outputOptions.file) : ".");
|
|
200
|
+
for (const { fileName, source } of sourceMaps) {
|
|
201
|
+
const minifiedFilename = fileName.replace(".map", "");
|
|
202
|
+
const url = resolvedOptions.urlPrefix + minifiedFilename;
|
|
203
|
+
if (resolvedOptions.dryRun) {
|
|
204
|
+
log(resolvedOptions, `[Dry Run] Would upload: ${url}`);
|
|
205
|
+
uploaded++;
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
try {
|
|
209
|
+
await uploadSourceMap(resolvedOptions, url, source);
|
|
210
|
+
log(resolvedOptions, `Uploaded: ${url}`);
|
|
211
|
+
uploaded++;
|
|
212
|
+
if (resolvedOptions.deleteAfterUpload) {
|
|
213
|
+
const mapPath = path.join(outputDir, fileName);
|
|
214
|
+
if (fs.existsSync(mapPath)) {
|
|
215
|
+
fs.unlinkSync(mapPath);
|
|
216
|
+
log(resolvedOptions, `Deleted: ${fileName}`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
} catch (err) {
|
|
220
|
+
warn(resolvedOptions, `Failed to upload ${fileName}: ${err}`);
|
|
221
|
+
failed++;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (!resolvedOptions.dryRun && uploaded > 0) {
|
|
225
|
+
await finalizeRelease(resolvedOptions);
|
|
226
|
+
log(resolvedOptions, "Finalized release");
|
|
227
|
+
}
|
|
228
|
+
log(
|
|
229
|
+
resolvedOptions,
|
|
230
|
+
`Source map upload complete: ${uploaded} uploaded, ${failed} failed`
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
var index_default = proliferate;
|
|
236
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
237
|
+
0 && (module.exports = {
|
|
238
|
+
detectRelease,
|
|
239
|
+
proliferate
|
|
240
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
import { execSync } from "child_process";
|
|
5
|
+
import FormData from "form-data";
|
|
6
|
+
function log(options, message) {
|
|
7
|
+
if (!options.silent) {
|
|
8
|
+
console.log(`[Proliferate] ${message}`);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function warn(options, message) {
|
|
12
|
+
if (!options.silent) {
|
|
13
|
+
console.warn(`[Proliferate] Warning: ${message}`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function error(options, message) {
|
|
17
|
+
if (!options.silent) {
|
|
18
|
+
console.error(`[Proliferate] Error: ${message}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function detectRelease() {
|
|
22
|
+
const envVars = [
|
|
23
|
+
"PROLIFERATE_RELEASE",
|
|
24
|
+
"GITHUB_SHA",
|
|
25
|
+
"VERCEL_GIT_COMMIT_SHA",
|
|
26
|
+
"CF_PAGES_COMMIT_SHA",
|
|
27
|
+
"RENDER_GIT_COMMIT",
|
|
28
|
+
"RAILWAY_GIT_COMMIT_SHA",
|
|
29
|
+
"GITLAB_CI_COMMIT_SHA",
|
|
30
|
+
"CIRCLE_SHA1",
|
|
31
|
+
"COMMIT_SHA",
|
|
32
|
+
"GIT_COMMIT",
|
|
33
|
+
"BITBUCKET_COMMIT",
|
|
34
|
+
"DRONE_COMMIT_SHA",
|
|
35
|
+
"TRAVIS_COMMIT"
|
|
36
|
+
];
|
|
37
|
+
for (const envVar of envVars) {
|
|
38
|
+
const value = process.env[envVar];
|
|
39
|
+
if (value) {
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const sha = execSync("git rev-parse HEAD", {
|
|
45
|
+
encoding: "utf8",
|
|
46
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
47
|
+
}).trim();
|
|
48
|
+
return sha;
|
|
49
|
+
} catch {
|
|
50
|
+
}
|
|
51
|
+
return `build-${Date.now()}`;
|
|
52
|
+
}
|
|
53
|
+
async function createRelease(options) {
|
|
54
|
+
const form = new FormData();
|
|
55
|
+
form.append("version", options.release);
|
|
56
|
+
form.append("url_prefix", options.urlPrefix);
|
|
57
|
+
const response = await fetch(`${options.endpoint}/releases`, {
|
|
58
|
+
method: "POST",
|
|
59
|
+
headers: {
|
|
60
|
+
Authorization: `Bearer ${options.apiKey}`
|
|
61
|
+
},
|
|
62
|
+
body: form
|
|
63
|
+
});
|
|
64
|
+
if (!response.ok) {
|
|
65
|
+
const text = await response.text();
|
|
66
|
+
throw new Error(`Failed to create release: ${response.status} ${text}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async function uploadSourceMap(options, url, content) {
|
|
70
|
+
const form = new FormData();
|
|
71
|
+
form.append("release", options.release);
|
|
72
|
+
form.append("url", url);
|
|
73
|
+
form.append("url_prefix", options.urlPrefix);
|
|
74
|
+
form.append("sourcemap", Buffer.from(content), {
|
|
75
|
+
filename: "sourcemap.map",
|
|
76
|
+
contentType: "application/json"
|
|
77
|
+
});
|
|
78
|
+
const response = await fetch(`${options.endpoint}/sourcemaps`, {
|
|
79
|
+
method: "POST",
|
|
80
|
+
headers: {
|
|
81
|
+
Authorization: `Bearer ${options.apiKey}`
|
|
82
|
+
},
|
|
83
|
+
body: form
|
|
84
|
+
});
|
|
85
|
+
if (!response.ok) {
|
|
86
|
+
const text = await response.text();
|
|
87
|
+
throw new Error(`${response.status} ${text}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async function finalizeRelease(options) {
|
|
91
|
+
const response = await fetch(
|
|
92
|
+
`${options.endpoint}/releases/${encodeURIComponent(options.release)}/finalize`,
|
|
93
|
+
{
|
|
94
|
+
method: "POST",
|
|
95
|
+
headers: {
|
|
96
|
+
Authorization: `Bearer ${options.apiKey}`
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
if (!response.ok) {
|
|
101
|
+
const text = await response.text();
|
|
102
|
+
warn(options, `Failed to finalize release: ${response.status} ${text}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function proliferate(options = {}) {
|
|
106
|
+
const release = options.release || detectRelease();
|
|
107
|
+
const apiKey = options.apiKey || process.env.PROLIFERATE_API_KEY;
|
|
108
|
+
const endpoint = options.endpoint || process.env.PROLIFERATE_ENDPOINT;
|
|
109
|
+
const resolvedOptions = {
|
|
110
|
+
endpoint: endpoint || "",
|
|
111
|
+
apiKey: apiKey || "",
|
|
112
|
+
release,
|
|
113
|
+
urlPrefix: options.urlPrefix || "~/",
|
|
114
|
+
uploadSourceMaps: options.uploadSourceMaps ?? true,
|
|
115
|
+
deleteAfterUpload: options.deleteAfterUpload ?? false,
|
|
116
|
+
silent: options.silent ?? false,
|
|
117
|
+
dryRun: options.dryRun ?? false
|
|
118
|
+
};
|
|
119
|
+
return {
|
|
120
|
+
name: "proliferate",
|
|
121
|
+
// Inject __PROLIFERATE_RELEASE__ at the start of each bundle
|
|
122
|
+
banner() {
|
|
123
|
+
return `var __PROLIFERATE_RELEASE__ = ${JSON.stringify(release)};`;
|
|
124
|
+
},
|
|
125
|
+
async writeBundle(outputOptions, bundle) {
|
|
126
|
+
if (!resolvedOptions.uploadSourceMaps) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (!resolvedOptions.apiKey || !resolvedOptions.endpoint) {
|
|
130
|
+
warn(
|
|
131
|
+
resolvedOptions,
|
|
132
|
+
"Skipping source map upload: missing apiKey or endpoint"
|
|
133
|
+
);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const sourceMaps = [];
|
|
137
|
+
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
138
|
+
if (fileName.endsWith(".map") && "source" in chunk) {
|
|
139
|
+
sourceMaps.push({
|
|
140
|
+
fileName,
|
|
141
|
+
source: chunk.source
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (sourceMaps.length === 0) {
|
|
146
|
+
warn(resolvedOptions, "No source maps found in bundle");
|
|
147
|
+
warn(resolvedOptions, "Make sure sourcemap: true is set in output options");
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
log(resolvedOptions, `Found ${sourceMaps.length} source map(s) to upload`);
|
|
151
|
+
log(resolvedOptions, `Release: ${release}`);
|
|
152
|
+
if (!resolvedOptions.dryRun) {
|
|
153
|
+
try {
|
|
154
|
+
await createRelease(resolvedOptions);
|
|
155
|
+
log(resolvedOptions, "Created release");
|
|
156
|
+
} catch (err) {
|
|
157
|
+
error(resolvedOptions, `Failed to create release: ${err}`);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
let uploaded = 0;
|
|
162
|
+
let failed = 0;
|
|
163
|
+
const outputDir = outputOptions.dir || (outputOptions.file ? path.dirname(outputOptions.file) : ".");
|
|
164
|
+
for (const { fileName, source } of sourceMaps) {
|
|
165
|
+
const minifiedFilename = fileName.replace(".map", "");
|
|
166
|
+
const url = resolvedOptions.urlPrefix + minifiedFilename;
|
|
167
|
+
if (resolvedOptions.dryRun) {
|
|
168
|
+
log(resolvedOptions, `[Dry Run] Would upload: ${url}`);
|
|
169
|
+
uploaded++;
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
await uploadSourceMap(resolvedOptions, url, source);
|
|
174
|
+
log(resolvedOptions, `Uploaded: ${url}`);
|
|
175
|
+
uploaded++;
|
|
176
|
+
if (resolvedOptions.deleteAfterUpload) {
|
|
177
|
+
const mapPath = path.join(outputDir, fileName);
|
|
178
|
+
if (fs.existsSync(mapPath)) {
|
|
179
|
+
fs.unlinkSync(mapPath);
|
|
180
|
+
log(resolvedOptions, `Deleted: ${fileName}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
} catch (err) {
|
|
184
|
+
warn(resolvedOptions, `Failed to upload ${fileName}: ${err}`);
|
|
185
|
+
failed++;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (!resolvedOptions.dryRun && uploaded > 0) {
|
|
189
|
+
await finalizeRelease(resolvedOptions);
|
|
190
|
+
log(resolvedOptions, "Finalized release");
|
|
191
|
+
}
|
|
192
|
+
log(
|
|
193
|
+
resolvedOptions,
|
|
194
|
+
`Source map upload complete: ${uploaded} uploaded, ${failed} failed`
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
var index_default = proliferate;
|
|
200
|
+
export {
|
|
201
|
+
index_default as default,
|
|
202
|
+
detectRelease,
|
|
203
|
+
proliferate
|
|
204
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@proliferate_ai/rollup-plugin",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Rollup plugin for Proliferate - injects release and uploads source maps",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
20
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:watch": "vitest",
|
|
23
|
+
"typecheck": "tsc --noEmit"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"rollup",
|
|
27
|
+
"rollup-plugin",
|
|
28
|
+
"sourcemap",
|
|
29
|
+
"source-map",
|
|
30
|
+
"error-monitoring",
|
|
31
|
+
"proliferate"
|
|
32
|
+
],
|
|
33
|
+
"author": "",
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "https://github.com/YOUR_ORG/proliferation.git",
|
|
38
|
+
"directory": "sdks/rollup-plugin"
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public",
|
|
42
|
+
"provenance": true
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"rollup": "^3.0.0 || ^4.0.0"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/node": "^20.19.27",
|
|
49
|
+
"rollup": "^4.0.0",
|
|
50
|
+
"tsup": "^8.0.0",
|
|
51
|
+
"typescript": "^5.0.0",
|
|
52
|
+
"vitest": "^4.0.16"
|
|
53
|
+
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"form-data": "^4.0.0"
|
|
56
|
+
},
|
|
57
|
+
"engines": {
|
|
58
|
+
"node": ">=18"
|
|
59
|
+
}
|
|
60
|
+
}
|