@fleetless/sdk 3.0.2 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/CONTRIBUTING.md +76 -71
- package/README.md +66 -344
- package/SECURITY.md +11 -11
- package/dist/index.cjs +311 -209
- package/dist/index.d.cts +331 -94
- package/dist/index.d.ts +331 -94
- package/dist/index.js +311 -209
- package/package.json +9 -5
- package/RELEASING.md +0 -195
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fleetless/sdk",
|
|
3
|
-
"version": "3.0
|
|
4
|
-
"description": "The official TypeScript SDK for Fleetless client apps
|
|
3
|
+
"version": "3.1.0",
|
|
4
|
+
"description": "The official TypeScript SDK for Fleetless client apps — a ROS 2 robot as a REST and realtime API, cameras, jobs, and the app's own user accounts, federated sign-in and MCP consent.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Dehne Robotik GmbH",
|
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
"url": "https://dehne-robotik.de"
|
|
10
10
|
},
|
|
11
11
|
"homepage": "https://docs.fleetless.dev/reference/sdk/",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://github.com/fleetless/sdk"
|
|
15
|
+
},
|
|
12
16
|
"bugs": {
|
|
13
17
|
"email": "hello@fleetless.dev"
|
|
14
18
|
},
|
|
@@ -51,8 +55,7 @@
|
|
|
51
55
|
"CHANGELOG.md",
|
|
52
56
|
"SECURITY.md",
|
|
53
57
|
"CONTRIBUTING.md",
|
|
54
|
-
"CODE_OF_CONDUCT.md"
|
|
55
|
-
"RELEASING.md"
|
|
58
|
+
"CODE_OF_CONDUCT.md"
|
|
56
59
|
],
|
|
57
60
|
"engines": {
|
|
58
61
|
"node": ">=20"
|
|
@@ -61,6 +64,7 @@
|
|
|
61
64
|
"scripts": {
|
|
62
65
|
"build": "tsup && node scripts/stamp-dist.mjs",
|
|
63
66
|
"prepare": "tsup && node scripts/stamp-dist.mjs",
|
|
67
|
+
"prepublishOnly": "node scripts/refuse-manual-publish.mjs",
|
|
64
68
|
"typecheck": "tsc --noEmit",
|
|
65
69
|
"test": "vitest run",
|
|
66
70
|
"test:pack": "node scripts/verify-published-types.mjs",
|
|
@@ -72,7 +76,7 @@
|
|
|
72
76
|
"zod": "^4.0.0"
|
|
73
77
|
},
|
|
74
78
|
"devDependencies": {
|
|
75
|
-
"@fleetless/contracts": "1.0
|
|
79
|
+
"@fleetless/contracts": "1.1.0",
|
|
76
80
|
"@types/node": "^22.20.1",
|
|
77
81
|
"tsup": "^8.3.0",
|
|
78
82
|
"typedoc": "0.28.20",
|
package/RELEASING.md
DELETED
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
# Releasing `@fleetless/sdk`
|
|
2
|
-
|
|
3
|
-
Maintainer notes: the development setup, the checks, and the release
|
|
4
|
-
procedure. This file is not part of the published package.
|
|
5
|
-
|
|
6
|
-
**CI runs on GitLab; the repository will mirror to GitHub.** The pipeline
|
|
7
|
-
that verifies and publishes this package lives on an internal GitLab instance,
|
|
8
|
-
and that is the only thing that publishes to npm. The public repository does not
|
|
9
|
-
exist yet; when it does it is a mirror, where issues and pull requests arrive
|
|
10
|
-
and no check runs. A contributor's pull request is verified by a maintainer
|
|
11
|
-
running the same commands locally — see
|
|
12
|
-
[CONTRIBUTING.md](CONTRIBUTING.md), which says so to the contributor as well.
|
|
13
|
-
|
|
14
|
-
A mirror pushes what it is given, so **everything in a commit becomes public
|
|
15
|
-
the moment it is pushed**, including the commit message and every file the
|
|
16
|
-
branch touched.
|
|
17
|
-
## Development setup
|
|
18
|
-
|
|
19
|
-
Node 22 via `nvm`, and pnpm through corepack:
|
|
20
|
-
|
|
21
|
-
```sh
|
|
22
|
-
nvm use 22
|
|
23
|
-
corepack enable
|
|
24
|
-
pnpm install
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
**That install needs nothing private.** `@fleetless/contracts` — the source
|
|
28
|
-
of truth for every wire type this SDK reads or writes — is a devDependency on
|
|
29
|
-
the public npm package, pinned to an exact version. It used to be a private
|
|
30
|
-
`git+ssh://` URL that only somebody with GitLab group access could install;
|
|
31
|
-
that is over. The published SDK is unaffected either way: `tsup` inlines
|
|
32
|
-
contracts' types into `dist/`, so a consumer of `@fleetless/sdk` never
|
|
33
|
-
resolves it.
|
|
34
|
-
|
|
35
|
-
Never redefine a shape the SDK sends to or reads from the API. Import it from
|
|
36
|
-
`@fleetless/contracts` instead.
|
|
37
|
-
|
|
38
|
-
## Checks
|
|
39
|
-
|
|
40
|
-
| Command | What it does |
|
|
41
|
-
|---|---|
|
|
42
|
-
| `pnpm typecheck` | `tsc --noEmit` over the package. |
|
|
43
|
-
| `pnpm test` | vitest. Most suites drive a fake `fetch` and a fake WebSocket; the three auth suites drive the SDK's own default `fetch` against a real `node:http` server (`test/local-api.ts`). No cloud needed. |
|
|
44
|
-
| `pnpm build` | tsup into `dist/` — ESM, CJS and `.d.ts`. |
|
|
45
|
-
| `pnpm run test:pack` | `npm pack`s the tarball, installs it into a bare project with nothing but `typescript`, and typechecks and runs real usage against it. This is what catches a `dist/index.d.ts` that still imports from `@fleetless/contracts` — a devDependency, so a consumer of the SDK never installs it. |
|
|
46
|
-
|
|
47
|
-
Two further scripts check the built package against a **running** cloud
|
|
48
|
-
(`./infra/dev.sh` in the umbrella repo). Each one runs against `dist/`, not
|
|
49
|
-
`src/`, so run `pnpm build` first, and each fails by name on a missing
|
|
50
|
-
variable rather than defaulting quietly.
|
|
51
|
-
|
|
52
|
-
- `pnpm run verify:live` — a `busy` refusal carrying the job that is already
|
|
53
|
-
running, `command_outcome_unknown` and its documented recovery, a
|
|
54
|
-
`parameter_invalid` naming the flat key, job-id-addressed cancel, and
|
|
55
|
-
per-session camera release. Needs `FLEETLESS_API_URL` (or `API`),
|
|
56
|
-
`APP_IDENTIFIER`, `EMAIL`, `PASSWORD`, `ROBOT_ID`, `ACTION_SLUG`,
|
|
57
|
-
`SERVICE_SLUG`, `CAMERA_SLUG`, and two optional identities:
|
|
58
|
-
- `SECOND_EMAIL` — a second, distinct **app user** with the same role,
|
|
59
|
-
without which the busy check only proves that a second request is refused,
|
|
60
|
-
not that a different user's is.
|
|
61
|
-
- `OBSERVER_EMAIL` — a **third** app user, and the one whose password check
|
|
62
|
-
[6] rotates and restores. Leave it unset and the round trip runs on
|
|
63
|
-
`EMAIL`, the identity every other check in the file signs in as; the
|
|
64
|
-
script says so out loud when that happens. `infra/seed-dev.mjs --env`
|
|
65
|
-
exports all three.
|
|
66
|
-
|
|
67
|
-
Since 3.0.0 it also drives the client auth API as check [6]: `listProviders`
|
|
68
|
-
without a session, `login`, `me` (kind, app, role, address), `logout`, the
|
|
69
|
-
`changePassword` round trip with its restore, and the reset acknowledgement
|
|
70
|
-
compared byte for byte across a known and an unknown address. What it does
|
|
71
|
-
**not** drive is anything needing a mailed token — `register`,
|
|
72
|
-
`verifyEmail`, `acceptInvitation`, `confirmPasswordReset` — or the federated
|
|
73
|
-
and MCP-consent flows. Those are `infra/browser/app-auth-check.mjs`'s
|
|
74
|
-
subject, which reads maildev and drives a real Keycloak.
|
|
75
|
-
- `pnpm run verify:history` — a relative range and its absolute equivalent
|
|
76
|
-
returning the same samples, aggregation matching arithmetic done here from
|
|
77
|
-
the raw rows, and the `not_recorded` / `not_aggregatable` refusals. Needs
|
|
78
|
-
`FLEETLESS_API_URL`, `APP_IDENTIFIER`, `EMAIL`, `PASSWORD`, `ROBOT_ID`,
|
|
79
|
-
`RECORDED_NUMERIC_SLUG`, `LIVE_ONLY_SLUG`, and optionally
|
|
80
|
-
`NON_NUMERIC_RECORDED_SLUG`.
|
|
81
|
-
(`verify:hosted-login` is gone. The hosted login flow it drove —
|
|
82
|
-
`beginHostedLogin` / `completeHostedLogin` and the app OAuth client behind
|
|
83
|
-
them — was removed in 3.0.0 along with the script and its `package.json`
|
|
84
|
-
entry.)
|
|
85
|
-
|
|
86
|
-
`infra/seed-dev.mjs --env` in the umbrella repo exports most of those
|
|
87
|
-
variables for a freshly seeded world.
|
|
88
|
-
|
|
89
|
-
## Commits
|
|
90
|
-
|
|
91
|
-
[Conventional Commits](https://www.conventionalcommits.org/). English, for
|
|
92
|
-
code, comments, commit messages and everything else that lands in the
|
|
93
|
-
repository.
|
|
94
|
-
|
|
95
|
-
## Releasing
|
|
96
|
-
|
|
97
|
-
Every version on npm is published by this repository's GitLab pipeline from a
|
|
98
|
-
release tag. `npm publish` by hand is retired.
|
|
99
|
-
|
|
100
|
-
1. Add the version's entry to `CHANGELOG.md` and set `version` in
|
|
101
|
-
`package.json` to the same number.
|
|
102
|
-
2. Commit (`chore(release): X.Y.Z`), push, and wait for the branch pipeline's
|
|
103
|
-
`verify` job to go green.
|
|
104
|
-
3. `git tag vX.Y.Z && git push origin vX.Y.Z`. The tag pipeline runs `verify`
|
|
105
|
-
again and then `publish`.
|
|
106
|
-
4. Check the registry yourself. The `publish` job already asserts the first
|
|
107
|
-
line; this is the independent look, and the second line is the one that
|
|
108
|
-
says which dist-tag moved.
|
|
109
|
-
|
|
110
|
-
```sh
|
|
111
|
-
npm view @fleetless/sdk@X.Y.Z version # answers X.Y.Z
|
|
112
|
-
npm view @fleetless/sdk dist-tags # latest -> X.Y.Z, or next -> X.Y.Z
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
Name the version. A bare `npm view @fleetless/sdk version` resolves the
|
|
116
|
-
`latest` dist-tag, so after a pre-release publish it answers the *previous*
|
|
117
|
-
stable release and reads as a publish that did not happen.
|
|
118
|
-
|
|
119
|
-
A pre-release tag — `vX.Y.Z-beta.1`, `vX.Y.Z-rc.2` — publishes under the npm
|
|
120
|
-
dist-tag `next` instead of `latest`. Nothing else about it differs, and it is
|
|
121
|
-
exactly why step 4 names the version.
|
|
122
|
-
|
|
123
|
-
**A red `publish` job does not mean nothing was published.** The job runs
|
|
124
|
-
`npm publish` and then looks the version up on the registry for about two
|
|
125
|
-
minutes; npm answers reads from a replica that lags a publish, so the lookup
|
|
126
|
-
can time out on a version that did land. The job says so itself, and it is
|
|
127
|
-
worth repeating here because a red pipeline invites exactly one reaction —
|
|
128
|
-
press retry — and that reaction cannot work: npm refuses to publish over an
|
|
129
|
-
existing version, so the retry ends in a 403 that reads like a broken
|
|
130
|
-
pipeline rather than like a release that already happened.
|
|
131
|
-
|
|
132
|
-
> publish may have succeeded; the registry has not served the version yet; do
|
|
133
|
-
> NOT retry this job (npm refuses to republish a version) — check
|
|
134
|
-
> `npm view @fleetless/sdk@$VERSION` by hand
|
|
135
|
-
|
|
136
|
-
If the hand check answers the version, the release is done: move the dist-tag
|
|
137
|
-
by hand if it is wrong (`npm dist-tag add @fleetless/sdk@X.Y.Z latest`) and
|
|
138
|
-
leave the job red. If it answers nothing after several minutes, the publish
|
|
139
|
-
genuinely did not land and the job can be retried.
|
|
140
|
-
|
|
141
|
-
**A red `publish` job that ends in `npm error code EOTP` published nothing.**
|
|
142
|
-
npm is asking for a one-time password, which a pipeline cannot supply: the
|
|
143
|
-
token in `NPM_TOKEN` does not bypass two-factor authentication, or the
|
|
144
|
-
package's *Publishing access* setting on npmjs.com disallows tokens. Fix the
|
|
145
|
-
token (a granular access token created with *Bypass two-factor
|
|
146
|
-
authentication*) or the package setting (*Require two-factor authentication
|
|
147
|
-
or an automation token*), then retry the job — nothing reached the registry,
|
|
148
|
-
so a retry is safe here — measured on a pipeline that hit it.
|
|
149
|
-
|
|
150
|
-
**The pipeline refuses a tag whose version disagrees with `package.json`.**
|
|
151
|
-
`scripts/verify-version-tag.mjs` is the one place that rule lives; `verify`
|
|
152
|
-
runs it first on a tag pipeline, so a mistyped tag fails in seconds and
|
|
153
|
-
`publish` never starts (measured: `verify-version-tag: tag v9.9.9 names
|
|
154
|
-
9.9.9 but package.json says 1.0.0`, publish skipped).
|
|
155
|
-
|
|
156
|
-
Removing that bad tag takes the API, not git. `v*` is a **protected** tag
|
|
157
|
-
pattern, so a delete over git is refused by the server with nothing but
|
|
158
|
-
`! [remote rejected] v9.9.9 (pre-receive hook declined)`:
|
|
159
|
-
|
|
160
|
-
```sh
|
|
161
|
-
git tag -d vX.Y.Z # local
|
|
162
|
-
glab api -X DELETE projects/37/repository/tags/vX.Y.Z # remote
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
Then fix `package.json` and tag again.
|
|
166
|
-
|
|
167
|
-
### The one-time setting
|
|
168
|
-
|
|
169
|
-
It is already in place; it is written down because nothing in this repository
|
|
170
|
-
would tell you it exists if it were removed.
|
|
171
|
-
|
|
172
|
-
There used to be a second one — `fleetless/fleetless-sdk` on the job-token
|
|
173
|
-
allow-list of `fleetless/fleetless-contracts`, so the pipeline could rewrite
|
|
174
|
-
the private `git+ssh://` contracts URL to HTTPS with `CI_JOB_TOKEN`. Contracts
|
|
175
|
-
is a public npm package now, the rewrite is gone from `.gitlab-ci.yml`, and
|
|
176
|
-
the allow-list entry buys this project nothing. Removing it is safe; leaving
|
|
177
|
-
it is harmless.
|
|
178
|
-
|
|
179
|
-
- **`NPM_TOKEN` is a protected, masked CI variable on this project**, holding
|
|
180
|
-
an npm granular automation token with publish rights on `@fleetless/sdk`.
|
|
181
|
-
Protected means an unprotected ref receives an *empty* value rather than no
|
|
182
|
-
value, which is why the tag pattern `v*` is a protected tag and why the
|
|
183
|
-
`publish` job's first action is to refuse an empty `NPM_TOKEN` by name.
|
|
184
|
-
|
|
185
|
-
```sh
|
|
186
|
-
glab api projects/37/protected_tags # v*, create access: Maintainers
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
The token reaches npm through an `.npmrc` written in the job's working
|
|
190
|
-
directory holding `//registry.npmjs.org/:_authToken=${NPM_TOKEN}` **literally**
|
|
191
|
-
— npm expands the variable when it reads the file, so the secret itself never
|
|
192
|
-
lands on disk, and `after_script` removes the file either way. It cannot be
|
|
193
|
-
passed as an environment assignment instead: `NPM_CONFIG_//registry…` is not a
|
|
194
|
-
valid shell identifier, so both `bash` and `dash` parse it as a command name.
|
|
195
|
-
|