@sasjs/api 0.4.0 → 0.6.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 +12 -13
- package/build/browser.js +515 -54
- package/build/cjs/corpus/drive.js +119 -0
- package/build/cjs/corpus/runner.js +18 -2
- package/build/cjs/drive/deploy.js +270 -0
- package/build/cjs/drive/service.js +5 -0
- package/build/cjs/host/dispatch.js +15 -2
- package/build/cjs/index.js +10 -1
- package/build/cjs/routes/generated.js +8 -0
- package/build/cjs/routes/index.js +8 -2
- package/build/cjs/routes/overlay.js +181 -40
- package/build/cjs/types.js +11 -1
- package/build/esm/corpus/drive.d.ts +6 -0
- package/build/esm/corpus/drive.d.ts.map +1 -1
- package/build/esm/corpus/drive.js +119 -0
- package/build/esm/corpus/runner.d.ts.map +1 -1
- package/build/esm/corpus/runner.js +18 -2
- package/build/esm/drive/deploy.d.ts +143 -0
- package/build/esm/drive/deploy.d.ts.map +1 -0
- package/build/esm/drive/deploy.js +262 -0
- package/build/esm/drive/service.d.ts +8 -0
- package/build/esm/drive/service.d.ts.map +1 -1
- package/build/esm/drive/service.js +5 -0
- package/build/esm/host/dispatch.d.ts.map +1 -1
- package/build/esm/host/dispatch.js +15 -2
- package/build/esm/index.d.ts +2 -0
- package/build/esm/index.d.ts.map +1 -1
- package/build/esm/index.js +1 -0
- package/build/esm/routes/generated.d.ts.map +1 -1
- package/build/esm/routes/generated.js +8 -0
- package/build/esm/routes/index.d.ts.map +1 -1
- package/build/esm/routes/index.js +8 -2
- package/build/esm/routes/overlay.d.ts +26 -3
- package/build/esm/routes/overlay.d.ts.map +1 -1
- package/build/esm/routes/overlay.js +181 -40
- package/build/esm/types.d.ts +26 -1
- package/build/esm/types.d.ts.map +1 -1
- package/build/esm/types.js +11 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,9 +9,10 @@ The plan that this package implements is tracked in `sasjs/cli#1550`.
|
|
|
9
9
|
|
|
10
10
|
## What is in it
|
|
11
11
|
|
|
12
|
-
**The route table** (`ROUTES`, `findRoute`) is every operation in the API
|
|
12
|
+
**The route table** (`ROUTES`, `findRoute`) is every operation in the API, derived from `spec/swagger.yaml` by `npm run sync:routes`.
|
|
13
13
|
The statuses come from that document and nowhere else: the overlay cannot add one, and an overlay entry naming a status the document does not state fails the build rather than describing a wish.
|
|
14
|
-
The document cannot say everything a host needs, so the reviewed overlay adds the body each response carries, the capability a route needs, and
|
|
14
|
+
The document cannot say everything a host needs, so the reviewed overlay adds the body each response carries, the capability a route needs, and the decision for the operation: `implemented: true`, or `implemented: false` with the reason it is not.
|
|
15
|
+
Every operation has an entry - the table refuses one that does not, so "nobody has looked at this yet" cannot hide as silence - and a host asked for an unimplemented route answers `501` carrying that reason.
|
|
15
16
|
Where the document is wrong, it is corrected in `sasjs/server` and re-vendored here - never worked around in the overlay.
|
|
16
17
|
|
|
17
18
|
### Regenerating the vendored document
|
|
@@ -66,8 +67,8 @@ The bundle is deliberately a classic-worker IIFE: a service worker registered by
|
|
|
66
67
|
Both hosts answer with the same shapes:
|
|
67
68
|
|
|
68
69
|
- a successful write is `{ status: 'success' }`;
|
|
69
|
-
- a refusal is an `ApiError` carrying `status` and `message
|
|
70
|
-
- an operation this package has no handler for is `501`, naming the operation - not a `404` that looks like a typo in the caller;
|
|
70
|
+
- a refusal is an `ApiError` carrying `status`, `message` and, where the route answers an envelope rather than text, the `body` to send instead of the bare message - which a host renders as its own transport requires (`res.status(code).send(...)` on the server, a `Response` in the worker);
|
|
71
|
+
- an operation this package has no handler for is `501`, naming the operation and the reason it is not implemented here - not a `404` that looks like a typo in the caller;
|
|
71
72
|
- an operation the API does not have is `404`.
|
|
72
73
|
|
|
73
74
|
## Guarantees the build enforces
|
|
@@ -75,17 +76,14 @@ Both hosts answer with the same shapes:
|
|
|
75
76
|
- **No runtime imports.** `src` compiles with `"types": []` and `lib: ES2020`, so a `Buffer`, a `process` or a `document` reference fails `npm run build` rather than a worker at run time. Nothing node-shaped can creep into the browser path.
|
|
76
77
|
- **No Node-only APIs in the published surface.** Storage is a port (`DriveStore`), and `MemoryDriveStore` ships so a host without a filesystem has an implementation to use.
|
|
77
78
|
- **Three builds from one source.** `build/cjs` for node, `build/esm` for a bundler (with `build/esm` marked `"type": "module"` by the build script so Node runs it as ESM), and `build/browser.js` - a classic-worker IIFE that assigns `self.SASjsApi` - for a service worker that has only `importScripts`. CI loads all three.
|
|
78
|
-
- **The table cannot rot silently.** `npm run check:routes` fails when `src/routes/generated.ts` and `spec/swagger.yaml` disagree, and the module throws at import when an overlay entry names an operation the document does not have.
|
|
79
|
+
- **The table cannot rot silently.** `npm run check:routes` fails when `src/routes/generated.ts` and `spec/swagger.yaml` disagree, and the module throws at import when an overlay entry names an operation the document does not have, or when an operation has no entry at all.
|
|
79
80
|
|
|
80
81
|
## Status
|
|
81
82
|
|
|
82
|
-
|
|
83
|
+
`src/routes/overlay.ts` is the status, and the table refuses an operation that is not in it: each entry is `implemented: true` - the package answers the route - or `implemented: false` with the dependency it waits on.
|
|
84
|
+
`ROUTES.filter((route) => !route.implemented)` is therefore the list of what is left, each row naming the port, host decision or plan it is waiting for; a host asked for one answers `501` with that reason.
|
|
83
85
|
|
|
84
|
-
|
|
85
|
-
- the seven sign-in handlers - `auth/token`, `auth/refresh`, `auth/logout`, `SASLogon/login`, `SASLogon/authorize`, `SASLogon/logout`, and the session read.
|
|
86
|
-
|
|
87
|
-
Not implemented yet, in the order the plan sets: the rest of identity (`user`, `group`, `permission`, `auth/updatePassword`, `info/authorizedRoutes`), the session record behind `log`/`output`, program execution (`stp`, `code`), `drive/deploy` and its size cap, and the admin routes.
|
|
88
|
-
`src/routes/overlay.ts` is the list: an operation with `implemented: true` has a handler, and everything else answers `501` with its own name.
|
|
86
|
+
Every implemented operation is exercised by the corpus, and a handler without a case fails `spec/corpus-parity.spec.ts` - so "implemented" and "proven against the contract" are the same list rather than two that drift.
|
|
89
87
|
|
|
90
88
|
A status the document states but only a host can send - an account lockout (`429`), a provider failure (`500`), a session-store failure - is marked `hostResponses` in the overlay. It stays in the document, because a client still receives it, and is excluded from the parity check, whose other side is what this package answers; the host's own suite pins it.
|
|
91
89
|
|
|
@@ -96,6 +94,7 @@ Three of the sign-in flow's defences are the host's, because the package has no
|
|
|
96
94
|
- **Re-resolve the caller on every request.** A host with its own session passes the subject in (`session`, `authorize`), so the service re-reads the account behind it and refuses a deactivated one; a host that caches the subject it resolved at sign-in defeats that check. `logout` is the exception and does not refuse: dropping a credential is not access, and refusing would leave the pair in the store.
|
|
97
95
|
- **Lock the account out after repeated failures.** `POST /SASLogon/login` answers `401 Username is not found.` for an unknown username and `401 Invalid Password.` for a wrong one, because that is what the server's own form tells a user - which also means the route cannot tell a caller to stop guessing on its own. The defence is the host's limiter, answering `429` with `Retry-After` in seconds; without it the route is a way to enumerate usernames and account state.
|
|
98
96
|
- **Answer a session-store or identity-provider failure with `500`.** Those are the host's own dependencies, and the overlay marks the statuses as `hostResponses`.
|
|
97
|
+
- **Admit `DEPLOY_PAYLOAD_BYTES` on the deploy route, and only there.** The deploy cap is stated in decoded bytes and its tree travels as JSON in which file contents are base64, so a tree at the cap reaches the parser at up to ~134 MB; a smaller body limit refuses first, with its own shape, and the cap is never consulted. Every other route keeps the smaller limit, because a body is buffered before authentication.
|
|
99
98
|
|
|
100
99
|
## Development
|
|
101
100
|
|
|
@@ -107,9 +106,9 @@ npm run check:routes # the generated table matches spec/swagger.yaml
|
|
|
107
106
|
npm run lint
|
|
108
107
|
```
|
|
109
108
|
|
|
110
|
-
Refreshing the API surface: regenerate `api/public/swagger.yaml` in `sasjs/server` (`npm run swagger`), copy it to `spec/swagger.yaml`, and run `npm run sync:routes`. Review the diff
|
|
109
|
+
Refreshing the API surface: regenerate `api/public/swagger.yaml` in `sasjs/server` (`npm run swagger`), copy it to `spec/swagger.yaml`, and run `npm run sync:routes`. Review the diff: a new operation needs an overlay entry, and the table refuses to build without one.
|
|
111
110
|
|
|
112
|
-
Re-vendoring is a two-repository change and the server half merges first: the document is only true once the controllers it is generated from answer what it states, so a copy taken from an unmerged server branch describes a server that does not exist yet.
|
|
111
|
+
Re-vendoring is a two-repository change and the server half merges first: the document is only true once the controllers it is generated from answer what it states, so a copy taken from an unmerged server branch describes a server that does not exist yet. Take the copy from a released tag of `sasjs/server` rather than from its `main`, and the document and the code a host runs cannot disagree.
|
|
113
112
|
|
|
114
113
|
## Licence
|
|
115
114
|
|