@rlanz/socket 0.0.1-4 → 0.0.1-6
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 +430 -26
- package/build/chunk-B4Y3TNDI.js +159 -0
- package/build/chunk-B4Y3TNDI.js.map +1 -0
- package/build/{chunk-GKAD2UOA.js → chunk-D3HUBCBW.js} +1 -1
- package/build/chunk-D3HUBCBW.js.map +1 -0
- package/build/chunk-FVPY6HZW.js +136 -0
- package/build/chunk-FVPY6HZW.js.map +1 -0
- package/build/chunk-SFAY2ZA4.js +28 -0
- package/build/chunk-SFAY2ZA4.js.map +1 -0
- package/build/{chunk-XUDFDJME.js → chunk-SHH6U4CI.js} +12 -9
- package/build/chunk-SHH6U4CI.js.map +1 -0
- package/build/chunk-YAX5EHHB.js +453 -0
- package/build/chunk-YAX5EHHB.js.map +1 -0
- package/build/framework-DuW6zpPk.d.ts +14 -0
- package/build/index.d.ts +7 -13
- package/build/index.js +18 -10
- package/build/index.js.map +1 -1
- package/build/providers/socket_provider.d.ts +4 -3
- package/build/providers/socket_provider.js +1780 -57
- package/build/providers/socket_provider.js.map +1 -1
- package/build/services/socket.d.ts +4 -3
- package/build/socket_service-D3jKrleE.d.ts +105 -0
- package/build/src/assembler_hook.d.ts +15 -0
- package/build/src/assembler_hook.js +261 -0
- package/build/src/assembler_hook.js.map +1 -0
- package/build/src/client/index.d.ts +46 -12
- package/build/src/client/index.js +223 -76
- package/build/src/client/index.js.map +1 -1
- package/build/src/client/react.d.ts +27 -0
- package/build/src/client/react.js +69 -0
- package/build/src/client/react.js.map +1 -0
- package/build/src/client/svelte.d.ts +23 -0
- package/build/src/client/svelte.js +82 -0
- package/build/src/client/svelte.js.map +1 -0
- package/build/src/client/types.d.ts +69 -5
- package/build/src/client/vue.d.ts +26 -0
- package/build/src/client/vue.js +81 -0
- package/build/src/client/vue.js.map +1 -0
- package/build/src/decorators.d.ts +4 -4
- package/build/src/decorators.js +1 -1
- package/build/src/health_check.d.ts +4 -3
- package/build/src/otel.js +4 -5
- package/build/src/otel.js.map +1 -1
- package/build/src/testing.d.ts +54 -0
- package/build/src/testing.js +7 -0
- package/build/src/testing.js.map +1 -0
- package/build/src/types.d.ts +2 -2
- package/build/{types-BBLNfcWk.d.ts → types-DiYaFvgi.d.ts} +112 -63
- package/package.json +41 -6
- package/build/chunk-GKAD2UOA.js.map +0 -1
- package/build/chunk-ILDK672E.js +0 -1921
- package/build/chunk-ILDK672E.js.map +0 -1
- package/build/chunk-XUDFDJME.js.map +0 -1
- package/build/shared_types-Dw9AphfO.d.ts +0 -21
- package/build/socket_service-CRmPa74K.d.ts +0 -144
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
// src/assembler_hook.ts
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import ts from "typescript";
|
|
4
|
+
function quote(value) {
|
|
5
|
+
return `'${value.replaceAll("\\", "\\\\").replaceAll("'", "\\'")}'`;
|
|
6
|
+
}
|
|
7
|
+
function generatedImportPath(importPath) {
|
|
8
|
+
return importPath.replace(/\.ts$/, "");
|
|
9
|
+
}
|
|
10
|
+
function appImportAlias(source) {
|
|
11
|
+
const normalized = source.replace(/^\.\//, "");
|
|
12
|
+
if (normalized === "app") return "#app";
|
|
13
|
+
if (normalized.startsWith("app/")) return `#app/${normalized.slice("app/".length)}`;
|
|
14
|
+
throw new Error("[socket] Channel source must be inside the app directory");
|
|
15
|
+
}
|
|
16
|
+
function fail(filePath, message) {
|
|
17
|
+
throw new Error(`[socket] Cannot generate client types for ${filePath}: ${message}`);
|
|
18
|
+
}
|
|
19
|
+
function propertyName(node) {
|
|
20
|
+
if (node && (ts.isIdentifier(node) || ts.isStringLiteral(node))) return node.text;
|
|
21
|
+
}
|
|
22
|
+
function isPublic(method) {
|
|
23
|
+
return !method.modifiers?.some(
|
|
24
|
+
(modifier) => modifier.kind === ts.SyntaxKind.PrivateKeyword || modifier.kind === ts.SyntaxKind.ProtectedKeyword
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
function isStatic(member) {
|
|
28
|
+
return ts.canHaveModifiers(member) && !!ts.getModifiers(member)?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword);
|
|
29
|
+
}
|
|
30
|
+
function validateHandlerMethod(filePath, method, name) {
|
|
31
|
+
const parameters = method.parameters.filter(
|
|
32
|
+
(parameter) => !(ts.isIdentifier(parameter.name) && parameter.name.text === "this")
|
|
33
|
+
);
|
|
34
|
+
if (parameters.some((parameter) => parameter.dotDotDotToken)) {
|
|
35
|
+
fail(filePath, `handler method ${name} must not use rest parameters`);
|
|
36
|
+
}
|
|
37
|
+
if (parameters.slice(2).some((parameter) => !parameter.questionToken && !parameter.initializer)) {
|
|
38
|
+
fail(filePath, `handler method ${name} must not require parameters after the payload`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
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
|
+
function inspectChannel(filePath, importPath) {
|
|
56
|
+
const source = ts.createSourceFile(
|
|
57
|
+
filePath,
|
|
58
|
+
fs.readFileSync(filePath, "utf8"),
|
|
59
|
+
ts.ScriptTarget.Latest,
|
|
60
|
+
true,
|
|
61
|
+
filePath.endsWith(".js") ? ts.ScriptKind.JS : ts.ScriptKind.TS
|
|
62
|
+
);
|
|
63
|
+
const decoratorImports = /* @__PURE__ */ new Set();
|
|
64
|
+
const decoratorNamespaces = /* @__PURE__ */ new Set();
|
|
65
|
+
const baseChannelImports = /* @__PURE__ */ new Set();
|
|
66
|
+
const socketNamespaces = /* @__PURE__ */ new Set();
|
|
67
|
+
for (const statement of source.statements) {
|
|
68
|
+
if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier) || statement.moduleSpecifier.text !== "@rlanz/socket/decorators" && statement.moduleSpecifier.text !== "@rlanz/socket") {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const bindings = statement.importClause?.namedBindings;
|
|
72
|
+
if (bindings && ts.isNamedImports(bindings)) {
|
|
73
|
+
for (const binding of bindings.elements) {
|
|
74
|
+
const importedName = (binding.propertyName ?? binding.name).text;
|
|
75
|
+
if (statement.moduleSpecifier.text === "@rlanz/socket/decorators" && importedName === "onMessage") {
|
|
76
|
+
decoratorImports.add(binding.name.text);
|
|
77
|
+
}
|
|
78
|
+
if (statement.moduleSpecifier.text === "@rlanz/socket" && importedName === "BaseChannel") {
|
|
79
|
+
baseChannelImports.add(binding.name.text);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} else if (bindings && ts.isNamespaceImport(bindings)) {
|
|
83
|
+
if (statement.moduleSpecifier.text === "@rlanz/socket/decorators") {
|
|
84
|
+
decoratorNamespaces.add(bindings.name.text);
|
|
85
|
+
} else {
|
|
86
|
+
socketNamespaces.add(bindings.name.text);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const classes = source.statements.filter(ts.isClassDeclaration);
|
|
91
|
+
let channelClass = classes.find(
|
|
92
|
+
(node) => node.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.DefaultKeyword)
|
|
93
|
+
);
|
|
94
|
+
if (!channelClass) {
|
|
95
|
+
const defaultExport = source.statements.find(
|
|
96
|
+
(node) => ts.isExportAssignment(node) && !node.isExportEquals
|
|
97
|
+
);
|
|
98
|
+
if (defaultExport && ts.isIdentifier(defaultExport.expression)) {
|
|
99
|
+
const defaultClassName = defaultExport.expression.text;
|
|
100
|
+
channelClass = classes.find((node) => node.name?.text === defaultClassName);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (!channelClass) fail(filePath, "a default-exported channel class was not found");
|
|
104
|
+
if (channelClass.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.AbstractKeyword)) {
|
|
105
|
+
fail(filePath, "the default-exported channel class must not be abstract");
|
|
106
|
+
}
|
|
107
|
+
const extendsType = channelClass.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types.at(0);
|
|
108
|
+
const extendsExpression = extendsType?.expression;
|
|
109
|
+
const directlyExtendsBaseChannel = extendsExpression && ts.isIdentifier(extendsExpression) && baseChannelImports.has(extendsExpression.text) || extendsExpression && ts.isPropertyAccessExpression(extendsExpression) && ts.isIdentifier(extendsExpression.expression) && socketNamespaces.has(extendsExpression.expression.text) && extendsExpression.name.text === "BaseChannel";
|
|
110
|
+
if (!directlyExtendsBaseChannel) {
|
|
111
|
+
return `Omitted ${importPath}: generated contracts do not support channel inheritance; the default export must directly extend BaseChannel imported from @rlanz/socket.`;
|
|
112
|
+
}
|
|
113
|
+
const patternMember = channelClass.members.find(
|
|
114
|
+
(member) => ts.isPropertyDeclaration(member) && propertyName(member.name) === "pattern" && !!member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword)
|
|
115
|
+
);
|
|
116
|
+
if (!patternMember || !patternMember.initializer || !ts.isStringLiteral(patternMember.initializer)) {
|
|
117
|
+
return `Omitted ${importPath}: static pattern must be a direct string literal.`;
|
|
118
|
+
}
|
|
119
|
+
if (!isSupportedPattern(patternMember.initializer.text)) {
|
|
120
|
+
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
|
+
}
|
|
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
|
+
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
|
+
for (const method of channelClass.members.filter(ts.isMethodDeclaration)) {
|
|
159
|
+
for (const decorator of ts.getDecorators(method) ?? []) {
|
|
160
|
+
const expression = decorator.expression;
|
|
161
|
+
const isImportedDecorator = ts.isCallExpression(expression) && (ts.isIdentifier(expression.expression) && decoratorImports.has(expression.expression.text) || ts.isPropertyAccessExpression(expression.expression) && ts.isIdentifier(expression.expression.expression) && decoratorNamespaces.has(expression.expression.expression.text) && expression.expression.name.text === "onMessage");
|
|
162
|
+
if (!isImportedDecorator || !ts.isCallExpression(expression)) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
if (isStatic(method)) {
|
|
166
|
+
fail(filePath, "@onMessage cannot generate a contract for a static method");
|
|
167
|
+
}
|
|
168
|
+
if (expression.arguments.length !== 1 || !ts.isStringLiteral(expression.arguments[0])) {
|
|
169
|
+
fail(
|
|
170
|
+
filePath,
|
|
171
|
+
`@onMessage on ${propertyName(method.name) ?? "<computed>"} needs a literal event`
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
const event = expression.arguments[0].text;
|
|
175
|
+
const name = propertyName(method.name);
|
|
176
|
+
if (!name || !ts.isIdentifier(method.name)) fail(filePath, "@onMessage methods must be named");
|
|
177
|
+
if (!isPublic(method)) fail(filePath, `decorated handler method ${name} must be public`);
|
|
178
|
+
validateHandlerMethod(filePath, method, name);
|
|
179
|
+
if (handlers.some((handler) => handler.event === event)) {
|
|
180
|
+
fail(filePath, `event "${event}" is mapped more than once`);
|
|
181
|
+
}
|
|
182
|
+
handlers.push({ event, method: name });
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return { pattern: patternMember.initializer.text, importPath, handlers };
|
|
186
|
+
}
|
|
187
|
+
function generateSocketRegistry(options = {}) {
|
|
188
|
+
return {
|
|
189
|
+
run(_parent, hooks, indexGenerator) {
|
|
190
|
+
const source = options.source ?? "./app/channels";
|
|
191
|
+
const glob = options.glob ?? ["**/*_channel.{ts,js}"];
|
|
192
|
+
const importAlias = appImportAlias(source);
|
|
193
|
+
indexGenerator.add("socketChannels", {
|
|
194
|
+
source,
|
|
195
|
+
glob,
|
|
196
|
+
importAlias,
|
|
197
|
+
output: options.output ?? "./.adonisjs/client/socket.ts",
|
|
198
|
+
as(vfs, buffer, _config, helpers) {
|
|
199
|
+
const channels = [];
|
|
200
|
+
const diagnostics = [];
|
|
201
|
+
for (const filePath of Object.values(vfs.asList())) {
|
|
202
|
+
const importPath = generatedImportPath(helpers.toImportPath(filePath));
|
|
203
|
+
const inspected = inspectChannel(filePath, importPath);
|
|
204
|
+
if (typeof inspected === "string") diagnostics.push(inspected);
|
|
205
|
+
else channels.push(inspected);
|
|
206
|
+
}
|
|
207
|
+
for (const diagnostic of diagnostics) buffer.writeLine(`// [socket] ${diagnostic}`);
|
|
208
|
+
if (diagnostics.length) buffer.writeLine("");
|
|
209
|
+
buffer.writeLine("export interface AppSocket {").indent();
|
|
210
|
+
if (diagnostics.length) {
|
|
211
|
+
buffer.writeLine("readonly uncertain: true");
|
|
212
|
+
}
|
|
213
|
+
buffer.writeLine("readonly channels: readonly [").indent();
|
|
214
|
+
for (const channel of channels) {
|
|
215
|
+
buffer.writeLine("{").indent();
|
|
216
|
+
buffer.writeLine(`readonly pattern: ${quote(channel.pattern)}`);
|
|
217
|
+
buffer.writeLine(
|
|
218
|
+
`readonly channel: typeof import(${quote(channel.importPath)}).default`
|
|
219
|
+
);
|
|
220
|
+
buffer.writeLine("readonly handlers: {").indent();
|
|
221
|
+
for (const handler of channel.handlers) {
|
|
222
|
+
buffer.writeLine(`readonly ${quote(handler.event)}: ${quote(handler.method)}`);
|
|
223
|
+
}
|
|
224
|
+
buffer.dedent().writeLine("}");
|
|
225
|
+
buffer.dedent().writeLine("},");
|
|
226
|
+
}
|
|
227
|
+
buffer.dedent().writeLine("]");
|
|
228
|
+
buffer.dedent().writeLine("}");
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
indexGenerator.add("socketServerChannels", {
|
|
232
|
+
source,
|
|
233
|
+
glob,
|
|
234
|
+
importAlias,
|
|
235
|
+
output: "./.adonisjs/server/socket_channels.ts",
|
|
236
|
+
as(vfs, buffer, _config, helpers) {
|
|
237
|
+
const filePaths = Object.values(vfs.asList());
|
|
238
|
+
filePaths.forEach((filePath, index) => {
|
|
239
|
+
const importPath = generatedImportPath(helpers.toImportPath(filePath));
|
|
240
|
+
buffer.writeLine(`import Channel${index} from ${quote(importPath)}`);
|
|
241
|
+
});
|
|
242
|
+
if (filePaths.length) buffer.writeLine("");
|
|
243
|
+
buffer.writeLine(
|
|
244
|
+
`export const socketChannels = [${filePaths.map((_filePath, index) => `Channel${index}`).join(", ")}] as const`
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
hooks.add("fileChanged", (_relativePath, absolutePath) => {
|
|
249
|
+
return indexGenerator.addFile(absolutePath);
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
var socketRegistryHook = generateSocketRegistry();
|
|
255
|
+
var lazySocketRegistryHook = socketRegistryHook.run;
|
|
256
|
+
var assembler_hook_default = lazySocketRegistryHook;
|
|
257
|
+
export {
|
|
258
|
+
assembler_hook_default as default,
|
|
259
|
+
generateSocketRegistry
|
|
260
|
+
};
|
|
261
|
+
//# sourceMappingURL=assembler_hook.js.map
|
|
@@ -0,0 +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":";AAAA,OAAO,QAAQ;AACf,OAAO,QAAQ;AAcf,SAAS,MAAM,OAAe;AAC5B,SAAO,IAAI,MAAM,WAAW,MAAM,MAAM,EAAE,WAAW,KAAK,KAAK,CAAC;AAClE;AAEA,SAAS,oBAAoB,YAA4B;AACvD,SAAO,WAAW,QAAQ,SAAS,EAAE;AACvC;AAEA,SAAS,eAAe,QAAwB;AAC9C,QAAM,aAAa,OAAO,QAAQ,SAAS,EAAE;AAC7C,MAAI,eAAe,MAAO,QAAO;AACjC,MAAI,WAAW,WAAW,MAAM,EAAG,QAAO,QAAQ,WAAW,MAAM,OAAO,MAAM,CAAC;AACjF,QAAM,IAAI,MAAM,0DAA0D;AAC5E;AAEA,SAAS,KAAK,UAAkB,SAAwB;AACtD,QAAM,IAAI,MAAM,6CAA6C,QAAQ,KAAK,OAAO,EAAE;AACrF;AAEA,SAAS,aAAa,MAAuD;AAC3E,MAAI,SAAS,GAAG,aAAa,IAAI,KAAK,GAAG,gBAAgB,IAAI,GAAI,QAAO,KAAK;AAC/E;AAEA,SAAS,SAAS,QAA8B;AAC9C,SAAO,CAAC,OAAO,WAAW;AAAA,IACxB,CAAC,aACC,SAAS,SAAS,GAAG,WAAW,kBAChC,SAAS,SAAS,GAAG,WAAW;AAAA,EACpC;AACF;AAEA,SAAS,SAAS,QAAkC;AAClD,SACE,GAAG,iBAAiB,MAAM,KAC1B,CAAC,CAAC,GAAG,aAAa,MAAM,GAAG,KAAK,CAAC,aAAa,SAAS,SAAS,GAAG,WAAW,aAAa;AAE/F;AAEA,SAAS,sBAAsB,UAAkB,QAA8B,MAAoB;AACjG,QAAM,aAAa,OAAO,WAAW;AAAA,IACnC,CAAC,cAAc,EAAE,GAAG,aAAa,UAAU,IAAI,KAAK,UAAU,KAAK,SAAS;AAAA,EAC9E;AACA,MAAI,WAAW,KAAK,CAAC,cAAc,UAAU,cAAc,GAAG;AAC5D,SAAK,UAAU,kBAAkB,IAAI,+BAA+B;AAAA,EACtE;AACA,MAAI,WAAW,MAAM,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,UAAU,iBAAiB,CAAC,UAAU,WAAW,GAAG;AAC/F,SAAK,UAAU,kBAAkB,IAAI,gDAAgD;AAAA,EACvF;AACF;AAEA,SAAS,mBAAmB,SAA0B;AACpD,QAAM,aAAa,YAAY,MAAM,MAAM,QAAQ,QAAQ,OAAO,EAAE,EAAE,QAAQ,OAAO,EAAE;AACvF,MAAI,eAAe,KAAK;AACtB,WAAO;AAAA,EACT;AACA,QAAM,WAAW,WAAW,MAAM,GAAG;AAErC,SAAO,SAAS,MAAM,CAAC,SAAS,UAAU;AACxC,UAAM,UAAU,UAAU,SAAS,SAAS;AAC5C,UAAM,UAAU,QAAQ,SAAS,KAAK,CAAC,QAAQ,KAAK,OAAO;AAC3D,UAAM,gBAAgB,eAAe,KAAK,OAAO;AACjD,UAAM,gBAAgB,iBAAiB,KAAK,OAAO;AAEnD,WAAO,WAAW,iBAAkB,YAAY,iBAAiB,YAAY;AAAA,EAC/E,CAAC;AACH;AAEA,SAAS,eAAe,UAAkB,YAAsC;AAC9E,QAAM,SAAS,GAAG;AAAA,IAChB;AAAA,IACA,GAAG,aAAa,UAAU,MAAM;AAAA,IAChC,GAAG,aAAa;AAAA,IAChB;AAAA,IACA,SAAS,SAAS,KAAK,IAAI,GAAG,WAAW,KAAK,GAAG,WAAW;AAAA,EAC9D;AACA,QAAM,mBAAmB,oBAAI,IAAY;AACzC,QAAM,sBAAsB,oBAAI,IAAY;AAC5C,QAAM,qBAAqB,oBAAI,IAAY;AAC3C,QAAM,mBAAmB,oBAAI,IAAY;AAEzC,aAAW,aAAa,OAAO,YAAY;AACzC,QACE,CAAC,GAAG,oBAAoB,SAAS,KACjC,CAAC,GAAG,gBAAgB,UAAU,eAAe,KAC5C,UAAU,gBAAgB,SAAS,8BAClC,UAAU,gBAAgB,SAAS,iBACrC;AACA;AAAA,IACF;AAEA,UAAM,WAAW,UAAU,cAAc;AACzC,QAAI,YAAY,GAAG,eAAe,QAAQ,GAAG;AAC3C,iBAAW,WAAW,SAAS,UAAU;AACvC,cAAM,gBAAgB,QAAQ,gBAAgB,QAAQ,MAAM;AAC5D,YACE,UAAU,gBAAgB,SAAS,8BACnC,iBAAiB,aACjB;AACA,2BAAiB,IAAI,QAAQ,KAAK,IAAI;AAAA,QACxC;AACA,YAAI,UAAU,gBAAgB,SAAS,mBAAmB,iBAAiB,eAAe;AACxF,6BAAmB,IAAI,QAAQ,KAAK,IAAI;AAAA,QAC1C;AAAA,MACF;AAAA,IACF,WAAW,YAAY,GAAG,kBAAkB,QAAQ,GAAG;AACrD,UAAI,UAAU,gBAAgB,SAAS,4BAA4B;AACjE,4BAAoB,IAAI,SAAS,KAAK,IAAI;AAAA,MAC5C,OAAO;AACL,yBAAiB,IAAI,SAAS,KAAK,IAAI;AAAA,MACzC;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,OAAO,WAAW,OAAO,GAAG,kBAAkB;AAC9D,MAAI,eAAe,QAAQ;AAAA,IAAK,CAAC,SAC/B,KAAK,WAAW,KAAK,CAAC,aAAa,SAAS,SAAS,GAAG,WAAW,cAAc;AAAA,EACnF;AAEA,MAAI,CAAC,cAAc;AACjB,UAAM,gBAAgB,OAAO,WAAW;AAAA,MACtC,CAAC,SAAsC,GAAG,mBAAmB,IAAI,KAAK,CAAC,KAAK;AAAA,IAC9E;AACA,QAAI,iBAAiB,GAAG,aAAa,cAAc,UAAU,GAAG;AAC9D,YAAM,mBAAmB,cAAc,WAAW;AAClD,qBAAe,QAAQ,KAAK,CAAC,SAAS,KAAK,MAAM,SAAS,gBAAgB;AAAA,IAC5E;AAAA,EACF;AACA,MAAI,CAAC,aAAc,MAAK,UAAU,gDAAgD;AAClF,MAAI,aAAa,WAAW,KAAK,CAAC,aAAa,SAAS,SAAS,GAAG,WAAW,eAAe,GAAG;AAC/F,SAAK,UAAU,yDAAyD;AAAA,EAC1E;AAEA,QAAM,cAAc,aAAa,iBAC7B,KAAK,CAAC,WAAW,OAAO,UAAU,GAAG,WAAW,cAAc,GAC9D,MAAM,GAAG,CAAC;AACd,QAAM,oBAAoB,aAAa;AACvC,QAAM,6BACH,qBACC,GAAG,aAAa,iBAAiB,KACjC,mBAAmB,IAAI,kBAAkB,IAAI,KAC9C,qBACC,GAAG,2BAA2B,iBAAiB,KAC/C,GAAG,aAAa,kBAAkB,UAAU,KAC5C,iBAAiB,IAAI,kBAAkB,WAAW,IAAI,KACtD,kBAAkB,KAAK,SAAS;AAEpC,MAAI,CAAC,4BAA4B;AAC/B,WACE,WAAW,UAAU;AAAA,EAGzB;AAEA,QAAM,gBAAgB,aAAa,QAAQ;AAAA,IACzC,CAAC,WACC,GAAG,sBAAsB,MAAM,KAC/B,aAAa,OAAO,IAAI,MAAM,aAC9B,CAAC,CAAC,OAAO,WAAW,KAAK,CAAC,aAAa,SAAS,SAAS,GAAG,WAAW,aAAa;AAAA,EACxF;AACA,MACE,CAAC,iBACD,CAAC,cAAc,eACf,CAAC,GAAG,gBAAgB,cAAc,WAAW,GAC7C;AACA,WAAO,WAAW,UAAU;AAAA,EAC9B;AAEA,MAAI,CAAC,mBAAmB,cAAc,YAAY,IAAI,GAAG;AACvD,WACE,WAAW,UAAU,aAAa,MAAM,cAAc,YAAY,IAAI,CAAC;AAAA,EAG3E;AAEA,QAAM,UAAU,oBAAI,IAAkC;AACtD,aAAW,UAAU,aAAa,SAAS;AACzC,QAAI,GAAG,oBAAoB,MAAM,KAAK,CAAC,SAAS,MAAM,GAAG;AACvD,YAAM,OAAO,aAAa,OAAO,IAAI;AACrC,UAAI,KAAM,SAAQ,IAAI,MAAM,MAAM;AAAA,IACpC;AAAA,EACF;AAEA,QAAM,WAAsB,CAAC;AAC7B,QAAM,gBAAgB,aAAa,QAAQ;AAAA,IACzC,CAAC,WACC,GAAG,sBAAsB,MAAM,KAC/B,CAAC,SAAS,MAAM,KAChB,aAAa,OAAO,IAAI,MAAM;AAAA,EAClC;AACA,MAAI,eAAe;AACjB,QAAI,CAAC,cAAc,eAAe,CAAC,GAAG,0BAA0B,cAAc,WAAW,GAAG;AAC1F,WAAK,UAAU,oCAAoC;AAAA,IACrD;AACA,eAAW,YAAY,cAAc,YAAY,YAAY;AAC3D,UAAI,CAAC,GAAG,qBAAqB,QAAQ,KAAK,CAAC,GAAG,gBAAgB,SAAS,IAAI,GAAG;AAC5E,aAAK,UAAU,mDAAmD;AAAA,MACpE;AACA,YAAM,QAAQ,SAAS,KAAK;AAC5B,YAAM,QAAQ,SAAS;AACvB,UACE,CAAC,GAAG,2BAA2B,KAAK,KACpC,MAAM,WAAW,SAAS,GAAG,WAAW,eACxC,CAAC,GAAG,aAAa,MAAM,IAAI,GAC3B;AACA,aAAK,UAAU,YAAY,KAAK,sCAAsC;AAAA,MACxE;AACA,YAAM,SAAS,QAAQ,IAAI,MAAM,KAAK,IAAI;AAC1C,UAAI,CAAC,OAAQ,MAAK,UAAU,YAAY,KAAK,+BAA+B,MAAM,KAAK,IAAI,EAAE;AAC7F,UAAI,CAAC,SAAS,MAAM,GAAG;AACrB,aAAK,UAAU,kBAAkB,MAAM,KAAK,IAAI,iBAAiB;AAAA,MACnE;AACA,4BAAsB,UAAU,QAAQ,MAAM,KAAK,IAAI;AACvD,UAAI,SAAS,KAAK,CAAC,YAAY,QAAQ,UAAU,KAAK,GAAG;AACvD,aAAK,UAAU,UAAU,KAAK,4BAA4B;AAAA,MAC5D;AACA,eAAS,KAAK,EAAE,OAAO,QAAQ,MAAM,KAAK,KAAK,CAAC;AAAA,IAClD;AAAA,EACF;AAEA,aAAW,UAAU,aAAa,QAAQ,OAAO,GAAG,mBAAmB,GAAG;AACxE,eAAW,aAAa,GAAG,cAAc,MAAM,KAAK,CAAC,GAAG;AACtD,YAAM,aAAa,UAAU;AAC7B,YAAM,sBACJ,GAAG,iBAAiB,UAAU,MAC5B,GAAG,aAAa,WAAW,UAAU,KACrC,iBAAiB,IAAI,WAAW,WAAW,IAAI,KAC9C,GAAG,2BAA2B,WAAW,UAAU,KAClD,GAAG,aAAa,WAAW,WAAW,UAAU,KAChD,oBAAoB,IAAI,WAAW,WAAW,WAAW,IAAI,KAC7D,WAAW,WAAW,KAAK,SAAS;AAE1C,UAAI,CAAC,uBAAuB,CAAC,GAAG,iBAAiB,UAAU,GAAG;AAC5D;AAAA,MACF;AAEA,UAAI,SAAS,MAAM,GAAG;AACpB,aAAK,UAAU,2DAA2D;AAAA,MAC5E;AAEA,UAAI,WAAW,UAAU,WAAW,KAAK,CAAC,GAAG,gBAAgB,WAAW,UAAU,CAAC,CAAC,GAAG;AACrF;AAAA,UACE;AAAA,UACA,iBAAiB,aAAa,OAAO,IAAI,KAAK,YAAY;AAAA,QAC5D;AAAA,MACF;AACA,YAAM,QAAQ,WAAW,UAAU,CAAC,EAAE;AACtC,YAAM,OAAO,aAAa,OAAO,IAAI;AACrC,UAAI,CAAC,QAAQ,CAAC,GAAG,aAAa,OAAO,IAAI,EAAG,MAAK,UAAU,kCAAkC;AAC7F,UAAI,CAAC,SAAS,MAAM,EAAG,MAAK,UAAU,4BAA4B,IAAI,iBAAiB;AACvF,4BAAsB,UAAU,QAAQ,IAAI;AAC5C,UAAI,SAAS,KAAK,CAAC,YAAY,QAAQ,UAAU,KAAK,GAAG;AACvD,aAAK,UAAU,UAAU,KAAK,4BAA4B;AAAA,MAC5D;AACA,eAAS,KAAK,EAAE,OAAO,QAAQ,KAAK,CAAC;AAAA,IACvC;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,cAAc,YAAY,MAAM,YAAY,SAAS;AACzE;AAGO,SAAS,uBACd,UAAsC,CAAC,GAClB;AACrB,SAAO;AAAA,IACL,IAAI,SAAS,OAAO,gBAAgB;AAClC,YAAM,SAAS,QAAQ,UAAU;AACjC,YAAM,OAAO,QAAQ,QAAQ,CAAC,sBAAsB;AACpD,YAAM,cAAc,eAAe,MAAM;AAEzC,qBAAe,IAAI,kBAAkB;AAAA,QACnC;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ,QAAQ,UAAU;AAAA,QAC1B,GAAG,KAAK,QAAQ,SAAS,SAAS;AAChC,gBAAM,WAAsB,CAAC;AAC7B,gBAAM,cAAwB,CAAC;AAC/B,qBAAW,YAAY,OAAO,OAAO,IAAI,OAAO,CAAC,GAAG;AAClD,kBAAM,aAAa,oBAAoB,QAAQ,aAAa,QAAQ,CAAC;AACrE,kBAAM,YAAY,eAAe,UAAU,UAAU;AACrD,gBAAI,OAAO,cAAc,SAAU,aAAY,KAAK,SAAS;AAAA,gBACxD,UAAS,KAAK,SAAS;AAAA,UAC9B;AAEA,qBAAW,cAAc,YAAa,QAAO,UAAU,eAAe,UAAU,EAAE;AAClF,cAAI,YAAY,OAAQ,QAAO,UAAU,EAAE;AAC3C,iBAAO,UAAU,8BAA8B,EAAE,OAAO;AACxD,cAAI,YAAY,QAAQ;AACtB,mBAAO,UAAU,0BAA0B;AAAA,UAC7C;AACA,iBAAO,UAAU,+BAA+B,EAAE,OAAO;AACzD,qBAAW,WAAW,UAAU;AAC9B,mBAAO,UAAU,GAAG,EAAE,OAAO;AAC7B,mBAAO,UAAU,qBAAqB,MAAM,QAAQ,OAAO,CAAC,EAAE;AAC9D,mBAAO;AAAA,cACL,mCAAmC,MAAM,QAAQ,UAAU,CAAC;AAAA,YAC9D;AACA,mBAAO,UAAU,sBAAsB,EAAE,OAAO;AAChD,uBAAW,WAAW,QAAQ,UAAU;AACtC,qBAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,CAAC,KAAK,MAAM,QAAQ,MAAM,CAAC,EAAE;AAAA,YAC/E;AACA,mBAAO,OAAO,EAAE,UAAU,GAAG;AAC7B,mBAAO,OAAO,EAAE,UAAU,IAAI;AAAA,UAChC;AACA,iBAAO,OAAO,EAAE,UAAU,GAAG;AAC7B,iBAAO,OAAO,EAAE,UAAU,GAAG;AAAA,QAC/B;AAAA,MACF,CAAsC;AAEtC,qBAAe,IAAI,wBAAwB;AAAA,QACzC;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,QACR,GAAG,KAAK,QAAQ,SAAS,SAAS;AAChC,gBAAM,YAAY,OAAO,OAAO,IAAI,OAAO,CAAC;AAC5C,oBAAU,QAAQ,CAAC,UAAU,UAAU;AACrC,kBAAM,aAAa,oBAAoB,QAAQ,aAAa,QAAQ,CAAC;AACrE,mBAAO,UAAU,iBAAiB,KAAK,SAAS,MAAM,UAAU,CAAC,EAAE;AAAA,UACrE,CAAC;AACD,cAAI,UAAU,OAAQ,QAAO,UAAU,EAAE;AACzC,iBAAO;AAAA,YACL,kCAAkC,UAAU,IAAI,CAAC,WAAW,UAAU,UAAU,KAAK,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,UACrG;AAAA,QACF;AAAA,MACF,CAAsC;AAEtC,YAAM,IAAI,eAAe,CAAC,eAAe,iBAAiB;AACxD,eAAO,eAAe,QAAQ,YAAY;AAAA,MAC5C,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,IAAM,qBAAqB,uBAAuB;AAClD,IAAM,yBAAqD,mBAAmB;AAE9E,IAAO,yBAAQ;","names":[]}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import { SocketClientTransport, PresenceUser, EventHandler, SubscribeOptions, UnsubscribeOptions, SocketOptions, ConnectionState } from './types.js';
|
|
1
|
+
import { ChannelContract, SocketClientTransport, PresenceUser, EventHandler, SubscribeOptions, UnsubscribeOptions, SocketOptions, ConnectionState, ChannelContractFor } from './types.js';
|
|
2
2
|
export { PresenceData, SubscribeAckData, SubscribeResult } from './types.js';
|
|
3
|
-
export {
|
|
3
|
+
export { b as ChannelAck, c as ChannelMessage } from '../../types-DiYaFvgi.js';
|
|
4
|
+
import 'ws';
|
|
5
|
+
import 'node:http';
|
|
6
|
+
import '@adonisjs/core/types/http';
|
|
7
|
+
import '@adonisjs/core/http';
|
|
8
|
+
import '@boringnode/bus/types/main';
|
|
4
9
|
|
|
5
10
|
/**
|
|
6
11
|
* Represents a subscribed channel.
|
|
@@ -16,7 +21,13 @@ export { C as ChannelAck, a as ChannelMessage } from '../../shared_types-Dw9Aphf
|
|
|
16
21
|
* .subscribe()
|
|
17
22
|
* ```
|
|
18
23
|
*/
|
|
19
|
-
|
|
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> {
|
|
20
31
|
#private;
|
|
21
32
|
/**
|
|
22
33
|
* Channel name.
|
|
@@ -27,6 +38,8 @@ declare class Channel {
|
|
|
27
38
|
* Whether the channel should stay subscribed.
|
|
28
39
|
*/
|
|
29
40
|
get subscribed(): boolean;
|
|
41
|
+
/** Whether a framework lifecycle currently owns this channel. @internal */
|
|
42
|
+
get $managed(): boolean;
|
|
30
43
|
/**
|
|
31
44
|
* Whether the channel is active on the server.
|
|
32
45
|
*/
|
|
@@ -55,11 +68,17 @@ declare class Channel {
|
|
|
55
68
|
/**
|
|
56
69
|
* Listens for an event on this channel.
|
|
57
70
|
*/
|
|
58
|
-
listen<T = unknown>(event: string, handler: EventHandler<T>): this;
|
|
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;
|
|
59
73
|
/**
|
|
60
74
|
* Removes an event listener.
|
|
61
75
|
*/
|
|
62
|
-
stopListening(event: string, handler?: EventHandler): this;
|
|
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;
|
|
63
82
|
/**
|
|
64
83
|
* Listens for a client event whispered by another channel member.
|
|
65
84
|
*/
|
|
@@ -67,7 +86,7 @@ declare class Channel {
|
|
|
67
86
|
/**
|
|
68
87
|
* Removes a whispered client event listener.
|
|
69
88
|
*/
|
|
70
|
-
stopListeningForWhisper(event: string, handler?: EventHandler): this;
|
|
89
|
+
stopListeningForWhisper<T = unknown>(event: string, handler?: EventHandler<T>): this;
|
|
71
90
|
/**
|
|
72
91
|
* Subscribes to the channel.
|
|
73
92
|
*
|
|
@@ -77,6 +96,13 @@ declare class Channel {
|
|
|
77
96
|
* events ready presence sync send/listen
|
|
78
97
|
*/
|
|
79
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>;
|
|
80
106
|
/**
|
|
81
107
|
* Unsubscribes from the channel.
|
|
82
108
|
*/
|
|
@@ -84,7 +110,10 @@ declare class Channel {
|
|
|
84
110
|
/**
|
|
85
111
|
* Sends an event to the server.
|
|
86
112
|
*/
|
|
87
|
-
send<T = unknown>(event: string, data?: T): this;
|
|
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;
|
|
88
117
|
/**
|
|
89
118
|
* Relays a client event to other members of this channel.
|
|
90
119
|
*/
|
|
@@ -92,25 +121,30 @@ declare class Channel {
|
|
|
92
121
|
/**
|
|
93
122
|
* Sends an event and waits for a response.
|
|
94
123
|
*/
|
|
95
|
-
sendWithAck<T = unknown,
|
|
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>;
|
|
96
130
|
}
|
|
97
131
|
|
|
98
132
|
/**
|
|
99
133
|
* Main Socket client.
|
|
100
134
|
*/
|
|
101
|
-
|
|
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 {
|
|
102
137
|
#private;
|
|
103
138
|
constructor(options?: SocketOptions);
|
|
104
139
|
get state(): ConnectionState;
|
|
105
140
|
get connected(): boolean;
|
|
106
|
-
get id(): string | undefined;
|
|
107
141
|
connect(): Promise<void>;
|
|
108
142
|
disconnect(): void;
|
|
109
|
-
channel(name:
|
|
143
|
+
channel<const Name extends string>(name: Name & (ChannelResult<Registry, Name> extends never ? never : unknown)): ChannelResult<Registry, Name>;
|
|
110
144
|
leave(name: string): Promise<void>;
|
|
111
145
|
onStateChange(handler: EventHandler<ConnectionState>): () => void;
|
|
112
146
|
on<T = unknown>(event: string, handler: EventHandler<T>): () => void;
|
|
113
|
-
off(event: string, handler: EventHandler): void;
|
|
147
|
+
off<T = unknown>(event: string, handler: EventHandler<T>): void;
|
|
114
148
|
send(message: Record<string, unknown>): void;
|
|
115
149
|
sendRequest<T = unknown>(message: Record<string, unknown>, timeout?: number): Promise<T>;
|
|
116
150
|
}
|