@getexception/cli 0.1.24 → 0.1.25

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 CHANGED
@@ -1,78 +1,86 @@
1
1
  # @getexception/cli
2
2
 
3
- Prepare and privately upload source maps for a GetException project. Requires Node.js 20.19.6 or newer and a GetException server with source map support.
3
+ Prepare and privately upload browser JavaScript source maps. Node.js 20.19.6 or newer. No Git repository, CI/CD provider or deployment platform is required. Use matching SDK/server/CLI releases that include ADR-0009; these APIs are new and are not in earlier published packages.
4
4
 
5
- ```bash
5
+ ```sh
6
6
  yarn add --dev --exact @getexception/cli
7
7
  ```
8
8
 
9
- Build your ESM application with external source maps (Vite: `build.sourcemap: "hidden"`). Include `sourcesContent` to display source snippets. Set the SDK's `release` to the same `<project-slug>@<full 40-character Git SHA>` used below.
9
+ In Settings → Source maps, the project Owner labels a key and selects **Production** or **Preview**. Each new key permits one environment: `production` or `preview`. To upload for both, create a separate key for each. There is no second project permission switch. The key label is only a name in the dashboard.
10
10
 
11
- ```bash
12
- yarn build
13
- yarn getexception sourcemaps prepare --dir dist --output .getexception-maps --release "account@$CI_COMMIT_SHA"
14
- yarn getexception sourcemaps upload --dir .getexception-maps --url https://sentry.frontend.sndsy.ru --project "$GETEXCEPTION_PROJECT_ID"
15
- ```
16
-
17
- The Owner creates **Source map upload tokens** in the project's settings. Store the token in the CI secret `GETEXCEPTION_UPLOAD_TOKEN`. It expires after 90 days and can be revoked. Never pass it as a command-line argument or include it in the browser environment, repository, logs or public artifacts. Only trusted build jobs may read this secret.
18
-
19
- For GitLab MR previews use short-lived `GETEXCEPTION_GITLAB_ID_TOKEN` instead, after the operator has configured the pinned GitLab trust policy. Run `getexception ci context --url <HTTPS dashboard origin> --project <UUID>` before building; use the returned release, deployment and asset prefix for the actual JavaScript output. Upload and release registration use that identity automatically. Never set both credential variables. See the [GitLab integration guide](../../docs/gitlab-ci.md) for server configuration, exact build isolation and production restrictions. Version 0.1.7 does not support this flow.
11
+ Store the key in private secret storage. Your script must read the key from your secret storage and pass it explicitly as `token` to `uploadSourceMaps`. The function does not read environment variables or `.env` files and has no default secret name. Never put the key in browser config, CLI arguments, Git, logs or public build output. It grants upload/release metadata rights only for its project and environment, expires within 90 days and can be revoked. Production keys must not be available to preview builds.
20
12
 
21
- ## Reusable GitLab deployment integration
13
+ ## Independent functions
22
14
 
23
- Applications with a Node deployment script can use `@getexception/cli/integration` instead of implementing CI identity checks, source-map batching, public-output checks, upload retries and release registration themselves:
15
+ ```js
16
+ import {
17
+ prepareSourceMaps,
18
+ uploadSourceMaps,
19
+ assertPublicOutput,
20
+ } from "@getexception/cli/integration";
24
21
 
25
- ```ts
26
- import { deployWithGetException } from "@getexception/cli/integration";
22
+ // MY_UPLOAD_KEY is your chosen secret variable, read by this script.
23
+ const uploadKey = process.env.MY_UPLOAD_KEY;
27
24
 
28
- await deployWithGetException({
25
+ // Run your own build first with external/hidden JS maps and sourcesContent.
26
+ const prepared = await prepareSourceMaps({
27
+ directory: "dist",
28
+ output: "../private-maps", // a NEW private directory outside public output
29
+ release: "web-app@1.2.3",
30
+ buildId: "build-42",
31
+ format: "esm", // or classic for ordinary browser scripts
32
+ credentials: [uploadKey ?? ""], // reject this key in public files
33
+ });
34
+ await assertPublicOutput("dist", {
35
+ mapsEnabled: true,
36
+ credentials: [uploadKey ?? ""],
37
+ });
38
+ const result = await uploadSourceMaps({
39
+ directory: prepared.directory,
29
40
  url: "https://monitor.example.com",
30
- projectId: process.env.GETEXCEPTION_PROJECT_ID!,
31
- releasePrefix: "account",
32
- repository: { id: 123, path: "company/frontend/account" },
33
- environment: "production",
34
- environmentName: "production/app",
35
- output: "packages/app/build",
36
- runtimeEnv: {
37
- release: "APP_GETEXCEPTION_RELEASE",
38
- environment: "APP_GETEXCEPTION_ENVIRONMENT",
39
- },
40
- beforeBuild: async (safeEnv) => installAndSetUpDeployment(safeEnv),
41
- build: async (safeEnv) => buildApplication(safeEnv),
42
- deploy: async () => deployApplication(),
41
+ projectId: "<project UUID from Settings>",
42
+ environment: "preview",
43
+ token: uploadKey,
43
44
  });
45
+ if (result.status !== "ready") {
46
+ console.warn("[getexception] Source maps unavailable", result.diagnostic);
47
+ }
44
48
  ```
45
49
 
46
- `beforeBuild` is optional and runs once after the GitLab token has been removed from the process and the environment passed to the callback; use it for installation or SSH setup. `build` and `deploy` are the application's existing operations. `build` must start from a clean output directory on every call: if private map preparation fails or exceeds its five-minute preparation deadline, the integration calls it once more with maps disabled, then checks the public output before deploy. A compiler error, unsafe public output or failed deploy still stops the job. Context, registration and map-delivery failures do not undo a successful deploy; the result records `ready`, `disabled`, `failed` or `incomplete` and logs one safe summary. Registration and upload run only after deploy. The signed server context still decides what each job may upload. The integration works for other projects by changing the explicit project, repository, release prefix, environment and callbacks. It supports final ESM `.js`/`.mjs` and external non-indexed source maps; framework-specific build and deploy commands remain in the application.
50
+ The SDK must use the same `release`, `buildId` and upload `environment`. A version does not have to be a commit SHA. Change buildId for every rebuild; retain it when publishing the exact same files in another environment. The upload key must explicitly permit that environment. `buildId` is serialized as Sentry-compatible `dist`.
47
51
 
48
- The current CI context contract is **version 2**; CLI 0.1.8 must be upgraded to use it. The Owner selects **Production only** or **Production and MR** under project settings and adds trusted fork project IDs/paths. No container restart is needed. A context includes `sourceMaps: {enabled: true}` or, for a trusted preview with maps disabled, `{enabled: false, reason: "preview_disabled"}`. An unlisted preview source receives only `{version: 2, sourceMaps: {enabled: false, reason: "source_not_allowed"}}` with no build context or release-registration permission. Skip responses mean build/deploy without maps, not disable SDK events. Invalid credentials, HTTP failures and unknown contracts remain CLI errors; the caller handles them as optional monitoring failures and continues the normal application build/deploy without maps. A trusted context can still register its release while maps are disabled. Production never receives a skip response.
52
+ `prepareSourceMaps` changes JS by adding one Debug ID line, shifts mappings and removes `.js.map`/`.mjs.map` from public output. Run once before compression, SRI signing and publication. Classic scripts retain their directive prologue. Indexed maps, CSS maps and archives are unsupported. `urlPrefix` can prepend a deployment base path to artifact paths; paths must match actual browser JS URLs. Preparation fails closed on unsafe output, symlinks and private output inside the public directory. On failure, rebuild cleanly without maps and verify again before publication.
49
53
 
50
- Permanent upload tokens cannot be created or used for projects with GitLab authentication configured. They remain available for other trusted CI integrations. Forks may upload only their own preview job's maps; the main repository remains the only production source. Actual map read access is never granted to CI.
54
+ `uploadSourceMaps` does not build or deploy. It returns `{ status: "ready", batches }` only after every part validates, otherwise `{ status: "unavailable", diagnostic }`. Monitoring failure does not throw into your normal deployment. Production callers should make the warning prominent; preview callers can use one neutral log line. The default whole-delivery budget is 30 minutes, configurable via `timeoutMs` up to 60 minutes. Requests have bounded retries and timeouts. Both functions accept an optional `signal: AbortSignal` for cancellation.
51
55
 
52
- `prepare` modifies the **final ESM JavaScript**: it adds a Debug ID, shifts mappings by one line, removes sourceMappingURL comments and moves `.js.map` / `.mjs.map` files out of the public build. The private output directory must not exist and must be outside `dist`. Run this once per fresh build, before compression, SRI signing or deployment. Legacy IIFE/CommonJS bundles are unsupported. If assets are served below an additional base path, pass `--url-prefix <base-path>`; paths must match deployed JavaScript URLs.
56
+ Publish only the verified public directory. Keep private maps out of Git, CI artifacts/cache, image layers and public hosting. Use a private per-run workspace and delete it on success, failure and cancellation. A full `try/finally` example, separate manual upload and optional release registration are in the [project connection guide](../../docs/project-onboarding.md). Build, preparation, upload and deployment may be separate steps; moving private maps between hosts requires your own access-controlled temporary storage. No hosted provider artifact store is required or used automatically.
53
57
 
54
- Deploy the resulting `dist` unchanged. Upload failure does not undo preparation: retry within the same job using the same prepared directory. **Do not save source maps as GitLab artifacts or cache when access has not been verified.** The GitLab identity flow keeps them only in the isolated job workspace and uploads directly to GetException. A retry after that job ends requires a new build with a new job prefix; it cannot replace maps for the old build. Do not run `prepare` twice or rebuild only the maps. Never publish the private artifact directory alongside the application. Other map formats (for example CSS maps) should also be excluded from the public deploy artifact by your build configuration.
58
+ Retry with the same prepared maps; never prepare twice or rebuild just the maps. Existing files are reused by checksum within the project without sharing environment permissions. An immutable manifest receipt prevents replacing a build even after its map bytes expire. There is no fallback to the latest map or another environment. Late uploads reprocess retained matching events.
55
59
 
56
- `upload` sends an authenticated manifest, gzip-compresses each map in memory, uploads up to eight files concurrently with checksums, then waits for background validation. It retries bounded transient network/server failures, resumes the same manifest from its missing files, has a twenty-minute deadline per batch, and exits nonzero on failure. Neither production nor preview deployment depends on GetException availability. Deploy the safe prepared JavaScript first, then attempt map delivery from the same isolated job workspace. The CI wrapper catches monitoring failures and emits a prominent production warning or a single neutral preview log line. Only report successful map delivery when all batches are ready. A failed local prepare requires one clean rebuild without maps; a late successful upload automatically reprocesses existing errors. Do not retain maps in GitLab artifacts as a fallback. Raw maps have no download endpoint.
60
+ ## Equivalent commands
57
61
 
58
- Limits: 128 JS files and 128 MiB per upload, 16 MiB per map, 4 GiB per project, 8 GiB per installation, with a 5 GiB free-disk reserve for uploads. The Node integration splits a larger build into upload batches automatically. Non-indexed Source Map v3 JSON only; no archives or remote source downloads. Gzip is used only as bounded HTTPS transfer encoding and does not change the stored map format. Existing events are processed after a late upload. Errors thrown in the browser console have no source file and cannot gain a source snippet from a map.
62
+ ```sh
63
+ yarn getexception sourcemaps prepare --dir dist --output ../private-maps --release web-app@1.2.3 --build-id build-42 --token-env MY_UPLOAD_KEY
64
+ yarn getexception sourcemaps check --dir dist --token-env MY_UPLOAD_KEY
65
+ yarn getexception sourcemaps deliver --dir ../private-maps/maps --url https://monitor.example.com --project "$GETEXCEPTION_PROJECT_ID" --environment preview --token-env MY_UPLOAD_KEY
66
+ ```
59
67
 
60
- MIT. See `THIRD-PARTY-NOTICES.md`.
68
+ `--token-env` explicitly names the private variable to read; it never contains the key value. Choose your own name. `deliver` does not select a variable automatically. For `prepare`/`check`, the selected key is used only to detect accidental leaks in public files.
61
69
 
62
- ## Release context
70
+ `deliver` has the same optional-monitoring behavior as `uploadSourceMaps`. `prepare` and `check` exit nonzero for unsafe output. Never make all three commands unconditional success. Your ordinary compilation failures must also remain failures.
63
71
 
64
- Register the environment after a successful deployment, with the same project token. This works independently of source-map upload:
72
+ Limits: at most 4,096 maps per prepared build; 128 files and 128 MiB per upload batch; 16 MiB per map; 4 GiB per project; 8 GiB per installation; 5 GiB free-disk reserve. Large sets split into batches. Up to eight gzip-compressed maps upload concurrently, with compressed/uncompressed bounds and checksums. Source Map v3 JSON only, no remote downloads. Raw maps have no public download endpoint. Incomplete uploads expire after a day; ready maps follow the 30–60 day policy.
65
73
 
66
- ```bash
67
- yarn getexception releases register --url https://sentry.frontend.sndsy.ru --project "$GETEXCEPTION_PROJECT_ID" --release "account@$CI_COMMIT_SHA" --environment staging --repository-id "$CI_MERGE_REQUEST_TARGET_PROJECT_ID" --merge-request "$CI_MERGE_REQUEST_IID"
68
- ```
74
+ ## Compatibility
69
75
 
70
- Use the GitLab target repository's numeric project ID and the MR IID belonging to it. Standard merge-request pipelines provide these [predefined GitLab variables](https://docs.gitlab.com/ci/variables/predefined_variables/); custom preview pipelines must supply the actual pair explicitly. For production, use `--environment production` and omit both MR options. Repeated registration is safe. One SHA may have both production and staging contexts; this records release history, not current deployment status. Old events only establish an environment and cannot reveal an MR number.
76
+ Only legacy credential-selection commands and `deployWithGetException` retain their published `GETEXCEPTION_UPLOAD_TOKEN` / GitLab identity convention. The independent functions and `sourcemaps deliver` do not use it.
71
77
 
72
- With GitLab build authentication, use the exact `release` and `deployment` returned by `ci context` instead of constructing registration metadata yourself. `CI_MERGE_REQUEST_PROJECT_ID` is not a substitute for the target project in a fork workflow.
78
+ The lower-level `sourcemaps upload` command retains strict failure exit status and accepts a single prepared manifest directory. Legacy preparation without `--build-id` remains available for earlier clients; new integrations should always send a build ID and explicit environment.
73
79
 
74
- Debug IDs are deterministic for identical JS, maps and paths, regardless of the release SHA. The server reuses private bytes within the project and `upload` skips files it already has. Every release still sends its own manifest. Changed JavaScript requires its matching map: there is no fallback to the latest production map. Ready maps older than 30 days are eligible for cleanup when retained events do not use their Debug IDs, and expire after 60 days even if those events remain. Pending events postpone cleanup until processed. Shared files survive until all references expire.
80
+ Existing keys keep their previously effective permissions, including existing environment names. The API retains support for one explicit environment name when creating a key; existing multi-environment keys remain valid until expiry or revocation. No names are automatically aliased to Production or Preview.
75
81
 
76
- CI wrappers must keep `ci context` and release registration on short timeouts. Run map delivery only after the application is deployed and give each upload subprocess a hard timeout slightly longer than the CLI's twenty-minute deadline. Do not impose one small shared timeout on all batches: that makes valid larger builds fail based on transfer time. See the [failure handling contract](../../docs/gitlab-ci.md#обработка-сбоев-в-account). Do not mark the whole build job as allowed to fail. Compiler, deployment and public-output safety failures remain real job failures.
82
+ Existing GitLab identity clients and `deployWithGetException` remain supported with their former identity/namespace validation and legacy project policy. That policy does not control upload keys. These are optional compatibility APIs, not the onboarding path for new projects. See the [legacy GitLab guide](../../docs/gitlab-ci.md). Do not pass both legacy identity and permanent key variables to legacy credential-selection commands.
77
83
 
78
- On failure the CLI exits 1 and prints one `GETEXCEPTION_DIAGNOSTIC` JSON line to stderr with `version:1`, an allowlisted `code`, optional `httpStatus` and optional server UUID `requestId`. Network, response-contract and CI identity failures have separate codes. It never prints raw errors, tokens, headers or response bodies. Callers must parse and validate this diagnostic, not forward arbitrary stderr. Successful `ci context` stdout remains JSON only. Older CLI versions without this format can be handled with a generic safe failure code without blocking application deployment.
84
+ Permanent keys belong only in trusted execution contexts. An author who can change the script receiving a key can read it. A preview-only key does not make arbitrary external fork code safe to run with secrets.
85
+
86
+ MIT. See `THIRD-PARTY-NOTICES.md`.