@zero-server/sdk 0.9.1 → 0.9.3
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/LICENSE +21 -21
- package/README.md +460 -443
- package/index.js +414 -412
- package/lib/app.js +1172 -1172
- package/lib/auth/authorize.js +399 -399
- package/lib/auth/enrollment.js +367 -367
- package/lib/auth/index.js +57 -57
- package/lib/auth/jwt.js +731 -731
- package/lib/auth/oauth.js +362 -362
- package/lib/auth/session.js +588 -588
- package/lib/auth/trustedDevice.js +409 -409
- package/lib/auth/twoFactor.js +1150 -1150
- package/lib/auth/webauthn.js +946 -946
- package/lib/body/index.js +14 -14
- package/lib/body/json.js +109 -109
- package/lib/body/multipart.js +440 -440
- package/lib/body/raw.js +71 -71
- package/lib/body/rawBuffer.js +160 -160
- package/lib/body/sendError.js +25 -25
- package/lib/body/text.js +75 -75
- package/lib/body/typeMatch.js +41 -41
- package/lib/body/urlencoded.js +235 -235
- package/lib/cli.js +845 -845
- package/lib/cluster.js +666 -666
- package/lib/debug.js +372 -372
- package/lib/env/index.js +465 -465
- package/lib/errors.js +683 -683
- package/lib/fetch/index.js +256 -256
- package/lib/grpc/balancer.js +378 -378
- package/lib/grpc/call.js +708 -708
- package/lib/grpc/client.js +764 -764
- package/lib/grpc/codec.js +1221 -1221
- package/lib/grpc/credentials.js +398 -398
- package/lib/grpc/frame.js +262 -262
- package/lib/grpc/health.js +287 -287
- package/lib/grpc/index.js +121 -121
- package/lib/grpc/metadata.js +461 -461
- package/lib/grpc/proto.js +821 -821
- package/lib/grpc/reflection.js +590 -590
- package/lib/grpc/server.js +445 -445
- package/lib/grpc/status.js +118 -118
- package/lib/grpc/watch.js +173 -173
- package/lib/http/index.js +10 -10
- package/lib/http/request.js +727 -727
- package/lib/http/response.js +799 -799
- package/lib/lifecycle.js +557 -557
- package/lib/middleware/compress.js +230 -230
- package/lib/middleware/cookieParser.js +237 -237
- package/lib/middleware/cors.js +93 -93
- package/lib/middleware/csrf.js +137 -137
- package/lib/middleware/errorHandler.js +101 -101
- package/lib/middleware/helmet.js +175 -175
- package/lib/middleware/index.js +19 -17
- package/lib/middleware/logger.js +74 -74
- package/lib/middleware/rateLimit.js +88 -88
- package/lib/middleware/requestId.js +53 -53
- package/lib/middleware/static.js +326 -326
- package/lib/middleware/timeout.js +71 -71
- package/lib/middleware/validator.js +255 -255
- package/lib/observe/health.js +326 -326
- package/lib/observe/index.js +50 -50
- package/lib/observe/logger.js +359 -359
- package/lib/observe/metrics.js +805 -805
- package/lib/observe/tracing.js +592 -592
- package/lib/orm/adapters/json.js +290 -290
- package/lib/orm/adapters/memory.js +764 -764
- package/lib/orm/adapters/mongo.js +764 -764
- package/lib/orm/adapters/mysql.js +933 -933
- package/lib/orm/adapters/postgres.js +1144 -1144
- package/lib/orm/adapters/redis.js +1534 -1534
- package/lib/orm/adapters/sql-base.js +212 -212
- package/lib/orm/adapters/sqlite.js +858 -858
- package/lib/orm/audit.js +649 -649
- package/lib/orm/cache.js +394 -394
- package/lib/orm/geo.js +387 -387
- package/lib/orm/index.js +784 -784
- package/lib/orm/migrate.js +432 -432
- package/lib/orm/model.js +1706 -1706
- package/lib/orm/plugin.js +375 -375
- package/lib/orm/procedures.js +836 -836
- package/lib/orm/profiler.js +233 -233
- package/lib/orm/query.js +1772 -1772
- package/lib/orm/replicas.js +241 -241
- package/lib/orm/schema.js +307 -307
- package/lib/orm/search.js +380 -380
- package/lib/orm/seed/data/commerce.js +136 -136
- package/lib/orm/seed/data/internet.js +111 -111
- package/lib/orm/seed/data/locations.js +204 -204
- package/lib/orm/seed/data/names.js +338 -338
- package/lib/orm/seed/data/person.js +128 -128
- package/lib/orm/seed/data/phone.js +211 -211
- package/lib/orm/seed/data/words.js +134 -134
- package/lib/orm/seed/factory.js +178 -178
- package/lib/orm/seed/fake.js +1186 -1186
- package/lib/orm/seed/index.js +18 -18
- package/lib/orm/seed/rng.js +70 -70
- package/lib/orm/seed/seeder.js +124 -124
- package/lib/orm/seed/unique.js +68 -68
- package/lib/orm/snapshot.js +366 -366
- package/lib/orm/tenancy.js +605 -605
- package/lib/orm/views.js +350 -350
- package/lib/router/index.js +436 -436
- package/lib/sse/index.js +8 -8
- package/lib/sse/stream.js +349 -349
- package/lib/ws/connection.js +451 -451
- package/lib/ws/handshake.js +125 -125
- package/lib/ws/index.js +14 -14
- package/lib/ws/room.js +223 -223
- package/package.json +73 -73
- package/types/app.d.ts +223 -223
- package/types/auth.d.ts +520 -520
- package/types/body.d.ts +14 -0
- package/types/cli.d.ts +2 -0
- package/types/cluster.d.ts +75 -75
- package/types/env.d.ts +80 -80
- package/types/errors.d.ts +316 -316
- package/types/fetch.d.ts +43 -43
- package/types/grpc.d.ts +432 -432
- package/types/index.d.ts +384 -384
- package/types/lifecycle.d.ts +60 -60
- package/types/middleware.d.ts +320 -320
- package/types/observe.d.ts +304 -304
- package/types/orm.d.ts +1887 -1887
- package/types/request.d.ts +109 -109
- package/types/response.d.ts +157 -157
- package/types/router.d.ts +78 -78
- package/types/sse.d.ts +78 -78
- package/types/websocket.d.ts +126 -126
package/README.md
CHANGED
|
@@ -1,443 +1,460 @@
|
|
|
1
|
-
<p align="center">
|
|
2
|
-
<img src="website-docs/public/icons/logo-animated.svg" alt="zero-server logo" width="300" height="300">
|
|
3
|
-
</p>
|
|
4
|
-
|
|
5
|
-
<h1 align="center">zero-server</h1>
|
|
6
|
-
|
|
7
|
-
<p align="center">
|
|
8
|
-
<a href="https://www.npmjs.com/package/@zero-server/sdk"><img src="https://img.shields.io/badge/%40zero--server%2Fsdk-000?style=flat-square&logo=npm&logoColor=white" alt="@zero-server/sdk"></a>
|
|
9
|
-
<a href="https://www.npmjs.com/package/@zero-server/sdk"><img src="https://img.shields.io/npm/v/%40zero-server%2Fsdk?style=flat-square&logo=npm&logoColor=white&label=&color=00d8e0" alt="npm version"></a>
|
|
10
|
-
<a href="https://www.npmjs.com/package/@zero-server/sdk"><img src="https://img.shields.io/npm/dm/%40zero-server%2Fsdk?style=flat-square&logo=npm&logoColor=white&label=downloads&color=ff6b35" alt="npm downloads"></a>
|
|
11
|
-
</p>
|
|
12
|
-
|
|
13
|
-
<p align="center">
|
|
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-
|
|
17
|
-
<a href="https://z-server.dev"><img src="https://img.shields.io/badge/docs-z--server.
|
|
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
|
-
<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
|
-
</p>
|
|
21
|
-
|
|
22
|
-
> **Zero-dependency backend framework for Node.js — routing, ORM, auth, WebSocket, SSE, observability, and 20+ middleware from a single `require`.**
|
|
23
|
-
|
|
24
|
-
<p align="center">
|
|
25
|
-
<strong>
|
|
26
|
-
<a href="https://z-server.dev">📖 Full Documentation & Live Playground →</a>
|
|
27
|
-
</strong>
|
|
28
|
-
</p>
|
|
29
|
-
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
## Install
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
npm install @zero-server/sdk
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
Requires Node.js 18+. No external dependencies — everything is built on Node.js core APIs.
|
|
39
|
-
|
|
40
|
-
### Or install only what you need (scoped packages)
|
|
41
|
-
|
|
42
|
-
`@zero-server/sdk` is the meta-package that re-exports every module. If you want a smaller install footprint, every section of the SDK is also published as its own scoped package and re-exports just that surface from the SDK:
|
|
43
|
-
|
|
44
|
-
| Package | Surface |
|
|
45
|
-
|---|---|
|
|
46
|
-
| `@zero-server/core` | `createApp`, `Router`, `Request`, `Response` |
|
|
47
|
-
| `@zero-server/body` | `json`, `urlencoded`, `text`, `raw`, `multipart` |
|
|
48
|
-
| `@zero-server/middleware` | `cors`, `helmet`, `compress`, `rateLimit`, `logger`, `timeout`, `requestId`, `cookieParser`, `csrf`, `validate`, `errorHandler`, `static` |
|
|
49
|
-
| `@zero-server/auth` | `jwt`, `session`, `oauth`, `authorize`, `twoFactor`, `webauthn`, `trustedDevice`, `enrollment` |
|
|
50
|
-
| `@zero-server/orm` | `Database`, `Model`, `Query`, `TYPES`, migrations, seeders, replicas, search, geo, tenancy, audit |
|
|
51
|
-
| `@zero-server/realtime` | `WebSocketConnection`, `WebSocketPool`, `SSEStream` |
|
|
52
|
-
| `@zero-server/grpc` | gRPC server, client, codec, status, metadata, framing, health, reflection, balancer |
|
|
53
|
-
| `@zero-server/observe` | `MetricsRegistry`, `Tracer`, structured `Logger`, health checks |
|
|
54
|
-
| `@zero-server/lifecycle` | `LifecycleManager`, `ClusterManager`, `clusterize` |
|
|
55
|
-
| `@zero-server/env` | typed `.env` loader |
|
|
56
|
-
| `@zero-server/fetch` | server-side `fetch` client |
|
|
57
|
-
| `@zero-server/errors` | every typed `HttpError` class plus ORM/framework errors |
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
app.
|
|
75
|
-
app.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
| `
|
|
98
|
-
| `
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
105
|
-
| `
|
|
106
|
-
| `
|
|
107
|
-
| `
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
- **
|
|
115
|
-
- **
|
|
116
|
-
- **
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
static
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
|
150
|
-
|
|
|
151
|
-
|
|
|
152
|
-
|
|
|
153
|
-
|
|
|
154
|
-
|
|
|
155
|
-
|
|
|
156
|
-
|
|
|
157
|
-
|
|
|
158
|
-
|
|
|
159
|
-
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
- **
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
app.
|
|
180
|
-
app.
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
- **
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
- **
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
npx zh migrate
|
|
224
|
-
npx zh migrate:
|
|
225
|
-
npx zh
|
|
226
|
-
npx zh
|
|
227
|
-
npx zh make:
|
|
228
|
-
npx zh make:
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
const
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
app.use(
|
|
285
|
-
app.use(
|
|
286
|
-
app.use(
|
|
287
|
-
app.use(
|
|
288
|
-
app.use(
|
|
289
|
-
app.use(
|
|
290
|
-
app.use(
|
|
291
|
-
app.use(
|
|
292
|
-
app.use(
|
|
293
|
-
app.use(
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
app.
|
|
298
|
-
app.
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
api
|
|
303
|
-
api.get('/
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
pool.
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
sse.
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
})
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="website-docs/public/icons/logo-animated.svg" alt="zero-server logo" width="300" height="300">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">zero-server</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://www.npmjs.com/package/@zero-server/sdk"><img src="https://img.shields.io/badge/%40zero--server%2Fsdk-000?style=flat-square&logo=npm&logoColor=white" alt="@zero-server/sdk"></a>
|
|
9
|
+
<a href="https://www.npmjs.com/package/@zero-server/sdk"><img src="https://img.shields.io/npm/v/%40zero-server%2Fsdk?style=flat-square&logo=npm&logoColor=white&label=&color=00d8e0" alt="npm version"></a>
|
|
10
|
+
<a href="https://www.npmjs.com/package/@zero-server/sdk"><img src="https://img.shields.io/npm/dm/%40zero-server%2Fsdk?style=flat-square&logo=npm&logoColor=white&label=downloads&color=ff6b35" alt="npm downloads"></a>
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<p align="center">
|
|
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-7443%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-55.35%25-yellow?style=flat-square&logo=vitest&logoColor=white" alt="coverage"></a>
|
|
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
|
+
<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
|
+
<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
|
+
</p>
|
|
21
|
+
|
|
22
|
+
> **Zero-dependency backend framework for Node.js — routing, ORM, auth, WebSocket, SSE, observability, and 20+ middleware from a single `require`.**
|
|
23
|
+
|
|
24
|
+
<p align="center">
|
|
25
|
+
<strong>
|
|
26
|
+
<a href="https://z-server.dev">📖 Full Documentation & Live Playground →</a>
|
|
27
|
+
</strong>
|
|
28
|
+
</p>
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install @zero-server/sdk
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Requires Node.js 18+. No external dependencies — everything is built on Node.js core APIs.
|
|
39
|
+
|
|
40
|
+
### Or install only what you need (scoped packages)
|
|
41
|
+
|
|
42
|
+
`@zero-server/sdk` is the meta-package that re-exports every module. If you want a smaller install footprint, every section of the SDK is also published as its own scoped package and re-exports just that surface from the SDK:
|
|
43
|
+
|
|
44
|
+
| Package | Surface |
|
|
45
|
+
|---|---|
|
|
46
|
+
| `@zero-server/core` | `createApp`, `Router`, `Request`, `Response` |
|
|
47
|
+
| `@zero-server/body` | `json`, `urlencoded`, `text`, `raw`, `multipart` |
|
|
48
|
+
| `@zero-server/middleware` | `cors`, `helmet`, `compress`, `rateLimit`, `logger`, `timeout`, `requestId`, `cookieParser`, `csrf`, `validate`, `errorHandler`, `static` |
|
|
49
|
+
| `@zero-server/auth` | `jwt`, `session`, `oauth`, `authorize`, `twoFactor`, `webauthn`, `trustedDevice`, `enrollment` |
|
|
50
|
+
| `@zero-server/orm` | `Database`, `Model`, `Query`, `TYPES`, migrations, seeders, replicas, search, geo, tenancy, audit |
|
|
51
|
+
| `@zero-server/realtime` | `WebSocketConnection`, `WebSocketPool`, `SSEStream` |
|
|
52
|
+
| `@zero-server/grpc` | gRPC server, client, codec, status, metadata, framing, health, reflection, balancer |
|
|
53
|
+
| `@zero-server/observe` | `MetricsRegistry`, `Tracer`, structured `Logger`, health checks |
|
|
54
|
+
| `@zero-server/lifecycle` | `LifecycleManager`, `ClusterManager`, `clusterize` |
|
|
55
|
+
| `@zero-server/env` | typed `.env` loader |
|
|
56
|
+
| `@zero-server/fetch` | server-side `fetch` client |
|
|
57
|
+
| `@zero-server/errors` | every typed `HttpError` class plus ORM/framework errors |
|
|
58
|
+
| `@zero-server/cli` | programmatic `CLI` / `runCLI` entry points for `zh` / `zs` |
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
npm install @zero-server/core @zero-server/body @zero-server/middleware
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
> All scoped packages depend on `@zero-server/sdk` and pin to the same version, so mixing-and-matching is safe.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Quick Start
|
|
69
|
+
|
|
70
|
+
```js
|
|
71
|
+
const { createApp, json } = require('@zero-server/sdk')
|
|
72
|
+
const app = createApp()
|
|
73
|
+
|
|
74
|
+
app.use(json())
|
|
75
|
+
app.post('/echo', (req, res) => res.json({ received: req.body }))
|
|
76
|
+
app.listen(3000, () => console.log('Listening on :3000'))
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Features
|
|
82
|
+
|
|
83
|
+
### Routing
|
|
84
|
+
|
|
85
|
+
`get`, `post`, `put`, `delete`, `patch`, `head`, `options`, `all`, plus `Router()` sub-apps with `use()` mounting. Route chaining via `chain(path)`, route grouping via `group(prefix, ...mw, cb)`, wildcard & parameter patterns, and `param()` pre-processing. Full route introspection with `routes()`.
|
|
86
|
+
|
|
87
|
+
### Body Parsers
|
|
88
|
+
|
|
89
|
+
`json()`, `urlencoded()`, `text()`, `raw()`, and `multipart()` with streaming file uploads, size limits, and progress tracking.
|
|
90
|
+
|
|
91
|
+
### Middleware
|
|
92
|
+
|
|
93
|
+
20+ built-in middleware — all zero-dependency:
|
|
94
|
+
|
|
95
|
+
| Middleware | Purpose |
|
|
96
|
+
|---|---|
|
|
97
|
+
| `cors()` | Cross-origin resource sharing |
|
|
98
|
+
| `helmet()` | Security headers |
|
|
99
|
+
| `compress()` | Gzip, Brotli, and deflate compression |
|
|
100
|
+
| `rateLimit()` | Per-IP request throttling |
|
|
101
|
+
| `logger()` | Request logging with timing and colors |
|
|
102
|
+
| `timeout()` | Request timeout enforcement |
|
|
103
|
+
| `requestId()` | Unique request IDs |
|
|
104
|
+
| `cookieParser()` | Cookie parsing with signed cookie support |
|
|
105
|
+
| `csrf()` | CSRF token protection |
|
|
106
|
+
| `validate()` | Schema-based request validation |
|
|
107
|
+
| `errorHandler()` | Centralized error handling |
|
|
108
|
+
| `static()` | Static file serving with ETags and HTTP/2 push |
|
|
109
|
+
|
|
110
|
+
### Authentication & Authorization
|
|
111
|
+
|
|
112
|
+
Full auth stack with no external libraries:
|
|
113
|
+
|
|
114
|
+
- **JWT** — `jwt()` middleware, `jwtSign()`, `jwtVerify()`, `jwtDecode()`, JWKS key sets, access/refresh token pairs
|
|
115
|
+
- **Sessions** — `session()` middleware with in-memory store (pluggable)
|
|
116
|
+
- **OAuth 2.0** — `oauth()` middleware with PKCE, pre-configured providers (Google, GitHub, Microsoft, etc.)
|
|
117
|
+
- **Authorization** — `authorize()` policies, `can()` / `canAny()` permission checks, `gate()` middleware
|
|
118
|
+
|
|
119
|
+
### ORM & Database
|
|
120
|
+
|
|
121
|
+
Full-featured ORM with 7 adapters — memory, JSON file, SQLite, MySQL, PostgreSQL, MongoDB, and Redis:
|
|
122
|
+
|
|
123
|
+
```js
|
|
124
|
+
const { Database, Model, TYPES } = require('@zero-server/sdk')
|
|
125
|
+
|
|
126
|
+
const db = Database.connect('sqlite', { filename: 'app.db' })
|
|
127
|
+
|
|
128
|
+
class User extends Model {
|
|
129
|
+
static table = 'users'
|
|
130
|
+
static schema = {
|
|
131
|
+
name: { type: TYPES.STRING, required: true },
|
|
132
|
+
email: { type: TYPES.STRING, unique: true },
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
db.register(User)
|
|
137
|
+
await db.sync()
|
|
138
|
+
|
|
139
|
+
await User.create({ name: 'Alice', email: 'alice@example.com' })
|
|
140
|
+
const users = await User.find({ name: 'Alice' })
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Query builder** — `where()`, `select()`, `orderBy()`, `limit()`, `offset()`, `join()`, `groupBy()`, `having()`, `paginate()`, `findOrCreate()`
|
|
144
|
+
|
|
145
|
+
**Advanced ORM features:**
|
|
146
|
+
|
|
147
|
+
| Feature | Description |
|
|
148
|
+
|---|---|
|
|
149
|
+
| Migrations | `Migrator` with up/down, rollback, and status tracking |
|
|
150
|
+
| Seeding | `Seeder`, `Factory`, and `Fake` for test data generation |
|
|
151
|
+
| Query caching | In-memory LRU cache with TTL and write-through invalidation |
|
|
152
|
+
| Read replicas | `ReplicaManager` with automatic primary/replica routing |
|
|
153
|
+
| Full-text search | `FullTextSearch` with indexing and ranked results |
|
|
154
|
+
| Geo queries | `GeoQuery` with distance, bounding box, and nearest-neighbor |
|
|
155
|
+
| Multi-tenancy | `TenantManager` with isolated per-tenant scoping |
|
|
156
|
+
| Audit logging | `AuditLog` for change tracking with diffs and user attribution |
|
|
157
|
+
| Schema snapshots | EF Core-style snapshot diffing with auto-generated migrations |
|
|
158
|
+
| Query profiler | N+1 detection, slow query tracking, and execution analysis |
|
|
159
|
+
| Views & procedures | `DatabaseView`, `StoredProcedure`, `StoredFunction`, `TriggerManager` |
|
|
160
|
+
| Plugins | `PluginManager` for extending ORM behavior |
|
|
161
|
+
|
|
162
|
+
### Real-Time
|
|
163
|
+
|
|
164
|
+
- **WebSocket** — `app.ws(path, handler)` with RFC 6455, `WebSocketPool` for rooms, broadcasting, and sub-protocols
|
|
165
|
+
- **Server-Sent Events** — `res.sse()` with auto-IDs, named events, and keep-alive
|
|
166
|
+
|
|
167
|
+
### Observability
|
|
168
|
+
|
|
169
|
+
Built-in Prometheus metrics, health checks, distributed tracing, and structured logging — zero dependencies.
|
|
170
|
+
|
|
171
|
+
```js
|
|
172
|
+
const { createApp, metricsMiddleware } = require('@zero-server/sdk')
|
|
173
|
+
const app = createApp()
|
|
174
|
+
|
|
175
|
+
// Auto-instrument all HTTP requests (counters, histograms, active connections)
|
|
176
|
+
app.use(metricsMiddleware({ registry: app.metrics() }))
|
|
177
|
+
|
|
178
|
+
// Expose endpoints
|
|
179
|
+
app.metricsEndpoint() // GET /metrics (Prometheus scrape target)
|
|
180
|
+
app.health() // GET /healthz (liveness probe)
|
|
181
|
+
app.ready() // GET /readyz (readiness probe)
|
|
182
|
+
|
|
183
|
+
// Custom metrics
|
|
184
|
+
const logins = app.metrics().counter({
|
|
185
|
+
name: 'user_logins_total',
|
|
186
|
+
help: 'Total login attempts',
|
|
187
|
+
labels: ['provider'],
|
|
188
|
+
})
|
|
189
|
+
logins.inc({ provider: 'github' })
|
|
190
|
+
|
|
191
|
+
app.listen(3000)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Scrape with Prometheus** — create a `prometheus.yml`:
|
|
195
|
+
|
|
196
|
+
```yaml
|
|
197
|
+
scrape_configs:
|
|
198
|
+
- job_name: 'my-app'
|
|
199
|
+
scrape_interval: 5s
|
|
200
|
+
static_configs:
|
|
201
|
+
- targets: ['localhost:3000']
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
docker run -d -p 9090:9090 -v ./prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus
|
|
206
|
+
# Open http://localhost:9090 → Graph → query http_requests_total
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**Also includes:**
|
|
210
|
+
- **Distributed tracing** — `Tracer` and `Span` with W3C Trace Context (`traceparent` propagation), `instrumentFetch()` for outgoing requests
|
|
211
|
+
- **Structured logging** — `Logger` with levels, JSON output, and namespaced `debug()` logger
|
|
212
|
+
|
|
213
|
+
### Lifecycle & Clustering
|
|
214
|
+
|
|
215
|
+
- **Graceful shutdown** — signal handlers (SIGTERM/SIGINT), in-flight request draining, automatic WebSocket/SSE/database cleanup
|
|
216
|
+
- **Clustering** — `clusterize()` for multi-worker processes with auto-respawn and exponential backoff
|
|
217
|
+
|
|
218
|
+
### CLI
|
|
219
|
+
|
|
220
|
+
Scaffolding and database management via `npx zh`:
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
npx zh migrate # run pending migrations
|
|
224
|
+
npx zh migrate:rollback # rollback last migration
|
|
225
|
+
npx zh migrate:status # show migration status
|
|
226
|
+
npx zh seed # run seeders
|
|
227
|
+
npx zh make:model User # scaffold a model
|
|
228
|
+
npx zh make:migration name # create migration file
|
|
229
|
+
npx zh make:seeder User # create seeder file
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Environment Config
|
|
233
|
+
|
|
234
|
+
Typed `.env` loader with schema validation, multi-file support (`.env`, `.env.local`, `.env.{NODE_ENV}`), variable interpolation, and type coercion (string, number, boolean, integer, array, json, url, port, enum).
|
|
235
|
+
|
|
236
|
+
### HTTP Client
|
|
237
|
+
|
|
238
|
+
Built-in `fetch()` with HTTPS/mTLS support, timeouts, `AbortSignal`, progress callbacks, and JSON/form/stream bodies.
|
|
239
|
+
|
|
240
|
+
### HTTPS & HTTP/2
|
|
241
|
+
|
|
242
|
+
```js
|
|
243
|
+
app.listen(443, {
|
|
244
|
+
key: fs.readFileSync('key.pem'),
|
|
245
|
+
cert: fs.readFileSync('cert.pem'),
|
|
246
|
+
}, () => console.log('HTTPS on 443'))
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Native HTTP/2 with automatic HTTP/1.1 fallback. `req.secure`, `req.protocol`, `ws.secure`, and `sse.secure` everywhere.
|
|
250
|
+
|
|
251
|
+
### Error Handling
|
|
252
|
+
|
|
253
|
+
20+ typed error classes (`NotFoundError`, `ValidationError`, `ForbiddenError`, `PayloadTooLargeError`, `DatabaseError`, `MigrationError`, etc.) plus `createError(status, message)` factory and `isHttpError()` check. Built-in CRLF injection prevention, prototype pollution filtering, path traversal guards, and filename sanitization.
|
|
254
|
+
|
|
255
|
+
### TypeScript
|
|
256
|
+
|
|
257
|
+
Full type definitions for every API, middleware option, ORM model, auth flow, and plugin interface.
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Production Example
|
|
262
|
+
|
|
263
|
+
```js
|
|
264
|
+
const path = require('path')
|
|
265
|
+
const {
|
|
266
|
+
createApp, Router, cors, json, urlencoded, compress,
|
|
267
|
+
helmet, timeout, requestId, cookieParser, logger,
|
|
268
|
+
static: serveStatic, rateLimit, jwt, session,
|
|
269
|
+
Database, Model, TYPES, env, clusterize,
|
|
270
|
+
WebSocketPool,
|
|
271
|
+
} = require('@zero-server/sdk')
|
|
272
|
+
|
|
273
|
+
env.load({
|
|
274
|
+
PORT: { type: 'port', default: 3000 },
|
|
275
|
+
JWT_SECRET: { type: 'string', required: true },
|
|
276
|
+
DB_PATH: { type: 'string', default: './data.db' },
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
clusterize(() => {
|
|
280
|
+
const app = createApp()
|
|
281
|
+
const db = Database.connect('sqlite', { filename: env.DB_PATH })
|
|
282
|
+
|
|
283
|
+
// Middleware stack
|
|
284
|
+
app.use(helmet())
|
|
285
|
+
app.use(logger())
|
|
286
|
+
app.use(cors())
|
|
287
|
+
app.use(compress())
|
|
288
|
+
app.use(timeout(30_000))
|
|
289
|
+
app.use(rateLimit())
|
|
290
|
+
app.use(cookieParser())
|
|
291
|
+
app.use(session({ secret: env.JWT_SECRET }))
|
|
292
|
+
app.use(json())
|
|
293
|
+
app.use(urlencoded())
|
|
294
|
+
app.use(serveStatic(path.join(__dirname, 'public')))
|
|
295
|
+
|
|
296
|
+
// Observability
|
|
297
|
+
app.health()
|
|
298
|
+
app.ready()
|
|
299
|
+
app.metricsEndpoint()
|
|
300
|
+
|
|
301
|
+
// API routes
|
|
302
|
+
const api = Router()
|
|
303
|
+
api.get('/health', (req, res) => res.json({ status: 'ok' }))
|
|
304
|
+
api.get('/users/:id', jwt({ secret: env.JWT_SECRET }), (req, res) => {
|
|
305
|
+
res.json({ id: req.params.id, user: req.user })
|
|
306
|
+
})
|
|
307
|
+
app.use('/api', api)
|
|
308
|
+
|
|
309
|
+
// WebSocket
|
|
310
|
+
const pool = new WebSocketPool()
|
|
311
|
+
app.ws('/chat', (ws) => {
|
|
312
|
+
pool.add(ws)
|
|
313
|
+
pool.join(ws, 'lobby')
|
|
314
|
+
ws.on('message', msg => pool.toRoom('lobby', msg, ws))
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
// SSE
|
|
318
|
+
app.get('/events', (req, res) => {
|
|
319
|
+
const sse = res.sse({ retry: 3000, autoId: true })
|
|
320
|
+
sse.send('connected')
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
app.listen(env.PORT, () => console.log(`Worker ${process.pid} on :${env.PORT}`))
|
|
324
|
+
})
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Exports
|
|
330
|
+
|
|
331
|
+
All exports from the package root:
|
|
332
|
+
|
|
333
|
+
```js
|
|
334
|
+
const {
|
|
335
|
+
// Core
|
|
336
|
+
createApp, Router, version,
|
|
337
|
+
|
|
338
|
+
// Body parsers
|
|
339
|
+
json, urlencoded, text, raw, multipart,
|
|
340
|
+
|
|
341
|
+
// Middleware
|
|
342
|
+
cors, helmet, compress, rateLimit, logger,
|
|
343
|
+
timeout, requestId, cookieParser, csrf,
|
|
344
|
+
validate, errorHandler, static: serveStatic,
|
|
345
|
+
|
|
346
|
+
// Auth
|
|
347
|
+
jwt, jwtSign, jwtVerify, jwtDecode, jwks, tokenPair,
|
|
348
|
+
session, Session, MemoryStore,
|
|
349
|
+
oauth, generatePKCE, generateState, OAUTH_PROVIDERS,
|
|
350
|
+
authorize, can, canAny, Policy, gate,
|
|
351
|
+
|
|
352
|
+
// ORM
|
|
353
|
+
Database, Model, TYPES, Query,
|
|
354
|
+
Migrator, defineMigration,
|
|
355
|
+
Seeder, SeederRunner, Factory, Fake,
|
|
356
|
+
QueryCache, QueryProfiler, ReplicaManager,
|
|
357
|
+
FullTextSearch, GeoQuery, TenantManager, AuditLog,
|
|
358
|
+
DatabaseView, StoredProcedure, StoredFunction, TriggerManager,
|
|
359
|
+
PluginManager, buildSnapshot, diffSnapshots,
|
|
360
|
+
|
|
361
|
+
// Observability
|
|
362
|
+
Logger, structuredLogger,
|
|
363
|
+
Counter, Gauge, Histogram, MetricsRegistry,
|
|
364
|
+
metricsMiddleware, metricsEndpoint,
|
|
365
|
+
Span, Tracer, tracingMiddleware, instrumentFetch,
|
|
366
|
+
healthCheck, memoryCheck, eventLoopCheck, diskSpaceCheck,
|
|
367
|
+
|
|
368
|
+
// Real-time
|
|
369
|
+
WebSocketConnection, WebSocketPool, SSEStream,
|
|
370
|
+
|
|
371
|
+
// gRPC
|
|
372
|
+
GrpcStatus, grpcToHttp, grpcStatusName, GRPC_STATUS_NAMES,
|
|
373
|
+
GrpcMetadata, ProtoWriter, ProtoReader, protoEncode, protoDecode,
|
|
374
|
+
parseProto, parseProtoFile, frameEncode, FrameParser,
|
|
375
|
+
GrpcServiceRegistry, GrpcClient,
|
|
376
|
+
GrpcHealthService, GrpcServingStatus, GrpcReflectionService,
|
|
377
|
+
GrpcLoadBalancer, GrpcSubchannel, GrpcSubchannelState,
|
|
378
|
+
ChannelCredentials, createRotatingCredentials, watchProto,
|
|
379
|
+
|
|
380
|
+
// Utilities
|
|
381
|
+
fetch, env, debug,
|
|
382
|
+
ClusterManager, clusterize,
|
|
383
|
+
LifecycleManager, LIFECYCLE_STATE,
|
|
384
|
+
|
|
385
|
+
// Errors
|
|
386
|
+
HttpError, BadRequestError, UnauthorizedError,
|
|
387
|
+
ForbiddenError, NotFoundError, ValidationError,
|
|
388
|
+
ConflictError, PayloadTooLargeError, TooManyRequestsError,
|
|
389
|
+
TimeoutError, DatabaseError, MigrationError,
|
|
390
|
+
createError, isHttpError,
|
|
391
|
+
|
|
392
|
+
// CLI
|
|
393
|
+
CLI, runCLI,
|
|
394
|
+
} = require('@zero-server/sdk')
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## Documentation
|
|
400
|
+
|
|
401
|
+
| Resource | Description |
|
|
402
|
+
|---|---|
|
|
403
|
+
| **[z-server.dev](https://z-server.dev)** | Interactive documentation with live playground, search, and examples |
|
|
404
|
+
| **[API.md](API.md)** | Full API reference with tables, examples, and options for every export |
|
|
405
|
+
|
|
406
|
+
### Run docs locally
|
|
407
|
+
|
|
408
|
+
```bash
|
|
409
|
+
cp website-docs/.env.example website-docs/.env
|
|
410
|
+
npm run docs
|
|
411
|
+
# open http://localhost:7273
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
## File Layout
|
|
417
|
+
|
|
418
|
+
```
|
|
419
|
+
lib/
|
|
420
|
+
app.js — App class (middleware, routing, listen, ws upgrade, lifecycle)
|
|
421
|
+
auth/ — JWT, OAuth 2.0, sessions, MFA (TOTP/WebAuthn), authorization
|
|
422
|
+
body/ — body parsers (json, urlencoded, text, raw, multipart)
|
|
423
|
+
cli.js — CLI runner (migrate, seed, scaffold commands)
|
|
424
|
+
cluster.js — multi-worker clustering with auto-respawn
|
|
425
|
+
debug.js — namespaced debug logger
|
|
426
|
+
env/ — typed .env loader with schema validation
|
|
427
|
+
errors.js — 25+ HttpError / framework / ORM error classes
|
|
428
|
+
fetch/ — HTTP/HTTPS client (mTLS, AbortSignal, retries)
|
|
429
|
+
grpc/ — HTTP/2 gRPC stack: server, client, codec, framing,
|
|
430
|
+
status, metadata, health, reflection, balancer, watch
|
|
431
|
+
http/ — Request & Response wrappers
|
|
432
|
+
lifecycle.js — graceful shutdown and lifecycle management
|
|
433
|
+
middleware/ — cors, helmet, logger, rateLimit, compress, static, timeout,
|
|
434
|
+
requestId, cookieParser, csrf, validate, errorHandler
|
|
435
|
+
observe/ — Prometheus metrics, W3C tracing, health checks, structured logging
|
|
436
|
+
orm/ — Database, Model, Query, adapters, migrations, seeds, cache,
|
|
437
|
+
replicas, search, geo, tenancy, audit, views, procedures, plugins
|
|
438
|
+
router/ — Router with sub-app mounting and pattern matching
|
|
439
|
+
sse/ — SSE stream controller
|
|
440
|
+
ws/ — WebSocket connection, handshake, and room management
|
|
441
|
+
packages/ — generated scoped @zero-server/* re-exports (one dir per scope)
|
|
442
|
+
.tools/
|
|
443
|
+
scope-manifest.js — single source of truth for scoped packages & their surface
|
|
444
|
+
generate-package-stubs.js
|
|
445
|
+
generate-scope-docs.js
|
|
446
|
+
types/ — full TypeScript definitions
|
|
447
|
+
website-docs/ — live demo server, controllers, and playground UI
|
|
448
|
+
test/ — vitest test suite (7000+ tests, 95%+ coverage)
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
## Testing
|
|
452
|
+
|
|
453
|
+
```bash
|
|
454
|
+
npm test # vitest run (single pass)
|
|
455
|
+
npm run test:watch # vitest (watch mode)
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
## License
|
|
459
|
+
|
|
460
|
+
MIT
|