@zero-server/sdk 0.9.5 → 0.9.7
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 +54 -64
- package/index.js +116 -4
- package/lib/app.js +22 -22
- package/lib/auth/authorize.js +11 -11
- package/lib/auth/enrollment.js +5 -5
- package/lib/auth/jwt.js +9 -9
- package/lib/auth/oauth.js +1 -1
- package/lib/auth/session.js +5 -5
- package/lib/auth/trustedDevice.js +2 -2
- package/lib/auth/twoFactor.js +11 -11
- package/lib/auth/webauthn.js +6 -6
- package/lib/body/json.js +1 -1
- package/lib/body/raw.js +1 -1
- package/lib/body/rawBuffer.js +1 -1
- package/lib/body/text.js +1 -1
- package/lib/body/urlencoded.js +3 -3
- package/lib/cli.js +19 -4
- package/lib/cluster.js +3 -3
- package/lib/debug.js +10 -10
- package/lib/env/index.js +11 -11
- package/lib/errors.js +131 -16
- package/lib/fetch/index.js +1 -1
- package/lib/grpc/call.js +14 -14
- package/lib/grpc/client.js +4 -4
- package/lib/grpc/codec.js +7 -7
- package/lib/grpc/credentials.js +2 -2
- package/lib/grpc/frame.js +2 -2
- package/lib/grpc/health.js +3 -3
- package/lib/grpc/index.js +3 -3
- package/lib/grpc/metadata.js +3 -3
- package/lib/grpc/proto.js +5 -5
- package/lib/grpc/reflection.js +2 -2
- package/lib/grpc/server.js +3 -3
- package/lib/grpc/status.js +2 -2
- package/lib/grpc/watch.js +1 -1
- package/lib/http/request.js +13 -13
- package/lib/http/response.js +2 -2
- package/lib/lifecycle.js +5 -5
- package/lib/middleware/compress.js +4 -4
- package/lib/observe/health.js +1 -1
- package/lib/observe/index.js +1 -1
- package/lib/observe/logger.js +3 -3
- package/lib/observe/metrics.js +4 -4
- package/lib/observe/tracing.js +4 -4
- package/lib/orm/adapters/json.js +1 -1
- package/lib/orm/adapters/memory.js +2 -2
- package/lib/orm/adapters/mongo.js +2 -2
- package/lib/orm/adapters/mysql.js +2 -2
- package/lib/orm/adapters/postgres.js +2 -2
- package/lib/orm/adapters/sqlite.js +3 -3
- package/lib/orm/audit.js +1 -1
- package/lib/orm/index.js +7 -7
- package/lib/orm/migrate.js +1 -1
- package/lib/orm/model.js +15 -15
- package/lib/orm/procedures.js +1 -1
- package/lib/orm/profiler.js +1 -1
- package/lib/orm/query.js +9 -9
- package/lib/orm/schema.js +1 -1
- package/lib/orm/seed/data/person.js +1 -1
- package/lib/orm/seed/fake.js +10 -10
- package/lib/orm/seed/index.js +4 -4
- package/lib/orm/seed/rng.js +1 -1
- package/lib/orm/snapshot.js +2 -2
- package/lib/orm/tenancy.js +6 -6
- package/lib/orm/views.js +1 -1
- package/lib/router/index.js +9 -9
- package/lib/webrtc/bot.js +361 -0
- package/lib/webrtc/cli.js +182 -0
- package/lib/webrtc/cluster.js +350 -0
- package/lib/webrtc/e2ee.js +282 -0
- package/lib/webrtc/ice.js +370 -0
- package/lib/webrtc/index.js +132 -0
- package/lib/webrtc/joinToken.js +116 -0
- package/lib/webrtc/observe.js +229 -0
- package/lib/webrtc/peer.js +116 -0
- package/lib/webrtc/room.js +171 -0
- package/lib/webrtc/sdp.js +508 -0
- package/lib/webrtc/sfu/index.js +201 -0
- package/lib/webrtc/sfu/livekit.js +301 -0
- package/lib/webrtc/sfu/mediasoup.js +317 -0
- package/lib/webrtc/sfu/memory.js +204 -0
- package/lib/webrtc/signaling.js +546 -0
- package/lib/webrtc/stun.js +492 -0
- package/lib/webrtc/turn/codec.js +370 -0
- package/lib/webrtc/turn/credentials.js +141 -0
- package/lib/webrtc/turn/server.js +633 -0
- package/package.json +2 -2
- package/types/body.d.ts +1 -1
- package/types/cli.d.ts +1 -1
- package/types/index.d.ts +16 -4
- package/types/middleware.d.ts +1 -1
- package/types/orm.d.ts +3 -3
- package/types/request.d.ts +3 -3
- package/types/webrtc.d.ts +501 -0
package/README.md
CHANGED
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
|
|
13
13
|
<p align="center">
|
|
14
14
|
<a href="https://github.com/tonywied17/zero-server/actions"><img src="https://img.shields.io/github/actions/workflow/status/tonywied17/zero-server/ci.yml?branch=main&style=flat-square&logo=githubactions&logoColor=white&label=CI" alt="CI"></a>
|
|
15
|
-
<a href="https://github.com/tonywied17/zero-server/actions"><img src="https://img.shields.io/badge/tests-
|
|
16
|
-
<a href="https://github.com/tonywied17/zero-server"><img src="https://img.shields.io/badge/coverage-
|
|
15
|
+
<a href="https://github.com/tonywied17/zero-server/actions"><img src="https://img.shields.io/badge/tests-7767%20passing-brightgreen?style=flat-square&logo=vitest&logoColor=white" alt="tests"></a>
|
|
16
|
+
<a href="https://github.com/tonywied17/zero-server"><img src="https://img.shields.io/badge/coverage-95.85%25-brightgreen?style=flat-square&logo=vitest&logoColor=white" alt="coverage"></a>
|
|
17
17
|
<a href="https://z-server.dev"><img src="https://img.shields.io/badge/docs-z--server.dev-00d8e0?style=flat-square&logo=readthedocs&logoColor=white" alt="docs"></a>
|
|
18
18
|
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-00d8e0?style=flat-square&logo=opensourceinitiative&logoColor=white" alt="MIT"></a>
|
|
19
19
|
<a href="https://nodejs.org"><img src="https://img.shields.io/badge/node-%3E%3D18-brightgreen?style=flat-square&logo=nodedotjs&logoColor=white" alt="node >=18"></a>
|
|
20
20
|
</p>
|
|
21
21
|
|
|
22
|
-
> **Zero-dependency backend framework for Node.js
|
|
22
|
+
> **Zero-dependency backend framework for Node.js - routing, ORM, auth, WebSocket, SSE, observability, and 20+ middleware as one SDK or focused scoped packages.**
|
|
23
23
|
|
|
24
24
|
<p align="center">
|
|
25
25
|
<strong>
|
|
@@ -31,15 +31,21 @@
|
|
|
31
31
|
|
|
32
32
|
## Install
|
|
33
33
|
|
|
34
|
-
zero-server is published as a set of focused, standalone scoped packages under `@zero-server/*`. Install only the surfaces you actually use:
|
|
35
|
-
|
|
36
34
|
```bash
|
|
37
|
-
npm install @zero-server/
|
|
35
|
+
npm install @zero-server/sdk
|
|
38
36
|
```
|
|
39
37
|
|
|
40
|
-
Requires Node.js 18+. No external dependencies
|
|
38
|
+
Requires Node.js 18+. No external dependencies - everything is built on Node.js core APIs.
|
|
41
39
|
|
|
42
|
-
|
|
40
|
+
`@zero-server/sdk` is the recommended install - it re-exports the entire framework from a single import. Use it for new projects, demos, and most production apps.
|
|
41
|
+
|
|
42
|
+
### Or install only what you need (scoped packages)
|
|
43
|
+
|
|
44
|
+
Every section of the framework is also published as its own standalone scoped package, so libraries and microservices that only touch a slice of the surface can install just those packages and skip the rest:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm install @zero-server/core @zero-server/body @zero-server/middleware
|
|
48
|
+
```
|
|
43
49
|
|
|
44
50
|
| Package | Surface |
|
|
45
51
|
|---|---|
|
|
@@ -57,30 +63,14 @@ Requires Node.js 18+. No external dependencies — everything is built on Node.j
|
|
|
57
63
|
| `@zero-server/errors` | every typed `HttpError` class plus ORM/framework errors |
|
|
58
64
|
| `@zero-server/cli` | programmatic `CLI` / `runCLI` entry points for `zh` / `zs` |
|
|
59
65
|
|
|
60
|
-
> Each scoped package is fully standalone at runtime
|
|
61
|
-
|
|
62
|
-
### Aggregate install (optional)
|
|
63
|
-
|
|
64
|
-
For demos, scratch projects, or apps that touch most of the surface, `@zero-server/sdk` is a convenience aggregate that re-exports the entire public API in one install:
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
npm install @zero-server/sdk
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
```js
|
|
71
|
-
const { createApp, json } = require('@zero-server/sdk')
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
Production apps and libraries should prefer the focused scoped packages above.
|
|
66
|
+
> Each scoped package is fully standalone at runtime - its own `index.js`, its own bundled lib, its own types. Mix and match freely; versions stay aligned across the `@zero-server/*` release set.
|
|
75
67
|
|
|
76
68
|
---
|
|
77
69
|
|
|
78
70
|
## Quick Start
|
|
79
71
|
|
|
80
72
|
```js
|
|
81
|
-
const { createApp } = require('@zero-server/
|
|
82
|
-
const { json } = require('@zero-server/body')
|
|
83
|
-
|
|
73
|
+
const { createApp, json } = require('@zero-server/sdk')
|
|
84
74
|
const app = createApp()
|
|
85
75
|
|
|
86
76
|
app.use(json())
|
|
@@ -102,7 +92,7 @@ app.listen(3000, () => console.log('Listening on :3000'))
|
|
|
102
92
|
|
|
103
93
|
### Middleware
|
|
104
94
|
|
|
105
|
-
20+ built-in middleware
|
|
95
|
+
20+ built-in middleware - all zero-dependency:
|
|
106
96
|
|
|
107
97
|
| Middleware | Purpose |
|
|
108
98
|
|---|---|
|
|
@@ -123,14 +113,14 @@ app.listen(3000, () => console.log('Listening on :3000'))
|
|
|
123
113
|
|
|
124
114
|
Full auth stack with no external libraries:
|
|
125
115
|
|
|
126
|
-
- **JWT**
|
|
127
|
-
- **Sessions**
|
|
128
|
-
- **OAuth 2.0**
|
|
129
|
-
- **Authorization**
|
|
116
|
+
- **JWT** - `jwt()` middleware, `jwtSign()`, `jwtVerify()`, `jwtDecode()`, JWKS key sets, access/refresh token pairs
|
|
117
|
+
- **Sessions** - `session()` middleware with in-memory store (pluggable)
|
|
118
|
+
- **OAuth 2.0** - `oauth()` middleware with PKCE, pre-configured providers (Google, GitHub, Microsoft, etc.)
|
|
119
|
+
- **Authorization** - `authorize()` policies, `can()` / `canAny()` permission checks, `gate()` middleware
|
|
130
120
|
|
|
131
121
|
### ORM & Database
|
|
132
122
|
|
|
133
|
-
Full-featured ORM with 7 adapters
|
|
123
|
+
Full-featured ORM with 7 adapters - memory, JSON file, SQLite, MySQL, PostgreSQL, MongoDB, and Redis:
|
|
134
124
|
|
|
135
125
|
```js
|
|
136
126
|
const { Database, Model, TYPES } = require('@zero-server/sdk')
|
|
@@ -152,7 +142,7 @@ await User.create({ name: 'Alice', email: 'alice@example.com' })
|
|
|
152
142
|
const users = await User.find({ name: 'Alice' })
|
|
153
143
|
```
|
|
154
144
|
|
|
155
|
-
**Query builder**
|
|
145
|
+
**Query builder** - `where()`, `select()`, `orderBy()`, `limit()`, `offset()`, `join()`, `groupBy()`, `having()`, `paginate()`, `findOrCreate()`
|
|
156
146
|
|
|
157
147
|
**Advanced ORM features:**
|
|
158
148
|
|
|
@@ -173,12 +163,12 @@ const users = await User.find({ name: 'Alice' })
|
|
|
173
163
|
|
|
174
164
|
### Real-Time
|
|
175
165
|
|
|
176
|
-
- **WebSocket**
|
|
177
|
-
- **Server-Sent Events**
|
|
166
|
+
- **WebSocket** - `app.ws(path, handler)` with RFC 6455, `WebSocketPool` for rooms, broadcasting, and sub-protocols
|
|
167
|
+
- **Server-Sent Events** - `res.sse()` with auto-IDs, named events, and keep-alive
|
|
178
168
|
|
|
179
169
|
### Observability
|
|
180
170
|
|
|
181
|
-
Built-in Prometheus metrics, health checks, distributed tracing, and structured logging
|
|
171
|
+
Built-in Prometheus metrics, health checks, distributed tracing, and structured logging - zero dependencies.
|
|
182
172
|
|
|
183
173
|
```js
|
|
184
174
|
const { createApp, metricsMiddleware } = require('@zero-server/sdk')
|
|
@@ -203,7 +193,7 @@ logins.inc({ provider: 'github' })
|
|
|
203
193
|
app.listen(3000)
|
|
204
194
|
```
|
|
205
195
|
|
|
206
|
-
**Scrape with Prometheus**
|
|
196
|
+
**Scrape with Prometheus** - create a `prometheus.yml`:
|
|
207
197
|
|
|
208
198
|
```yaml
|
|
209
199
|
scrape_configs:
|
|
@@ -219,13 +209,13 @@ docker run -d -p 9090:9090 -v ./prometheus.yml:/etc/prometheus/prometheus.yml pr
|
|
|
219
209
|
```
|
|
220
210
|
|
|
221
211
|
**Also includes:**
|
|
222
|
-
- **Distributed tracing**
|
|
223
|
-
- **Structured logging**
|
|
212
|
+
- **Distributed tracing** - `Tracer` and `Span` with W3C Trace Context (`traceparent` propagation), `instrumentFetch()` for outgoing requests
|
|
213
|
+
- **Structured logging** - `Logger` with levels, JSON output, and namespaced `debug()` logger
|
|
224
214
|
|
|
225
215
|
### Lifecycle & Clustering
|
|
226
216
|
|
|
227
|
-
- **Graceful shutdown**
|
|
228
|
-
- **Clustering**
|
|
217
|
+
- **Graceful shutdown** - signal handlers (SIGTERM/SIGINT), in-flight request draining, automatic WebSocket/SSE/database cleanup
|
|
218
|
+
- **Clustering** - `clusterize()` for multi-worker processes with auto-respawn and exponential backoff
|
|
229
219
|
|
|
230
220
|
### CLI
|
|
231
221
|
|
|
@@ -429,35 +419,35 @@ npm run docs
|
|
|
429
419
|
|
|
430
420
|
```
|
|
431
421
|
lib/
|
|
432
|
-
app.js
|
|
433
|
-
auth/
|
|
434
|
-
body/
|
|
435
|
-
cli.js
|
|
436
|
-
cluster.js
|
|
437
|
-
debug.js
|
|
438
|
-
env/
|
|
439
|
-
errors.js
|
|
440
|
-
fetch/
|
|
441
|
-
grpc/
|
|
422
|
+
app.js - App class (middleware, routing, listen, ws upgrade, lifecycle)
|
|
423
|
+
auth/ - JWT, OAuth 2.0, sessions, MFA (TOTP/WebAuthn), authorization
|
|
424
|
+
body/ - body parsers (json, urlencoded, text, raw, multipart)
|
|
425
|
+
cli.js - CLI runner (migrate, seed, scaffold commands)
|
|
426
|
+
cluster.js - multi-worker clustering with auto-respawn
|
|
427
|
+
debug.js - namespaced debug logger
|
|
428
|
+
env/ - typed .env loader with schema validation
|
|
429
|
+
errors.js - 25+ HttpError / framework / ORM error classes
|
|
430
|
+
fetch/ - HTTP/HTTPS client (mTLS, AbortSignal, retries)
|
|
431
|
+
grpc/ - HTTP/2 gRPC stack: server, client, codec, framing,
|
|
442
432
|
status, metadata, health, reflection, balancer, watch
|
|
443
|
-
http/
|
|
444
|
-
lifecycle.js
|
|
445
|
-
middleware/
|
|
433
|
+
http/ - Request & Response wrappers
|
|
434
|
+
lifecycle.js - graceful shutdown and lifecycle management
|
|
435
|
+
middleware/ - cors, helmet, logger, rateLimit, compress, static, timeout,
|
|
446
436
|
requestId, cookieParser, csrf, validate, errorHandler
|
|
447
|
-
observe/
|
|
448
|
-
orm/
|
|
437
|
+
observe/ - Prometheus metrics, W3C tracing, health checks, structured logging
|
|
438
|
+
orm/ - Database, Model, Query, adapters, migrations, seeds, cache,
|
|
449
439
|
replicas, search, geo, tenancy, audit, views, procedures, plugins
|
|
450
|
-
router/
|
|
451
|
-
sse/
|
|
452
|
-
ws/
|
|
453
|
-
packages/
|
|
440
|
+
router/ - Router with sub-app mounting and pattern matching
|
|
441
|
+
sse/ - SSE stream controller
|
|
442
|
+
ws/ - WebSocket connection, handshake, and room management
|
|
443
|
+
packages/ - generated scoped @zero-server/* re-exports (one dir per scope)
|
|
454
444
|
.tools/
|
|
455
|
-
scope-manifest.js
|
|
445
|
+
scope-manifest.js - single source of truth for scoped packages & their surface
|
|
456
446
|
generate-package-stubs.js
|
|
457
447
|
generate-scope-docs.js
|
|
458
|
-
types/
|
|
459
|
-
website-docs/
|
|
460
|
-
test/
|
|
448
|
+
types/ - full TypeScript definitions
|
|
449
|
+
website-docs/ - live demo server, controllers, and playground UI
|
|
450
|
+
test/ - vitest test suite (7000+ tests, 95%+ coverage)
|
|
461
451
|
```
|
|
462
452
|
|
|
463
453
|
## Testing
|
package/index.js
CHANGED
|
@@ -59,6 +59,23 @@ const {
|
|
|
59
59
|
ChannelCredentials, createRotatingCredentials,
|
|
60
60
|
watchProto,
|
|
61
61
|
} = require('./lib/grpc');
|
|
62
|
+
const {
|
|
63
|
+
createWebRTC, SignalingHub, Room, Peer,
|
|
64
|
+
parseSdp, stringifySdp,
|
|
65
|
+
parseCandidate, stringifyCandidate, filterCandidates,
|
|
66
|
+
isPrivateIp, isLoopbackIp, isLinkLocalIp, isMdnsHostname,
|
|
67
|
+
stunBinding, encodeBindingRequest, decodeMessage,
|
|
68
|
+
encodeXorMappedAddress, decodeXorMappedAddress,
|
|
69
|
+
STUN_MAGIC_COOKIE, STUN_METHOD, STUN_CLASS, STUN_ATTR,
|
|
70
|
+
issueTurnCredentials, TurnServer,
|
|
71
|
+
SfuAdapter, MemorySfuAdapter, MediasoupSfuAdapter, LiveKitSfuAdapter, loadSfuAdapter, signJoinToken, verifyJoinToken,
|
|
72
|
+
spawnBotPeer,
|
|
73
|
+
bindObservability,
|
|
74
|
+
E2eeChannel, attachE2ee, generateE2eeKeyPair, sealKey, openSealedKey,
|
|
75
|
+
useCluster, ClusterCoordinator, MemoryClusterAdapter,
|
|
76
|
+
runWebRTCCommand,
|
|
77
|
+
WebRTCError, SignalingError, IceError, TurnError, SdpError,
|
|
78
|
+
} = require('./lib/webrtc');
|
|
62
79
|
const { version } = require('./package.json');
|
|
63
80
|
|
|
64
81
|
module.exports = {
|
|
@@ -247,12 +264,12 @@ module.exports = {
|
|
|
247
264
|
ClusterManager,
|
|
248
265
|
/** @see module:cluster */
|
|
249
266
|
cluster: clusterize,
|
|
250
|
-
// Observability
|
|
267
|
+
// Observability - Structured Logging
|
|
251
268
|
/** @see module:observe/logger */
|
|
252
269
|
Logger,
|
|
253
270
|
/** @see module:observe/logger */
|
|
254
271
|
structuredLogger,
|
|
255
|
-
// Observability
|
|
272
|
+
// Observability - Metrics
|
|
256
273
|
/** @see module:observe/metrics */
|
|
257
274
|
Counter,
|
|
258
275
|
/** @see module:observe/metrics */
|
|
@@ -269,7 +286,7 @@ module.exports = {
|
|
|
269
286
|
metricsMiddleware,
|
|
270
287
|
/** @see module:observe/metrics */
|
|
271
288
|
metricsEndpoint: metricsEndpointHandler,
|
|
272
|
-
// Observability
|
|
289
|
+
// Observability - Tracing
|
|
273
290
|
/** @see module:observe/tracing */
|
|
274
291
|
Span,
|
|
275
292
|
/** @see module:observe/tracing */
|
|
@@ -282,7 +299,7 @@ module.exports = {
|
|
|
282
299
|
tracingMiddleware,
|
|
283
300
|
/** @see module:observe/tracing */
|
|
284
301
|
instrumentFetch,
|
|
285
|
-
// Observability
|
|
302
|
+
// Observability - Health Checks
|
|
286
303
|
/** @see module:observe/health */
|
|
287
304
|
healthCheck,
|
|
288
305
|
/** @see module:observe/health */
|
|
@@ -409,6 +426,101 @@ module.exports = {
|
|
|
409
426
|
// gRPC: Proto hot-reload
|
|
410
427
|
/** @see module:grpc/watch */
|
|
411
428
|
watchProto,
|
|
429
|
+
// WebRTC
|
|
430
|
+
/** @see module:webrtc */
|
|
431
|
+
createWebRTC,
|
|
432
|
+
/** @see module:webrtc/signaling */
|
|
433
|
+
SignalingHub,
|
|
434
|
+
/** @see module:webrtc/room */
|
|
435
|
+
Room,
|
|
436
|
+
/** @see module:webrtc/peer */
|
|
437
|
+
Peer,
|
|
438
|
+
/** @see module:webrtc/sdp */
|
|
439
|
+
parseSdp,
|
|
440
|
+
/** @see module:webrtc/sdp */
|
|
441
|
+
stringifySdp,
|
|
442
|
+
/** @see module:webrtc/ice */
|
|
443
|
+
parseCandidate,
|
|
444
|
+
/** @see module:webrtc/ice */
|
|
445
|
+
stringifyCandidate,
|
|
446
|
+
/** @see module:webrtc/ice */
|
|
447
|
+
filterCandidates,
|
|
448
|
+
/** @see module:webrtc/ice */
|
|
449
|
+
isPrivateIp,
|
|
450
|
+
/** @see module:webrtc/ice */
|
|
451
|
+
isLoopbackIp,
|
|
452
|
+
/** @see module:webrtc/ice */
|
|
453
|
+
isLinkLocalIp,
|
|
454
|
+
/** @see module:webrtc/ice */
|
|
455
|
+
isMdnsHostname,
|
|
456
|
+
/** @see module:webrtc/stun */
|
|
457
|
+
stunBinding,
|
|
458
|
+
/** @see module:webrtc/stun */
|
|
459
|
+
encodeBindingRequest,
|
|
460
|
+
/** @see module:webrtc/stun */
|
|
461
|
+
decodeMessage,
|
|
462
|
+
/** @see module:webrtc/stun */
|
|
463
|
+
encodeXorMappedAddress,
|
|
464
|
+
/** @see module:webrtc/stun */
|
|
465
|
+
decodeXorMappedAddress,
|
|
466
|
+
/** @see module:webrtc/stun */
|
|
467
|
+
STUN_MAGIC_COOKIE,
|
|
468
|
+
/** @see module:webrtc/stun */
|
|
469
|
+
STUN_METHOD,
|
|
470
|
+
/** @see module:webrtc/stun */
|
|
471
|
+
STUN_CLASS,
|
|
472
|
+
/** @see module:webrtc/stun */
|
|
473
|
+
STUN_ATTR,
|
|
474
|
+
/** @see module:webrtc/turn/credentials */
|
|
475
|
+
issueTurnCredentials,
|
|
476
|
+
/** @see module:webrtc/turn/server */
|
|
477
|
+
TurnServer,
|
|
478
|
+
/** @see module:webrtc/sfu */
|
|
479
|
+
SfuAdapter,
|
|
480
|
+
/** @see module:webrtc/sfu/memory */
|
|
481
|
+
MemorySfuAdapter,
|
|
482
|
+
/** @see module:webrtc/sfu/mediasoup */
|
|
483
|
+
MediasoupSfuAdapter,
|
|
484
|
+
/** @see module:webrtc/sfu/livekit */
|
|
485
|
+
LiveKitSfuAdapter,
|
|
486
|
+
/** @see module:webrtc/sfu */
|
|
487
|
+
loadSfuAdapter,
|
|
488
|
+
/** @see module:webrtc/signaling */
|
|
489
|
+
signJoinToken,
|
|
490
|
+
/** @see module:webrtc/signaling */
|
|
491
|
+
verifyJoinToken,
|
|
492
|
+
/** @see module:webrtc/bot */
|
|
493
|
+
spawnBotPeer,
|
|
494
|
+
/** @see module:webrtc/observe */
|
|
495
|
+
bindObservability,
|
|
496
|
+
/** @see module:webrtc/e2ee */
|
|
497
|
+
E2eeChannel,
|
|
498
|
+
/** @see module:webrtc/e2ee */
|
|
499
|
+
attachE2ee,
|
|
500
|
+
/** @see module:webrtc/e2ee */
|
|
501
|
+
generateE2eeKeyPair,
|
|
502
|
+
/** @see module:webrtc/e2ee */
|
|
503
|
+
sealKey,
|
|
504
|
+
/** @see module:webrtc/e2ee */
|
|
505
|
+
openSealedKey,
|
|
506
|
+
/** @see module:webrtc/cluster */
|
|
507
|
+
useCluster,
|
|
508
|
+
/** @see module:webrtc/cluster */
|
|
509
|
+
ClusterCoordinator,
|
|
510
|
+
/** @see module:webrtc/cluster */
|
|
511
|
+
MemoryClusterAdapter,
|
|
512
|
+
/** @see module:webrtc/cli */
|
|
513
|
+
runWebRTCCommand,
|
|
514
|
+
/** @see module:errors */
|
|
515
|
+
WebRTCError,
|
|
516
|
+
/** @see module:errors */
|
|
517
|
+
SignalingError,
|
|
518
|
+
/** @see module:errors */
|
|
519
|
+
IceError,
|
|
520
|
+
/** @see module:errors */
|
|
521
|
+
TurnError,
|
|
522
|
+
/** @see module:errors */
|
|
523
|
+
SdpError,
|
|
412
524
|
/** Package version */
|
|
413
525
|
version,
|
|
414
526
|
};
|
package/lib/app.js
CHANGED
|
@@ -74,7 +74,7 @@ class App
|
|
|
74
74
|
this._settings = {};
|
|
75
75
|
|
|
76
76
|
/**
|
|
77
|
-
* Application-level locals
|
|
77
|
+
* Application-level locals - persistent across the app lifecycle.
|
|
78
78
|
* Merged into every `req.locals` and `res.locals` on every request.
|
|
79
79
|
* @type {Object<string, *>}
|
|
80
80
|
*/
|
|
@@ -167,10 +167,10 @@ class App
|
|
|
167
167
|
|
|
168
168
|
/**
|
|
169
169
|
* Register middleware or mount a sub-router.
|
|
170
|
-
* - `use(fn)`
|
|
171
|
-
* - `use('/prefix', fn)`
|
|
170
|
+
* - `use(fn)` - global middleware applied to every request.
|
|
171
|
+
* - `use('/prefix', fn)` - path-scoped middleware (strips the prefix
|
|
172
172
|
* before calling `fn` so downstream sees relative paths).
|
|
173
|
-
* - `use('/prefix', router)`
|
|
173
|
+
* - `use('/prefix', router)` - mount a Router sub-app at the given prefix.
|
|
174
174
|
*
|
|
175
175
|
* @param {string|Function} pathOrFn - A path prefix string, or middleware function.
|
|
176
176
|
* @param {Function|Router} [fn] - Middleware function or Router when first arg is a path.
|
|
@@ -254,7 +254,7 @@ class App
|
|
|
254
254
|
*/
|
|
255
255
|
handle(req, res)
|
|
256
256
|
{
|
|
257
|
-
// Skip gRPC requests
|
|
257
|
+
// Skip gRPC requests - already handled via server.on('stream')
|
|
258
258
|
if (this._grpcRegistry && req.headers['content-type']?.startsWith('application/grpc'))
|
|
259
259
|
return;
|
|
260
260
|
|
|
@@ -356,7 +356,7 @@ class App
|
|
|
356
356
|
*/
|
|
357
357
|
listen(port = 3000, opts, cb)
|
|
358
358
|
{
|
|
359
|
-
// Normalise arguments
|
|
359
|
+
// Normalise arguments - allow `listen(port, cb)` without opts
|
|
360
360
|
if (typeof opts === 'function') { cb = opts; opts = undefined; }
|
|
361
361
|
|
|
362
362
|
const isH2 = opts && opts.http2;
|
|
@@ -376,7 +376,7 @@ class App
|
|
|
376
376
|
}
|
|
377
377
|
else if (isH2)
|
|
378
378
|
{
|
|
379
|
-
// HTTP/2 cleartext (h2c)
|
|
379
|
+
// HTTP/2 cleartext (h2c) - no TLS, for internal services
|
|
380
380
|
const h2Opts = opts ? { ...opts } : {};
|
|
381
381
|
delete h2Opts.http2;
|
|
382
382
|
server = http2.createServer(h2Opts, this.handler);
|
|
@@ -402,7 +402,7 @@ class App
|
|
|
402
402
|
{
|
|
403
403
|
if (this._grpcRegistry.handleStream(stream, headers))
|
|
404
404
|
return; // handled as gRPC
|
|
405
|
-
// Otherwise fall through
|
|
405
|
+
// Otherwise fall through - the compat handler fires the normal request event
|
|
406
406
|
});
|
|
407
407
|
}
|
|
408
408
|
|
|
@@ -461,8 +461,8 @@ class App
|
|
|
461
461
|
* Register a lifecycle event listener.
|
|
462
462
|
*
|
|
463
463
|
* Supported events:
|
|
464
|
-
* - `'beforeShutdown'`
|
|
465
|
-
* - `'shutdown'`
|
|
464
|
+
* - `'beforeShutdown'` - fires before shutdown begins (flush caches, finish writes)
|
|
465
|
+
* - `'shutdown'` - fires after shutdown is complete
|
|
466
466
|
*
|
|
467
467
|
* @param {'beforeShutdown'|'shutdown'} event - Lifecycle event name.
|
|
468
468
|
* @param {Function} fn - Async or sync callback.
|
|
@@ -570,7 +570,7 @@ class App
|
|
|
570
570
|
}
|
|
571
571
|
|
|
572
572
|
/**
|
|
573
|
-
* Configure the shutdown timeout
|
|
573
|
+
* Configure the shutdown timeout-the maximum time (ms) to wait for
|
|
574
574
|
* in-flight requests to finish before forcefully terminating them.
|
|
575
575
|
*
|
|
576
576
|
* @param {number} ms - Timeout in milliseconds.
|
|
@@ -730,7 +730,7 @@ class App
|
|
|
730
730
|
* @param {object|Function} [opts] - Options object, or the handler function directly.
|
|
731
731
|
* @param {number} [opts.maxPayload=1048576] - Maximum incoming frame size in bytes (default 1 MB).
|
|
732
732
|
* @param {number} [opts.pingInterval=30000] - Auto-ping interval in ms. Set `0` to disable.
|
|
733
|
-
* @param {Function} [opts.verifyClient] - `(req) => boolean`
|
|
733
|
+
* @param {Function} [opts.verifyClient] - `(req) => boolean` - return false to reject the upgrade.
|
|
734
734
|
* @param {Function} handler - `(ws, req) => void`.
|
|
735
735
|
*
|
|
736
736
|
* @example | Simple
|
|
@@ -815,56 +815,56 @@ class App
|
|
|
815
815
|
route(method, path, ...fns) { const o = this._extractOpts(fns); this.router.add(method, path, fns, o); }
|
|
816
816
|
|
|
817
817
|
/**
|
|
818
|
-
* @see App#route
|
|
818
|
+
* @see App#route - shortcut for GET requests.
|
|
819
819
|
* @param {string} path - Route pattern.
|
|
820
820
|
* @param {...Function} fns - Handler functions.
|
|
821
821
|
* @returns {App} `this` for chaining.
|
|
822
822
|
*/
|
|
823
823
|
get(path, ...fns) { if (arguments.length === 1 && typeof path === 'string' && fns.length === 0) return this.set(path); this.route('GET', path, ...fns); return this; }
|
|
824
824
|
/**
|
|
825
|
-
* @see App#route
|
|
825
|
+
* @see App#route - shortcut for POST requests.
|
|
826
826
|
* @param {string} path - Route pattern.
|
|
827
827
|
* @param {...Function} fns - Handler functions.
|
|
828
828
|
* @returns {App} `this` for chaining.
|
|
829
829
|
*/
|
|
830
830
|
post(path, ...fns) { this.route('POST', path, ...fns); return this; }
|
|
831
831
|
/**
|
|
832
|
-
* @see App#route
|
|
832
|
+
* @see App#route - shortcut for PUT requests.
|
|
833
833
|
* @param {string} path - Route pattern.
|
|
834
834
|
* @param {...Function} fns - Handler functions.
|
|
835
835
|
* @returns {App} `this` for chaining.
|
|
836
836
|
*/
|
|
837
837
|
put(path, ...fns) { this.route('PUT', path, ...fns); return this; }
|
|
838
838
|
/**
|
|
839
|
-
* @see App#route
|
|
839
|
+
* @see App#route - shortcut for DELETE requests.
|
|
840
840
|
* @param {string} path - Route pattern.
|
|
841
841
|
* @param {...Function} fns - Handler functions.
|
|
842
842
|
* @returns {App} `this` for chaining.
|
|
843
843
|
*/
|
|
844
844
|
delete(path, ...fns) { this.route('DELETE', path, ...fns); return this; }
|
|
845
845
|
/**
|
|
846
|
-
* @see App#route
|
|
846
|
+
* @see App#route - shortcut for PATCH requests.
|
|
847
847
|
* @param {string} path - Route pattern.
|
|
848
848
|
* @param {...Function} fns - Handler functions.
|
|
849
849
|
* @returns {App} `this` for chaining.
|
|
850
850
|
*/
|
|
851
851
|
patch(path, ...fns) { this.route('PATCH', path, ...fns); return this; }
|
|
852
852
|
/**
|
|
853
|
-
* @see App#route
|
|
853
|
+
* @see App#route - shortcut for OPTIONS requests.
|
|
854
854
|
* @param {string} path - Route pattern.
|
|
855
855
|
* @param {...Function} fns - Handler functions.
|
|
856
856
|
* @returns {App} `this` for chaining.
|
|
857
857
|
*/
|
|
858
858
|
options(path, ...fns) { this.route('OPTIONS', path, ...fns); return this; }
|
|
859
859
|
/**
|
|
860
|
-
* @see App#route
|
|
860
|
+
* @see App#route - shortcut for HEAD requests.
|
|
861
861
|
* @param {string} path - Route pattern.
|
|
862
862
|
* @param {...Function} fns - Handler functions.
|
|
863
863
|
* @returns {App} `this` for chaining.
|
|
864
864
|
*/
|
|
865
865
|
head(path, ...fns) { this.route('HEAD', path, ...fns); return this; }
|
|
866
866
|
/**
|
|
867
|
-
* @see App#route
|
|
867
|
+
* @see App#route - matches every HTTP method.
|
|
868
868
|
* @param {string} path - Route pattern.
|
|
869
869
|
* @param {...Function} fns - Handler functions.
|
|
870
870
|
* @returns {App} `this` for chaining.
|
|
@@ -872,7 +872,7 @@ class App
|
|
|
872
872
|
all(path, ...fns) { this.route('ALL', path, ...fns); return this; }
|
|
873
873
|
|
|
874
874
|
/**
|
|
875
|
-
* Chainable route builder
|
|
875
|
+
* Chainable route builder - register multiple methods on the same path.
|
|
876
876
|
*
|
|
877
877
|
* @param {string} path - Route pattern.
|
|
878
878
|
* @returns {object} Chain object with HTTP verb methods.
|
|
@@ -1149,7 +1149,7 @@ class App
|
|
|
1149
1149
|
|
|
1150
1150
|
/**
|
|
1151
1151
|
* Create an OAuth2 client bound to this app.
|
|
1152
|
-
* Returns the client
|
|
1152
|
+
* Returns the client - does NOT mount any middleware automatically.
|
|
1153
1153
|
*
|
|
1154
1154
|
* @param {object} opts - OAuth options (see `oauth()` for full documentation).
|
|
1155
1155
|
* @returns {{ authorize: Function, callback: Function, refresh: Function, userInfo: Function }}
|
package/lib/auth/authorize.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module auth/authorize
|
|
3
|
-
* @description Authorization helpers
|
|
3
|
+
* @description Authorization helpers - role-based access control (RBAC),
|
|
4
4
|
* permission-based access, and policy classes.
|
|
5
5
|
*
|
|
6
6
|
* Works with any authentication middleware that sets `req.user`.
|
|
@@ -13,22 +13,22 @@
|
|
|
13
13
|
* app.use(jwt({ secret: process.env.JWT_SECRET }));
|
|
14
14
|
* app.use(attachUserHelpers());
|
|
15
15
|
*
|
|
16
|
-
* // Role-based
|
|
16
|
+
* // Role-based - only admins and editors can modify posts
|
|
17
17
|
* app.put('/posts/:id', authorize('admin', 'editor'), (req, res) => {
|
|
18
18
|
* res.json({ updated: true });
|
|
19
19
|
* });
|
|
20
20
|
*
|
|
21
|
-
* // Permission-based
|
|
21
|
+
* // Permission-based - require ALL listed permissions
|
|
22
22
|
* app.delete('/users/:id', can('users:read', 'users:delete'), (req, res) => {
|
|
23
23
|
* res.json({ deleted: true });
|
|
24
24
|
* });
|
|
25
25
|
*
|
|
26
|
-
* // ANY permission
|
|
26
|
+
* // ANY permission - useful for overlapping access
|
|
27
27
|
* app.get('/reports', canAny('reports:read', 'admin:read'), (req, res) => {
|
|
28
28
|
* res.json({ reports: [] });
|
|
29
29
|
* });
|
|
30
30
|
*
|
|
31
|
-
* // Policy class
|
|
31
|
+
* // Policy class - resource-level authorization
|
|
32
32
|
* class PostPolicy extends Policy {
|
|
33
33
|
* before(user) { if (user.role === 'superadmin') return true; }
|
|
34
34
|
* update(user, post) { return user.id === post.authorId || user.role === 'admin'; }
|
|
@@ -114,9 +114,9 @@ function authorize(...roles)
|
|
|
114
114
|
* Checks `req.user.permissions` (array or Set) for the required permission(s).
|
|
115
115
|
*
|
|
116
116
|
* Permission strings follow a `resource:action` convention:
|
|
117
|
-
* - `'posts:write'`
|
|
118
|
-
* - `'users:delete'`
|
|
119
|
-
* - `'*'`
|
|
117
|
+
* - `'posts:write'` - write access to posts
|
|
118
|
+
* - `'users:delete'` - delete users
|
|
119
|
+
* - `'*'` - superuser wildcard
|
|
120
120
|
*
|
|
121
121
|
* @param {...string} permissions - Required permissions (ALL must be present unless `opts.any` is true).
|
|
122
122
|
* @returns {Function} Middleware `(req, res, next) => void`.
|
|
@@ -293,7 +293,7 @@ function gate(policy, action, getResource)
|
|
|
293
293
|
});
|
|
294
294
|
}
|
|
295
295
|
|
|
296
|
-
// Attach resource if loaded
|
|
296
|
+
// Attach resource if loaded - saves a redundant DB query in the handler
|
|
297
297
|
if (resource && !req.resource) req.resource = resource;
|
|
298
298
|
next();
|
|
299
299
|
};
|
|
@@ -306,8 +306,8 @@ function gate(policy, action, getResource)
|
|
|
306
306
|
* Call this middleware after JWT/session middleware.
|
|
307
307
|
*
|
|
308
308
|
* Adds:
|
|
309
|
-
* - `req.user.is(...roles)`
|
|
310
|
-
* - `req.user.can(...perms)`
|
|
309
|
+
* - `req.user.is(...roles)` - check roles
|
|
310
|
+
* - `req.user.can(...perms)` - check permissions
|
|
311
311
|
*
|
|
312
312
|
* @returns {Function} Middleware.
|
|
313
313
|
*
|
package/lib/auth/enrollment.js
CHANGED
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
* for TOTP-based two-factor authentication.
|
|
6
6
|
*
|
|
7
7
|
* Steps:
|
|
8
|
-
* 1. `start()`
|
|
9
|
-
* 2. `verify()`
|
|
10
|
-
* 3. `complete()`
|
|
11
|
-
* 4. `disable()`
|
|
8
|
+
* 1. `start()` - Generate secret + backup codes, store in session
|
|
9
|
+
* 2. `verify()` - Confirm user can produce a valid TOTP code
|
|
10
|
+
* 3. `complete()` - Persist the verified secret to the database
|
|
11
|
+
* 4. `disable()` - Remove 2FA from the account
|
|
12
12
|
*
|
|
13
13
|
* @example | Full enrollment flow
|
|
14
14
|
* const { enrollment } = require('@zero-server/sdk');
|
|
@@ -356,7 +356,7 @@ function enrollment(opts = {})
|
|
|
356
356
|
|
|
357
357
|
function _defaultGetAccount(req)
|
|
358
358
|
{
|
|
359
|
-
if (!req.user) throw new Error('No user on request
|
|
359
|
+
if (!req.user) throw new Error('No user on request - authentication middleware required');
|
|
360
360
|
return req.user.email || req.user.id || req.user.sub;
|
|
361
361
|
}
|
|
362
362
|
|