@allstak/react 0.3.0 → 0.3.2
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 +57 -0
- package/README.md +211 -45
- package/dist/build/chunk-G6VPGDP6.mjs +214 -0
- package/dist/build/chunk-G6VPGDP6.mjs.map +1 -0
- package/dist/build/chunk-ZY4H5AN4.mjs +32 -0
- package/dist/build/chunk-ZY4H5AN4.mjs.map +1 -0
- package/dist/build/next.d.mts +33 -0
- package/dist/build/next.d.ts +33 -0
- package/dist/build/next.js +274 -0
- package/dist/build/next.js.map +1 -0
- package/dist/build/next.mjs +26 -0
- package/dist/build/next.mjs.map +1 -0
- package/dist/build/sourcemaps.d.mts +160 -0
- package/dist/build/sourcemaps.d.ts +160 -0
- package/dist/build/sourcemaps.js +248 -0
- package/dist/build/sourcemaps.js.map +1 -0
- package/dist/build/sourcemaps.mjs +23 -0
- package/dist/build/sourcemaps.mjs.map +1 -0
- package/dist/build/vite.d.mts +65 -0
- package/dist/build/vite.d.ts +65 -0
- package/dist/build/vite.js +269 -0
- package/dist/build/vite.js.map +1 -0
- package/dist/build/vite.mjs +43 -0
- package/dist/build/vite.mjs.map +1 -0
- package/dist/build/webpack.d.mts +58 -0
- package/dist/build/webpack.d.ts +58 -0
- package/dist/build/webpack.js +256 -0
- package/dist/build/webpack.js.map +1 -0
- package/dist/build/webpack.mjs +8 -0
- package/dist/build/webpack.mjs.map +1 -0
- package/dist/index.d.mts +196 -42
- package/dist/index.d.ts +196 -42
- package/dist/index.js +435 -50
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +435 -50
- package/dist/index.mjs.map +1 -1
- package/package.json +25 -2
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build-time only. File-system walking for the source-map pipeline.
|
|
3
|
+
* Pure Node 18+ (built-in `node:fs` only). Browser runtime never imports
|
|
4
|
+
* this — it's behind a `./build/*` subpath that's marked Node-platform.
|
|
5
|
+
*/
|
|
6
|
+
/** A bundle and its companion source map on disk. */
|
|
7
|
+
interface BundlePair {
|
|
8
|
+
/** Absolute path to the JS bundle (`.js` / `.mjs` / `.cjs`). */
|
|
9
|
+
jsPath: string;
|
|
10
|
+
/** Absolute path to the matching `.map` file. */
|
|
11
|
+
mapPath: string;
|
|
12
|
+
/** Bare filename of the bundle (no directory), for log lines. */
|
|
13
|
+
bundleName: string;
|
|
14
|
+
}
|
|
15
|
+
/** Recursively list every file under `dir`. Symlinks are followed. */
|
|
16
|
+
declare function walk(dir: string, out?: string[]): string[];
|
|
17
|
+
/**
|
|
18
|
+
* Returns every `(bundle, sourcemap)` pair under `root`.
|
|
19
|
+
*
|
|
20
|
+
* A pair is a `.js` / `.mjs` / `.cjs` file with a sibling file of the
|
|
21
|
+
* same name plus a `.map` suffix — the convention every modern bundler
|
|
22
|
+
* (Vite, Webpack, esbuild, Rollup, tsup) follows.
|
|
23
|
+
*/
|
|
24
|
+
declare function findPairs(root: string): BundlePair[];
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Debug-ID injection. Build-time only.
|
|
28
|
+
*
|
|
29
|
+
* For each `(bundle.js, bundle.js.map)` pair we:
|
|
30
|
+
* - Generate a stable per-bundle UUID (one already on the bundle is
|
|
31
|
+
* reused so re-running is idempotent).
|
|
32
|
+
* - Append `//# debugId=<uuid>` to the JS so the runtime resolver in
|
|
33
|
+
* `src/debug-id.ts` can read it back.
|
|
34
|
+
* - Write a top-level `debugId` field into the `.map` JSON so the
|
|
35
|
+
* symbolicator on the backend can join `bundle.js` ↔ `bundle.js.map`
|
|
36
|
+
* by ID rather than guessing from filenames.
|
|
37
|
+
*
|
|
38
|
+
* Bundlers re-write hashed filenames on every build, so joining by ID
|
|
39
|
+
* (instead of by URL or path) is what makes resolved stack frames
|
|
40
|
+
* survive across releases.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/** Outcome of injecting one pair. */
|
|
44
|
+
interface InjectResult {
|
|
45
|
+
/** UUID injected (or reused) for this bundle. */
|
|
46
|
+
debugId: string;
|
|
47
|
+
/** True if the bundle already had a debugId — we reused it. */
|
|
48
|
+
reused: boolean;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Inject (or reuse) the debug ID for a single bundle/sourcemap pair.
|
|
52
|
+
* Mutates both files on disk. Pure synchronous Node — safe to call from
|
|
53
|
+
* a Vite `closeBundle` or Webpack `afterEmit` hook.
|
|
54
|
+
*/
|
|
55
|
+
declare function injectPair(p: BundlePair): InjectResult;
|
|
56
|
+
/** Inject every pair under `root`. Returns one record per pair. */
|
|
57
|
+
declare function injectAll(pairs: BundlePair[]): Array<{
|
|
58
|
+
pair: BundlePair;
|
|
59
|
+
result: InjectResult;
|
|
60
|
+
}>;
|
|
61
|
+
/** Read a debug ID back from a `.map` file. */
|
|
62
|
+
declare function readDebugIdFromMap(mapPath: string): string | null;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Source-map / bundle upload client. Build-time only.
|
|
66
|
+
*
|
|
67
|
+
* Wraps the AllStak `/api/v1/artifacts/upload` endpoint with multipart
|
|
68
|
+
* form data and best-effort retries. Pure Node 18+ (uses the global
|
|
69
|
+
* `fetch` and `FormData`), no third-party HTTP client required.
|
|
70
|
+
*
|
|
71
|
+
* Auth: `X-AllStak-Upload-Token` header (NOT the runtime API key —
|
|
72
|
+
* uploads have a dedicated, narrower scope. Generate one in the
|
|
73
|
+
* dashboard → Project Settings → Upload Tokens).
|
|
74
|
+
*/
|
|
75
|
+
|
|
76
|
+
/** Default ingest host — overridden via `host` option or `ALLSTAK_HOST`. */
|
|
77
|
+
declare const DEFAULT_HOST = "https://api.allstak.sa";
|
|
78
|
+
/** Options for {@link uploadAll} / {@link uploadPair}. */
|
|
79
|
+
interface UploadOptions {
|
|
80
|
+
/** Release identifier, e.g. `myapp@1.4.2`. Required server-side. */
|
|
81
|
+
release: string;
|
|
82
|
+
/** Optional distribution tag (`web`, `ios-hermes`, `staging`, …). */
|
|
83
|
+
dist?: string;
|
|
84
|
+
/** AllStak ingest host (default `https://api.allstak.sa`). */
|
|
85
|
+
host?: string;
|
|
86
|
+
/** Project upload token (`aspk_…`). May come from `ALLSTAK_UPLOAD_TOKEN`. */
|
|
87
|
+
token: string;
|
|
88
|
+
/**
|
|
89
|
+
* Drop `sourcesContent` from the map before upload (smaller payload).
|
|
90
|
+
* Off by default — sourcesContent enables full-source rendering on the
|
|
91
|
+
* dashboard. Turn on if you don't want source code uploaded.
|
|
92
|
+
*/
|
|
93
|
+
stripSources?: boolean;
|
|
94
|
+
/** Also upload the JS bundle alongside the map (off by default). */
|
|
95
|
+
uploadBundles?: boolean;
|
|
96
|
+
}
|
|
97
|
+
/** One artifact upload result. */
|
|
98
|
+
interface UploadResult {
|
|
99
|
+
bundleName: string;
|
|
100
|
+
debugId: string;
|
|
101
|
+
/** True when both the map (and bundle, if requested) uploaded OK. */
|
|
102
|
+
ok: boolean;
|
|
103
|
+
/** Per-artifact responses, in the order we sent them. */
|
|
104
|
+
steps: Array<{
|
|
105
|
+
type: 'sourcemap' | 'bundle';
|
|
106
|
+
status: number;
|
|
107
|
+
sha8: string;
|
|
108
|
+
body?: string;
|
|
109
|
+
}>;
|
|
110
|
+
}
|
|
111
|
+
/** Upload one bundle/map pair. The map is always uploaded; bundle is opt-in. */
|
|
112
|
+
declare function uploadPair(p: BundlePair, opts: UploadOptions): Promise<UploadResult>;
|
|
113
|
+
/** Upload every pair in parallel. */
|
|
114
|
+
declare function uploadAll(pairs: BundlePair[], opts: UploadOptions): Promise<UploadResult[]>;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Programmatic source-map pipeline. Build-time only.
|
|
118
|
+
*
|
|
119
|
+
* The high-level "do everything" entry point Vite/Webpack/Next plugins
|
|
120
|
+
* call. Walk the build output → inject debug IDs → upload artifacts.
|
|
121
|
+
*
|
|
122
|
+
* import { processBuildOutput } from '@allstak/react/sourcemaps';
|
|
123
|
+
*
|
|
124
|
+
* await processBuildOutput({
|
|
125
|
+
* dir: 'dist',
|
|
126
|
+
* release: 'web@1.4.2',
|
|
127
|
+
* token: process.env.ALLSTAK_UPLOAD_TOKEN!,
|
|
128
|
+
* });
|
|
129
|
+
*/
|
|
130
|
+
|
|
131
|
+
/** Options for {@link processBuildOutput}. */
|
|
132
|
+
interface ProcessOptions extends Partial<UploadOptions> {
|
|
133
|
+
/** Build output directory to scan (e.g. `dist`, `.next/static`). */
|
|
134
|
+
dir: string;
|
|
135
|
+
/**
|
|
136
|
+
* If true, only inject debug IDs and skip upload. Useful for sample
|
|
137
|
+
* apps and CI dry-runs.
|
|
138
|
+
*/
|
|
139
|
+
injectOnly?: boolean;
|
|
140
|
+
/** Suppress per-pair console output. Default false (you want to see this). */
|
|
141
|
+
silent?: boolean;
|
|
142
|
+
}
|
|
143
|
+
/** What `processBuildOutput` reports back. */
|
|
144
|
+
interface ProcessReport {
|
|
145
|
+
/** Absolute output dir scanned. */
|
|
146
|
+
dir: string;
|
|
147
|
+
/** Pairs found. */
|
|
148
|
+
pairs: number;
|
|
149
|
+
/** Per-pair injection results (debugId + reused?). */
|
|
150
|
+
injected: Array<{
|
|
151
|
+
bundleName: string;
|
|
152
|
+
debugId: string;
|
|
153
|
+
reused: boolean;
|
|
154
|
+
}>;
|
|
155
|
+
/** Per-pair upload results, omitted when no token / `injectOnly: true`. */
|
|
156
|
+
uploaded?: UploadResult[];
|
|
157
|
+
}
|
|
158
|
+
declare function processBuildOutput(opts: ProcessOptions): Promise<ProcessReport>;
|
|
159
|
+
|
|
160
|
+
export { type BundlePair, DEFAULT_HOST, type InjectResult, type ProcessOptions, type ProcessReport, type UploadOptions, type UploadResult, findPairs, injectAll, injectPair, processBuildOutput, readDebugIdFromMap, uploadAll, uploadPair, walk };
|
|
@@ -0,0 +1,248 @@
|
|
|
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/build/sourcemaps.ts
|
|
21
|
+
var sourcemaps_exports = {};
|
|
22
|
+
__export(sourcemaps_exports, {
|
|
23
|
+
DEFAULT_HOST: () => DEFAULT_HOST,
|
|
24
|
+
findPairs: () => findPairs,
|
|
25
|
+
injectAll: () => injectAll,
|
|
26
|
+
injectPair: () => injectPair,
|
|
27
|
+
processBuildOutput: () => processBuildOutput,
|
|
28
|
+
readDebugIdFromMap: () => readDebugIdFromMap,
|
|
29
|
+
uploadAll: () => uploadAll,
|
|
30
|
+
uploadPair: () => uploadPair,
|
|
31
|
+
walk: () => walk
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(sourcemaps_exports);
|
|
34
|
+
|
|
35
|
+
// src/build/walk.ts
|
|
36
|
+
var import_node_fs = require("fs");
|
|
37
|
+
var import_node_path = require("path");
|
|
38
|
+
function walk(dir, out = []) {
|
|
39
|
+
for (const name of (0, import_node_fs.readdirSync)(dir)) {
|
|
40
|
+
const full = (0, import_node_path.join)(dir, name);
|
|
41
|
+
const st = (0, import_node_fs.statSync)(full);
|
|
42
|
+
if (st.isDirectory()) walk(full, out);
|
|
43
|
+
else out.push(full);
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
function findPairs(root) {
|
|
48
|
+
const all = walk(root);
|
|
49
|
+
const maps = new Set(all.filter((p) => p.endsWith(".map")));
|
|
50
|
+
const pairs = [];
|
|
51
|
+
for (const js of all) {
|
|
52
|
+
if (!js.endsWith(".js") && !js.endsWith(".mjs") && !js.endsWith(".cjs")) continue;
|
|
53
|
+
const map = js + ".map";
|
|
54
|
+
if (maps.has(map)) {
|
|
55
|
+
pairs.push({ jsPath: js, mapPath: map, bundleName: (0, import_node_path.basename)(js) });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return pairs;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// src/build/inject.ts
|
|
62
|
+
var import_node_fs2 = require("fs");
|
|
63
|
+
var import_node_crypto = require("crypto");
|
|
64
|
+
var DEBUG_ID_LINE_RE = /^\/\/# debugId=([0-9a-f-]{36})\s*$/m;
|
|
65
|
+
var REGISTRATION_MARKER = "/*!__allstak_debug_id_registration__*/";
|
|
66
|
+
function buildRegistrationSnippet(jsBody, debugId) {
|
|
67
|
+
const isEsm = /\bimport\.meta\b/.test(jsBody) || /^\s*(?:import|export)\b/m.test(jsBody);
|
|
68
|
+
if (isEsm) {
|
|
69
|
+
return `${REGISTRATION_MARKER}try{(globalThis._allstakDebugIds=globalThis._allstakDebugIds||{})[import.meta.url]="${debugId}"}catch(_){}`;
|
|
70
|
+
}
|
|
71
|
+
return `${REGISTRATION_MARKER}(function(){try{var u=(typeof document!=="undefined"&&document.currentScript&&document.currentScript.src)||(typeof location!=="undefined"?location.href:"");(globalThis._allstakDebugIds=globalThis._allstakDebugIds||{})[u]="${debugId}"}catch(_){}})();`;
|
|
72
|
+
}
|
|
73
|
+
function stripRegistration(js) {
|
|
74
|
+
const lineRe = new RegExp(
|
|
75
|
+
"^" + REGISTRATION_MARKER.replace(/[/*!]/g, (c) => "\\" + c) + ".*$",
|
|
76
|
+
"m"
|
|
77
|
+
);
|
|
78
|
+
return js.replace(lineRe, "");
|
|
79
|
+
}
|
|
80
|
+
function injectPair(p) {
|
|
81
|
+
const jsRaw = (0, import_node_fs2.readFileSync)(p.jsPath, "utf8");
|
|
82
|
+
const mapRaw = (0, import_node_fs2.readFileSync)(p.mapPath, "utf8");
|
|
83
|
+
const map = JSON.parse(mapRaw);
|
|
84
|
+
let debugId = typeof map.debugId === "string" ? map.debugId : "";
|
|
85
|
+
const existing = DEBUG_ID_LINE_RE.exec(jsRaw);
|
|
86
|
+
if (existing && existing[1]) debugId = debugId || existing[1];
|
|
87
|
+
const reused = !!debugId;
|
|
88
|
+
if (!debugId) debugId = (0, import_node_crypto.randomUUID)();
|
|
89
|
+
map.debugId = debugId;
|
|
90
|
+
(0, import_node_fs2.writeFileSync)(p.mapPath, JSON.stringify(map));
|
|
91
|
+
let jsOut = stripRegistration(jsRaw.replace(DEBUG_ID_LINE_RE, ""));
|
|
92
|
+
jsOut = jsOut.replace(/\s+$/, "");
|
|
93
|
+
jsOut += `
|
|
94
|
+
${buildRegistrationSnippet(jsOut, debugId)}
|
|
95
|
+
//# debugId=${debugId}
|
|
96
|
+
`;
|
|
97
|
+
(0, import_node_fs2.writeFileSync)(p.jsPath, jsOut);
|
|
98
|
+
return { debugId, reused };
|
|
99
|
+
}
|
|
100
|
+
function injectAll(pairs) {
|
|
101
|
+
return pairs.map((pair) => ({ pair, result: injectPair(pair) }));
|
|
102
|
+
}
|
|
103
|
+
function readDebugIdFromMap(mapPath) {
|
|
104
|
+
const json = JSON.parse((0, import_node_fs2.readFileSync)(mapPath, "utf8"));
|
|
105
|
+
return typeof json.debugId === "string" ? json.debugId : null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// src/build/upload.ts
|
|
109
|
+
var import_node_fs3 = require("fs");
|
|
110
|
+
var import_node_path2 = require("path");
|
|
111
|
+
var DEFAULT_HOST = "https://api.allstak.sa";
|
|
112
|
+
async function uploadOne(type, filePath, debugId, opts) {
|
|
113
|
+
let buf = (0, import_node_fs3.readFileSync)(filePath);
|
|
114
|
+
if (type === "sourcemap" && opts.stripSources) {
|
|
115
|
+
const json = JSON.parse(buf.toString("utf8"));
|
|
116
|
+
if (Array.isArray(json.sourcesContent)) delete json.sourcesContent;
|
|
117
|
+
buf = Buffer.from(JSON.stringify(json));
|
|
118
|
+
}
|
|
119
|
+
const form = new FormData();
|
|
120
|
+
form.append("debugId", debugId);
|
|
121
|
+
form.append("type", type);
|
|
122
|
+
form.append("release", opts.release);
|
|
123
|
+
if (opts.dist) form.append("dist", opts.dist);
|
|
124
|
+
form.append(
|
|
125
|
+
"file",
|
|
126
|
+
new Blob([buf], {
|
|
127
|
+
type: type === "sourcemap" ? "application/json" : "application/javascript"
|
|
128
|
+
}),
|
|
129
|
+
(0, import_node_path2.basename)(filePath)
|
|
130
|
+
);
|
|
131
|
+
const res = await fetch(opts.host.replace(/\/$/, "") + "/api/v1/artifacts/upload", {
|
|
132
|
+
method: "POST",
|
|
133
|
+
headers: { "X-AllStak-Upload-Token": opts.token },
|
|
134
|
+
body: form
|
|
135
|
+
});
|
|
136
|
+
return { status: res.status, body: await res.text(), ok: res.ok };
|
|
137
|
+
}
|
|
138
|
+
function sha8(buf) {
|
|
139
|
+
let hash = 0;
|
|
140
|
+
for (let i = 0; i < buf.length; i++) hash = (hash << 5) - hash + buf[i] | 0;
|
|
141
|
+
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
142
|
+
}
|
|
143
|
+
async function uploadPair(p, opts) {
|
|
144
|
+
const debugId = readDebugIdFromMap(p.mapPath);
|
|
145
|
+
if (!debugId) {
|
|
146
|
+
return {
|
|
147
|
+
bundleName: p.bundleName,
|
|
148
|
+
debugId: "",
|
|
149
|
+
ok: false,
|
|
150
|
+
steps: [{
|
|
151
|
+
type: "sourcemap",
|
|
152
|
+
status: 0,
|
|
153
|
+
sha8: "",
|
|
154
|
+
body: `[allstak/upload] no debugId in ${p.mapPath} \u2014 run inject first`
|
|
155
|
+
}]
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
const merged = {
|
|
159
|
+
release: opts.release,
|
|
160
|
+
host: opts.host ?? process.env.ALLSTAK_HOST ?? DEFAULT_HOST,
|
|
161
|
+
token: opts.token,
|
|
162
|
+
dist: opts.dist,
|
|
163
|
+
stripSources: opts.stripSources
|
|
164
|
+
};
|
|
165
|
+
const steps = [];
|
|
166
|
+
const mapResult = await uploadOne("sourcemap", p.mapPath, debugId, merged);
|
|
167
|
+
steps.push({
|
|
168
|
+
type: "sourcemap",
|
|
169
|
+
status: mapResult.status,
|
|
170
|
+
sha8: sha8((0, import_node_fs3.readFileSync)(p.mapPath)),
|
|
171
|
+
body: mapResult.ok ? void 0 : mapResult.body
|
|
172
|
+
});
|
|
173
|
+
let allOk = mapResult.ok;
|
|
174
|
+
if (opts.uploadBundles) {
|
|
175
|
+
const bundleResult = await uploadOne("bundle", p.jsPath, debugId, merged);
|
|
176
|
+
steps.push({
|
|
177
|
+
type: "bundle",
|
|
178
|
+
status: bundleResult.status,
|
|
179
|
+
sha8: sha8((0, import_node_fs3.readFileSync)(p.jsPath)),
|
|
180
|
+
body: bundleResult.ok ? void 0 : bundleResult.body
|
|
181
|
+
});
|
|
182
|
+
allOk = allOk && bundleResult.ok;
|
|
183
|
+
}
|
|
184
|
+
return { bundleName: p.bundleName, debugId, ok: allOk, steps };
|
|
185
|
+
}
|
|
186
|
+
async function uploadAll(pairs, opts) {
|
|
187
|
+
return Promise.all(pairs.map((p) => uploadPair(p, opts)));
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// src/build/sourcemaps.ts
|
|
191
|
+
var import_node_path3 = require("path");
|
|
192
|
+
async function processBuildOutput(opts) {
|
|
193
|
+
const dir = (0, import_node_path3.resolve)(opts.dir);
|
|
194
|
+
const pairs = findPairs(dir);
|
|
195
|
+
const log = opts.silent ? () => void 0 : (m) => console.log(`[allstak/sourcemaps] ${m}`);
|
|
196
|
+
log(`scanning ${dir} \u2014 ${pairs.length} bundle/map pair(s)`);
|
|
197
|
+
if (pairs.length === 0) {
|
|
198
|
+
return { dir, pairs: 0, injected: [] };
|
|
199
|
+
}
|
|
200
|
+
const injectedRaw = injectAll(pairs);
|
|
201
|
+
const injected = injectedRaw.map(({ pair, result }) => ({
|
|
202
|
+
bundleName: pair.bundleName,
|
|
203
|
+
debugId: result.debugId,
|
|
204
|
+
reused: result.reused
|
|
205
|
+
}));
|
|
206
|
+
for (const i of injected) {
|
|
207
|
+
log(` ${i.bundleName} ${i.debugId} ${i.reused ? "(reused)" : "(new)"}`);
|
|
208
|
+
}
|
|
209
|
+
const token = opts.token ?? process.env.ALLSTAK_UPLOAD_TOKEN;
|
|
210
|
+
const release = opts.release ?? process.env.ALLSTAK_RELEASE;
|
|
211
|
+
if (opts.injectOnly || !token) {
|
|
212
|
+
if (!opts.injectOnly && !token) {
|
|
213
|
+
log("skipping upload \u2014 no token (set ALLSTAK_UPLOAD_TOKEN or pass `token`)");
|
|
214
|
+
}
|
|
215
|
+
return { dir, pairs: pairs.length, injected };
|
|
216
|
+
}
|
|
217
|
+
if (!release) {
|
|
218
|
+
log("skipping upload \u2014 no release (set ALLSTAK_RELEASE or pass `release`)");
|
|
219
|
+
return { dir, pairs: pairs.length, injected };
|
|
220
|
+
}
|
|
221
|
+
const uploaded = await uploadAll(pairs, {
|
|
222
|
+
...opts,
|
|
223
|
+
release,
|
|
224
|
+
token
|
|
225
|
+
});
|
|
226
|
+
for (const u of uploaded) {
|
|
227
|
+
if (u.ok) {
|
|
228
|
+
log(` ${u.bundleName} uploaded debugId=${u.debugId}`);
|
|
229
|
+
} else {
|
|
230
|
+
const last = u.steps[u.steps.length - 1];
|
|
231
|
+
log(` ${u.bundleName} FAIL status=${last?.status ?? "?"} body=${last?.body ?? ""}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return { dir, pairs: pairs.length, injected, uploaded };
|
|
235
|
+
}
|
|
236
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
237
|
+
0 && (module.exports = {
|
|
238
|
+
DEFAULT_HOST,
|
|
239
|
+
findPairs,
|
|
240
|
+
injectAll,
|
|
241
|
+
injectPair,
|
|
242
|
+
processBuildOutput,
|
|
243
|
+
readDebugIdFromMap,
|
|
244
|
+
uploadAll,
|
|
245
|
+
uploadPair,
|
|
246
|
+
walk
|
|
247
|
+
});
|
|
248
|
+
//# sourceMappingURL=sourcemaps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/build/sourcemaps.ts","../../src/build/walk.ts","../../src/build/inject.ts","../../src/build/upload.ts"],"sourcesContent":["/**\n * Programmatic source-map pipeline. Build-time only.\n *\n * The high-level \"do everything\" entry point Vite/Webpack/Next plugins\n * call. Walk the build output → inject debug IDs → upload artifacts.\n *\n * import { processBuildOutput } from '@allstak/react/sourcemaps';\n *\n * await processBuildOutput({\n * dir: 'dist',\n * release: 'web@1.4.2',\n * token: process.env.ALLSTAK_UPLOAD_TOKEN!,\n * });\n */\n\nexport type { BundlePair } from './walk';\nexport { findPairs, walk } from './walk';\nexport type { InjectResult } from './inject';\nexport { injectPair, injectAll, readDebugIdFromMap } from './inject';\nexport type { UploadOptions, UploadResult } from './upload';\nexport { uploadPair, uploadAll, DEFAULT_HOST } from './upload';\n\nimport { resolve } from 'node:path';\nimport { findPairs } from './walk';\nimport { injectAll } from './inject';\nimport { uploadAll, type UploadOptions, type UploadResult } from './upload';\n\n/** Options for {@link processBuildOutput}. */\nexport interface ProcessOptions extends Partial<UploadOptions> {\n /** Build output directory to scan (e.g. `dist`, `.next/static`). */\n dir: string;\n /**\n * If true, only inject debug IDs and skip upload. Useful for sample\n * apps and CI dry-runs.\n */\n injectOnly?: boolean;\n /** Suppress per-pair console output. Default false (you want to see this). */\n silent?: boolean;\n}\n\n/** What `processBuildOutput` reports back. */\nexport interface ProcessReport {\n /** Absolute output dir scanned. */\n dir: string;\n /** Pairs found. */\n pairs: number;\n /** Per-pair injection results (debugId + reused?). */\n injected: Array<{ bundleName: string; debugId: string; reused: boolean }>;\n /** Per-pair upload results, omitted when no token / `injectOnly: true`. */\n uploaded?: UploadResult[];\n}\n\nexport async function processBuildOutput(opts: ProcessOptions): Promise<ProcessReport> {\n const dir = resolve(opts.dir);\n const pairs = findPairs(dir);\n const log = opts.silent ? () => undefined : (m: string) => console.log(`[allstak/sourcemaps] ${m}`);\n\n log(`scanning ${dir} — ${pairs.length} bundle/map pair(s)`);\n if (pairs.length === 0) {\n return { dir, pairs: 0, injected: [] };\n }\n\n const injectedRaw = injectAll(pairs);\n const injected = injectedRaw.map(({ pair, result }) => ({\n bundleName: pair.bundleName,\n debugId: result.debugId,\n reused: result.reused,\n }));\n for (const i of injected) {\n log(` ${i.bundleName} ${i.debugId} ${i.reused ? '(reused)' : '(new)'}`);\n }\n\n const token = opts.token ?? process.env.ALLSTAK_UPLOAD_TOKEN;\n const release = opts.release ?? process.env.ALLSTAK_RELEASE;\n\n if (opts.injectOnly || !token) {\n if (!opts.injectOnly && !token) {\n log('skipping upload — no token (set ALLSTAK_UPLOAD_TOKEN or pass `token`)');\n }\n return { dir, pairs: pairs.length, injected };\n }\n if (!release) {\n log('skipping upload — no release (set ALLSTAK_RELEASE or pass `release`)');\n return { dir, pairs: pairs.length, injected };\n }\n\n const uploaded = await uploadAll(pairs, {\n ...opts,\n release,\n token,\n });\n for (const u of uploaded) {\n if (u.ok) {\n log(` ${u.bundleName} uploaded debugId=${u.debugId}`);\n } else {\n const last = u.steps[u.steps.length - 1];\n log(` ${u.bundleName} FAIL status=${last?.status ?? '?'} body=${last?.body ?? ''}`);\n }\n }\n return { dir, pairs: pairs.length, injected, uploaded };\n}\n","/**\n * Build-time only. File-system walking for the source-map pipeline.\n * Pure Node 18+ (built-in `node:fs` only). Browser runtime never imports\n * this — it's behind a `./build/*` subpath that's marked Node-platform.\n */\n\nimport { readdirSync, statSync } from 'node:fs';\nimport { basename, join } from 'node:path';\n\n/** A bundle and its companion source map on disk. */\nexport interface BundlePair {\n /** Absolute path to the JS bundle (`.js` / `.mjs` / `.cjs`). */\n jsPath: string;\n /** Absolute path to the matching `.map` file. */\n mapPath: string;\n /** Bare filename of the bundle (no directory), for log lines. */\n bundleName: string;\n}\n\n/** Recursively list every file under `dir`. Symlinks are followed. */\nexport function walk(dir: string, out: string[] = []): string[] {\n for (const name of readdirSync(dir)) {\n const full = join(dir, name);\n const st = statSync(full);\n if (st.isDirectory()) walk(full, out);\n else out.push(full);\n }\n return out;\n}\n\n/**\n * Returns every `(bundle, sourcemap)` pair under `root`.\n *\n * A pair is a `.js` / `.mjs` / `.cjs` file with a sibling file of the\n * same name plus a `.map` suffix — the convention every modern bundler\n * (Vite, Webpack, esbuild, Rollup, tsup) follows.\n */\nexport function findPairs(root: string): BundlePair[] {\n const all = walk(root);\n const maps = new Set(all.filter((p) => p.endsWith('.map')));\n const pairs: BundlePair[] = [];\n for (const js of all) {\n if (!js.endsWith('.js') && !js.endsWith('.mjs') && !js.endsWith('.cjs')) continue;\n const map = js + '.map';\n if (maps.has(map)) {\n pairs.push({ jsPath: js, mapPath: map, bundleName: basename(js) });\n }\n }\n return pairs;\n}\n","/**\n * Debug-ID injection. Build-time only.\n *\n * For each `(bundle.js, bundle.js.map)` pair we:\n * - Generate a stable per-bundle UUID (one already on the bundle is\n * reused so re-running is idempotent).\n * - Append `//# debugId=<uuid>` to the JS so the runtime resolver in\n * `src/debug-id.ts` can read it back.\n * - Write a top-level `debugId` field into the `.map` JSON so the\n * symbolicator on the backend can join `bundle.js` ↔ `bundle.js.map`\n * by ID rather than guessing from filenames.\n *\n * Bundlers re-write hashed filenames on every build, so joining by ID\n * (instead of by URL or path) is what makes resolved stack frames\n * survive across releases.\n */\n\nimport { readFileSync, writeFileSync } from 'node:fs';\nimport { randomUUID } from 'node:crypto';\n\nimport type { BundlePair } from './walk';\n\nconst DEBUG_ID_LINE_RE = /^\\/\\/# debugId=([0-9a-f-]{36})\\s*$/m;\nconst REGISTRATION_MARKER = '/*!__allstak_debug_id_registration__*/';\n\nfunction buildRegistrationSnippet(jsBody: string, debugId: string): string {\n const isEsm = /\\bimport\\.meta\\b/.test(jsBody) || /^\\s*(?:import|export)\\b/m.test(jsBody);\n if (isEsm) {\n return `${REGISTRATION_MARKER}try{(globalThis._allstakDebugIds=globalThis._allstakDebugIds||{})[import.meta.url]=\"${debugId}\"}catch(_){}`;\n }\n return `${REGISTRATION_MARKER}(function(){try{var u=(typeof document!==\"undefined\"&&document.currentScript&&document.currentScript.src)||(typeof location!==\"undefined\"?location.href:\"\");(globalThis._allstakDebugIds=globalThis._allstakDebugIds||{})[u]=\"${debugId}\"}catch(_){}})();`;\n}\n\nfunction stripRegistration(js: string): string {\n const lineRe = new RegExp(\n '^' + REGISTRATION_MARKER.replace(/[/*!]/g, (c) => '\\\\' + c) + '.*$',\n 'm',\n );\n return js.replace(lineRe, '');\n}\n\n/** Outcome of injecting one pair. */\nexport interface InjectResult {\n /** UUID injected (or reused) for this bundle. */\n debugId: string;\n /** True if the bundle already had a debugId — we reused it. */\n reused: boolean;\n}\n\n/**\n * Inject (or reuse) the debug ID for a single bundle/sourcemap pair.\n * Mutates both files on disk. Pure synchronous Node — safe to call from\n * a Vite `closeBundle` or Webpack `afterEmit` hook.\n */\nexport function injectPair(p: BundlePair): InjectResult {\n const jsRaw = readFileSync(p.jsPath, 'utf8');\n const mapRaw = readFileSync(p.mapPath, 'utf8');\n const map = JSON.parse(mapRaw) as { debugId?: unknown; [k: string]: unknown };\n\n let debugId = typeof map.debugId === 'string' ? map.debugId : '';\n const existing = DEBUG_ID_LINE_RE.exec(jsRaw);\n if (existing && existing[1]) debugId = debugId || existing[1];\n const reused = !!debugId;\n if (!debugId) debugId = randomUUID();\n\n map.debugId = debugId;\n writeFileSync(p.mapPath, JSON.stringify(map));\n\n let jsOut = stripRegistration(jsRaw.replace(DEBUG_ID_LINE_RE, ''));\n jsOut = jsOut.replace(/\\s+$/, '');\n jsOut += `\\n${buildRegistrationSnippet(jsOut, debugId)}\\n//# debugId=${debugId}\\n`;\n writeFileSync(p.jsPath, jsOut);\n\n return { debugId, reused };\n}\n\n/** Inject every pair under `root`. Returns one record per pair. */\nexport function injectAll(pairs: BundlePair[]): Array<{ pair: BundlePair; result: InjectResult }> {\n return pairs.map((pair) => ({ pair, result: injectPair(pair) }));\n}\n\n/** Read a debug ID back from a `.map` file. */\nexport function readDebugIdFromMap(mapPath: string): string | null {\n const json = JSON.parse(readFileSync(mapPath, 'utf8')) as { debugId?: unknown };\n return typeof json.debugId === 'string' ? json.debugId : null;\n}\n","/**\n * Source-map / bundle upload client. Build-time only.\n *\n * Wraps the AllStak `/api/v1/artifacts/upload` endpoint with multipart\n * form data and best-effort retries. Pure Node 18+ (uses the global\n * `fetch` and `FormData`), no third-party HTTP client required.\n *\n * Auth: `X-AllStak-Upload-Token` header (NOT the runtime API key —\n * uploads have a dedicated, narrower scope. Generate one in the\n * dashboard → Project Settings → Upload Tokens).\n */\n\nimport { readFileSync } from 'node:fs';\nimport { basename } from 'node:path';\n\nimport type { BundlePair } from './walk';\nimport { readDebugIdFromMap } from './inject';\n\n/** Default ingest host — overridden via `host` option or `ALLSTAK_HOST`. */\nexport const DEFAULT_HOST = 'https://api.allstak.sa';\n\n/** Options for {@link uploadAll} / {@link uploadPair}. */\nexport interface UploadOptions {\n /** Release identifier, e.g. `myapp@1.4.2`. Required server-side. */\n release: string;\n /** Optional distribution tag (`web`, `ios-hermes`, `staging`, …). */\n dist?: string;\n /** AllStak ingest host (default `https://api.allstak.sa`). */\n host?: string;\n /** Project upload token (`aspk_…`). May come from `ALLSTAK_UPLOAD_TOKEN`. */\n token: string;\n /**\n * Drop `sourcesContent` from the map before upload (smaller payload).\n * Off by default — sourcesContent enables full-source rendering on the\n * dashboard. Turn on if you don't want source code uploaded.\n */\n stripSources?: boolean;\n /** Also upload the JS bundle alongside the map (off by default). */\n uploadBundles?: boolean;\n}\n\n/** One artifact upload result. */\nexport interface UploadResult {\n bundleName: string;\n debugId: string;\n /** True when both the map (and bundle, if requested) uploaded OK. */\n ok: boolean;\n /** Per-artifact responses, in the order we sent them. */\n steps: Array<{\n type: 'sourcemap' | 'bundle';\n status: number;\n sha8: string;\n body?: string;\n }>;\n}\n\ninterface OneStepResult {\n status: number;\n body: string;\n ok: boolean;\n}\n\nasync function uploadOne(\n type: 'sourcemap' | 'bundle',\n filePath: string,\n debugId: string,\n opts: Required<Pick<UploadOptions, 'release' | 'host' | 'token'>> &\n Pick<UploadOptions, 'dist' | 'stripSources'>,\n): Promise<OneStepResult> {\n let buf = readFileSync(filePath);\n if (type === 'sourcemap' && opts.stripSources) {\n const json = JSON.parse(buf.toString('utf8')) as { sourcesContent?: unknown };\n if (Array.isArray(json.sourcesContent)) delete json.sourcesContent;\n buf = Buffer.from(JSON.stringify(json));\n }\n\n const form = new FormData();\n form.append('debugId', debugId);\n form.append('type', type);\n form.append('release', opts.release);\n if (opts.dist) form.append('dist', opts.dist);\n form.append(\n 'file',\n new Blob([buf], {\n type: type === 'sourcemap' ? 'application/json' : 'application/javascript',\n }),\n basename(filePath),\n );\n\n const res = await fetch(opts.host.replace(/\\/$/, '') + '/api/v1/artifacts/upload', {\n method: 'POST',\n headers: { 'X-AllStak-Upload-Token': opts.token },\n body: form,\n });\n return { status: res.status, body: await res.text(), ok: res.ok };\n}\n\nfunction sha8(buf: Buffer): string {\n // Browser/Node fallback — keeps this file pure-JS (no node:crypto in\n // the public surface). Caller doesn't need cryptographic strength;\n // this is for log identification only.\n let hash = 0;\n for (let i = 0; i < buf.length; i++) hash = ((hash << 5) - hash + buf[i]!) | 0;\n return (hash >>> 0).toString(16).padStart(8, '0');\n}\n\n/** Upload one bundle/map pair. The map is always uploaded; bundle is opt-in. */\nexport async function uploadPair(p: BundlePair, opts: UploadOptions): Promise<UploadResult> {\n const debugId = readDebugIdFromMap(p.mapPath);\n if (!debugId) {\n return {\n bundleName: p.bundleName,\n debugId: '',\n ok: false,\n steps: [{\n type: 'sourcemap',\n status: 0,\n sha8: '',\n body: `[allstak/upload] no debugId in ${p.mapPath} — run inject first`,\n }],\n };\n }\n const merged = {\n release: opts.release,\n host: opts.host ?? process.env.ALLSTAK_HOST ?? DEFAULT_HOST,\n token: opts.token,\n dist: opts.dist,\n stripSources: opts.stripSources,\n };\n\n const steps: UploadResult['steps'] = [];\n const mapResult = await uploadOne('sourcemap', p.mapPath, debugId, merged);\n steps.push({\n type: 'sourcemap',\n status: mapResult.status,\n sha8: sha8(readFileSync(p.mapPath)),\n body: mapResult.ok ? undefined : mapResult.body,\n });\n\n let allOk = mapResult.ok;\n if (opts.uploadBundles) {\n const bundleResult = await uploadOne('bundle', p.jsPath, debugId, merged);\n steps.push({\n type: 'bundle',\n status: bundleResult.status,\n sha8: sha8(readFileSync(p.jsPath)),\n body: bundleResult.ok ? undefined : bundleResult.body,\n });\n allOk = allOk && bundleResult.ok;\n }\n\n return { bundleName: p.bundleName, debugId, ok: allOk, steps };\n}\n\n/** Upload every pair in parallel. */\nexport async function uploadAll(\n pairs: BundlePair[],\n opts: UploadOptions,\n): Promise<UploadResult[]> {\n return Promise.all(pairs.map((p) => uploadPair(p, opts)));\n}\n"],"mappings":"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","names":["import_node_fs","import_node_fs","import_node_path","import_node_path"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_HOST,
|
|
3
|
+
findPairs,
|
|
4
|
+
injectAll,
|
|
5
|
+
injectPair,
|
|
6
|
+
processBuildOutput,
|
|
7
|
+
readDebugIdFromMap,
|
|
8
|
+
uploadAll,
|
|
9
|
+
uploadPair,
|
|
10
|
+
walk
|
|
11
|
+
} from "./chunk-G6VPGDP6.mjs";
|
|
12
|
+
export {
|
|
13
|
+
DEFAULT_HOST,
|
|
14
|
+
findPairs,
|
|
15
|
+
injectAll,
|
|
16
|
+
injectPair,
|
|
17
|
+
processBuildOutput,
|
|
18
|
+
readDebugIdFromMap,
|
|
19
|
+
uploadAll,
|
|
20
|
+
uploadPair,
|
|
21
|
+
walk
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=sourcemaps.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { ProcessOptions } from './sourcemaps.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Vite plugin — injects AllStak debug IDs into the build output and
|
|
5
|
+
* (optionally) uploads source maps when the build finishes.
|
|
6
|
+
*
|
|
7
|
+
* // vite.config.ts
|
|
8
|
+
* import { defineConfig } from 'vite';
|
|
9
|
+
* import react from '@vitejs/plugin-react';
|
|
10
|
+
* import { allstakSourcemaps } from '@allstak/react/vite';
|
|
11
|
+
*
|
|
12
|
+
* export default defineConfig({
|
|
13
|
+
* plugins: [
|
|
14
|
+
* react(),
|
|
15
|
+
* allstakSourcemaps({
|
|
16
|
+
* release: process.env.ALLSTAK_RELEASE,
|
|
17
|
+
* token: process.env.ALLSTAK_UPLOAD_TOKEN,
|
|
18
|
+
* dist: 'web',
|
|
19
|
+
* }),
|
|
20
|
+
* ],
|
|
21
|
+
* build: { sourcemap: true },
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* The plugin runs in `closeBundle` (after Vite finishes writing every
|
|
25
|
+
* file to disk) so it works for both library and application builds
|
|
26
|
+
* and never blocks the dev server.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/** Options for {@link allstakSourcemaps}. */
|
|
30
|
+
interface AllStakVitePluginOptions extends Omit<ProcessOptions, 'dir'> {
|
|
31
|
+
/**
|
|
32
|
+
* Build output directory, relative to the project root or absolute.
|
|
33
|
+
* Defaults to Vite's `build.outDir` (resolved at config time).
|
|
34
|
+
* Override only if you write maps to a non-default location.
|
|
35
|
+
*/
|
|
36
|
+
dir?: string;
|
|
37
|
+
/** If true, plugin is skipped entirely. */
|
|
38
|
+
disabled?: boolean;
|
|
39
|
+
}
|
|
40
|
+
/** Minimal Vite plugin shape — defined locally so we don't peer-depend on `vite` types. */
|
|
41
|
+
interface MinimalVitePlugin {
|
|
42
|
+
name: string;
|
|
43
|
+
apply?: 'build' | 'serve';
|
|
44
|
+
enforce?: 'pre' | 'post';
|
|
45
|
+
configResolved?: (config: {
|
|
46
|
+
build?: {
|
|
47
|
+
outDir?: string;
|
|
48
|
+
};
|
|
49
|
+
root?: string;
|
|
50
|
+
}) => void;
|
|
51
|
+
closeBundle?: () => void | Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Returns a Vite plugin you spread into `plugins: []`. Doesn't import
|
|
55
|
+
* from `vite` directly — Vite's plugin contract is a duck-typed object,
|
|
56
|
+
* which keeps this package install-time light.
|
|
57
|
+
*/
|
|
58
|
+
declare function allstakSourcemaps(opts?: AllStakVitePluginOptions): MinimalVitePlugin;
|
|
59
|
+
/**
|
|
60
|
+
* Backwards-compatible alias matching the @allstak/js naming. Prefer
|
|
61
|
+
* `allstakSourcemaps` going forward — short, unambiguous.
|
|
62
|
+
*/
|
|
63
|
+
declare const allstakVitePlugin: typeof allstakSourcemaps;
|
|
64
|
+
|
|
65
|
+
export { type AllStakVitePluginOptions, allstakSourcemaps, allstakVitePlugin };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { ProcessOptions } from './sourcemaps.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Vite plugin — injects AllStak debug IDs into the build output and
|
|
5
|
+
* (optionally) uploads source maps when the build finishes.
|
|
6
|
+
*
|
|
7
|
+
* // vite.config.ts
|
|
8
|
+
* import { defineConfig } from 'vite';
|
|
9
|
+
* import react from '@vitejs/plugin-react';
|
|
10
|
+
* import { allstakSourcemaps } from '@allstak/react/vite';
|
|
11
|
+
*
|
|
12
|
+
* export default defineConfig({
|
|
13
|
+
* plugins: [
|
|
14
|
+
* react(),
|
|
15
|
+
* allstakSourcemaps({
|
|
16
|
+
* release: process.env.ALLSTAK_RELEASE,
|
|
17
|
+
* token: process.env.ALLSTAK_UPLOAD_TOKEN,
|
|
18
|
+
* dist: 'web',
|
|
19
|
+
* }),
|
|
20
|
+
* ],
|
|
21
|
+
* build: { sourcemap: true },
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* The plugin runs in `closeBundle` (after Vite finishes writing every
|
|
25
|
+
* file to disk) so it works for both library and application builds
|
|
26
|
+
* and never blocks the dev server.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/** Options for {@link allstakSourcemaps}. */
|
|
30
|
+
interface AllStakVitePluginOptions extends Omit<ProcessOptions, 'dir'> {
|
|
31
|
+
/**
|
|
32
|
+
* Build output directory, relative to the project root or absolute.
|
|
33
|
+
* Defaults to Vite's `build.outDir` (resolved at config time).
|
|
34
|
+
* Override only if you write maps to a non-default location.
|
|
35
|
+
*/
|
|
36
|
+
dir?: string;
|
|
37
|
+
/** If true, plugin is skipped entirely. */
|
|
38
|
+
disabled?: boolean;
|
|
39
|
+
}
|
|
40
|
+
/** Minimal Vite plugin shape — defined locally so we don't peer-depend on `vite` types. */
|
|
41
|
+
interface MinimalVitePlugin {
|
|
42
|
+
name: string;
|
|
43
|
+
apply?: 'build' | 'serve';
|
|
44
|
+
enforce?: 'pre' | 'post';
|
|
45
|
+
configResolved?: (config: {
|
|
46
|
+
build?: {
|
|
47
|
+
outDir?: string;
|
|
48
|
+
};
|
|
49
|
+
root?: string;
|
|
50
|
+
}) => void;
|
|
51
|
+
closeBundle?: () => void | Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Returns a Vite plugin you spread into `plugins: []`. Doesn't import
|
|
55
|
+
* from `vite` directly — Vite's plugin contract is a duck-typed object,
|
|
56
|
+
* which keeps this package install-time light.
|
|
57
|
+
*/
|
|
58
|
+
declare function allstakSourcemaps(opts?: AllStakVitePluginOptions): MinimalVitePlugin;
|
|
59
|
+
/**
|
|
60
|
+
* Backwards-compatible alias matching the @allstak/js naming. Prefer
|
|
61
|
+
* `allstakSourcemaps` going forward — short, unambiguous.
|
|
62
|
+
*/
|
|
63
|
+
declare const allstakVitePlugin: typeof allstakSourcemaps;
|
|
64
|
+
|
|
65
|
+
export { type AllStakVitePluginOptions, allstakSourcemaps, allstakVitePlugin };
|