@autter/runtime-cli 1.1.0 → 1.2.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/README.md +85 -13
- package/dist/{build-CPXR9Xd3.d.cts → build-BqjqqeLg.d.cts} +10 -3
- package/dist/{build-CPXR9Xd3.d.ts → build-BqjqqeLg.d.ts} +10 -3
- package/dist/{chunk-DQLLM2NT.js → chunk-KIQRQY3X.js} +16 -7
- package/dist/{chunk-I2743JCN.js → chunk-SIL3WZZ3.js} +1 -1
- package/dist/cli.js +1867 -36
- package/dist/index.cjs +273 -14
- package/dist/index.d.cts +56 -2
- package/dist/index.d.ts +56 -2
- package/dist/index.js +253 -2
- package/dist/next.cjs +11 -7
- package/dist/next.d.cts +1 -1
- package/dist/next.d.ts +1 -1
- package/dist/next.js +2 -2
- package/dist/vite.cjs +11 -7
- package/dist/vite.d.cts +1 -1
- package/dist/vite.d.ts +1 -1
- package/dist/vite.js +1 -1
- package/dist/webpack.cjs +11 -7
- package/dist/webpack.d.cts +1 -1
- package/dist/webpack.d.ts +1 -1
- package/dist/webpack.js +2 -2
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -5,24 +5,85 @@ content-addressed **debug id** and uploads its **source map** to the ingester,
|
|
|
5
5
|
so minified browser frames resolve to your original source, even when the
|
|
6
6
|
release your SDK reports doesn't match the upload.
|
|
7
7
|
|
|
8
|
+
- `autter-runtime sourcemaps setup` wires it into a project; `verify` checks a build
|
|
8
9
|
- `autter-runtime sourcemaps inject <dir>` / `upload <dir>` CLI
|
|
9
10
|
- Vite/Rollup plugin: `@autter/runtime-cli/vite`
|
|
10
11
|
- webpack 5 plugin: `@autter/runtime-cli/webpack`
|
|
11
12
|
- Next.js wrapper: `withAutterSourceMaps` from `@autter/runtime-cli/next`
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
[docs/SOURCE-MAPS.md](../../docs/SOURCE-MAPS.md).
|
|
14
|
+
Bundlers are optional peer dependencies. Debug ids need ingester 1.6.0+ and
|
|
15
|
+
`@autter/runtime-browser` 1.6.0+ (older ingesters still match `.js` maps by
|
|
16
|
+
release + path). Full guide: [docs/SOURCE-MAPS.md](../../docs/SOURCE-MAPS.md).
|
|
17
17
|
|
|
18
|
-
##
|
|
18
|
+
## Quick start (people and coding agents)
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
|
-
|
|
21
|
+
npx @autter/runtime-cli@latest sourcemaps setup # in the app's directory
|
|
22
|
+
npm run build # with AUTTER_RUNTIME_KEY set
|
|
23
|
+
npx autter-runtime sourcemaps verify dist # before deploying
|
|
22
24
|
```
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
**`setup [dir]`** is non-interactive and safe to re-run. It detects the build
|
|
27
|
+
tool (Vite and the frameworks built on it: SvelteKit, Nuxt, Astro, Remix,
|
|
28
|
+
React Router, Solid, Qwik; Next.js; webpack and Vue CLI; Rollup; Create React
|
|
29
|
+
App; Angular CLI; Parcel; esbuild), the package manager, the CI (GitHub
|
|
30
|
+
Actions, Vercel, Netlify, Cloudflare Pages, GitLab CI), the output directory,
|
|
31
|
+
existing source map settings, the installed browser SDK, and whether
|
|
32
|
+
`initAutterBrowser` gets a `release`. Then it:
|
|
33
|
+
|
|
34
|
+
- adds `@autter/runtime-cli` to `devDependencies` and prints the install
|
|
35
|
+
command (`--install` runs it);
|
|
36
|
+
- adds the Vite/Rollup or webpack plugin, or wraps the Next.js config in
|
|
37
|
+
`withAutterSourceMaps` (outermost), when the config has a shape it can edit
|
|
38
|
+
safely: `export default defineConfig({...})`, `module.exports = {...}`, a
|
|
39
|
+
config variable, a function returning an object, `withX(nextConfig)`
|
|
40
|
+
wrappers. It parses the file (JavaScript or TypeScript) and changes only
|
|
41
|
+
what it adds; anything else becomes a `manual` action with the exact snippet;
|
|
42
|
+
- for builds without a plugin (CRA, Angular, Parcel, esbuild), adds a
|
|
43
|
+
`postbuild` step (appended to `build` for pnpm, Yarn 2+ and Bun, which skip
|
|
44
|
+
`postbuild`) that runs `inject`, then `upload --delete-after-upload
|
|
45
|
+
--best-effort`, and turns on hidden maps where the tool can
|
|
46
|
+
(`GENERATE_SOURCEMAP=true`, Angular `"sourceMap": { "scripts": true, "hidden": true }`);
|
|
47
|
+
- reports, never edits, app code: a missing `release` gets a `manual` action
|
|
48
|
+
showing how to pass the commit SHA through the tool's public env or define
|
|
49
|
+
mechanism;
|
|
50
|
+
- never writes a key. It says where to store `AUTTER_RUNTIME_KEY` for each CI
|
|
51
|
+
it found, with commands that read the value from a prompt or stdin, never
|
|
52
|
+
from argv: `gh secret set AUTTER_RUNTIME_KEY --repo <owner/repo>`,
|
|
53
|
+
`vercel env add AUTTER_RUNTIME_KEY production`, `netlify env:set …
|
|
54
|
+
"$(cat)"`, and dashboard notes for Cloudflare Pages and GitLab.
|
|
55
|
+
|
|
56
|
+
`--dry-run` writes nothing; `--json` prints `{ detected, actions: [{ type:
|
|
57
|
+
"edit"|"add-dependency"|"add-script"|"manual"|"set-secret", file?,
|
|
58
|
+
description, snippet?, command? }], secret: { name, key, where }, next }`.
|
|
59
|
+
Exit codes: `0` everything applied, `2` manual actions remain, `1` error.
|
|
60
|
+
|
|
61
|
+
**`verify <dir>`** checks a production build before deploy: every JS bundle
|
|
62
|
+
has a debug id (the comment and the registration snippet), no `.map` file is
|
|
63
|
+
left and no `sourceMappingURL` points at a missing map (both deploy risks),
|
|
64
|
+
and, when `AUTTER_RUNTIME_KEY` is set, every bundle's map is on the ingester
|
|
65
|
+
(`/v1/sourcemaps/check` by debug id, ingester 1.7.0+). Without a key the
|
|
66
|
+
local checks still run and the upload is reported as unverified. Files copied
|
|
67
|
+
unchanged from `public/`, Next.js build manifests and polyfills, and service workers are
|
|
68
|
+
skipped; `--ignore <glob>` skips more. `--allow-maps` reports leftover maps
|
|
69
|
+
without failing. `--json` for machines; exit `1` on any failure, with the
|
|
70
|
+
reason per file.
|
|
71
|
+
|
|
72
|
+
## Keys
|
|
73
|
+
|
|
74
|
+
Set `AUTTER_RUNTIME_KEY` where your build runs. The recommended key for CI is
|
|
75
|
+
an **upload-only key** (`autter_rtu_…`): it can upload and check source maps
|
|
76
|
+
and nothing else, so a leaked CI secret can't send telemetry. The full server
|
|
77
|
+
key (`autter_rt_…`) also works. A publishable client key (`autter_rtc_…`) is
|
|
78
|
+
refused. Upload keys need ingester 1.7.0+. Without a key, the plugins turn no
|
|
79
|
+
source maps on and change nothing, and `upload --best-effort` uploads nothing
|
|
80
|
+
and exits 0.
|
|
81
|
+
|
|
82
|
+
## By hand
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
npm install -D @autter/runtime-cli
|
|
86
|
+
```
|
|
26
87
|
|
|
27
88
|
## Vite / Rollup
|
|
28
89
|
|
|
@@ -67,9 +128,13 @@ npx autter-runtime sourcemaps upload dist --dry-run
|
|
|
67
128
|
```
|
|
68
129
|
|
|
69
130
|
```
|
|
70
|
-
autter-runtime sourcemaps
|
|
131
|
+
autter-runtime sourcemaps setup [dir] [--dry-run] [--install] [--json]
|
|
132
|
+
autter-runtime sourcemaps verify <dir> [--endpoint <url>] [--url-prefix <prefix>]
|
|
133
|
+
[--ignore <glob>]... [--allow-maps] [--json]
|
|
134
|
+
autter-runtime sourcemaps inject <dir> [--dry-run] [--json]
|
|
71
135
|
autter-runtime sourcemaps upload <dir> [--release <r>] [--url-prefix <prefix>]
|
|
72
|
-
[--endpoint <url>] [--concurrency <n>] [--delete-after-upload]
|
|
136
|
+
[--endpoint <url>] [--concurrency <n>] [--delete-after-upload]
|
|
137
|
+
[--best-effort] [--dry-run] [--json]
|
|
73
138
|
```
|
|
74
139
|
|
|
75
140
|
- **inject** writes `//# debugId=<id>`, a one-line snippet that registers
|
|
@@ -84,15 +149,22 @@ autter-runtime sourcemaps upload <dir> [--release <r>] [--url-prefix <prefix>]
|
|
|
84
149
|
without them, with a warning. Release: `--release`, else `GITHUB_SHA`,
|
|
85
150
|
`VERCEL_GIT_COMMIT_SHA`, `CF_PAGES_COMMIT_SHA`, `GIT_SHA`, then
|
|
86
151
|
`git rev-parse HEAD`.
|
|
152
|
+
- **upload --best-effort** is for build scripts that also run locally and in
|
|
153
|
+
fork PRs: without a key, or when the upload fails, it says so and exits 0;
|
|
154
|
+
with `--delete-after-upload`, every `.map` under `<dir>` is then deleted
|
|
155
|
+
anyway, so the output is the same with or without a key and never ships
|
|
156
|
+
maps.
|
|
87
157
|
|
|
88
158
|
Exit codes: `0` ok, `1` some maps failed, `2` no key / no release / key
|
|
89
|
-
rejected, `64` usage error.
|
|
159
|
+
rejected, `64` usage error (`--best-effort`: always `0`). `setup` and `verify`
|
|
160
|
+
have their own, above.
|
|
90
161
|
|
|
91
162
|
## Programmatic API
|
|
92
163
|
|
|
93
164
|
```ts
|
|
94
|
-
import { injectDir, uploadDir } from "@autter/runtime-cli";
|
|
165
|
+
import { injectDir, uploadDir, verifyDir } from "@autter/runtime-cli";
|
|
95
166
|
|
|
96
167
|
await injectDir("dist");
|
|
97
|
-
const summary = await uploadDir("dist", { urlPrefix: "/", release: process.env.GIT_SHA });
|
|
168
|
+
const summary = await uploadDir("dist", { urlPrefix: "/", release: process.env.GIT_SHA, deleteAfterUpload: true });
|
|
169
|
+
const check = await verifyDir("dist"); // check.ok, check.failures, check.upload.status
|
|
98
170
|
```
|
|
@@ -75,6 +75,11 @@ declare const MAX_MAP_CHARS: number;
|
|
|
75
75
|
/** The ingester's `/v1/sourcemaps` body limit, counted after the gzip body
|
|
76
76
|
* is inflated: the map plus room for the rest of the request. */
|
|
77
77
|
declare const MAX_UPLOAD_BYTES: number;
|
|
78
|
+
/** Keys `upload` accepts, and the one it refuses before sending anything. */
|
|
79
|
+
declare const UPLOAD_KEY_PREFIX = "autter_rtu_";
|
|
80
|
+
declare const SERVER_KEY_PREFIX = "autter_rt_";
|
|
81
|
+
declare const CLIENT_KEY_PREFIX = "autter_rtc_";
|
|
82
|
+
declare const KEY_ADVICE: string;
|
|
78
83
|
interface UploadOptions {
|
|
79
84
|
/** Only these bundles (absolute, or relative to the directory). */
|
|
80
85
|
files?: string[];
|
|
@@ -86,7 +91,8 @@ interface UploadOptions {
|
|
|
86
91
|
/** Ingester base URL. Default: $AUTTER_ENDPOINT, $AUTTER_RUNTIME_ENDPOINT,
|
|
87
92
|
* $OTEL_EXPORTER_OTLP_ENDPOINT, else https://otlp.autter.dev. */
|
|
88
93
|
endpoint?: string;
|
|
89
|
-
/**
|
|
94
|
+
/** Upload key (`autter_rtu_…`, recommended for CI) or server key
|
|
95
|
+
* (`autter_rt_…`). Default: $AUTTER_RUNTIME_KEY. */
|
|
90
96
|
key?: string;
|
|
91
97
|
/** List what would be uploaded; no network, no key needed. */
|
|
92
98
|
dryRun?: boolean;
|
|
@@ -149,7 +155,8 @@ interface AutterSourceMapsOptions {
|
|
|
149
155
|
/** Ingester base URL. Default: $AUTTER_ENDPOINT, $AUTTER_RUNTIME_ENDPOINT,
|
|
150
156
|
* $OTEL_EXPORTER_OTLP_ENDPOINT, else https://otlp.autter.dev. */
|
|
151
157
|
endpoint?: string;
|
|
152
|
-
/**
|
|
158
|
+
/** Upload-only key (`autter_rtu_…`, recommended for CI) or server key
|
|
159
|
+
* (`autter_rt_…`). Default: $AUTTER_RUNTIME_KEY. Without one (and
|
|
153
160
|
* without `upload: false` or `dryRun`), the plugin generates no source
|
|
154
161
|
* maps it would have to delete again: the build is left as it was. */
|
|
155
162
|
key?: string;
|
|
@@ -203,4 +210,4 @@ declare function processBuildOutput(input: {
|
|
|
203
210
|
maps?: string[];
|
|
204
211
|
}): Promise<BuildOutputResult>;
|
|
205
212
|
|
|
206
|
-
export { type AutterSourceMapsOptions as A, BUNDLE_RE as B, DEFAULT_ENDPOINT as D, FatalUploadError as F, type InjectOptions as I, MAX_MAP_CHARS as M,
|
|
213
|
+
export { type AutterSourceMapsOptions as A, BUNDLE_RE as B, CLIENT_KEY_PREFIX as C, DEFAULT_ENDPOINT as D, FatalUploadError as F, type InjectOptions as I, KEY_ADVICE as K, MAX_MAP_CHARS as M, SERVER_KEY_PREFIX as S, UPLOAD_KEY_PREFIX as U, type BuildOutputResult as a, type BundleWithMap as b, type InjectResult as c, MAX_UPLOAD_BYTES as d, SNIPPET_LINE_KEY as e, type UploadItem as f, type UploadOptions as g, type UploadSummary as h, findBundles as i, formatUploadSummary as j, injectBundle as k, injectDir as l, mapPathFor as m, resolveEndpoint as n, shiftMappings as o, processBuildOutput as p, snippetLine as q, readSourceMappingUrl as r, servedFilename as s, storedMapJson as t, stripSourceMappingUrl as u, uploadDir as v };
|
|
@@ -75,6 +75,11 @@ declare const MAX_MAP_CHARS: number;
|
|
|
75
75
|
/** The ingester's `/v1/sourcemaps` body limit, counted after the gzip body
|
|
76
76
|
* is inflated: the map plus room for the rest of the request. */
|
|
77
77
|
declare const MAX_UPLOAD_BYTES: number;
|
|
78
|
+
/** Keys `upload` accepts, and the one it refuses before sending anything. */
|
|
79
|
+
declare const UPLOAD_KEY_PREFIX = "autter_rtu_";
|
|
80
|
+
declare const SERVER_KEY_PREFIX = "autter_rt_";
|
|
81
|
+
declare const CLIENT_KEY_PREFIX = "autter_rtc_";
|
|
82
|
+
declare const KEY_ADVICE: string;
|
|
78
83
|
interface UploadOptions {
|
|
79
84
|
/** Only these bundles (absolute, or relative to the directory). */
|
|
80
85
|
files?: string[];
|
|
@@ -86,7 +91,8 @@ interface UploadOptions {
|
|
|
86
91
|
/** Ingester base URL. Default: $AUTTER_ENDPOINT, $AUTTER_RUNTIME_ENDPOINT,
|
|
87
92
|
* $OTEL_EXPORTER_OTLP_ENDPOINT, else https://otlp.autter.dev. */
|
|
88
93
|
endpoint?: string;
|
|
89
|
-
/**
|
|
94
|
+
/** Upload key (`autter_rtu_…`, recommended for CI) or server key
|
|
95
|
+
* (`autter_rt_…`). Default: $AUTTER_RUNTIME_KEY. */
|
|
90
96
|
key?: string;
|
|
91
97
|
/** List what would be uploaded; no network, no key needed. */
|
|
92
98
|
dryRun?: boolean;
|
|
@@ -149,7 +155,8 @@ interface AutterSourceMapsOptions {
|
|
|
149
155
|
/** Ingester base URL. Default: $AUTTER_ENDPOINT, $AUTTER_RUNTIME_ENDPOINT,
|
|
150
156
|
* $OTEL_EXPORTER_OTLP_ENDPOINT, else https://otlp.autter.dev. */
|
|
151
157
|
endpoint?: string;
|
|
152
|
-
/**
|
|
158
|
+
/** Upload-only key (`autter_rtu_…`, recommended for CI) or server key
|
|
159
|
+
* (`autter_rt_…`). Default: $AUTTER_RUNTIME_KEY. Without one (and
|
|
153
160
|
* without `upload: false` or `dryRun`), the plugin generates no source
|
|
154
161
|
* maps it would have to delete again: the build is left as it was. */
|
|
155
162
|
key?: string;
|
|
@@ -203,4 +210,4 @@ declare function processBuildOutput(input: {
|
|
|
203
210
|
maps?: string[];
|
|
204
211
|
}): Promise<BuildOutputResult>;
|
|
205
212
|
|
|
206
|
-
export { type AutterSourceMapsOptions as A, BUNDLE_RE as B, DEFAULT_ENDPOINT as D, FatalUploadError as F, type InjectOptions as I, MAX_MAP_CHARS as M,
|
|
213
|
+
export { type AutterSourceMapsOptions as A, BUNDLE_RE as B, CLIENT_KEY_PREFIX as C, DEFAULT_ENDPOINT as D, FatalUploadError as F, type InjectOptions as I, KEY_ADVICE as K, MAX_MAP_CHARS as M, SERVER_KEY_PREFIX as S, UPLOAD_KEY_PREFIX as U, type BuildOutputResult as a, type BundleWithMap as b, type InjectResult as c, MAX_UPLOAD_BYTES as d, SNIPPET_LINE_KEY as e, type UploadItem as f, type UploadOptions as g, type UploadSummary as h, findBundles as i, formatUploadSummary as j, injectBundle as k, injectDir as l, mapPathFor as m, resolveEndpoint as n, shiftMappings as o, processBuildOutput as p, snippetLine as q, readSourceMappingUrl as r, servedFilename as s, storedMapJson as t, stripSourceMappingUrl as u, uploadDir as v };
|
|
@@ -667,6 +667,10 @@ var DEFAULT_ENDPOINT = "https://otlp.autter.dev";
|
|
|
667
667
|
var MAX_MAP_CHARS = 32 * 1024 * 1024;
|
|
668
668
|
var MAX_UPLOAD_BYTES = MAX_MAP_CHARS + 1024 * 1024;
|
|
669
669
|
var LEGACY_MAX_BYTES = 5 * 1024 * 1024;
|
|
670
|
+
var UPLOAD_KEY_PREFIX = "autter_rtu_";
|
|
671
|
+
var SERVER_KEY_PREFIX = "autter_rt_";
|
|
672
|
+
var CLIENT_KEY_PREFIX = "autter_rtc_";
|
|
673
|
+
var KEY_ADVICE = "set AUTTER_RUNTIME_KEY to an upload-only key (autter_rtu_\u2026, recommended for CI: it can only upload source maps) or the full server key (autter_rt_\u2026, also works)";
|
|
670
674
|
var gzip = promisify(gzipCallback);
|
|
671
675
|
var CHECK_BATCH = 500;
|
|
672
676
|
var MAX_ATTEMPTS = 3;
|
|
@@ -775,10 +779,13 @@ async function uploadDir(dir, options = {}) {
|
|
|
775
779
|
return summary;
|
|
776
780
|
}
|
|
777
781
|
const key = (options.key ?? env.AUTTER_RUNTIME_KEY ?? "").trim();
|
|
778
|
-
if (!key) throw new FatalUploadError(
|
|
779
|
-
if (key.startsWith(
|
|
780
|
-
throw new FatalUploadError(
|
|
782
|
+
if (!key) throw new FatalUploadError(`no ingest key: ${KEY_ADVICE}`);
|
|
783
|
+
if (key.startsWith(CLIENT_KEY_PREFIX)) {
|
|
784
|
+
throw new FatalUploadError(`AUTTER_RUNTIME_KEY is a publishable client key (autter_rtc_\u2026), which cannot upload source maps: ${KEY_ADVICE}`);
|
|
781
785
|
}
|
|
786
|
+
const rejected = (status, detail) => new FatalUploadError(
|
|
787
|
+
`the ingester rejected the key (${status}): ${detail}` + (key.startsWith(UPLOAD_KEY_PREFIX) ? " (upload keys, autter_rtu_\u2026, need ingester 1.7.0 or later; the server key works with any)" : "")
|
|
788
|
+
);
|
|
782
789
|
const headers = { "content-type": "application/json", authorization: `Bearer ${key}` };
|
|
783
790
|
const uploadHeaders = { ...headers, "content-encoding": "gzip" };
|
|
784
791
|
const skipped = /* @__PURE__ */ new Set();
|
|
@@ -800,9 +807,7 @@ async function uploadDir(dir, options = {}) {
|
|
|
800
807
|
);
|
|
801
808
|
break;
|
|
802
809
|
}
|
|
803
|
-
if (res.status === 401 || res.status === 403)
|
|
804
|
-
throw new FatalUploadError(`the ingester rejected the key (${res.status}): ${(await res.text()).slice(0, 300)}`);
|
|
805
|
-
}
|
|
810
|
+
if (res.status === 401 || res.status === 403) throw rejected(res.status, (await res.text()).slice(0, 300));
|
|
806
811
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
807
812
|
const body = await res.json();
|
|
808
813
|
const present = new Set(Array.isArray(body.present) ? body.present : []);
|
|
@@ -833,7 +838,7 @@ async function uploadDir(dir, options = {}) {
|
|
|
833
838
|
detail = err.message;
|
|
834
839
|
}
|
|
835
840
|
if (status === 401 || status === 403) {
|
|
836
|
-
fatal =
|
|
841
|
+
fatal = rejected(status, detail);
|
|
837
842
|
return;
|
|
838
843
|
}
|
|
839
844
|
const retryable = status === 0 || status === 429 || status >= 500;
|
|
@@ -1023,6 +1028,10 @@ export {
|
|
|
1023
1028
|
DEFAULT_ENDPOINT,
|
|
1024
1029
|
MAX_MAP_CHARS,
|
|
1025
1030
|
MAX_UPLOAD_BYTES,
|
|
1031
|
+
UPLOAD_KEY_PREFIX,
|
|
1032
|
+
SERVER_KEY_PREFIX,
|
|
1033
|
+
CLIENT_KEY_PREFIX,
|
|
1034
|
+
KEY_ADVICE,
|
|
1026
1035
|
resolveEndpoint,
|
|
1027
1036
|
servedFilename,
|
|
1028
1037
|
storedMapJson,
|