@rlanz/socket 0.0.1-6 → 0.0.1-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 +186 -147
- package/build/{types-DiYaFvgi.d.ts → base_channel-DPOnqned.d.ts} +185 -171
- package/build/chunk-6PJ4ALJD.js +115 -0
- package/build/chunk-6PJ4ALJD.js.map +1 -0
- package/build/chunk-E6ILCRL3.js +182 -0
- package/build/chunk-E6ILCRL3.js.map +1 -0
- package/build/{chunk-SHH6U4CI.js → chunk-G75J233Z.js} +1 -1
- package/build/chunk-G75J233Z.js.map +1 -0
- package/build/{chunk-B4Y3TNDI.js → chunk-IUQ3GYZZ.js} +5 -24
- package/build/chunk-IUQ3GYZZ.js.map +1 -0
- package/build/chunk-K243S3QP.js +131 -0
- package/build/chunk-K243S3QP.js.map +1 -0
- package/build/chunk-QNOOQXYY.js +899 -0
- package/build/chunk-QNOOQXYY.js.map +1 -0
- package/build/{chunk-FVPY6HZW.js → chunk-YVC7IMDN.js} +21 -5
- package/build/chunk-YVC7IMDN.js.map +1 -0
- package/build/framework-B8pJ4cCA.d.ts +13 -0
- package/build/index-DjBYUhFR.d.ts +150 -0
- package/build/index.d.ts +23 -12
- package/build/index.js +12 -14
- package/build/index.js.map +1 -1
- package/build/providers/socket_provider.d.ts +2 -2
- package/build/providers/socket_provider.js +478 -215
- package/build/providers/socket_provider.js.map +1 -1
- package/build/services/socket.d.ts +2 -2
- package/build/{socket_service-D3jKrleE.d.ts → socket_service-BcC9ASCE.d.ts} +8 -7
- package/build/src/assembler_hook.js +33 -59
- package/build/src/assembler_hook.js.map +1 -1
- package/build/src/client/index.d.ts +3 -147
- package/build/src/client/index.js +4 -837
- package/build/src/client/index.js.map +1 -1
- package/build/src/client/react.d.ts +13 -5
- package/build/src/client/react.js +27 -11
- package/build/src/client/react.js.map +1 -1
- package/build/src/client/types.d.ts +30 -36
- package/build/src/client/vue.d.ts +17 -6
- package/build/src/client/vue.js +31 -13
- package/build/src/client/vue.js.map +1 -1
- package/build/src/decorators.d.ts +3 -2
- package/build/src/decorators.js +1 -1
- package/build/src/health_check.d.ts +2 -2
- package/build/src/health_check.js +14 -3
- package/build/src/health_check.js.map +1 -1
- package/build/src/otel.js +0 -1
- package/build/src/otel.js.map +1 -1
- package/build/src/testing.d.ts +3 -12
- package/build/src/testing.js +1 -1
- package/build/src/types/tracing_channels.d.ts +1 -2
- package/build/src/types.d.ts +1 -1
- package/package.json +3 -9
- package/build/chunk-B4Y3TNDI.js.map +0 -1
- package/build/chunk-FVPY6HZW.js.map +0 -1
- package/build/chunk-HK7Z65DA.js +0 -19
- package/build/chunk-HK7Z65DA.js.map +0 -1
- package/build/chunk-SFAY2ZA4.js +0 -28
- package/build/chunk-SFAY2ZA4.js.map +0 -1
- package/build/chunk-SHH6U4CI.js.map +0 -1
- package/build/chunk-YAX5EHHB.js +0 -453
- package/build/chunk-YAX5EHHB.js.map +0 -1
- package/build/framework-DuW6zpPk.d.ts +0 -14
- package/build/src/client/svelte.d.ts +0 -23
- package/build/src/client/svelte.js +0 -82
- package/build/src/client/svelte.js.map +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { S as SocketService } from '../socket_service-
|
|
1
|
+
import { S as SocketService } from '../socket_service-BcC9ASCE.js';
|
|
2
2
|
import 'node:http';
|
|
3
3
|
import '@adonisjs/logger';
|
|
4
4
|
import 'emittery';
|
|
5
5
|
import 'ws';
|
|
6
|
-
import '../
|
|
6
|
+
import '../base_channel-DPOnqned.js';
|
|
7
7
|
import '@adonisjs/core/types/http';
|
|
8
8
|
import '@adonisjs/core/http';
|
|
9
9
|
import '@boringnode/bus/types/main';
|
|
@@ -2,10 +2,13 @@ import { IncomingMessage, Server } from 'node:http';
|
|
|
2
2
|
import { Logger } from '@adonisjs/logger';
|
|
3
3
|
import Emittery from 'emittery';
|
|
4
4
|
import { WebSocketServer } from 'ws';
|
|
5
|
-
import {
|
|
5
|
+
import { v as BaseChannelConstructor, B as BaseChannel, w as ChannelMiddlewareRunnerFactory, x as ChannelMatch, A as AuthenticatedSocket, y as PresenceData, d as ChannelOptions, l as SocketEvents, P as PresenceManager, c as SocketConfig, s as SocketServiceStatus, m as SocketHealthSnapshot } from './base_channel-DPOnqned.js';
|
|
6
6
|
import { HttpContext } from '@adonisjs/core/http';
|
|
7
7
|
import { SocketFake } from './src/testing.js';
|
|
8
8
|
|
|
9
|
+
type SocketUpgradeContextRunner = <Result>(request: IncomingMessage, handler: (httpContext: HttpContext) => Promise<Result>, shortCircuitBeforeMiddleware?: (httpContext: HttpContext) => Result | undefined | Promise<Result | undefined>) => Promise<Result>;
|
|
10
|
+
|
|
11
|
+
type ChannelFactory = (channel: BaseChannelConstructor) => BaseChannel<any> | Promise<BaseChannel<any>>;
|
|
9
12
|
/**
|
|
10
13
|
* Matches channel names against registered patterns.
|
|
11
14
|
*
|
|
@@ -18,6 +21,9 @@ import { SocketFake } from './src/testing.js';
|
|
|
18
21
|
*/
|
|
19
22
|
declare class ChannelRouter {
|
|
20
23
|
#private;
|
|
24
|
+
private makeChannel;
|
|
25
|
+
private createMiddlewareRunner?;
|
|
26
|
+
constructor(makeChannel?: ChannelFactory, createMiddlewareRunner?: ChannelMiddlewareRunnerFactory | undefined);
|
|
21
27
|
/**
|
|
22
28
|
* Registers a channel.
|
|
23
29
|
*/
|
|
@@ -47,7 +53,7 @@ declare class ChannelRouter {
|
|
|
47
53
|
readonly presenceData?: undefined;
|
|
48
54
|
} | {
|
|
49
55
|
readonly success: true;
|
|
50
|
-
readonly instance: BaseChannel<User,
|
|
56
|
+
readonly instance: BaseChannel<User, Record<never, never>>;
|
|
51
57
|
readonly params: Record<string, string>;
|
|
52
58
|
readonly paramValues: string[];
|
|
53
59
|
readonly presenceData: Record<string, unknown> | PresenceData | null;
|
|
@@ -68,8 +74,6 @@ declare class ChannelRouter {
|
|
|
68
74
|
get size(): number;
|
|
69
75
|
}
|
|
70
76
|
|
|
71
|
-
type SocketUpgradeContextRunner = <Result>(request: IncomingMessage, handler: (httpContext: HttpContext) => Promise<Result>) => Promise<Result>;
|
|
72
|
-
|
|
73
77
|
/**
|
|
74
78
|
* Main service for managing WebSocket connections.
|
|
75
79
|
*/
|
|
@@ -87,9 +91,6 @@ declare class SocketService<User = unknown> extends Emittery<SocketEvents<User>>
|
|
|
87
91
|
emit: (event: string, data: unknown) => void;
|
|
88
92
|
};
|
|
89
93
|
};
|
|
90
|
-
toUser(userId: string | number): {
|
|
91
|
-
emit: (event: string, data: unknown) => void;
|
|
92
|
-
};
|
|
93
94
|
broadcast(event: string, data: unknown): void;
|
|
94
95
|
getSocket(socketId: string): AuthenticatedSocket<User> | undefined;
|
|
95
96
|
get connectionsCount(): number;
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BindableChannelPattern
|
|
3
|
+
} from "../chunk-6PJ4ALJD.js";
|
|
4
|
+
import "../chunk-E6ILCRL3.js";
|
|
5
|
+
|
|
1
6
|
// src/assembler_hook.ts
|
|
2
7
|
import fs from "fs";
|
|
3
8
|
import ts from "typescript";
|
|
@@ -38,20 +43,6 @@ function validateHandlerMethod(filePath, method, name) {
|
|
|
38
43
|
fail(filePath, `handler method ${name} must not require parameters after the payload`);
|
|
39
44
|
}
|
|
40
45
|
}
|
|
41
|
-
function isSupportedPattern(pattern) {
|
|
42
|
-
const normalized = pattern === "/" ? "/" : pattern.replace(/^\//, "").replace(/\/$/, "");
|
|
43
|
-
if (normalized === "/") {
|
|
44
|
-
return true;
|
|
45
|
-
}
|
|
46
|
-
const segments = normalized.split("/");
|
|
47
|
-
return segments.every((segment, index) => {
|
|
48
|
-
const isFinal = index === segments.length - 1;
|
|
49
|
-
const literal = segment.length > 0 && !/[:*?]/.test(segment);
|
|
50
|
-
const requiredParam = /^:[^.:?/*]+$/.test(segment);
|
|
51
|
-
const optionalParam = /^:[^.:?/*]+\?$/.test(segment);
|
|
52
|
-
return literal || requiredParam || isFinal && (optionalParam || segment === "*");
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
46
|
function inspectChannel(filePath, importPath) {
|
|
56
47
|
const source = ts.createSourceFile(
|
|
57
48
|
filePath,
|
|
@@ -116,45 +107,11 @@ function inspectChannel(filePath, importPath) {
|
|
|
116
107
|
if (!patternMember || !patternMember.initializer || !ts.isStringLiteral(patternMember.initializer)) {
|
|
117
108
|
return `Omitted ${importPath}: static pattern must be a direct string literal.`;
|
|
118
109
|
}
|
|
119
|
-
|
|
110
|
+
const bindablePattern = BindableChannelPattern.parse(patternMember.initializer.text);
|
|
111
|
+
if (!bindablePattern) {
|
|
120
112
|
return `Omitted ${importPath}: pattern ${quote(patternMember.initializer.text)} is not supported by generated typing; use literals, required params, a final optional param, or a final wildcard.`;
|
|
121
113
|
}
|
|
122
|
-
const methods = /* @__PURE__ */ new Map();
|
|
123
|
-
for (const member of channelClass.members) {
|
|
124
|
-
if (ts.isMethodDeclaration(member) && !isStatic(member)) {
|
|
125
|
-
const name = propertyName(member.name);
|
|
126
|
-
if (name) methods.set(name, member);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
114
|
const handlers = [];
|
|
130
|
-
const handlerMember = channelClass.members.find(
|
|
131
|
-
(member) => ts.isPropertyDeclaration(member) && !isStatic(member) && propertyName(member.name) === "handlers"
|
|
132
|
-
);
|
|
133
|
-
if (handlerMember) {
|
|
134
|
-
if (!handlerMember.initializer || !ts.isObjectLiteralExpression(handlerMember.initializer)) {
|
|
135
|
-
fail(filePath, "handlers must be an object literal");
|
|
136
|
-
}
|
|
137
|
-
for (const property of handlerMember.initializer.properties) {
|
|
138
|
-
if (!ts.isPropertyAssignment(property) || !ts.isStringLiteral(property.name)) {
|
|
139
|
-
fail(filePath, "handler event keys must be direct string literals");
|
|
140
|
-
}
|
|
141
|
-
const event = property.name.text;
|
|
142
|
-
const value = property.initializer;
|
|
143
|
-
if (!ts.isPropertyAccessExpression(value) || value.expression.kind !== ts.SyntaxKind.ThisKeyword || !ts.isIdentifier(value.name)) {
|
|
144
|
-
fail(filePath, `handler "${event}" must reference this.<publicMethod>`);
|
|
145
|
-
}
|
|
146
|
-
const method = methods.get(value.name.text);
|
|
147
|
-
if (!method) fail(filePath, `handler "${event}" references missing method ${value.name.text}`);
|
|
148
|
-
if (!isPublic(method)) {
|
|
149
|
-
fail(filePath, `handler method ${value.name.text} must be public`);
|
|
150
|
-
}
|
|
151
|
-
validateHandlerMethod(filePath, method, value.name.text);
|
|
152
|
-
if (handlers.some((handler) => handler.event === event)) {
|
|
153
|
-
fail(filePath, `event "${event}" is mapped more than once`);
|
|
154
|
-
}
|
|
155
|
-
handlers.push({ event, method: value.name.text });
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
115
|
for (const method of channelClass.members.filter(ts.isMethodDeclaration)) {
|
|
159
116
|
for (const decorator of ts.getDecorators(method) ?? []) {
|
|
160
117
|
const expression = decorator.expression;
|
|
@@ -182,7 +139,7 @@ function inspectChannel(filePath, importPath) {
|
|
|
182
139
|
handlers.push({ event, method: name });
|
|
183
140
|
}
|
|
184
141
|
}
|
|
185
|
-
return { pattern: patternMember.initializer.text, importPath, handlers };
|
|
142
|
+
return { pattern: patternMember.initializer.text, bindablePattern, importPath, handlers };
|
|
186
143
|
}
|
|
187
144
|
function generateSocketRegistry(options = {}) {
|
|
188
145
|
return {
|
|
@@ -204,16 +161,33 @@ function generateSocketRegistry(options = {}) {
|
|
|
204
161
|
if (typeof inspected === "string") diagnostics.push(inspected);
|
|
205
162
|
else channels.push(inspected);
|
|
206
163
|
}
|
|
164
|
+
const patterns = /* @__PURE__ */ new Set();
|
|
165
|
+
for (const channel of channels) {
|
|
166
|
+
if (patterns.has(channel.bindablePattern.canonicalPattern)) {
|
|
167
|
+
fail(
|
|
168
|
+
channel.importPath,
|
|
169
|
+
`pattern ${quote(channel.pattern)} is declared more than once`
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
patterns.add(channel.bindablePattern.canonicalPattern);
|
|
173
|
+
}
|
|
207
174
|
for (const diagnostic of diagnostics) buffer.writeLine(`// [socket] ${diagnostic}`);
|
|
208
175
|
if (diagnostics.length) buffer.writeLine("");
|
|
209
176
|
buffer.writeLine("export interface AppSocket {").indent();
|
|
210
|
-
|
|
211
|
-
buffer.writeLine("readonly uncertain: true");
|
|
212
|
-
}
|
|
213
|
-
buffer.writeLine("readonly channels: readonly [").indent();
|
|
177
|
+
buffer.writeLine("readonly channels: {").indent();
|
|
214
178
|
for (const channel of channels) {
|
|
215
|
-
buffer.writeLine(
|
|
216
|
-
|
|
179
|
+
buffer.writeLine(`readonly ${quote(channel.pattern)}: {`).indent();
|
|
180
|
+
if (channel.bindablePattern.parameters.length === 0) {
|
|
181
|
+
buffer.writeLine("readonly params: undefined");
|
|
182
|
+
} else {
|
|
183
|
+
buffer.writeLine("readonly params: {").indent();
|
|
184
|
+
for (const parameter of channel.bindablePattern.parameters) {
|
|
185
|
+
buffer.writeLine(
|
|
186
|
+
`readonly ${quote(parameter.name)}${parameter.optional ? "?" : ""}: string | number`
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
buffer.dedent().writeLine("}");
|
|
190
|
+
}
|
|
217
191
|
buffer.writeLine(
|
|
218
192
|
`readonly channel: typeof import(${quote(channel.importPath)}).default`
|
|
219
193
|
);
|
|
@@ -222,9 +196,9 @@ function generateSocketRegistry(options = {}) {
|
|
|
222
196
|
buffer.writeLine(`readonly ${quote(handler.event)}: ${quote(handler.method)}`);
|
|
223
197
|
}
|
|
224
198
|
buffer.dedent().writeLine("}");
|
|
225
|
-
buffer.dedent().writeLine("}
|
|
199
|
+
buffer.dedent().writeLine("}");
|
|
226
200
|
}
|
|
227
|
-
buffer.dedent().writeLine("
|
|
201
|
+
buffer.dedent().writeLine("}");
|
|
228
202
|
buffer.dedent().writeLine("}");
|
|
229
203
|
}
|
|
230
204
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/assembler_hook.ts"],"sourcesContent":["import fs from 'node:fs'\nimport ts from 'typescript'\nimport type { CommonHooks } from '@adonisjs/assembler/types'\nimport type { IndexGeneratorSourceConfig } from '@adonisjs/assembler/types'\n\nexport interface SocketAssemblerHookOptions {\n source?: string\n glob?: string[]\n output?: string\n}\n\ntype Handler = { event: string; method: string }\ntype Channel = { pattern: string; importPath: string; handlers: Handler[] }\ntype SocketAssemblerHook = Extract<CommonHooks['init'][number], { run: (...args: any[]) => any }>\n\nfunction quote(value: string) {\n return `'${value.replaceAll('\\\\', '\\\\\\\\').replaceAll(\"'\", \"\\\\'\")}'`\n}\n\nfunction generatedImportPath(importPath: string): string {\n return importPath.replace(/\\.ts$/, '')\n}\n\nfunction appImportAlias(source: string): string {\n const normalized = source.replace(/^\\.\\//, '')\n if (normalized === 'app') return '#app'\n if (normalized.startsWith('app/')) return `#app/${normalized.slice('app/'.length)}`\n throw new Error('[socket] Channel source must be inside the app directory')\n}\n\nfunction fail(filePath: string, message: string): never {\n throw new Error(`[socket] Cannot generate client types for ${filePath}: ${message}`)\n}\n\nfunction propertyName(node: ts.PropertyName | undefined): string | undefined {\n if (node && (ts.isIdentifier(node) || ts.isStringLiteral(node))) return node.text\n}\n\nfunction isPublic(method: ts.MethodDeclaration) {\n return !method.modifiers?.some(\n (modifier) =>\n modifier.kind === ts.SyntaxKind.PrivateKeyword ||\n modifier.kind === ts.SyntaxKind.ProtectedKeyword\n )\n}\n\nfunction isStatic(member: ts.ClassElement): boolean {\n return (\n ts.canHaveModifiers(member) &&\n !!ts.getModifiers(member)?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword)\n )\n}\n\nfunction validateHandlerMethod(filePath: string, method: ts.MethodDeclaration, name: string): void {\n const parameters = method.parameters.filter(\n (parameter) => !(ts.isIdentifier(parameter.name) && parameter.name.text === 'this')\n )\n if (parameters.some((parameter) => parameter.dotDotDotToken)) {\n fail(filePath, `handler method ${name} must not use rest parameters`)\n }\n if (parameters.slice(2).some((parameter) => !parameter.questionToken && !parameter.initializer)) {\n fail(filePath, `handler method ${name} must not require parameters after the payload`)\n }\n}\n\nfunction isSupportedPattern(pattern: string): boolean {\n const normalized = pattern === '/' ? '/' : pattern.replace(/^\\//, '').replace(/\\/$/, '')\n if (normalized === '/') {\n return true\n }\n const segments = normalized.split('/')\n\n return segments.every((segment, index) => {\n const isFinal = index === segments.length - 1\n const literal = segment.length > 0 && !/[:*?]/.test(segment)\n const requiredParam = /^:[^.:?/*]+$/.test(segment)\n const optionalParam = /^:[^.:?/*]+\\?$/.test(segment)\n\n return literal || requiredParam || (isFinal && (optionalParam || segment === '*'))\n })\n}\n\nfunction inspectChannel(filePath: string, importPath: string): Channel | string {\n const source = ts.createSourceFile(\n filePath,\n fs.readFileSync(filePath, 'utf8'),\n ts.ScriptTarget.Latest,\n true,\n filePath.endsWith('.js') ? ts.ScriptKind.JS : ts.ScriptKind.TS\n )\n const decoratorImports = new Set<string>()\n const decoratorNamespaces = new Set<string>()\n const baseChannelImports = new Set<string>()\n const socketNamespaces = new Set<string>()\n\n for (const statement of source.statements) {\n if (\n !ts.isImportDeclaration(statement) ||\n !ts.isStringLiteral(statement.moduleSpecifier) ||\n (statement.moduleSpecifier.text !== '@rlanz/socket/decorators' &&\n statement.moduleSpecifier.text !== '@rlanz/socket')\n ) {\n continue\n }\n\n const bindings = statement.importClause?.namedBindings\n if (bindings && ts.isNamedImports(bindings)) {\n for (const binding of bindings.elements) {\n const importedName = (binding.propertyName ?? binding.name).text\n if (\n statement.moduleSpecifier.text === '@rlanz/socket/decorators' &&\n importedName === 'onMessage'\n ) {\n decoratorImports.add(binding.name.text)\n }\n if (statement.moduleSpecifier.text === '@rlanz/socket' && importedName === 'BaseChannel') {\n baseChannelImports.add(binding.name.text)\n }\n }\n } else if (bindings && ts.isNamespaceImport(bindings)) {\n if (statement.moduleSpecifier.text === '@rlanz/socket/decorators') {\n decoratorNamespaces.add(bindings.name.text)\n } else {\n socketNamespaces.add(bindings.name.text)\n }\n }\n }\n\n const classes = source.statements.filter(ts.isClassDeclaration)\n let channelClass = classes.find((node) =>\n node.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.DefaultKeyword)\n )\n\n if (!channelClass) {\n const defaultExport = source.statements.find(\n (node): node is ts.ExportAssignment => ts.isExportAssignment(node) && !node.isExportEquals\n )\n if (defaultExport && ts.isIdentifier(defaultExport.expression)) {\n const defaultClassName = defaultExport.expression.text\n channelClass = classes.find((node) => node.name?.text === defaultClassName)\n }\n }\n if (!channelClass) fail(filePath, 'a default-exported channel class was not found')\n if (channelClass.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.AbstractKeyword)) {\n fail(filePath, 'the default-exported channel class must not be abstract')\n }\n\n const extendsType = channelClass.heritageClauses\n ?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)\n ?.types.at(0)\n const extendsExpression = extendsType?.expression\n const directlyExtendsBaseChannel =\n (extendsExpression &&\n ts.isIdentifier(extendsExpression) &&\n baseChannelImports.has(extendsExpression.text)) ||\n (extendsExpression &&\n ts.isPropertyAccessExpression(extendsExpression) &&\n ts.isIdentifier(extendsExpression.expression) &&\n socketNamespaces.has(extendsExpression.expression.text) &&\n extendsExpression.name.text === 'BaseChannel')\n\n if (!directlyExtendsBaseChannel) {\n return (\n `Omitted ${importPath}: generated contracts do not support channel inheritance; ` +\n 'the default export must directly extend BaseChannel imported from @rlanz/socket.'\n )\n }\n\n const patternMember = channelClass.members.find(\n (member): member is ts.PropertyDeclaration =>\n ts.isPropertyDeclaration(member) &&\n propertyName(member.name) === 'pattern' &&\n !!member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword)\n )\n if (\n !patternMember ||\n !patternMember.initializer ||\n !ts.isStringLiteral(patternMember.initializer)\n ) {\n return `Omitted ${importPath}: static pattern must be a direct string literal.`\n }\n\n if (!isSupportedPattern(patternMember.initializer.text)) {\n return (\n `Omitted ${importPath}: pattern ${quote(patternMember.initializer.text)} is not supported by ` +\n 'generated typing; use literals, required params, a final optional param, or a final wildcard.'\n )\n }\n\n const methods = new Map<string, ts.MethodDeclaration>()\n for (const member of channelClass.members) {\n if (ts.isMethodDeclaration(member) && !isStatic(member)) {\n const name = propertyName(member.name)\n if (name) methods.set(name, member)\n }\n }\n\n const handlers: Handler[] = []\n const handlerMember = channelClass.members.find(\n (member): member is ts.PropertyDeclaration =>\n ts.isPropertyDeclaration(member) &&\n !isStatic(member) &&\n propertyName(member.name) === 'handlers'\n )\n if (handlerMember) {\n if (!handlerMember.initializer || !ts.isObjectLiteralExpression(handlerMember.initializer)) {\n fail(filePath, 'handlers must be an object literal')\n }\n for (const property of handlerMember.initializer.properties) {\n if (!ts.isPropertyAssignment(property) || !ts.isStringLiteral(property.name)) {\n fail(filePath, 'handler event keys must be direct string literals')\n }\n const event = property.name.text\n const value = property.initializer\n if (\n !ts.isPropertyAccessExpression(value) ||\n value.expression.kind !== ts.SyntaxKind.ThisKeyword ||\n !ts.isIdentifier(value.name)\n ) {\n fail(filePath, `handler \"${event}\" must reference this.<publicMethod>`)\n }\n const method = methods.get(value.name.text)\n if (!method) fail(filePath, `handler \"${event}\" references missing method ${value.name.text}`)\n if (!isPublic(method)) {\n fail(filePath, `handler method ${value.name.text} must be public`)\n }\n validateHandlerMethod(filePath, method, value.name.text)\n if (handlers.some((handler) => handler.event === event)) {\n fail(filePath, `event \"${event}\" is mapped more than once`)\n }\n handlers.push({ event, method: value.name.text })\n }\n }\n\n for (const method of channelClass.members.filter(ts.isMethodDeclaration)) {\n for (const decorator of ts.getDecorators(method) ?? []) {\n const expression = decorator.expression\n const isImportedDecorator =\n ts.isCallExpression(expression) &&\n ((ts.isIdentifier(expression.expression) &&\n decoratorImports.has(expression.expression.text)) ||\n (ts.isPropertyAccessExpression(expression.expression) &&\n ts.isIdentifier(expression.expression.expression) &&\n decoratorNamespaces.has(expression.expression.expression.text) &&\n expression.expression.name.text === 'onMessage'))\n\n if (!isImportedDecorator || !ts.isCallExpression(expression)) {\n continue\n }\n\n if (isStatic(method)) {\n fail(filePath, '@onMessage cannot generate a contract for a static method')\n }\n\n if (expression.arguments.length !== 1 || !ts.isStringLiteral(expression.arguments[0])) {\n fail(\n filePath,\n `@onMessage on ${propertyName(method.name) ?? '<computed>'} needs a literal event`\n )\n }\n const event = expression.arguments[0].text\n const name = propertyName(method.name)\n if (!name || !ts.isIdentifier(method.name)) fail(filePath, '@onMessage methods must be named')\n if (!isPublic(method)) fail(filePath, `decorated handler method ${name} must be public`)\n validateHandlerMethod(filePath, method, name)\n if (handlers.some((handler) => handler.event === event)) {\n fail(filePath, `event \"${event}\" is mapped more than once`)\n }\n handlers.push({ event, method: name })\n }\n }\n\n return { pattern: patternMember.initializer.text, importPath, handlers }\n}\n\n/** Registers generation of the application socket registry with AdonisJS Assembler. */\nexport function generateSocketRegistry(\n options: SocketAssemblerHookOptions = {}\n): SocketAssemblerHook {\n return {\n run(_parent, hooks, indexGenerator) {\n const source = options.source ?? './app/channels'\n const glob = options.glob ?? ['**/*_channel.{ts,js}']\n const importAlias = appImportAlias(source)\n\n indexGenerator.add('socketChannels', {\n source,\n glob,\n importAlias,\n output: options.output ?? './.adonisjs/client/socket.ts',\n as(vfs, buffer, _config, helpers) {\n const channels: Channel[] = []\n const diagnostics: string[] = []\n for (const filePath of Object.values(vfs.asList())) {\n const importPath = generatedImportPath(helpers.toImportPath(filePath))\n const inspected = inspectChannel(filePath, importPath)\n if (typeof inspected === 'string') diagnostics.push(inspected)\n else channels.push(inspected)\n }\n\n for (const diagnostic of diagnostics) buffer.writeLine(`// [socket] ${diagnostic}`)\n if (diagnostics.length) buffer.writeLine('')\n buffer.writeLine('export interface AppSocket {').indent()\n if (diagnostics.length) {\n buffer.writeLine('readonly uncertain: true')\n }\n buffer.writeLine('readonly channels: readonly [').indent()\n for (const channel of channels) {\n buffer.writeLine('{').indent()\n buffer.writeLine(`readonly pattern: ${quote(channel.pattern)}`)\n buffer.writeLine(\n `readonly channel: typeof import(${quote(channel.importPath)}).default`\n )\n buffer.writeLine('readonly handlers: {').indent()\n for (const handler of channel.handlers) {\n buffer.writeLine(`readonly ${quote(handler.event)}: ${quote(handler.method)}`)\n }\n buffer.dedent().writeLine('}')\n buffer.dedent().writeLine('},')\n }\n buffer.dedent().writeLine(']')\n buffer.dedent().writeLine('}')\n },\n } satisfies IndexGeneratorSourceConfig)\n\n indexGenerator.add('socketServerChannels', {\n source,\n glob,\n importAlias,\n output: './.adonisjs/server/socket_channels.ts',\n as(vfs, buffer, _config, helpers) {\n const filePaths = Object.values(vfs.asList())\n filePaths.forEach((filePath, index) => {\n const importPath = generatedImportPath(helpers.toImportPath(filePath))\n buffer.writeLine(`import Channel${index} from ${quote(importPath)}`)\n })\n if (filePaths.length) buffer.writeLine('')\n buffer.writeLine(\n `export const socketChannels = [${filePaths.map((_filePath, index) => `Channel${index}`).join(', ')}] as const`\n )\n },\n } satisfies IndexGeneratorSourceConfig)\n\n hooks.add('fileChanged', (_relativePath, absolutePath) => {\n return indexGenerator.addFile(absolutePath)\n })\n },\n }\n}\n\nconst socketRegistryHook = generateSocketRegistry()\nconst lazySocketRegistryHook: SocketAssemblerHook['run'] = socketRegistryHook.run\n\nexport default lazySocketRegistryHook\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/assembler_hook.ts"],"sourcesContent":["import fs from 'node:fs'\nimport ts from 'typescript'\nimport type { CommonHooks } from '@adonisjs/assembler/types'\nimport type { IndexGeneratorSourceConfig } from '@adonisjs/assembler/types'\nimport { BindableChannelPattern } from './bindable_channel_pattern.js'\n\nexport interface SocketAssemblerHookOptions {\n source?: string\n glob?: string[]\n output?: string\n}\n\ntype Handler = { event: string; method: string }\ntype Channel = {\n pattern: string\n bindablePattern: BindableChannelPattern\n importPath: string\n handlers: Handler[]\n}\ntype SocketAssemblerHook = Extract<CommonHooks['init'][number], { run: (...args: any[]) => any }>\n\nfunction quote(value: string) {\n return `'${value.replaceAll('\\\\', '\\\\\\\\').replaceAll(\"'\", \"\\\\'\")}'`\n}\n\nfunction generatedImportPath(importPath: string): string {\n return importPath.replace(/\\.ts$/, '')\n}\n\nfunction appImportAlias(source: string): string {\n const normalized = source.replace(/^\\.\\//, '')\n if (normalized === 'app') return '#app'\n if (normalized.startsWith('app/')) return `#app/${normalized.slice('app/'.length)}`\n throw new Error('[socket] Channel source must be inside the app directory')\n}\n\nfunction fail(filePath: string, message: string): never {\n throw new Error(`[socket] Cannot generate client types for ${filePath}: ${message}`)\n}\n\nfunction propertyName(node: ts.PropertyName | undefined): string | undefined {\n if (node && (ts.isIdentifier(node) || ts.isStringLiteral(node))) return node.text\n}\n\nfunction isPublic(method: ts.MethodDeclaration) {\n return !method.modifiers?.some(\n (modifier) =>\n modifier.kind === ts.SyntaxKind.PrivateKeyword ||\n modifier.kind === ts.SyntaxKind.ProtectedKeyword\n )\n}\n\nfunction isStatic(member: ts.ClassElement): boolean {\n return (\n ts.canHaveModifiers(member) &&\n !!ts.getModifiers(member)?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword)\n )\n}\n\nfunction validateHandlerMethod(filePath: string, method: ts.MethodDeclaration, name: string): void {\n const parameters = method.parameters.filter(\n (parameter) => !(ts.isIdentifier(parameter.name) && parameter.name.text === 'this')\n )\n if (parameters.some((parameter) => parameter.dotDotDotToken)) {\n fail(filePath, `handler method ${name} must not use rest parameters`)\n }\n if (parameters.slice(2).some((parameter) => !parameter.questionToken && !parameter.initializer)) {\n fail(filePath, `handler method ${name} must not require parameters after the payload`)\n }\n}\n\nfunction inspectChannel(filePath: string, importPath: string): Channel | string {\n const source = ts.createSourceFile(\n filePath,\n fs.readFileSync(filePath, 'utf8'),\n ts.ScriptTarget.Latest,\n true,\n filePath.endsWith('.js') ? ts.ScriptKind.JS : ts.ScriptKind.TS\n )\n const decoratorImports = new Set<string>()\n const decoratorNamespaces = new Set<string>()\n const baseChannelImports = new Set<string>()\n const socketNamespaces = new Set<string>()\n\n for (const statement of source.statements) {\n if (\n !ts.isImportDeclaration(statement) ||\n !ts.isStringLiteral(statement.moduleSpecifier) ||\n (statement.moduleSpecifier.text !== '@rlanz/socket/decorators' &&\n statement.moduleSpecifier.text !== '@rlanz/socket')\n ) {\n continue\n }\n\n const bindings = statement.importClause?.namedBindings\n if (bindings && ts.isNamedImports(bindings)) {\n for (const binding of bindings.elements) {\n const importedName = (binding.propertyName ?? binding.name).text\n if (\n statement.moduleSpecifier.text === '@rlanz/socket/decorators' &&\n importedName === 'onMessage'\n ) {\n decoratorImports.add(binding.name.text)\n }\n if (statement.moduleSpecifier.text === '@rlanz/socket' && importedName === 'BaseChannel') {\n baseChannelImports.add(binding.name.text)\n }\n }\n } else if (bindings && ts.isNamespaceImport(bindings)) {\n if (statement.moduleSpecifier.text === '@rlanz/socket/decorators') {\n decoratorNamespaces.add(bindings.name.text)\n } else {\n socketNamespaces.add(bindings.name.text)\n }\n }\n }\n\n const classes = source.statements.filter(ts.isClassDeclaration)\n let channelClass = classes.find((node) =>\n node.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.DefaultKeyword)\n )\n\n if (!channelClass) {\n const defaultExport = source.statements.find(\n (node): node is ts.ExportAssignment => ts.isExportAssignment(node) && !node.isExportEquals\n )\n if (defaultExport && ts.isIdentifier(defaultExport.expression)) {\n const defaultClassName = defaultExport.expression.text\n channelClass = classes.find((node) => node.name?.text === defaultClassName)\n }\n }\n if (!channelClass) fail(filePath, 'a default-exported channel class was not found')\n if (channelClass.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.AbstractKeyword)) {\n fail(filePath, 'the default-exported channel class must not be abstract')\n }\n\n const extendsType = channelClass.heritageClauses\n ?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)\n ?.types.at(0)\n const extendsExpression = extendsType?.expression\n const directlyExtendsBaseChannel =\n (extendsExpression &&\n ts.isIdentifier(extendsExpression) &&\n baseChannelImports.has(extendsExpression.text)) ||\n (extendsExpression &&\n ts.isPropertyAccessExpression(extendsExpression) &&\n ts.isIdentifier(extendsExpression.expression) &&\n socketNamespaces.has(extendsExpression.expression.text) &&\n extendsExpression.name.text === 'BaseChannel')\n\n if (!directlyExtendsBaseChannel) {\n return (\n `Omitted ${importPath}: generated contracts do not support channel inheritance; ` +\n 'the default export must directly extend BaseChannel imported from @rlanz/socket.'\n )\n }\n\n const patternMember = channelClass.members.find(\n (member): member is ts.PropertyDeclaration =>\n ts.isPropertyDeclaration(member) &&\n propertyName(member.name) === 'pattern' &&\n !!member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword)\n )\n if (\n !patternMember ||\n !patternMember.initializer ||\n !ts.isStringLiteral(patternMember.initializer)\n ) {\n return `Omitted ${importPath}: static pattern must be a direct string literal.`\n }\n\n const bindablePattern = BindableChannelPattern.parse(patternMember.initializer.text)\n if (!bindablePattern) {\n return (\n `Omitted ${importPath}: pattern ${quote(patternMember.initializer.text)} is not supported by ` +\n 'generated typing; use literals, required params, a final optional param, or a final wildcard.'\n )\n }\n\n const handlers: Handler[] = []\n for (const method of channelClass.members.filter(ts.isMethodDeclaration)) {\n for (const decorator of ts.getDecorators(method) ?? []) {\n const expression = decorator.expression\n const isImportedDecorator =\n ts.isCallExpression(expression) &&\n ((ts.isIdentifier(expression.expression) &&\n decoratorImports.has(expression.expression.text)) ||\n (ts.isPropertyAccessExpression(expression.expression) &&\n ts.isIdentifier(expression.expression.expression) &&\n decoratorNamespaces.has(expression.expression.expression.text) &&\n expression.expression.name.text === 'onMessage'))\n\n if (!isImportedDecorator || !ts.isCallExpression(expression)) {\n continue\n }\n\n if (isStatic(method)) {\n fail(filePath, '@onMessage cannot generate a contract for a static method')\n }\n\n if (expression.arguments.length !== 1 || !ts.isStringLiteral(expression.arguments[0])) {\n fail(\n filePath,\n `@onMessage on ${propertyName(method.name) ?? '<computed>'} needs a literal event`\n )\n }\n const event = expression.arguments[0].text\n const name = propertyName(method.name)\n if (!name || !ts.isIdentifier(method.name)) fail(filePath, '@onMessage methods must be named')\n if (!isPublic(method)) fail(filePath, `decorated handler method ${name} must be public`)\n validateHandlerMethod(filePath, method, name)\n if (handlers.some((handler) => handler.event === event)) {\n fail(filePath, `event \"${event}\" is mapped more than once`)\n }\n handlers.push({ event, method: name })\n }\n }\n\n return { pattern: patternMember.initializer.text, bindablePattern, importPath, handlers }\n}\n\n/** Registers generation of the application socket registry with AdonisJS Assembler. */\nexport function generateSocketRegistry(\n options: SocketAssemblerHookOptions = {}\n): SocketAssemblerHook {\n return {\n run(_parent, hooks, indexGenerator) {\n const source = options.source ?? './app/channels'\n const glob = options.glob ?? ['**/*_channel.{ts,js}']\n const importAlias = appImportAlias(source)\n\n indexGenerator.add('socketChannels', {\n source,\n glob,\n importAlias,\n output: options.output ?? './.adonisjs/client/socket.ts',\n as(vfs, buffer, _config, helpers) {\n const channels: Channel[] = []\n const diagnostics: string[] = []\n for (const filePath of Object.values(vfs.asList())) {\n const importPath = generatedImportPath(helpers.toImportPath(filePath))\n const inspected = inspectChannel(filePath, importPath)\n if (typeof inspected === 'string') diagnostics.push(inspected)\n else channels.push(inspected)\n }\n\n const patterns = new Set<string>()\n for (const channel of channels) {\n if (patterns.has(channel.bindablePattern.canonicalPattern)) {\n fail(\n channel.importPath,\n `pattern ${quote(channel.pattern)} is declared more than once`\n )\n }\n patterns.add(channel.bindablePattern.canonicalPattern)\n }\n\n for (const diagnostic of diagnostics) buffer.writeLine(`// [socket] ${diagnostic}`)\n if (diagnostics.length) buffer.writeLine('')\n buffer.writeLine('export interface AppSocket {').indent()\n buffer.writeLine('readonly channels: {').indent()\n for (const channel of channels) {\n buffer.writeLine(`readonly ${quote(channel.pattern)}: {`).indent()\n if (channel.bindablePattern.parameters.length === 0) {\n buffer.writeLine('readonly params: undefined')\n } else {\n buffer.writeLine('readonly params: {').indent()\n for (const parameter of channel.bindablePattern.parameters) {\n buffer.writeLine(\n `readonly ${quote(parameter.name)}${parameter.optional ? '?' : ''}: string | number`\n )\n }\n buffer.dedent().writeLine('}')\n }\n buffer.writeLine(\n `readonly channel: typeof import(${quote(channel.importPath)}).default`\n )\n buffer.writeLine('readonly handlers: {').indent()\n for (const handler of channel.handlers) {\n buffer.writeLine(`readonly ${quote(handler.event)}: ${quote(handler.method)}`)\n }\n buffer.dedent().writeLine('}')\n buffer.dedent().writeLine('}')\n }\n buffer.dedent().writeLine('}')\n buffer.dedent().writeLine('}')\n },\n } satisfies IndexGeneratorSourceConfig)\n\n indexGenerator.add('socketServerChannels', {\n source,\n glob,\n importAlias,\n output: './.adonisjs/server/socket_channels.ts',\n as(vfs, buffer, _config, helpers) {\n const filePaths = Object.values(vfs.asList())\n filePaths.forEach((filePath, index) => {\n const importPath = generatedImportPath(helpers.toImportPath(filePath))\n buffer.writeLine(`import Channel${index} from ${quote(importPath)}`)\n })\n if (filePaths.length) buffer.writeLine('')\n buffer.writeLine(\n `export const socketChannels = [${filePaths.map((_filePath, index) => `Channel${index}`).join(', ')}] as const`\n )\n },\n } satisfies IndexGeneratorSourceConfig)\n\n hooks.add('fileChanged', (_relativePath, absolutePath) => {\n return indexGenerator.addFile(absolutePath)\n })\n },\n }\n}\n\nconst socketRegistryHook = generateSocketRegistry()\nconst lazySocketRegistryHook: SocketAssemblerHook['run'] = socketRegistryHook.run\n\nexport default lazySocketRegistryHook\n"],"mappings":"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","names":[]}
|
|
@@ -1,152 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
export { PresenceData, SubscribeAckData, SubscribeResult } from './types.js';
|
|
3
|
-
export {
|
|
1
|
+
export { S as Socket } from '../../index-DjBYUhFR.js';
|
|
2
|
+
export { ChannelBroadcastEvent, ChannelBroadcastPayload, ChannelCallArgs, ChannelClientEvent, ChannelClientEventPayload, ChannelParameters, ChannelPattern, ConnectionState, EventHandler, PresenceData, PresenceUser, SocketOptions, SubscribeAckData, SubscribeOptions, SubscribeResult, UnsubscribeOptions } from './types.js';
|
|
3
|
+
export { a as ChannelAck, b as ChannelMessage } from '../../base_channel-DPOnqned.js';
|
|
4
4
|
import 'ws';
|
|
5
5
|
import 'node:http';
|
|
6
6
|
import '@adonisjs/core/types/http';
|
|
7
7
|
import '@adonisjs/core/http';
|
|
8
8
|
import '@boringnode/bus/types/main';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Represents a subscribed channel.
|
|
12
|
-
* Chainable API inspired by Laravel Echo.
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* ```ts
|
|
16
|
-
* socket.channel('chat/general')
|
|
17
|
-
* .here((users) => setOnlineUsers(users))
|
|
18
|
-
* .joining((user) => console.log(`${user.name} joined`))
|
|
19
|
-
* .leaving((user) => console.log(`${user.name} left`))
|
|
20
|
-
* .listen('chat:message', (msg) => addMessage(msg))
|
|
21
|
-
* .subscribe()
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
24
|
-
type UnknownContract = ChannelContract<unknown, unknown>;
|
|
25
|
-
type ClientMap<C> = C extends ChannelContract<infer E, unknown> ? E : unknown;
|
|
26
|
-
type ServerMap<C> = C extends ChannelContract<unknown, infer E> ? E : unknown;
|
|
27
|
-
type IsUnknown<T> = unknown extends T ? true : false;
|
|
28
|
-
type StringKey<T> = Extract<keyof T, string>;
|
|
29
|
-
type EventDataArgs<Payload> = undefined extends Payload ? [data?: Payload] : [data: Payload];
|
|
30
|
-
declare class Channel<Contract = UnknownContract> {
|
|
31
|
-
#private;
|
|
32
|
-
/**
|
|
33
|
-
* Channel name.
|
|
34
|
-
*/
|
|
35
|
-
readonly name: string;
|
|
36
|
-
constructor(name: string, transport: SocketClientTransport);
|
|
37
|
-
/**
|
|
38
|
-
* Whether the channel should stay subscribed.
|
|
39
|
-
*/
|
|
40
|
-
get subscribed(): boolean;
|
|
41
|
-
/** Whether a framework lifecycle currently owns this channel. @internal */
|
|
42
|
-
get $managed(): boolean;
|
|
43
|
-
/**
|
|
44
|
-
* Whether the channel is active on the server.
|
|
45
|
-
*/
|
|
46
|
-
get active(): boolean;
|
|
47
|
-
/**
|
|
48
|
-
* List of present users.
|
|
49
|
-
*/
|
|
50
|
-
get users(): PresenceUser[];
|
|
51
|
-
/**
|
|
52
|
-
* Number of present users.
|
|
53
|
-
*/
|
|
54
|
-
get count(): number;
|
|
55
|
-
/**
|
|
56
|
-
* Registers a handler called with the present users.
|
|
57
|
-
* Called immediately on subscribe and after each presence change.
|
|
58
|
-
*/
|
|
59
|
-
here(handler: EventHandler<PresenceUser[]>): this;
|
|
60
|
-
/**
|
|
61
|
-
* Registers a handler called when a user joins.
|
|
62
|
-
*/
|
|
63
|
-
joining(handler: EventHandler<PresenceUser>): this;
|
|
64
|
-
/**
|
|
65
|
-
* Registers a handler called when a user leaves.
|
|
66
|
-
*/
|
|
67
|
-
leaving(handler: EventHandler<PresenceUser>): this;
|
|
68
|
-
/**
|
|
69
|
-
* Listens for an event on this channel.
|
|
70
|
-
*/
|
|
71
|
-
listen<T = unknown>(this: IsUnknown<ServerMap<Contract>> extends true ? Channel<Contract> : never, event: string, handler: EventHandler<T>): this;
|
|
72
|
-
listen<Event extends StringKey<ServerMap<Contract>>>(this: Channel<Contract>, event: Event, handler: EventHandler<ServerMap<Contract>[Event]>): this;
|
|
73
|
-
/**
|
|
74
|
-
* Removes an event listener.
|
|
75
|
-
*/
|
|
76
|
-
stopListening<T = unknown>(this: IsUnknown<ServerMap<Contract>> extends true ? Channel<Contract> : never, event: string, handler?: EventHandler<T>): this;
|
|
77
|
-
stopListening<Event extends StringKey<ServerMap<Contract>>>(this: Channel<Contract>, event: Event, handler?: EventHandler<ServerMap<Contract>[Event]>): this;
|
|
78
|
-
/** Registers a lifecycle-owned event handler. @internal */
|
|
79
|
-
$listen(event: string, handler: EventHandler<any>): void;
|
|
80
|
-
/** Removes a lifecycle-owned event handler. @internal */
|
|
81
|
-
$stopListening(event: string, handler: EventHandler<any>): void;
|
|
82
|
-
/**
|
|
83
|
-
* Listens for a client event whispered by another channel member.
|
|
84
|
-
*/
|
|
85
|
-
listenForWhisper<T = unknown>(event: string, handler: EventHandler<T>): this;
|
|
86
|
-
/**
|
|
87
|
-
* Removes a whispered client event listener.
|
|
88
|
-
*/
|
|
89
|
-
stopListeningForWhisper<T = unknown>(event: string, handler?: EventHandler<T>): this;
|
|
90
|
-
/**
|
|
91
|
-
* Subscribes to the channel.
|
|
92
|
-
*
|
|
93
|
-
* client listeners -> subscribe ack -> active channel
|
|
94
|
-
* | | |
|
|
95
|
-
* v v v
|
|
96
|
-
* events ready presence sync send/listen
|
|
97
|
-
*/
|
|
98
|
-
subscribe(options?: SubscribeOptions): Promise<this>;
|
|
99
|
-
/** Acquires subscription intent without overriding a direct consumer. @internal */
|
|
100
|
-
$acquire(options?: SubscribeOptions): {
|
|
101
|
-
ready: Promise<Channel<Contract>>;
|
|
102
|
-
release: () => Promise<void>;
|
|
103
|
-
};
|
|
104
|
-
/** Restores desired subscriptions after the transport reconnects. @internal */
|
|
105
|
-
$resubscribe(options?: SubscribeOptions): Promise<this>;
|
|
106
|
-
/**
|
|
107
|
-
* Unsubscribes from the channel.
|
|
108
|
-
*/
|
|
109
|
-
unsubscribe(options?: UnsubscribeOptions): Promise<void>;
|
|
110
|
-
/**
|
|
111
|
-
* Sends an event to the server.
|
|
112
|
-
*/
|
|
113
|
-
send<T = unknown>(this: IsUnknown<ClientMap<Contract>> extends true ? Channel<Contract> : never, event: string, data?: T): this;
|
|
114
|
-
send<Event extends StringKey<ClientMap<Contract>>>(this: Channel<Contract>, event: Event, ...[data]: ClientMap<Contract>[Event] extends {
|
|
115
|
-
payload: infer Payload;
|
|
116
|
-
} ? EventDataArgs<Payload> : never): this;
|
|
117
|
-
/**
|
|
118
|
-
* Relays a client event to other members of this channel.
|
|
119
|
-
*/
|
|
120
|
-
whisper<T = unknown>(event: string, data?: T): this;
|
|
121
|
-
/**
|
|
122
|
-
* Sends an event and waits for a response.
|
|
123
|
-
*/
|
|
124
|
-
sendWithAck<T = unknown, Result = unknown>(this: IsUnknown<ClientMap<Contract>> extends true ? Channel<Contract> : never, event: string, data?: T): Promise<Result>;
|
|
125
|
-
sendWithAck<Event extends StringKey<ClientMap<Contract>>>(this: Channel<Contract>, event: Event, ...[data]: ClientMap<Contract>[Event] extends {
|
|
126
|
-
payload: infer Payload;
|
|
127
|
-
} ? EventDataArgs<Payload> : never): Promise<ClientMap<Contract>[Event] extends {
|
|
128
|
-
ack: infer Acknowledgement;
|
|
129
|
-
} ? Acknowledgement : unknown>;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Main Socket client.
|
|
134
|
-
*/
|
|
135
|
-
type ChannelResult<Registry, Name extends string> = string extends Name ? Channel<unknown> : [Registry] extends [never] ? Channel : ChannelContractFor<Registry, Name> extends infer Contract ? [Contract] extends [never] ? never : Channel<Contract> : never;
|
|
136
|
-
declare class Socket<Registry = never> implements SocketClientTransport {
|
|
137
|
-
#private;
|
|
138
|
-
constructor(options?: SocketOptions);
|
|
139
|
-
get state(): ConnectionState;
|
|
140
|
-
get connected(): boolean;
|
|
141
|
-
connect(): Promise<void>;
|
|
142
|
-
disconnect(): void;
|
|
143
|
-
channel<const Name extends string>(name: Name & (ChannelResult<Registry, Name> extends never ? never : unknown)): ChannelResult<Registry, Name>;
|
|
144
|
-
leave(name: string): Promise<void>;
|
|
145
|
-
onStateChange(handler: EventHandler<ConnectionState>): () => void;
|
|
146
|
-
on<T = unknown>(event: string, handler: EventHandler<T>): () => void;
|
|
147
|
-
off<T = unknown>(event: string, handler: EventHandler<T>): void;
|
|
148
|
-
send(message: Record<string, unknown>): void;
|
|
149
|
-
sendRequest<T = unknown>(message: Record<string, unknown>, timeout?: number): Promise<T>;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export { Channel, ConnectionState, EventHandler, PresenceUser, Socket, SocketOptions, SubscribeOptions, UnsubscribeOptions };
|