@zero-server/cli 0.9.6 → 0.9.8
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 +2 -2
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/lib/cli.js +43 -28
- package/package.json +5 -4
- package/types/body.d.ts +82 -14
- package/types/cli.d.ts +40 -2
- package/types/index.d.ts +19 -6
- package/types/middleware.d.ts +18 -72
- package/types/orm.d.ts +4 -13
- package/types/request.d.ts +3 -3
- package/types/webrtc.d.ts +501 -0
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @zero-server/cli
|
|
2
2
|
|
|
3
|
-
> Programmatic access to the `
|
|
3
|
+
> Programmatic access to the `zs` CLI.
|
|
4
4
|
|
|
5
|
-
Programmatic entry points for the bundled CLI (`
|
|
5
|
+
Programmatic entry points for the bundled CLI (`zs`): scaffolding, migrations, seeding, rollback, status. Useful when embedding the CLI inside your own tooling.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
package/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
// AUTO-GENERATED by .tools/generate-package-stubs.js
|
|
1
|
+
// AUTO-GENERATED by .tools/generate-package-stubs.js - edit .tools/scope-manifest.js and re-run `npm run packages:generate`.
|
|
2
2
|
export * from './types/cli';
|
package/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// AUTO-GENERATED by .tools/generate-package-stubs.js
|
|
1
|
+
// AUTO-GENERATED by .tools/generate-package-stubs.js - edit .tools/scope-manifest.js and re-run `npm run packages:generate`.
|
|
2
2
|
'use strict';
|
|
3
3
|
const lib = require("./lib/cli");
|
|
4
4
|
|
package/lib/cli.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* that exports your database adapter and connection settings.
|
|
10
10
|
*
|
|
11
11
|
* @example
|
|
12
|
-
* // zero.config.js
|
|
12
|
+
* // zero.config.js - required by all CLI commands except make:* and help
|
|
13
13
|
* module.exports = {
|
|
14
14
|
* adapter: 'sqlite',
|
|
15
15
|
* connection: { filename: './app.db' },
|
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
* };
|
|
19
19
|
*
|
|
20
20
|
* // Run via npx (no global install needed):
|
|
21
|
-
* // npx
|
|
22
|
-
* // npx
|
|
23
|
-
* // npx
|
|
24
|
-
* // npx
|
|
25
|
-
* // npx
|
|
26
|
-
* // npx
|
|
27
|
-
* // npx
|
|
21
|
+
* // npx zs migrate
|
|
22
|
+
* // npx zs migrate:rollback
|
|
23
|
+
* // npx zs migrate:status
|
|
24
|
+
* // npx zs seed
|
|
25
|
+
* // npx zs make:model User
|
|
26
|
+
* // npx zs make:migration create_posts
|
|
27
|
+
* // npx zs make:seeder Users
|
|
28
28
|
*
|
|
29
29
|
* // Or programmatically:
|
|
30
30
|
* const { runCLI } = require('@zero-server/sdk');
|
|
@@ -150,6 +150,15 @@ class CLI
|
|
|
150
150
|
*/
|
|
151
151
|
async run()
|
|
152
152
|
{
|
|
153
|
+
// WebRTC subcommands - delegate the whole `webrtc:*` namespace to the
|
|
154
|
+
// webrtc CLI module so the top-level dispatcher stays small.
|
|
155
|
+
if (typeof this.command === 'string' && this.command.startsWith('webrtc:'))
|
|
156
|
+
{
|
|
157
|
+
const { runWebRTCCommand } = require('@zero-server/webrtc');
|
|
158
|
+
await runWebRTCCommand(this.command.slice('webrtc:'.length), this.flags);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
153
162
|
const commands = {
|
|
154
163
|
'migrate': () => this._migrate(),
|
|
155
164
|
'migrate:rollback': () => this._rollback(),
|
|
@@ -206,7 +215,7 @@ class CLI
|
|
|
206
215
|
throw new Error(
|
|
207
216
|
'No configuration file found.\n' +
|
|
208
217
|
'Create a zero.config.js with database and migration settings.\n' +
|
|
209
|
-
'See "
|
|
218
|
+
'See "zs help" for examples.'
|
|
210
219
|
);
|
|
211
220
|
}
|
|
212
221
|
|
|
@@ -421,8 +430,8 @@ class CLI
|
|
|
421
430
|
const status = await migrator.status();
|
|
422
431
|
if (status.executed.includes(lastMigration.name))
|
|
423
432
|
{
|
|
424
|
-
console.error(red(`Cannot remove "${lastMigration.name}"
|
|
425
|
-
console.error(dim('Run "
|
|
433
|
+
console.error(red(`Cannot remove "${lastMigration.name}" - it has already been applied.`));
|
|
434
|
+
console.error(dim('Run "zs migrate:rollback" first, then try again.'));
|
|
426
435
|
process.exitCode = 1;
|
|
427
436
|
await db.close();
|
|
428
437
|
return;
|
|
@@ -510,7 +519,7 @@ class CLI
|
|
|
510
519
|
const name = this.args.find(a => !a.startsWith('-'));
|
|
511
520
|
if (!name)
|
|
512
521
|
{
|
|
513
|
-
console.error(red('Usage:
|
|
522
|
+
console.error(red('Usage: zs make:model <Name>'));
|
|
514
523
|
process.exitCode = 1;
|
|
515
524
|
return;
|
|
516
525
|
}
|
|
@@ -566,7 +575,7 @@ module.exports = ${className};
|
|
|
566
575
|
const name = this.args.find(a => !a.startsWith('-'));
|
|
567
576
|
if (!name)
|
|
568
577
|
{
|
|
569
|
-
console.error(red('Usage:
|
|
578
|
+
console.error(red('Usage: zs make:migration <name>'));
|
|
570
579
|
process.exitCode = 1;
|
|
571
580
|
return;
|
|
572
581
|
}
|
|
@@ -645,7 +654,7 @@ module.exports = {
|
|
|
645
654
|
|
|
646
655
|
if (hasNoChanges(changes))
|
|
647
656
|
{
|
|
648
|
-
console.log(dim('No schema changes detected
|
|
657
|
+
console.log(dim('No schema changes detected - nothing to migrate.'));
|
|
649
658
|
return;
|
|
650
659
|
}
|
|
651
660
|
|
|
@@ -692,7 +701,7 @@ module.exports = {
|
|
|
692
701
|
const name = this.args.find(a => !a.startsWith('-'));
|
|
693
702
|
if (!name)
|
|
694
703
|
{
|
|
695
|
-
console.error(red('Usage:
|
|
704
|
+
console.error(red('Usage: zs make:seeder <name>'));
|
|
696
705
|
process.exitCode = 1;
|
|
697
706
|
return;
|
|
698
707
|
}
|
|
@@ -742,9 +751,9 @@ module.exports = ${className};
|
|
|
742
751
|
_help()
|
|
743
752
|
{
|
|
744
753
|
console.log(`
|
|
745
|
-
${bold('
|
|
754
|
+
${bold('zs CLI')} - zero-server ORM tooling
|
|
746
755
|
|
|
747
|
-
${bold('Usage:')} npx
|
|
756
|
+
${bold('Usage:')} npx zs <command> [options]
|
|
748
757
|
|
|
749
758
|
${bold('Commands:')}
|
|
750
759
|
|
|
@@ -761,6 +770,12 @@ ${bold('Commands:')}
|
|
|
761
770
|
${cyan('make:migration')} <n> Auto-generate migration from model changes
|
|
762
771
|
${cyan('make:seeder')} <name> Scaffold a new seeder file
|
|
763
772
|
|
|
773
|
+
${cyan('webrtc:stun')} Run a STUN binding probe, print public addr
|
|
774
|
+
${cyan('webrtc:turn-creds')} Issue ephemeral TURN credentials
|
|
775
|
+
${cyan('webrtc:join-token')} Sign a signaling join token
|
|
776
|
+
${cyan('webrtc:verify-token')} Verify and decode a join token
|
|
777
|
+
${cyan('webrtc:help')} Show webrtc subcommand help
|
|
778
|
+
|
|
764
779
|
${cyan('help')} Show this help message
|
|
765
780
|
${cyan('version')} Show version
|
|
766
781
|
|
|
@@ -788,19 +803,19 @@ ${bold('Config file:')} ${dim('zero.config.js (or .zero-server.js / legacy .zero
|
|
|
788
803
|
|
|
789
804
|
${bold('Auto-generated migrations:')}
|
|
790
805
|
|
|
791
|
-
${dim('$')} npx
|
|
792
|
-
${dim('$')} npx
|
|
793
|
-
${dim('$')} npx
|
|
794
|
-
${dim('$')} npx
|
|
795
|
-
${dim('$')} npx
|
|
806
|
+
${dim('$')} npx zs make:migration create_users ${dim('# detects new User model → generates CREATE TABLE')}
|
|
807
|
+
${dim('$')} npx zs make:migration add_email ${dim('# detects new email column → generates ADD COLUMN')}
|
|
808
|
+
${dim('$')} npx zs make:migration --empty init ${dim('# blank migration (manual mode)')}
|
|
809
|
+
${dim('$')} npx zs migrate ${dim('# apply pending migrations')}
|
|
810
|
+
${dim('$')} npx zs migrate:remove ${dim('# undo last make:migration')}
|
|
796
811
|
|
|
797
812
|
${bold('Examples:')}
|
|
798
813
|
|
|
799
|
-
${dim('$')} npx
|
|
800
|
-
${dim('$')} npx
|
|
801
|
-
${dim('$')} npx
|
|
802
|
-
${dim('$')} npx
|
|
803
|
-
${dim('$')} npx
|
|
814
|
+
${dim('$')} npx zs make:model User ${dim('# creates models/User.js')}
|
|
815
|
+
${dim('$')} npx zs make:migration create_users ${dim('# auto-generates from models')}
|
|
816
|
+
${dim('$')} npx zs migrate ${dim('# runs all pending migrations')}
|
|
817
|
+
${dim('$')} npx zs migrate --config=db.config.js
|
|
818
|
+
${dim('$')} npx zs seed ${dim('# runs all seeders')}
|
|
804
819
|
`);
|
|
805
820
|
}
|
|
806
821
|
|
|
@@ -810,7 +825,7 @@ ${bold('Examples:')}
|
|
|
810
825
|
_version()
|
|
811
826
|
{
|
|
812
827
|
const pkg = require('../package.json');
|
|
813
|
-
console.log(`
|
|
828
|
+
console.log(`zs v${pkg.version} (zero-server)`);
|
|
814
829
|
}
|
|
815
830
|
}
|
|
816
831
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zero-server/cli",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "Programmatic access to the `
|
|
3
|
+
"version": "0.9.8",
|
|
4
|
+
"description": "Programmatic access to the `zs` CLI.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"zero-server",
|
|
7
7
|
"zero-server",
|
|
@@ -45,10 +45,11 @@
|
|
|
45
45
|
},
|
|
46
46
|
"sideEffects": false,
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@zero-server/orm": "0.9.
|
|
48
|
+
"@zero-server/orm": "0.9.8",
|
|
49
|
+
"@zero-server/webrtc": "0.9.8"
|
|
49
50
|
},
|
|
50
51
|
"peerDependencies": {
|
|
51
|
-
"@zero-server/sdk": ">=0.9.
|
|
52
|
+
"@zero-server/sdk": ">=0.9.8"
|
|
52
53
|
},
|
|
53
54
|
"peerDependenciesMeta": {
|
|
54
55
|
"@zero-server/sdk": {
|
package/types/body.d.ts
CHANGED
|
@@ -1,14 +1,82 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
// TypeScript declarations for the bundled body parsers
|
|
2
|
+
// (`json`, `urlencoded`, `text`, `raw`, `multipart`).
|
|
3
|
+
//
|
|
4
|
+
// These live in `lib/body/*` at runtime and are surfaced both via the
|
|
5
|
+
// top-level SDK and the standalone `@zero-server/body` scope. They are
|
|
6
|
+
// declared here (not in `./middleware`) so the body-parser package has
|
|
7
|
+
// a self-contained declaration file.
|
|
8
|
+
|
|
9
|
+
import { MiddlewareFunction } from './middleware';
|
|
10
|
+
import { Request } from './request';
|
|
11
|
+
import { Response } from './response';
|
|
12
|
+
|
|
13
|
+
export interface BodyParserOptions {
|
|
14
|
+
/** Max body size (e.g. '10kb', '1mb'). Default: '1mb'. */
|
|
15
|
+
limit?: string | number;
|
|
16
|
+
/** Content-Type(s) to match. Accepts a string, an array of strings, or a predicate function. */
|
|
17
|
+
type?: string | string[] | ((ct: string) => boolean);
|
|
18
|
+
/** Reject non-HTTPS requests with 403. */
|
|
19
|
+
requireSecure?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Verification callback invoked with the raw buffer before parsing.
|
|
22
|
+
* Throw an error to reject the request with 403.
|
|
23
|
+
* Useful for webhook signature verification (e.g. Stripe, GitHub).
|
|
24
|
+
*/
|
|
25
|
+
verify?: (req: Request, res: Response, buf: Buffer, encoding: string) => void;
|
|
26
|
+
/** Decompress gzip/deflate/br request bodies. Default: true. When false, compressed bodies return 415. */
|
|
27
|
+
inflate?: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface JsonParserOptions extends BodyParserOptions {
|
|
31
|
+
/** JSON.parse reviver function. */
|
|
32
|
+
reviver?: (key: string, value: any) => any;
|
|
33
|
+
/** Reject non-object/array roots. Default: true. */
|
|
34
|
+
strict?: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface UrlencodedParserOptions extends BodyParserOptions {
|
|
38
|
+
/** Enable nested bracket parsing. Default: false. */
|
|
39
|
+
extended?: boolean;
|
|
40
|
+
/** Max number of parameters. Default: 1000. Prevents parameter flooding DoS. */
|
|
41
|
+
parameterLimit?: number;
|
|
42
|
+
/** Max nesting depth for bracket syntax. Default: 32. Prevents deep-nesting DoS. */
|
|
43
|
+
depth?: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface TextParserOptions extends BodyParserOptions {
|
|
47
|
+
/** Fallback character encoding when Content-Type has no charset. Default: 'utf8'. */
|
|
48
|
+
encoding?: BufferEncoding;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface MultipartOptions {
|
|
52
|
+
/** Upload directory (default: OS temp). */
|
|
53
|
+
dir?: string;
|
|
54
|
+
/** Maximum size per file in bytes. */
|
|
55
|
+
maxFileSize?: number;
|
|
56
|
+
/** Reject non-HTTPS requests with 403. */
|
|
57
|
+
requireSecure?: boolean;
|
|
58
|
+
/** Maximum number of non-file fields. Default: 1000. */
|
|
59
|
+
maxFields?: number;
|
|
60
|
+
/** Maximum number of uploaded files. Default: 10. */
|
|
61
|
+
maxFiles?: number;
|
|
62
|
+
/** Maximum size of a single field value in bytes. Default: 1 MB. */
|
|
63
|
+
maxFieldSize?: number;
|
|
64
|
+
/** Whitelist of allowed MIME types for uploaded files (e.g. ['image/png', 'image/jpeg']). */
|
|
65
|
+
allowedMimeTypes?: string[];
|
|
66
|
+
/** Maximum combined size of all uploaded files in bytes. */
|
|
67
|
+
maxTotalSize?: number;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface MultipartFile {
|
|
71
|
+
originalFilename: string;
|
|
72
|
+
storedName: string;
|
|
73
|
+
path: string;
|
|
74
|
+
contentType: string;
|
|
75
|
+
size: number;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function json(options?: JsonParserOptions): MiddlewareFunction;
|
|
79
|
+
export function urlencoded(options?: UrlencodedParserOptions): MiddlewareFunction;
|
|
80
|
+
export function text(options?: TextParserOptions): MiddlewareFunction;
|
|
81
|
+
export function raw(options?: BodyParserOptions): MiddlewareFunction;
|
|
82
|
+
export function multipart(options?: MultipartOptions): MiddlewareFunction;
|
package/types/cli.d.ts
CHANGED
|
@@ -1,2 +1,40 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
1
|
+
// TypeScript declarations for the bundled CLI runner (`zs` / `zh`).
|
|
2
|
+
//
|
|
3
|
+
// The CLI lives in `lib/cli.js` and is published both as the `zs` /
|
|
4
|
+
// `zh` bin scripts and as a programmatic API on the SDK. It dispatches
|
|
5
|
+
// ORM subcommands (`migrate`, `seed`, `make:*`) to `@zero-server/orm`
|
|
6
|
+
// and `webrtc:*` subcommands to `@zero-server/webrtc`, but the runner
|
|
7
|
+
// itself is scope-neutral - hence its own declaration file.
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* CLI runner for the bundled `zs` command.
|
|
11
|
+
*
|
|
12
|
+
* Parses `process.argv`-style input, resolves a config file
|
|
13
|
+
* (`zero.config.js` / `.zero-server.js` / `.zero-http.js`), and
|
|
14
|
+
* dispatches to the matching subcommand handler.
|
|
15
|
+
*/
|
|
16
|
+
export class CLI {
|
|
17
|
+
constructor(argv?: string[]);
|
|
18
|
+
|
|
19
|
+
/** The first positional argument (subcommand name). Defaults to `"help"`. */
|
|
20
|
+
readonly command: string;
|
|
21
|
+
|
|
22
|
+
/** Remaining positional arguments after the subcommand. */
|
|
23
|
+
readonly args: string[];
|
|
24
|
+
|
|
25
|
+
/** Parsed `--flag=value` and `-f value` pairs. */
|
|
26
|
+
readonly flags: Map<string, string>;
|
|
27
|
+
|
|
28
|
+
/** Execute the parsed command. Sets `process.exitCode` on failure. */
|
|
29
|
+
run(): Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* One-shot helper: `new CLI(argv).run()`.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* const { runCLI } = require('@zero-server/sdk');
|
|
37
|
+
* await runCLI(['migrate']);
|
|
38
|
+
* await runCLI(['make:model', 'User', '--dir=src/models']);
|
|
39
|
+
*/
|
|
40
|
+
export function runCLI(argv?: string[]): Promise<void>;
|
package/types/index.d.ts
CHANGED
|
@@ -11,6 +11,18 @@ export { RouterInstance, RouteChain, RouteEntry, RouteInfo, RouteOptions, RouteH
|
|
|
11
11
|
export { Request, RangeResult } from './request';
|
|
12
12
|
export { Response, SendFileOptions, CookieOptions, PushOptions } from './response';
|
|
13
13
|
export { SSEOptions, SSEStream } from './sse';
|
|
14
|
+
export {
|
|
15
|
+
createWebRTC, SignalingHub, Room as WebRTCRoom, Peer as WebRTCPeer,
|
|
16
|
+
parseSdp, stringifySdp, parseCandidate, stringifyCandidate,
|
|
17
|
+
stunBinding, encodeBindingRequest, decodeMessage,
|
|
18
|
+
encodeXorMappedAddress, decodeXorMappedAddress,
|
|
19
|
+
STUN_MAGIC_COOKIE, STUN_METHOD, STUN_CLASS, STUN_ATTR,
|
|
20
|
+
issueTurnCredentials, TurnServer, SfuAdapter,
|
|
21
|
+
signJoinToken, verifyJoinToken,
|
|
22
|
+
WebRTCOptions, RoomOptions as WebRTCRoomOptions, PeerInfo, SignalingMessage,
|
|
23
|
+
IceServerConfig, TurnCredentials, IssueTurnCredentialsOptions, ClusterAdapter as WebRTCClusterAdapter,
|
|
24
|
+
WebRTCError, SignalingError, IceError, TurnError, SdpError,
|
|
25
|
+
} from './webrtc';
|
|
14
26
|
export { LifecycleManager, LifecycleState, LIFECYCLE_STATE } from './lifecycle';
|
|
15
27
|
export { ClusterManager, ClusterOptions, cluster } from './cluster';
|
|
16
28
|
export {
|
|
@@ -85,8 +97,8 @@ export {
|
|
|
85
97
|
StoredProcedure, StoredProcedureOptions, ProcedureParam,
|
|
86
98
|
StoredFunction, StoredFunctionOptions,
|
|
87
99
|
TriggerManager, TriggerDefinition,
|
|
88
|
-
CLI, runCLI,
|
|
89
100
|
} from './orm';
|
|
101
|
+
export { CLI, runCLI } from './cli';
|
|
90
102
|
// Re-export validate from orm as schemaValidate to avoid collision with middleware validate
|
|
91
103
|
export { validate as schemaValidate } from './orm';
|
|
92
104
|
export {
|
|
@@ -149,7 +161,8 @@ import { Database, Model, Query } from './orm';
|
|
|
149
161
|
import { TYPES, validateFKAction, validateCheck } from './orm';
|
|
150
162
|
import { Migrator, QueryCache, Seeder, SeederRunner, Factory, Fake, defineMigration } from './orm';
|
|
151
163
|
import { QueryProfiler, ReplicaManager } from './orm';
|
|
152
|
-
import { TenantManager, AuditLog, PluginManager, StoredProcedure, StoredFunction, TriggerManager
|
|
164
|
+
import { TenantManager, AuditLog, PluginManager, StoredProcedure, StoredFunction, TriggerManager } from './orm';
|
|
165
|
+
import { CLI, runCLI } from './cli';
|
|
153
166
|
import { LifecycleManager, LIFECYCLE_STATE } from './lifecycle';
|
|
154
167
|
import { ClusterManager, cluster as clusterize } from './cluster';
|
|
155
168
|
import {
|
|
@@ -294,10 +307,10 @@ declare const zeroServer: {
|
|
|
294
307
|
LIFECYCLE_STATE: typeof LIFECYCLE_STATE;
|
|
295
308
|
ClusterManager: typeof ClusterManager;
|
|
296
309
|
cluster: typeof clusterize;
|
|
297
|
-
// Observability
|
|
310
|
+
// Observability - Structured Logging
|
|
298
311
|
Logger: typeof Logger;
|
|
299
312
|
structuredLogger: typeof structuredLogger;
|
|
300
|
-
// Observability
|
|
313
|
+
// Observability - Metrics
|
|
301
314
|
Counter: typeof Counter;
|
|
302
315
|
Gauge: typeof Gauge;
|
|
303
316
|
Histogram: typeof Histogram;
|
|
@@ -306,14 +319,14 @@ declare const zeroServer: {
|
|
|
306
319
|
createDefaultMetrics: typeof createDefaultMetrics;
|
|
307
320
|
metricsMiddleware: typeof metricsMiddleware;
|
|
308
321
|
metricsEndpoint: typeof metricsEndpointHandler;
|
|
309
|
-
// Observability
|
|
322
|
+
// Observability - Tracing
|
|
310
323
|
Span: typeof Span;
|
|
311
324
|
Tracer: typeof Tracer;
|
|
312
325
|
parseTraceparent: typeof parseTraceparent;
|
|
313
326
|
formatTraceparent: typeof formatTraceparent;
|
|
314
327
|
tracingMiddleware: typeof tracingMiddleware;
|
|
315
328
|
instrumentFetch: typeof instrumentFetch;
|
|
316
|
-
// Observability
|
|
329
|
+
// Observability - Health Checks
|
|
317
330
|
healthCheck: typeof healthCheck;
|
|
318
331
|
createHealthHandlers: typeof createHealthHandlers;
|
|
319
332
|
memoryCheck: typeof memoryCheck;
|
package/types/middleware.d.ts
CHANGED
|
@@ -21,77 +21,23 @@ export interface CorsOptions {
|
|
|
21
21
|
export function cors(options?: CorsOptions): MiddlewareFunction;
|
|
22
22
|
|
|
23
23
|
// --- Body Parsers ------------------------------------------------
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export interface JsonParserOptions extends BodyParserOptions {
|
|
43
|
-
/** JSON.parse reviver function. */
|
|
44
|
-
reviver?: (key: string, value: any) => any;
|
|
45
|
-
/** Reject non-object/array roots. Default: true. */
|
|
46
|
-
strict?: boolean;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export interface UrlencodedParserOptions extends BodyParserOptions {
|
|
50
|
-
/** Enable nested bracket parsing. Default: false. */
|
|
51
|
-
extended?: boolean;
|
|
52
|
-
/** Max number of parameters. Default: 1000. Prevents parameter flooding DoS. */
|
|
53
|
-
parameterLimit?: number;
|
|
54
|
-
/** Max nesting depth for bracket syntax. Default: 32. Prevents deep-nesting DoS. */
|
|
55
|
-
depth?: number;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface TextParserOptions extends BodyParserOptions {
|
|
59
|
-
/** Fallback character encoding when Content-Type has no charset. Default: 'utf8'. */
|
|
60
|
-
encoding?: BufferEncoding;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export interface MultipartOptions {
|
|
64
|
-
/** Upload directory (default: OS temp). */
|
|
65
|
-
dir?: string;
|
|
66
|
-
/** Maximum size per file in bytes. */
|
|
67
|
-
maxFileSize?: number;
|
|
68
|
-
/** Reject non-HTTPS requests with 403. */
|
|
69
|
-
requireSecure?: boolean;
|
|
70
|
-
/** Maximum number of non-file fields. Default: 1000. */
|
|
71
|
-
maxFields?: number;
|
|
72
|
-
/** Maximum number of uploaded files. Default: 10. */
|
|
73
|
-
maxFiles?: number;
|
|
74
|
-
/** Maximum size of a single field value in bytes. Default: 1 MB. */
|
|
75
|
-
maxFieldSize?: number;
|
|
76
|
-
/** Whitelist of allowed MIME types for uploaded files (e.g. ['image/png', 'image/jpeg']). */
|
|
77
|
-
allowedMimeTypes?: string[];
|
|
78
|
-
/** Maximum combined size of all uploaded files in bytes. */
|
|
79
|
-
maxTotalSize?: number;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export interface MultipartFile {
|
|
83
|
-
originalFilename: string;
|
|
84
|
-
storedName: string;
|
|
85
|
-
path: string;
|
|
86
|
-
contentType: string;
|
|
87
|
-
size: number;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export function json(options?: JsonParserOptions): MiddlewareFunction;
|
|
91
|
-
export function urlencoded(options?: UrlencodedParserOptions): MiddlewareFunction;
|
|
92
|
-
export function text(options?: TextParserOptions): MiddlewareFunction;
|
|
93
|
-
export function raw(options?: BodyParserOptions): MiddlewareFunction;
|
|
94
|
-
export function multipart(options?: MultipartOptions): MiddlewareFunction;
|
|
24
|
+
// Declarations live in `./body` so the standalone `@zero-server/body`
|
|
25
|
+
// package has its own self-contained type file. Re-exported here so
|
|
26
|
+
// callers using the aggregate middleware surface continue to work.
|
|
27
|
+
|
|
28
|
+
export {
|
|
29
|
+
BodyParserOptions,
|
|
30
|
+
JsonParserOptions,
|
|
31
|
+
UrlencodedParserOptions,
|
|
32
|
+
TextParserOptions,
|
|
33
|
+
MultipartOptions,
|
|
34
|
+
MultipartFile,
|
|
35
|
+
json,
|
|
36
|
+
urlencoded,
|
|
37
|
+
text,
|
|
38
|
+
raw,
|
|
39
|
+
multipart,
|
|
40
|
+
} from './body';
|
|
95
41
|
|
|
96
42
|
// --- Rate Limiting -----------------------------------------------
|
|
97
43
|
|
|
@@ -136,7 +82,7 @@ export interface CompressOptions {
|
|
|
136
82
|
level?: number;
|
|
137
83
|
/** Force specific encoding(s). */
|
|
138
84
|
encoding?: string | string[];
|
|
139
|
-
/** Filter function
|
|
85
|
+
/** Filter function - return false to skip compression. */
|
|
140
86
|
filter?: (req: Request, res: Response) => boolean;
|
|
141
87
|
}
|
|
142
88
|
|
package/types/orm.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ export interface SchemaColumnDef {
|
|
|
29
29
|
enum?: string[];
|
|
30
30
|
/** Allowed values (set type). */
|
|
31
31
|
values?: string[];
|
|
32
|
-
/** Mass-assignment protection
|
|
32
|
+
/** Mass-assignment protection - exclude from bulk writes. */
|
|
33
33
|
guarded?: boolean;
|
|
34
34
|
/** Precision for decimal types. */
|
|
35
35
|
precision?: number;
|
|
@@ -229,7 +229,7 @@ export class Query {
|
|
|
229
229
|
take(n: number): Query;
|
|
230
230
|
/** Alias for offset (LINQ naming). */
|
|
231
231
|
skip(n: number): Query;
|
|
232
|
-
/** Alias for exec
|
|
232
|
+
/** Alias for exec - explicitly convert to array. */
|
|
233
233
|
toArray(): Promise<Model[]>;
|
|
234
234
|
/** Shorthand for orderBy(field, 'desc'). */
|
|
235
235
|
orderByDesc(field: string): Query;
|
|
@@ -260,7 +260,7 @@ export class Query {
|
|
|
260
260
|
/** Inject a raw WHERE clause for SQL adapters (ignored by memory/mongo). */
|
|
261
261
|
whereRaw(sql: string, ...params: any[]): Query;
|
|
262
262
|
|
|
263
|
-
/** Thenable support
|
|
263
|
+
/** Thenable support - `await query`. */
|
|
264
264
|
then<TResult1 = Model[], TResult2 = never>(
|
|
265
265
|
onfulfilled?: ((value: Model[]) => TResult1 | PromiseLike<TResult1>) | null,
|
|
266
266
|
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
|
|
@@ -1875,13 +1875,4 @@ export class TriggerManager {
|
|
|
1875
1875
|
get(name: string): TriggerDefinition | undefined;
|
|
1876
1876
|
}
|
|
1877
1877
|
|
|
1878
|
-
//
|
|
1879
|
-
|
|
1880
|
-
export class CLI {
|
|
1881
|
-
constructor(argv?: string[]);
|
|
1882
|
-
/** Run the CLI command. */
|
|
1883
|
-
run(): Promise<void>;
|
|
1884
|
-
}
|
|
1885
|
-
|
|
1886
|
-
/** Create and run the CLI. */
|
|
1887
|
-
export function runCLI(argv?: string[]): Promise<void>;
|
|
1878
|
+
// CLI declarations live in `./cli` (re-exported from `./index`).
|
package/types/request.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export interface Request {
|
|
|
31
31
|
readonly ips: string[];
|
|
32
32
|
/** `true` when the connection is over TLS (trust-proxy-aware). */
|
|
33
33
|
readonly secure: boolean;
|
|
34
|
-
/** Protocol string
|
|
34
|
+
/** Protocol string - `'https'` or `'http'` (trust-proxy-aware). */
|
|
35
35
|
readonly protocol: 'http' | 'https';
|
|
36
36
|
/** HTTP version string (e.g. '1.1', '2.0'). */
|
|
37
37
|
httpVersion: string;
|
|
@@ -49,7 +49,7 @@ export interface Request {
|
|
|
49
49
|
id?: string;
|
|
50
50
|
/** Whether the request timed out (populated by timeout middleware). */
|
|
51
51
|
timedOut?: boolean;
|
|
52
|
-
/** The original URL as received
|
|
52
|
+
/** The original URL as received - never rewritten by middleware. */
|
|
53
53
|
originalUrl: string;
|
|
54
54
|
/** The URL path on which the current router was mounted. */
|
|
55
55
|
baseUrl: string;
|
|
@@ -83,7 +83,7 @@ export interface Request {
|
|
|
83
83
|
subdomains(offset?: number): string[];
|
|
84
84
|
|
|
85
85
|
/**
|
|
86
|
-
* Content negotiation
|
|
86
|
+
* Content negotiation - check which types the client accepts.
|
|
87
87
|
*/
|
|
88
88
|
accepts(...types: string[]): string | false;
|
|
89
89
|
|
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript surface for @zero-server/webrtc.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the runtime surface exported from `lib/webrtc/index.js` and
|
|
5
|
+
* re-exported from the top-level SDK in `index.js`. Every entry listed
|
|
6
|
+
* in `.tools/scope-manifest.js` under the `webrtc` scope MUST have a
|
|
7
|
+
* matching declaration here - this is enforced by
|
|
8
|
+
* `test/packages/webrtc-types.test.js`.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { EventEmitter } from 'node:events';
|
|
12
|
+
import type { KeyObject } from 'node:crypto';
|
|
13
|
+
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Shared option / config types
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
export interface IceServerConfig {
|
|
19
|
+
urls: string | string[];
|
|
20
|
+
username?: string;
|
|
21
|
+
credential?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface TurnCredentials {
|
|
25
|
+
urls: string[];
|
|
26
|
+
username: string;
|
|
27
|
+
credential: string;
|
|
28
|
+
ttl: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface IssueTurnCredentialsOptions {
|
|
32
|
+
secret: string;
|
|
33
|
+
userId: string;
|
|
34
|
+
ttl?: string | number;
|
|
35
|
+
servers: string[];
|
|
36
|
+
realm?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface SignalingHubOptions {
|
|
40
|
+
maxSdpSize?: number;
|
|
41
|
+
maxCandidatesPerOffer?: number;
|
|
42
|
+
peerMessageRate?: number;
|
|
43
|
+
maxProtocolErrors?: number;
|
|
44
|
+
ipAttachRate?: number;
|
|
45
|
+
originAllowlist?: string[];
|
|
46
|
+
joinTokenSecret?: string | Buffer;
|
|
47
|
+
autoCreateRooms?: boolean;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface WebRTCOptions extends SignalingHubOptions {
|
|
51
|
+
path?: string;
|
|
52
|
+
iceServers?: IceServerConfig[] | 'auto';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface PeerAttachInfo {
|
|
56
|
+
user?: unknown;
|
|
57
|
+
ip?: string;
|
|
58
|
+
origin?: string;
|
|
59
|
+
[extra: string]: unknown;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface PeerTransport {
|
|
63
|
+
send(data: string): void;
|
|
64
|
+
on(event: 'message' | 'close', cb: (...args: unknown[]) => void): void;
|
|
65
|
+
close(code?: number, reason?: string): void;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
// SDP / ICE helpers
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
|
|
72
|
+
export interface ParsedSdpMedia {
|
|
73
|
+
type: string;
|
|
74
|
+
port: number;
|
|
75
|
+
proto: string;
|
|
76
|
+
formats: string[];
|
|
77
|
+
iceUfrag?: string;
|
|
78
|
+
icePwd?: string;
|
|
79
|
+
fingerprint?: { algorithm: string; hash: string };
|
|
80
|
+
candidates?: ParsedIceCandidate[];
|
|
81
|
+
[key: string]: unknown;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface ParsedSdp {
|
|
85
|
+
version: number;
|
|
86
|
+
origin: Record<string, unknown>;
|
|
87
|
+
sessionName: string;
|
|
88
|
+
media: ParsedSdpMedia[];
|
|
89
|
+
[key: string]: unknown;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface ParsedIceCandidate {
|
|
93
|
+
foundation: string;
|
|
94
|
+
component: number;
|
|
95
|
+
transport: string;
|
|
96
|
+
priority: number;
|
|
97
|
+
address: string;
|
|
98
|
+
port: number;
|
|
99
|
+
type: string;
|
|
100
|
+
relatedAddress?: string;
|
|
101
|
+
relatedPort?: number;
|
|
102
|
+
tcpType?: string;
|
|
103
|
+
[key: string]: unknown;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export declare function parseSdp(sdp: string, opts?: { maxBytes?: number }): ParsedSdp;
|
|
107
|
+
export declare function stringifySdp(parsed: ParsedSdp): string;
|
|
108
|
+
|
|
109
|
+
export declare function parseCandidate(line: string): ParsedIceCandidate;
|
|
110
|
+
export declare function stringifyCandidate(parsed: ParsedIceCandidate): string;
|
|
111
|
+
export declare function filterCandidates(
|
|
112
|
+
candidates: ParsedIceCandidate[],
|
|
113
|
+
opts?: { allowPrivate?: boolean; allowLoopback?: boolean; allowLinkLocal?: boolean; allowMdns?: boolean }
|
|
114
|
+
): ParsedIceCandidate[];
|
|
115
|
+
|
|
116
|
+
export declare function isPrivateIp(addr: string): boolean;
|
|
117
|
+
export declare function isLoopbackIp(addr: string): boolean;
|
|
118
|
+
export declare function isLinkLocalIp(addr: string): boolean;
|
|
119
|
+
export declare function isMdnsHostname(addr: string): boolean;
|
|
120
|
+
|
|
121
|
+
export declare const CANDIDATE_TYPES: Readonly<{ HOST: string; SRFLX: string; PRFLX: string; RELAY: string }>;
|
|
122
|
+
export declare const TCP_TYPES: Readonly<{ ACTIVE: string; PASSIVE: string; SO: string }>;
|
|
123
|
+
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
// STUN / TURN
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
|
|
128
|
+
export declare function stunBinding(opts: {
|
|
129
|
+
host: string;
|
|
130
|
+
port?: number;
|
|
131
|
+
timeoutMs?: number;
|
|
132
|
+
retries?: number;
|
|
133
|
+
socketType?: 'udp4' | 'udp6';
|
|
134
|
+
}): Promise<{ family: 4 | 6; address: string; port: number }>;
|
|
135
|
+
|
|
136
|
+
export declare function encodeBindingRequest(transactionId?: Buffer): { buffer: Buffer; transactionId: Buffer };
|
|
137
|
+
export declare function decodeMessage(buf: Buffer): {
|
|
138
|
+
method: number;
|
|
139
|
+
class: number;
|
|
140
|
+
transactionId: Buffer;
|
|
141
|
+
attributes: Array<{ type: number; value: Buffer }>;
|
|
142
|
+
};
|
|
143
|
+
export declare function encodeXorMappedAddress(address: string, port: number, transactionId: Buffer): Buffer;
|
|
144
|
+
export declare function decodeXorMappedAddress(value: Buffer, transactionId: Buffer): { family: 4 | 6; address: string; port: number };
|
|
145
|
+
|
|
146
|
+
export declare const STUN_MAGIC_COOKIE: number;
|
|
147
|
+
export declare const STUN_METHOD: Readonly<{ BINDING: number }>;
|
|
148
|
+
export declare const STUN_CLASS: Readonly<{ REQUEST: number; INDICATION: number; SUCCESS: number; ERROR: number }>;
|
|
149
|
+
export declare const STUN_ATTR: Readonly<{ MAPPED_ADDRESS: number; XOR_MAPPED_ADDRESS: number; ERROR_CODE: number; SOFTWARE: number }>;
|
|
150
|
+
|
|
151
|
+
export declare function issueTurnCredentials(opts: IssueTurnCredentialsOptions): TurnCredentials;
|
|
152
|
+
|
|
153
|
+
export declare class TurnServer {
|
|
154
|
+
constructor(opts: {
|
|
155
|
+
secret: string;
|
|
156
|
+
realm?: string;
|
|
157
|
+
listeners: Array<{ proto: 'udp' | 'tcp' | 'tls'; port: number; host?: string; tls?: { cert: Buffer; key: Buffer } }>;
|
|
158
|
+
quotas?: { maxAllocationsPerUser?: number; maxBytesPerMinute?: number };
|
|
159
|
+
defaultLifetime?: number;
|
|
160
|
+
maxLifetime?: number;
|
|
161
|
+
relayHost?: string;
|
|
162
|
+
});
|
|
163
|
+
readonly realm: string;
|
|
164
|
+
start(): Promise<void>;
|
|
165
|
+
stop(): Promise<void>;
|
|
166
|
+
address(): { address: string; port: number } | null;
|
|
167
|
+
on(event: 'allocation', listener: (ev: { userId: string; relay: { address: string; port: number }; client: { address: string; port: number } }) => void): this;
|
|
168
|
+
on(event: 'deallocation', listener: (ev: { userId: string; client: { address: string; port: number }; reason?: string }) => void): this;
|
|
169
|
+
on(event: 'error', listener: (err: Error) => void): this;
|
|
170
|
+
on(event: string, listener: (...args: unknown[]) => void): this;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
// Signaling core
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
|
|
177
|
+
export type PeerState = 'stable' | 'have-local-offer' | 'have-remote-offer';
|
|
178
|
+
|
|
179
|
+
export declare const PEER_STATE: Readonly<{
|
|
180
|
+
STABLE: 'stable';
|
|
181
|
+
HAVE_LOCAL_OFFER: 'have-local-offer';
|
|
182
|
+
HAVE_REMOTE_OFFER: 'have-remote-offer';
|
|
183
|
+
}>;
|
|
184
|
+
|
|
185
|
+
export declare class Peer {
|
|
186
|
+
readonly id: string;
|
|
187
|
+
readonly user: unknown;
|
|
188
|
+
readonly ip: string | null;
|
|
189
|
+
readonly transport: PeerTransport;
|
|
190
|
+
state: PeerState;
|
|
191
|
+
room: Room | null;
|
|
192
|
+
errors: number;
|
|
193
|
+
readonly connectedAt: number;
|
|
194
|
+
closed: boolean;
|
|
195
|
+
e2ee?: E2eeChannel;
|
|
196
|
+
constructor(transport: PeerTransport, info?: PeerAttachInfo);
|
|
197
|
+
send(type: string, payload?: object): void;
|
|
198
|
+
sendError(code: string, message: string): void;
|
|
199
|
+
close(code?: number, reason?: string): void;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export declare class Room {
|
|
203
|
+
readonly name: string;
|
|
204
|
+
readonly hub: SignalingHub | null;
|
|
205
|
+
isOpen: boolean;
|
|
206
|
+
constructor(name: string, opts?: { hub?: SignalingHub });
|
|
207
|
+
open(): this;
|
|
208
|
+
require(fn: (peer: Peer) => boolean | Promise<boolean>): this;
|
|
209
|
+
canPublish(fn: (peer: Peer) => boolean): this;
|
|
210
|
+
canSubscribe(fn: (peer: Peer) => boolean): this;
|
|
211
|
+
readonly size: number;
|
|
212
|
+
peers(): Peer[];
|
|
213
|
+
canJoin(peer: Peer): boolean | Promise<boolean>;
|
|
214
|
+
broadcast(type: string, payload?: object, exceptPeerId?: string): void;
|
|
215
|
+
close(reason?: string): void;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export interface SignalingHubEvents {
|
|
219
|
+
join: (ev: { peer: Peer; room: Room }) => void;
|
|
220
|
+
leave: (ev: { peer: Peer; room: Room }) => void;
|
|
221
|
+
offer: (ev: { peer: Peer; target: Peer | null; room: Room; sdp: string }) => void;
|
|
222
|
+
answer: (ev: { peer: Peer; target: Peer | null; room: Room; sdp: string }) => void;
|
|
223
|
+
signal: (ev: { peer: Peer; type: string }) => void;
|
|
224
|
+
joinFailed: (ev: { peer: Peer; reason: string; room?: string }) => void;
|
|
225
|
+
publishFailed: (ev: { peer: Peer; reason: string; room: string }) => void;
|
|
226
|
+
subscribeFailed: (ev: { peer: Peer; reason: string; room: string }) => void;
|
|
227
|
+
wireError: (ev: { peer: Peer; code: string }) => void;
|
|
228
|
+
e2eeKey: (ev: { peer: Peer; room: Room; epoch: number; key: string }) => void;
|
|
229
|
+
clusterError: (err: Error) => void;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export declare class SignalingHub extends EventEmitter {
|
|
233
|
+
constructor(opts?: SignalingHubOptions);
|
|
234
|
+
readonly size: number;
|
|
235
|
+
room(name: string): Room;
|
|
236
|
+
rooms(): Room[];
|
|
237
|
+
attach(transport: PeerTransport, info?: PeerAttachInfo): Peer;
|
|
238
|
+
close(): void;
|
|
239
|
+
on<E extends keyof SignalingHubEvents>(event: E, listener: SignalingHubEvents[E]): this;
|
|
240
|
+
on(event: string, listener: (...args: unknown[]) => void): this;
|
|
241
|
+
off<E extends keyof SignalingHubEvents>(event: E, listener: SignalingHubEvents[E]): this;
|
|
242
|
+
off(event: string, listener: (...args: unknown[]) => void): this;
|
|
243
|
+
emit<E extends keyof SignalingHubEvents>(event: E, ...args: Parameters<SignalingHubEvents[E]>): boolean;
|
|
244
|
+
emit(event: string, ...args: unknown[]): boolean;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export declare function createWebRTC(app: unknown, opts?: WebRTCOptions): SignalingHub;
|
|
248
|
+
|
|
249
|
+
// ---------------------------------------------------------------------------
|
|
250
|
+
// Join tokens
|
|
251
|
+
// ---------------------------------------------------------------------------
|
|
252
|
+
|
|
253
|
+
export interface SignJoinTokenOptions {
|
|
254
|
+
secret: string | Buffer;
|
|
255
|
+
user: string | { id?: string; userId?: string; sub?: string; [k: string]: unknown };
|
|
256
|
+
room: string;
|
|
257
|
+
ttl?: number;
|
|
258
|
+
claims?: Record<string, unknown>;
|
|
259
|
+
algorithm?: string;
|
|
260
|
+
audience?: string;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export interface VerifyJoinTokenOptions {
|
|
264
|
+
secret: string | Buffer;
|
|
265
|
+
room?: string;
|
|
266
|
+
audience?: string | string[];
|
|
267
|
+
algorithms?: string | string[];
|
|
268
|
+
clockTolerance?: number;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export declare function signJoinToken(opts: SignJoinTokenOptions): string;
|
|
272
|
+
|
|
273
|
+
export declare function verifyJoinToken(
|
|
274
|
+
token: string,
|
|
275
|
+
opts: VerifyJoinTokenOptions
|
|
276
|
+
): { room: string; user: unknown; sub?: string; aud?: string; [k: string]: unknown };
|
|
277
|
+
|
|
278
|
+
// ---------------------------------------------------------------------------
|
|
279
|
+
// Observability
|
|
280
|
+
// ---------------------------------------------------------------------------
|
|
281
|
+
|
|
282
|
+
export interface ObservabilityBindOptions {
|
|
283
|
+
metrics?: unknown;
|
|
284
|
+
tracer?: unknown;
|
|
285
|
+
prefix?: string;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export declare function bindObservability(
|
|
289
|
+
hub: SignalingHub,
|
|
290
|
+
opts?: ObservabilityBindOptions
|
|
291
|
+
): () => void;
|
|
292
|
+
|
|
293
|
+
// ---------------------------------------------------------------------------
|
|
294
|
+
// E2EE key relay
|
|
295
|
+
// ---------------------------------------------------------------------------
|
|
296
|
+
|
|
297
|
+
export interface E2eeKeyEvent {
|
|
298
|
+
from: string;
|
|
299
|
+
epoch: number;
|
|
300
|
+
key: Buffer;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export declare class E2eeChannel {
|
|
304
|
+
readonly peer: Peer;
|
|
305
|
+
readonly hub: SignalingHub;
|
|
306
|
+
epoch: number;
|
|
307
|
+
constructor(peer: Peer, hub: SignalingHub);
|
|
308
|
+
publish(epoch: number | null, key: Buffer | Uint8Array | string): number;
|
|
309
|
+
subscribe(fn: (ev: E2eeKeyEvent) => void): () => void;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export declare function attachE2ee(peer: Peer, hub: SignalingHub): E2eeChannel;
|
|
313
|
+
export declare function generateE2eeKeyPair(): { publicKey: KeyObject; privateKey: KeyObject };
|
|
314
|
+
export declare function sealKey(plaintext: Buffer | Uint8Array, recipientPubKey: KeyObject | Buffer): Buffer;
|
|
315
|
+
export declare function openSealedKey(sealed: Buffer | Uint8Array, recipientPrivKey: KeyObject | Buffer): Buffer;
|
|
316
|
+
|
|
317
|
+
// ---------------------------------------------------------------------------
|
|
318
|
+
// Cluster adapter
|
|
319
|
+
// ---------------------------------------------------------------------------
|
|
320
|
+
|
|
321
|
+
export interface ClusterAdapter {
|
|
322
|
+
publish(channel: string, message: unknown): void | Promise<void>;
|
|
323
|
+
subscribe(channel: string, handler: (message: unknown) => void): (() => void) | void;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export interface UseClusterOptions {
|
|
327
|
+
nodeId?: string;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export declare class ClusterCoordinator {
|
|
331
|
+
readonly hub: SignalingHub;
|
|
332
|
+
readonly adapter: ClusterAdapter;
|
|
333
|
+
readonly nodeId: string;
|
|
334
|
+
constructor(hub: SignalingHub, adapter: ClusterAdapter, opts?: UseClusterOptions);
|
|
335
|
+
locate(peerId: string): { nodeId: string; room: string } | null;
|
|
336
|
+
routeDirect(toPeerId: string, type: string, payload: object): boolean;
|
|
337
|
+
fanoutRoom(roomName: string, type: string, payload: object, excludeId?: string): void;
|
|
338
|
+
close(): void;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export declare function useCluster(
|
|
342
|
+
hub: SignalingHub,
|
|
343
|
+
adapter: ClusterAdapter,
|
|
344
|
+
opts?: UseClusterOptions
|
|
345
|
+
): ClusterCoordinator;
|
|
346
|
+
|
|
347
|
+
export declare class MemoryClusterAdapter implements ClusterAdapter {
|
|
348
|
+
publish(channel: string, message: unknown): void;
|
|
349
|
+
subscribe(channel: string, handler: (message: unknown) => void): () => void;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// ---------------------------------------------------------------------------
|
|
353
|
+
// CLI
|
|
354
|
+
// ---------------------------------------------------------------------------
|
|
355
|
+
|
|
356
|
+
export interface WebRTCCommandDeps {
|
|
357
|
+
out?: (line: string) => void;
|
|
358
|
+
err?: (line: string) => void;
|
|
359
|
+
setExit?: (code: number) => void;
|
|
360
|
+
stunBinding?: typeof stunBinding;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export declare function runWebRTCCommand(
|
|
364
|
+
subcmd: 'stun' | 'turn-creds' | 'join-token' | 'verify-token' | 'help' | string,
|
|
365
|
+
flags?: Map<string, string>,
|
|
366
|
+
deps?: WebRTCCommandDeps
|
|
367
|
+
): Promise<number>;
|
|
368
|
+
|
|
369
|
+
// ---------------------------------------------------------------------------
|
|
370
|
+
// SFU adapter (interface only - real implementations land in later PRs)
|
|
371
|
+
// ---------------------------------------------------------------------------
|
|
372
|
+
|
|
373
|
+
export interface SfuPeerInfo {
|
|
374
|
+
id: string;
|
|
375
|
+
user?: unknown;
|
|
376
|
+
room: string;
|
|
377
|
+
joinedAt: number;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
export interface SfuRouter { id: string; routerId: string; }
|
|
381
|
+
export interface SfuTransport {
|
|
382
|
+
id: string;
|
|
383
|
+
transportId: string;
|
|
384
|
+
routerId: string;
|
|
385
|
+
peer: SfuPeerInfo | null;
|
|
386
|
+
iceParameters: unknown;
|
|
387
|
+
dtlsParameters: unknown;
|
|
388
|
+
}
|
|
389
|
+
export interface SfuProducer {
|
|
390
|
+
id: string;
|
|
391
|
+
producerId: string;
|
|
392
|
+
transportId: string;
|
|
393
|
+
kind: 'audio' | 'video';
|
|
394
|
+
rtpParams: unknown;
|
|
395
|
+
paused: boolean;
|
|
396
|
+
}
|
|
397
|
+
export interface SfuConsumer {
|
|
398
|
+
id: string;
|
|
399
|
+
consumerId: string;
|
|
400
|
+
transportId: string;
|
|
401
|
+
producerId: string;
|
|
402
|
+
kind: 'audio' | 'video';
|
|
403
|
+
rtpParams: unknown;
|
|
404
|
+
rtpCaps: unknown;
|
|
405
|
+
}
|
|
406
|
+
export interface SfuStats {
|
|
407
|
+
kind: 'global' | 'router' | 'transport';
|
|
408
|
+
[key: string]: unknown;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
export type SfuEventHandler = (event: string, payload: unknown) => void;
|
|
412
|
+
|
|
413
|
+
export declare class SfuAdapter {
|
|
414
|
+
constructor();
|
|
415
|
+
createRouter(opts?: unknown): Promise<SfuRouter>;
|
|
416
|
+
createTransport(router: SfuRouter, peer: SfuPeerInfo): Promise<SfuTransport>;
|
|
417
|
+
produce(transport: SfuTransport, kind: 'audio' | 'video', rtpParams: unknown): Promise<SfuProducer>;
|
|
418
|
+
consume(transport: SfuTransport, producerId: string, rtpCaps: unknown): Promise<SfuConsumer>;
|
|
419
|
+
pauseProducer(producerId: string): Promise<void>;
|
|
420
|
+
resumeProducer(producerId: string): Promise<void>;
|
|
421
|
+
closeRouter(routerId: string): Promise<void>;
|
|
422
|
+
stats(scope?: string): Promise<SfuStats>;
|
|
423
|
+
onEvent(handler: SfuEventHandler): () => void;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
export declare class MemorySfuAdapter extends SfuAdapter {
|
|
427
|
+
constructor(opts?: Record<string, unknown>);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
export interface MediasoupAdapterOptions {
|
|
431
|
+
mediasoup?: unknown;
|
|
432
|
+
worker?: unknown;
|
|
433
|
+
workerSettings?: Record<string, unknown>;
|
|
434
|
+
mediaCodecs?: Array<Record<string, unknown>>;
|
|
435
|
+
webRtcTransportOptions?: Record<string, unknown>;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
export declare class MediasoupSfuAdapter extends SfuAdapter {
|
|
439
|
+
constructor(opts?: MediasoupAdapterOptions);
|
|
440
|
+
close(): Promise<void>;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
export interface LiveKitAdapterOptions {
|
|
444
|
+
url: string;
|
|
445
|
+
apiKey: string;
|
|
446
|
+
apiSecret: string;
|
|
447
|
+
livekit?: unknown;
|
|
448
|
+
client?: unknown;
|
|
449
|
+
defaultRoomOpts?: Record<string, unknown>;
|
|
450
|
+
defaultGrants?: Record<string, unknown>;
|
|
451
|
+
tokenTtl?: string | number;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
export declare class LiveKitSfuAdapter extends SfuAdapter {
|
|
455
|
+
constructor(opts: LiveKitAdapterOptions);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
export declare function loadSfuAdapter(
|
|
459
|
+
spec: SfuAdapter | 'memory' | 'mediasoup' | 'livekit' | string,
|
|
460
|
+
opts?: Record<string, unknown>,
|
|
461
|
+
): SfuAdapter;
|
|
462
|
+
|
|
463
|
+
// ---------------------------------------------------------------------------
|
|
464
|
+
// Server-side bot peer (wrtc)
|
|
465
|
+
// ---------------------------------------------------------------------------
|
|
466
|
+
|
|
467
|
+
export interface BotPeerOptions {
|
|
468
|
+
hub: SignalingHub;
|
|
469
|
+
room: string;
|
|
470
|
+
user?: unknown;
|
|
471
|
+
ip?: string;
|
|
472
|
+
joinToken?: string;
|
|
473
|
+
iceServers?: Array<Record<string, unknown>>;
|
|
474
|
+
rtcConfig?: Record<string, unknown>;
|
|
475
|
+
wrtc?: unknown;
|
|
476
|
+
onTrack?: (track: unknown, streams: unknown[], fromPeerId: string) => void;
|
|
477
|
+
onDataChannel?: (channel: unknown, fromPeerId: string) => void;
|
|
478
|
+
onPeerJoin?: (remotePeerId: string) => void;
|
|
479
|
+
onPeerLeave?: (remotePeerId: string) => void;
|
|
480
|
+
onError?: (err: Error) => void;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
export interface BotPeerHandle {
|
|
484
|
+
peer: Peer;
|
|
485
|
+
peerConnections: Map<string, unknown>;
|
|
486
|
+
getPeerConnection: (remotePeerId: string) => unknown | undefined;
|
|
487
|
+
ready: Promise<{ peerId: string }>;
|
|
488
|
+
close: () => void;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
export declare function spawnBotPeer(opts: BotPeerOptions): BotPeerHandle;
|
|
492
|
+
|
|
493
|
+
// ---------------------------------------------------------------------------
|
|
494
|
+
// Errors
|
|
495
|
+
// ---------------------------------------------------------------------------
|
|
496
|
+
|
|
497
|
+
export declare class WebRTCError extends Error { readonly code: string; }
|
|
498
|
+
export declare class SignalingError extends WebRTCError {}
|
|
499
|
+
export declare class IceError extends WebRTCError {}
|
|
500
|
+
export declare class TurnError extends WebRTCError {}
|
|
501
|
+
export declare class SdpError extends WebRTCError {}
|