@goliapkg/sentori-cli 1.5.0 → 1.7.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 +297 -26
- package/lib/apps.d.ts +24 -0
- package/lib/apps.d.ts.map +1 -0
- package/lib/apps.js +17 -0
- package/lib/apps.js.map +1 -0
- package/lib/artifacts.d.ts +7 -0
- package/lib/artifacts.d.ts.map +1 -1
- package/lib/artifacts.js +5 -1
- package/lib/artifacts.js.map +1 -1
- package/lib/compatibility.d.ts +6 -0
- package/lib/compatibility.d.ts.map +1 -0
- package/lib/compatibility.js +21 -0
- package/lib/compatibility.js.map +1 -0
- package/lib/index.js +150 -68
- package/lib/index.js.map +1 -1
- package/lib/issue.d.ts +4 -0
- package/lib/issue.d.ts.map +1 -1
- package/lib/issue.js +8 -0
- package/lib/issue.js.map +1 -1
- package/lib/srcbundle.d.ts +37 -2
- package/lib/srcbundle.d.ts.map +1 -1
- package/lib/srcbundle.js +181 -58
- package/lib/srcbundle.js.map +1 -1
- package/lib/upload.d.ts +25 -0
- package/lib/upload.d.ts.map +1 -1
- package/lib/upload.js +52 -1
- package/lib/upload.js.map +1 -1
- package/lib/workflow.d.ts +47 -0
- package/lib/workflow.d.ts.map +1 -0
- package/lib/workflow.js +289 -0
- package/lib/workflow.js.map +1 -0
- package/package.json +10 -6
- package/src/__tests__/apps.test.ts +48 -0
- package/src/__tests__/artifacts.test.ts +1 -1
- package/src/__tests__/compatibility.test.ts +80 -0
- package/src/__tests__/expand-sourcemaps.test.ts +56 -0
- package/src/__tests__/rn-upload-hook.test.ts +35 -0
- package/src/__tests__/srcbundle.test.ts +66 -0
- package/src/__tests__/workflow.test.ts +102 -0
- package/src/apps.ts +31 -0
- package/src/artifacts.ts +12 -1
- package/src/compatibility.ts +21 -0
- package/src/index.ts +123 -69
- package/src/issue.ts +5 -1
- package/src/srcbundle.ts +150 -61
- package/src/upload.ts +51 -1
- package/src/workflow.ts +240 -0
- package/lib/source-bundle.d.ts +0 -28
- package/lib/source-bundle.d.ts.map +0 -1
- package/lib/source-bundle.js +0 -193
- package/lib/source-bundle.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,51 +1,322 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Sentori CLI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Configure, collect, upload and verify the debug files from an application build.
|
|
4
|
+
The package is `@goliapkg/sentori-cli`; its command is **`sentori`**.
|
|
5
|
+
`sentori-cli` remains an alias for existing scripts. The CLI runs on the build
|
|
6
|
+
machine and does not add runtime work to the application.
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
- **Issue triage** (list / resolve / silence / comment) — usable as
|
|
7
|
-
a Model Context Protocol (MCP) server so Claude / Cursor / Aider
|
|
8
|
-
can act on your error inbox
|
|
8
|
+
## Install the correct version
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
This guide requires **CLI 1.7.0**. Check registry availability before updating
|
|
11
|
+
your build pipeline. The older 1.5.0 package has only the
|
|
12
|
+
`sentori-cli` executable and does not have `init`, `doctor`, `upload all`, ZIP
|
|
13
|
+
packaging or exact-file `verify`. Do not install 1.5.0 and run this guide's commands.
|
|
14
|
+
|
|
15
|
+
Use Node **18.17 or newer**; use a maintained Node release for CI. Pin the CLI as a
|
|
16
|
+
development dependency and commit the package lock:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
npm view @goliapkg/sentori-cli@1.7.0 version
|
|
20
|
+
npm install --save-dev --save-exact @goliapkg/sentori-cli@1.7.0
|
|
21
|
+
npx --no-install sentori --version
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The last command must print `sentori 1.7.0`. If npm cannot find that version, use
|
|
25
|
+
the tested package supplied by the Sentori team, without assuming `latest` has
|
|
26
|
+
these features:
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
npm install --save-dev --save-exact /absolute/path/goliapkg-sentori-cli-1.7.0.tgz
|
|
30
|
+
npx --no-install sentori --version
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
For maintainers preparing that package, from the Sentori repository root with
|
|
34
|
+
its pinned Bun installed:
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
bun install --frozen-lockfile
|
|
38
|
+
bun run --cwd sdk/cli build
|
|
39
|
+
npm pack ./sdk/cli --ignore-scripts --pack-destination /tmp
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Consumers need Node/npm, not Bun. A local dev dependency is not added to an
|
|
43
|
+
interactive shell's PATH: use `npx --no-install sentori` as below, or `sentori`
|
|
44
|
+
inside an npm script. `--no-install` prevents npx from downloading a different
|
|
45
|
+
package if the local executable is missing. The server maintenance binary
|
|
46
|
+
`sentori-operator` is a separate tool.
|
|
47
|
+
|
|
48
|
+
## Compatibility and version identity
|
|
49
|
+
|
|
50
|
+
| Value | Meaning |
|
|
51
|
+
| --- | --- |
|
|
52
|
+
| CLI `1.7.0` | Build-tool package version, shown by `sentori --version` |
|
|
53
|
+
| Server version | Running server binary, reported by `sentori doctor` |
|
|
54
|
+
| SDK version | Independently versioned app library; it need not equal the CLI or server |
|
|
55
|
+
| Config `version: 1` | Upload configuration schema, not a product version |
|
|
56
|
+
| App `release` | Exact string reported by the SDK, including build number |
|
|
57
|
+
| Git tag | Optional source revision; it does not set the app release |
|
|
58
|
+
|
|
59
|
+
The current server advertises artifact protocol `1`, source formats `zip` and
|
|
60
|
+
`json`, and `sha256`/`format` verification on the existing authenticated artifact
|
|
61
|
+
inventory API. These fields are additive: old clients keep using that API and
|
|
62
|
+
legacy path-to-content JSON remains accepted.
|
|
63
|
+
|
|
64
|
+
CLI 1.6 checks capabilities rather than guessing from a server version. An older
|
|
65
|
+
build can have the same displayed server version without ZIP support. This
|
|
66
|
+
repository's server changes must be deployed before using source ZIPs against
|
|
67
|
+
that instance; changing the CLI alone is not enough.
|
|
68
|
+
|
|
69
|
+
| Server response | CLI 1.6 behavior |
|
|
70
|
+
| --- | --- |
|
|
71
|
+
| Protocol 1, ZIP and verification supported | Unified upload and verification, including sources |
|
|
72
|
+
| No capability advertisement | Source-map/dSYM/mapping workflows remain available; a ZIP plan stops before any upload |
|
|
73
|
+
| ZIP absent, unsupported protocol or incomplete verification support | Relevant workflow fails with an upgrade/compatibility message before uploading |
|
|
74
|
+
| Missing/false `usable`, wrong hash or wrong filename | Exact-file verification fails; stored bytes alone are not success |
|
|
75
|
+
|
|
76
|
+
Keep an existing CLI 1.5 pipeline pinned until its server is upgraded if it needs
|
|
77
|
+
legacy JSON sources. CLI 1.6 does not silently convert ZIPs to JSON or drop sources.
|
|
78
|
+
A new CLI also cannot reconstruct missing debug files from an SDK version: the
|
|
79
|
+
files must come from the actual application build being diagnosed.
|
|
80
|
+
|
|
81
|
+
## Cloud and self-hosted destinations
|
|
82
|
+
|
|
83
|
+
The same package and commands support both editions. Choose the destination
|
|
84
|
+
before running `init`:
|
|
85
|
+
|
|
86
|
+
| Edition | `--api-url` | Credential |
|
|
87
|
+
| --- | --- | --- |
|
|
88
|
+
| Sentori Cloud | The target workspace's runtime URL, shown when opening that workspace | API-scope token created in that workspace's project |
|
|
89
|
+
| Self-hosted | Your instance's public HTTPS base URL | API-scope token created in that instance's project |
|
|
90
|
+
|
|
91
|
+
The Cloud account/billing website is not the upload destination. Do not use its
|
|
92
|
+
login cookie, the SDK ingest hostname, or a token from another workspace. Open
|
|
93
|
+
the project, create an API token in its token settings, and supply it through
|
|
94
|
+
`SENTORI_TOKEN` or the configured `tokenEnv`. `doctor` must accept that exact
|
|
95
|
+
URL/token pair before uploading. Cloud storage/traffic quotas still apply;
|
|
96
|
+
429 is a failed upload, not a verified artifact. Resolve the quota, rerun the
|
|
97
|
+
same release, and require `verify` to pass. Revoking an API token stops future
|
|
98
|
+
CLI operations; rotate CI secrets before revocation.
|
|
99
|
+
|
|
100
|
+
Self-hosted operators must upgrade their server to a compatible release before
|
|
101
|
+
using ZIP sources. Cloud operators deploy the compatible data-plane image;
|
|
102
|
+
customers only need to update the CLI. Both use the capability checks below,
|
|
103
|
+
without assuming the CLI, SDK and server have matching version numbers.
|
|
104
|
+
|
|
105
|
+
## Configure once per build target
|
|
106
|
+
|
|
107
|
+
Run in the application or monorepo root. Choose only the files that target
|
|
108
|
+
produces. For a web build that writes maps under `dist`:
|
|
109
|
+
|
|
110
|
+
```sh
|
|
111
|
+
npx --no-install sentori init --api-url https://sentori.your-domain.com \
|
|
112
|
+
--sourcemap dist --sources src
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
For iOS, use `--dsym build/MyApp.app.dSYM --sources Sources`. For Android, use
|
|
116
|
+
`--mapping app/build/outputs/mapping/release/mapping.txt --sources app/src/main`.
|
|
117
|
+
For React Native, also select the build's final composed JS source map; source
|
|
118
|
+
ZIPs cannot replace it. Adjust these example paths to the actual build outputs.
|
|
119
|
+
|
|
120
|
+
`init` creates `sentori.config.json` and refuses to overwrite it. A minimal web
|
|
121
|
+
configuration is:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"version": 1,
|
|
126
|
+
"apiUrl": "https://sentori.your-domain.com",
|
|
127
|
+
"tokenEnv": "SENTORI_TOKEN",
|
|
128
|
+
"artifacts": { "sourcemap": ["dist"] },
|
|
129
|
+
"sources": { "root": ".", "include": ["src", "shared"], "exclude": ["shared/tests"] }
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Remove `shared` if it does not exist. Select only application/shared sources
|
|
134
|
+
needed for stack context. Dependencies, hidden paths, common build outputs and
|
|
135
|
+
symlinks are excluded; never select an entire monorepo indiscriminately. Keep
|
|
136
|
+
`.sentori/` out of version control because it contains the generated source ZIP.
|
|
137
|
+
Use `sourceArchive: "sources.zip"` instead of `sources` for an existing ZIP.
|
|
138
|
+
|
|
139
|
+
Paths in configuration are relative to the configuration file. Source includes
|
|
140
|
+
and excludes are relative to `sources.root`. For a configuration in an app
|
|
141
|
+
subdirectory that needs shared monorepo files, set `sources.root` to the monorepo
|
|
142
|
+
root relative to that configuration and use root-relative include paths.
|
|
143
|
+
|
|
144
|
+
Use separate configurations such as `sentori.ios.config.json` and
|
|
145
|
+
`sentori.android.config.json` when platforms have different releases or outputs.
|
|
146
|
+
Pass `--config` to **every** command, including `doctor` and `verify`. The API-scope
|
|
147
|
+
token determines the project; these commands do not need a project UUID. Different
|
|
148
|
+
projects require their own tokens.
|
|
149
|
+
|
|
150
|
+
## Check, build, upload, verify
|
|
151
|
+
|
|
152
|
+
Supply an **API-scope** token through the environment or the CI secret store. An
|
|
153
|
+
app's public ingest token cannot upload debug files. Never commit the token;
|
|
154
|
+
`init` stores only the environment variable name.
|
|
155
|
+
|
|
156
|
+
```sh
|
|
157
|
+
export SENTORI_TOKEN='your-api-scope-token'
|
|
158
|
+
export SENTORI_RELEASE='my-app@1.2.3+42'
|
|
159
|
+
npx --no-install sentori doctor
|
|
160
|
+
# Build the app here, with the same release string and source revision.
|
|
161
|
+
npx --no-install sentori config validate
|
|
162
|
+
npx --no-install sentori upload all --dry-run
|
|
163
|
+
npx --no-install sentori upload all
|
|
164
|
+
npx --no-install sentori verify
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
`doctor` checks authentication and configured server capabilities, even before
|
|
168
|
+
build outputs exist. It does not upload files or check build identity.
|
|
169
|
+
`config validate` and `upload all --dry-run` check local files and print the plan;
|
|
170
|
+
they do not contact the server. `upload all` checks compatibility before the first
|
|
171
|
+
write, attempts all selected files, then reads the server inventory back.
|
|
172
|
+
`verify` independently requires matching file kinds, names (except server-named
|
|
173
|
+
dSYM slices), SHA-256 bytes and successful format validation for the same local
|
|
174
|
+
plan. An older file of the same kind does not satisfy it.
|
|
175
|
+
|
|
176
|
+
Release precedence is `--release`, then `SENTORI_RELEASE`, then config `release`.
|
|
177
|
+
URL precedence is `--api-url`, then `SENTORI_API_URL`, then config `apiUrl`.
|
|
178
|
+
A Git override `--git-tag` takes precedence over `sources.gitTag`. Repeat the same
|
|
179
|
+
overrides for upload and verification; otherwise you may check a different build.
|
|
180
|
+
Individual legacy commands take their own arguments and do not read this config.
|
|
181
|
+
|
|
182
|
+
The app release must exactly match the SDK, including build number; it is never
|
|
183
|
+
guessed from `package.json`. Successful byte/format verification does **not** prove
|
|
184
|
+
that a binary and source revision match, or that every event can be symbolicated.
|
|
185
|
+
Native frames still need matching dSYM/debug IDs or mappings; source context needs
|
|
186
|
+
a resolved file path and line number. Supported servers reprocess stored events
|
|
187
|
+
after late uploads.
|
|
188
|
+
|
|
189
|
+
## CI and exit codes
|
|
190
|
+
|
|
191
|
+
Ordinary upload failures return zero to protect the host build, while printing
|
|
192
|
+
what failed. `--strict` opts into a nonzero upload result. `doctor`, `config
|
|
193
|
+
validate` and `verify` return nonzero when their checks fail. `--dry-run` is valid
|
|
194
|
+
only with `upload all`, so it cannot silently bypass a verification gate.
|
|
195
|
+
|
|
196
|
+
For a dedicated required debug-artifact job, after the application build:
|
|
11
197
|
|
|
12
198
|
```sh
|
|
13
|
-
|
|
14
|
-
|
|
199
|
+
# SENTORI_TOKEN and SENTORI_RELEASE are supplied by CI; URL is in the config.
|
|
200
|
+
npx --no-install sentori doctor --config sentori.ios.config.json
|
|
201
|
+
npx --no-install sentori config validate --config sentori.ios.config.json
|
|
202
|
+
npx --no-install sentori upload all --config sentori.ios.config.json --strict
|
|
203
|
+
npx --no-install sentori verify --config sentori.ios.config.json
|
|
15
204
|
```
|
|
16
205
|
|
|
17
|
-
|
|
206
|
+
Keep this job separate from compilation if upload outages must not block app
|
|
207
|
+
builds. For nonblocking upload hooks omit `--strict`; run `verify` separately to
|
|
208
|
+
notice missing files. `artifacts check --expect ...` is the older kind-presence
|
|
209
|
+
check and cannot replace exact-file `verify`. A receipt with unknown validation
|
|
210
|
+
is not a passing gate. After a partial failure, correct the cause and rerun the
|
|
211
|
+
same configuration and release.
|
|
212
|
+
|
|
213
|
+
## Source ZIPs without Git
|
|
214
|
+
|
|
215
|
+
Preserve project-relative paths so modules with identical basenames remain
|
|
216
|
+
distinct. Supported source types include Swift, Kotlin, Java, C/C++, Objective-C,
|
|
217
|
+
JS/TS, Vue/Svelte, Rust, Go, Python, Ruby, PHP, C# and Dart.
|
|
18
218
|
|
|
19
219
|
```sh
|
|
20
|
-
|
|
21
|
-
--
|
|
22
|
-
|
|
23
|
-
|
|
220
|
+
npx --no-install sentori sources pack --root . --release 'my-app@1.2.3+42' \
|
|
221
|
+
--exclude shared/tests --output sources.zip src shared
|
|
222
|
+
npx --no-install sentori upload srcbundle --api-url https://sentori.your-domain.com \
|
|
223
|
+
--release 'my-app@1.2.3+42' sources.zip --strict
|
|
24
224
|
```
|
|
25
225
|
|
|
26
|
-
|
|
226
|
+
The pack command writes a standard ZIP plus `sentori-source-manifest.json`
|
|
227
|
+
containing the release, file hashes, sizes and source provenance. It refuses to
|
|
228
|
+
overwrite an existing output. Limits: 10,000 files, 512 KiB per file, 64 MiB total
|
|
229
|
+
source text. Oversized/unreadable selected files cause an error, not truncation.
|
|
230
|
+
A plain ZIP of UTF-8 sources is also accepted; without a manifest, the uploader
|
|
231
|
+
is responsible for selecting the correct release. Include generated sources by
|
|
232
|
+
explicit file paths when needed; do not archive the whole output directory.
|
|
233
|
+
|
|
234
|
+
## Pin the source revision
|
|
235
|
+
|
|
236
|
+
Git is optional. In Git mode `sources.root` must be the repository root, and the
|
|
237
|
+
selected tag must already be available locally. Both lightweight and annotated
|
|
238
|
+
tags are supported:
|
|
27
239
|
|
|
28
240
|
```sh
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
--metro-map android/app/build/intermediates/sourcemaps/react/release/index.android.bundle.packager.map \
|
|
32
|
-
--hermes-map android/app/build/intermediates/sourcemaps/react/release/index.android.bundle.compiler.map \
|
|
33
|
-
--bundle android/app/build/generated/assets/react/release/index.android.bundle
|
|
241
|
+
npx --no-install sentori upload all --git-tag v1.2.3 --release 'my-app@1.2.3+42'
|
|
242
|
+
npx --no-install sentori verify --git-tag v1.2.3 --release 'my-app@1.2.3+42'
|
|
34
243
|
```
|
|
35
244
|
|
|
36
|
-
|
|
245
|
+
This reads `refs/tags/v1.2.3` at its resolved commit and records tag and commit in
|
|
246
|
+
the manifest. It does not check out that commit, fetch tags, include dirty files
|
|
247
|
+
or guess the latest tag. The app build, debug files and chosen tag must come from
|
|
248
|
+
the same revision. Build-generated sources require directory mode from that build
|
|
249
|
+
workspace. An existing `sourceArchive` cannot be combined with `--git-tag`.
|
|
250
|
+
|
|
251
|
+
## Individual uploads and Hermes
|
|
252
|
+
|
|
253
|
+
These commands remain available alongside the unified workflow:
|
|
37
254
|
|
|
38
255
|
```sh
|
|
39
|
-
|
|
256
|
+
npx --no-install sentori upload sourcemap --api-url https://sentori.your-domain.com \
|
|
257
|
+
--release "$SENTORI_RELEASE" ./dist
|
|
258
|
+
npx --no-install sentori upload dsym --api-url https://sentori.your-domain.com \
|
|
259
|
+
--release "$SENTORI_RELEASE" ./MyApp.app.dSYM
|
|
260
|
+
npx --no-install sentori upload mapping --api-url https://sentori.your-domain.com \
|
|
261
|
+
--release "$SENTORI_RELEASE" ./mapping.txt
|
|
262
|
+
npx --no-install sentori react-native upload --api-url https://sentori.your-domain.com \
|
|
263
|
+
--release "$SENTORI_RELEASE" --metro-map metro.map --hermes-map hermes.map
|
|
40
264
|
```
|
|
41
265
|
|
|
42
|
-
|
|
43
|
-
|
|
266
|
+
A source-map directory preserves relative filenames; individual files retain their
|
|
267
|
+
basename. Legacy individual dSYM upload uses macOS `dwarfdump`, or explicit
|
|
268
|
+
`--debug-id` and `--arch`; unified `upload all` passes the Mach-O binaries from the
|
|
269
|
+
`.dSYM` bundle and lets the server identify slices.
|
|
270
|
+
|
|
271
|
+
For Hermes, use the final composed map emitted by the build in
|
|
272
|
+
`artifacts.sourcemap`. If the build emits separate Metro and Hermes maps, use
|
|
273
|
+
`react-native upload` to compose them with the application's installed React
|
|
274
|
+
Native tooling. A Metro map alone does not resolve Hermes bytecode offsets.
|
|
275
|
+
|
|
276
|
+
## Troubleshooting
|
|
277
|
+
|
|
278
|
+
| Result | Action |
|
|
279
|
+
| --- | --- |
|
|
280
|
+
| No `sentori` binary / unknown `init` | Check the installed package version; use 1.7.0 or its supplied tarball, with `npx --no-install` |
|
|
281
|
+
| `doctor` rejects ZIP capability | Upgrade/deploy the compatible server; CLI installation cannot enable server support |
|
|
282
|
+
| 401 / `admin_token_required` | Use an API-scope token for the correct project and instance |
|
|
283
|
+
| Local file missing | Build first; resolve paths relative to the configuration file |
|
|
284
|
+
| ZIP manifest release mismatch | Repack from the intended build with exactly the SDK release string |
|
|
285
|
+
| Missing exact bytes / format not verified | Rerun the same upload, inspect individual failures, and verify again |
|
|
286
|
+
| Files verified, frame still unresolved | Check actual release, dSYM/debug identity, composed map, source path and line |
|
|
44
287
|
|
|
45
|
-
|
|
46
|
-
→ Recipes: [sentori.golia.jp/docs/recipes/sourcemap-upload](https://sentori.golia.jp/docs/recipes/sourcemap-upload)
|
|
288
|
+
Use `npx --no-install sentori --help` for issue, probe, MCP and push commands.
|
|
47
289
|
|
|
48
290
|
## License
|
|
49
291
|
|
|
50
292
|
Dual-licensed under [Apache-2.0](../../LICENSE-APACHE) OR
|
|
51
293
|
[MIT](../../LICENSE-MIT).
|
|
294
|
+
|
|
295
|
+
## Projects and apps
|
|
296
|
+
|
|
297
|
+
A token selects one project. Use that project's API token for inspection and
|
|
298
|
+
build uploads; an ingest token embedded in an app cannot read issues. Never put
|
|
299
|
+
an API token into browser or mobile bundles.
|
|
300
|
+
|
|
301
|
+
```sh
|
|
302
|
+
export SENTORI_API_TOKEN=st_...
|
|
303
|
+
npx --no-install sentori project show --json
|
|
304
|
+
npx --no-install sentori app list --json
|
|
305
|
+
npx --no-install sentori issue list --app <app-uuid> --environment production --json
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
These project/app commands require the CLI release shipped with server 5.1.17;
|
|
309
|
+
they are not part of CLI 1.6.0. The API equivalents are `GET /api/project`,
|
|
310
|
+
`GET /api/apps` and `GET /api/issues?appId=<uuid>`. Switching projects requires
|
|
311
|
+
switching tokens. A foreign App UUID returns 404. Issue counts use only events
|
|
312
|
+
matching the selected app, platform, environment and exact release together.
|
|
313
|
+
|
|
314
|
+
`--app` takes the UUID from `app list`, while the SDK reports a stable identifier
|
|
315
|
+
such as a bundle ID or `admin-panel`. App kind (`webapi`/`webapp`) describes the
|
|
316
|
+
product role; platform (`javascript`/`web`) describes the runtime. Releases and
|
|
317
|
+
debug files remain project scoped; select the destination project token when
|
|
318
|
+
uploading and preserve the exact release reported by the app.
|
|
319
|
+
|
|
320
|
+
`SENTORI_API_TOKEN` is accepted by inspection and direct upload commands. The
|
|
321
|
+
configured upload workflow uses its `tokenEnv` setting (default `SENTORI_TOKEN`);
|
|
322
|
+
set `tokenEnv` to `SENTORI_API_TOKEN` if using that variable consistently.
|
package/lib/apps.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ApiConfig } from './issue.js';
|
|
2
|
+
export type AppSummary = {
|
|
3
|
+
id: string;
|
|
4
|
+
projectId: string;
|
|
5
|
+
name: string | null;
|
|
6
|
+
identifier: string;
|
|
7
|
+
platform: string;
|
|
8
|
+
kind: string;
|
|
9
|
+
events24h: number;
|
|
10
|
+
errors24h: number;
|
|
11
|
+
releaseCount: number;
|
|
12
|
+
};
|
|
13
|
+
export declare function listApps(config: ApiConfig): Promise<{
|
|
14
|
+
projectId: string;
|
|
15
|
+
apps: AppSummary[];
|
|
16
|
+
}>;
|
|
17
|
+
export declare function showProject(config: ApiConfig): Promise<{
|
|
18
|
+
project: {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
createdAt: string;
|
|
22
|
+
};
|
|
23
|
+
}>;
|
|
24
|
+
//# sourceMappingURL=apps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../src/apps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE3C,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AAYD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,EAAE,CAAA;CAAE,CAAC,CAE9F;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC,CAEpH"}
|
package/lib/apps.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
async function read(config, path) {
|
|
2
|
+
const response = await fetch(`${config.apiUrl.replace(/\/+$/, '')}${path}`, {
|
|
3
|
+
headers: { Authorization: `Bearer ${config.token}` },
|
|
4
|
+
redirect: 'error',
|
|
5
|
+
signal: AbortSignal.timeout(30_000),
|
|
6
|
+
});
|
|
7
|
+
if (!response.ok)
|
|
8
|
+
throw new Error(`Sentori API returned ${response.status}`);
|
|
9
|
+
return await response.json();
|
|
10
|
+
}
|
|
11
|
+
export function listApps(config) {
|
|
12
|
+
return read(config, '/api/apps');
|
|
13
|
+
}
|
|
14
|
+
export function showProject(config) {
|
|
15
|
+
return read(config, '/api/project');
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=apps.js.map
|
package/lib/apps.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apps.js","sourceRoot":"","sources":["../src/apps.ts"],"names":[],"mappings":"AAcA,KAAK,UAAU,IAAI,CAAI,MAAiB,EAAE,IAAY;IACpD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE;QAC1E,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,MAAM,CAAC,KAAK,EAAE,EAAE;QACpD,QAAQ,EAAE,OAAO;QACjB,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;KACpC,CAAC,CAAA;IACF,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IAC5E,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAO,CAAA;AACnC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,MAAiB;IACxC,OAAO,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;AAClC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAiB;IAC3C,OAAO,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;AACrC,CAAC"}
|
package/lib/artifacts.d.ts
CHANGED
|
@@ -12,6 +12,13 @@ export type ArtifactRow = {
|
|
|
12
12
|
usable?: boolean | null;
|
|
13
13
|
};
|
|
14
14
|
export type ArtifactsResponse = {
|
|
15
|
+
/** Additive capability advertisement. Absent on older servers. */
|
|
16
|
+
compatibility?: {
|
|
17
|
+
serverVersion: string;
|
|
18
|
+
artifactProtocol: number;
|
|
19
|
+
sourceBundleFormats: string[];
|
|
20
|
+
verification: string[];
|
|
21
|
+
};
|
|
15
22
|
release: string;
|
|
16
23
|
/** False when the server has never heard this release name at all
|
|
17
24
|
* — a typo in `--release` and an un-uploaded release look the
|
package/lib/artifacts.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifacts.d.ts","sourceRoot":"","sources":["../src/artifacts.ts"],"names":[],"mappings":"AAqBA,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,kEAAkE;IAClE,OAAO,EAAE,IAAI,GAAG,MAAM,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB;;uEAEmE;IACnE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAA;IACf;;sEAEkE;IAClE,KAAK,EAAE,OAAO,CAAA;IACd,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,SAAS,EAAE,WAAW,EAAE,CAAA;CACzB,CAAA;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;CACd,GAAG,OAAO,CAAC,iBAAiB,CAAC,
|
|
1
|
+
{"version":3,"file":"artifacts.d.ts","sourceRoot":"","sources":["../src/artifacts.ts"],"names":[],"mappings":"AAqBA,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,kEAAkE;IAClE,OAAO,EAAE,IAAI,GAAG,MAAM,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB;;uEAEmE;IACnE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,kEAAkE;IAClE,aAAa,CAAC,EAAE;QACd,aAAa,EAAE,MAAM,CAAA;QACrB,gBAAgB,EAAE,MAAM,CAAA;QACxB,mBAAmB,EAAE,MAAM,EAAE,CAAA;QAC7B,YAAY,EAAE,MAAM,EAAE,CAAA;KACvB,CAAA;IACD,OAAO,EAAE,MAAM,CAAA;IACf;;sEAEkE;IAClE,KAAK,EAAE,OAAO,CAAA;IACd,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,SAAS,EAAE,WAAW,EAAE,CAAA;CACzB,CAAA;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;CACd,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAkB7B"}
|
package/lib/artifacts.js
CHANGED
|
@@ -28,6 +28,10 @@ export async function fetchArtifacts(opts) {
|
|
|
28
28
|
const detail = await resp.text().catch(() => '');
|
|
29
29
|
throw new Error(`${resp.status} ${resp.statusText}${detail ? ` — ${detail.slice(0, 200)}` : ''}`);
|
|
30
30
|
}
|
|
31
|
-
|
|
31
|
+
const result = await resp.json();
|
|
32
|
+
if (!result || result.release !== opts.release || typeof result.known !== 'boolean' || !Array.isArray(result.artifacts)) {
|
|
33
|
+
throw new Error('Unsupported artifact inventory response; check --api-url and upgrade the Sentori server or CLI together.');
|
|
34
|
+
}
|
|
35
|
+
return result;
|
|
32
36
|
}
|
|
33
37
|
//# sourceMappingURL=artifacts.js.map
|
package/lib/artifacts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../src/artifacts.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,EAAE;AACF,qEAAqE;AACrE,iEAAiE;AACjE,iEAAiE;AACjE,+DAA+D;AAC/D,sEAAsE;AACtE,oEAAoE;AACpE,kCAAkC;AAClC,EAAE;AACF,iEAAiE;AACjE,kEAAkE;AAClE,mEAAmE;AACnE,mEAAmE;AACnE,6CAA6C;AAC7C,EAAE;AACF,gEAAgE;AAChE,+DAA+D;AAC/D,4DAA4D;AAC5D,uCAAuC;
|
|
1
|
+
{"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../src/artifacts.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,EAAE;AACF,qEAAqE;AACrE,iEAAiE;AACjE,iEAAiE;AACjE,+DAA+D;AAC/D,sEAAsE;AACtE,oEAAoE;AACpE,kCAAkC;AAClC,EAAE;AACF,iEAAiE;AACjE,kEAAkE;AAClE,mEAAmE;AACnE,mEAAmE;AACnE,6CAA6C;AAC7C,EAAE;AACF,gEAAgE;AAChE,+DAA+D;AAC/D,4DAA4D;AAC5D,uCAAuC;AAkCvC,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAIpC;IACC,MAAM,GAAG,GACP,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,eAAe;QACjD,GAAG,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAA;IACjD,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC5B,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE,EAAE;KACnD,CAAC,CAAA;IACF,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;QAChD,MAAM,IAAI,KAAK,CACb,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACjF,CAAA;IACH,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,EAAuB,CAAA;IACrD,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;QACxH,MAAM,IAAI,KAAK,CAAC,0GAA0G,CAAC,CAAA;IAC7H,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ArtifactsResponse } from './artifacts.js';
|
|
2
|
+
/** Read the installed package, so a release bump cannot leave a stale constant. */
|
|
3
|
+
export declare const CLI_VERSION: string;
|
|
4
|
+
/** Capabilities, not a server version comparison: backports may share versions. */
|
|
5
|
+
export declare function checkCompatibility(result: ArtifactsResponse, sourceZip: boolean): string;
|
|
6
|
+
//# sourceMappingURL=compatibility.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compatibility.d.ts","sourceRoot":"","sources":["../src/compatibility.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAEvD,mFAAmF;AACnF,eAAO,MAAM,WAAW,EAAE,MAA8F,CAAA;AAExH,mFAAmF;AACnF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAE,OAAO,GAAG,MAAM,CAaxF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
/** Read the installed package, so a release bump cannot leave a stale constant. */
|
|
3
|
+
export const CLI_VERSION = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
|
|
4
|
+
/** Capabilities, not a server version comparison: backports may share versions. */
|
|
5
|
+
export function checkCompatibility(result, sourceZip) {
|
|
6
|
+
const info = result.compatibility;
|
|
7
|
+
if (info === undefined) {
|
|
8
|
+
if (sourceZip)
|
|
9
|
+
throw new Error('This server does not advertise source ZIP support. No files were uploaded. Upgrade the Sentori server to a build advertising artifact protocol 1 and sourceBundleFormats: ["zip"], then run sentori doctor. Existing CLI 1.5 pipelines may continue using legacy JSON sources.');
|
|
10
|
+
return 'Legacy artifact API: server capabilities are not advertised. Source maps, dSYM and mapping uploads remain available; verification still requires matching SHA-256 bytes and usable: true.';
|
|
11
|
+
}
|
|
12
|
+
if (!info || typeof info.serverVersion !== 'string' || info.artifactProtocol !== 1
|
|
13
|
+
|| !Array.isArray(info.sourceBundleFormats) || !Array.isArray(info.verification)
|
|
14
|
+
|| !info.verification.includes('sha256') || !info.verification.includes('format')) {
|
|
15
|
+
throw new Error('Unsupported server artifact protocol or verification capabilities. No files were uploaded. Install a compatible CLI/server pair; use sentori --version and sentori doctor to inspect it.');
|
|
16
|
+
}
|
|
17
|
+
if (sourceZip && !info.sourceBundleFormats.includes('zip'))
|
|
18
|
+
throw new Error(`Sentori server ${info.serverVersion} does not support source ZIPs. No files were uploaded. Upgrade the server before uploading sources.`);
|
|
19
|
+
return `Sentori CLI ${CLI_VERSION}; server ${info.serverVersion}; artifact protocol 1; source ZIP ${info.sourceBundleFormats.includes('zip') ? 'supported' : 'unavailable'}.`;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=compatibility.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compatibility.js","sourceRoot":"","sources":["../src/compatibility.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAGtC,mFAAmF;AACnF,MAAM,CAAC,MAAM,WAAW,GAAW,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAA;AAExH,mFAAmF;AACnF,MAAM,UAAU,kBAAkB,CAAC,MAAyB,EAAE,SAAkB;IAC9E,MAAM,IAAI,GAAG,MAAM,CAAC,aAAa,CAAA;IACjC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,IAAI,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,gRAAgR,CAAC,CAAA;QAChT,OAAO,2LAA2L,CAAA;IACpM,CAAC;IACD,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,aAAa,KAAK,QAAQ,IAAI,IAAI,CAAC,gBAAgB,KAAK,CAAC;WAC7E,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC;WAC7E,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpF,MAAM,IAAI,KAAK,CAAC,0LAA0L,CAAC,CAAA;IAC7M,CAAC;IACD,IAAI,SAAS,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,CAAC,aAAa,qGAAqG,CAAC,CAAA;IACtN,OAAO,eAAe,WAAW,YAAY,IAAI,CAAC,aAAa,qCAAqC,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,GAAG,CAAA;AAC/K,CAAC"}
|