@rlanz/socket 0.0.1-5 → 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 +12 -13
- package/build/{chunk-ANT2E3LT.js → chunk-FVPY6HZW.js} +1 -1
- package/build/chunk-FVPY6HZW.js.map +1 -0
- package/build/{framework-CvxgHwbv.d.ts → framework-DuW6zpPk.d.ts} +4 -2
- package/build/index.d.ts +3 -3
- package/build/providers/socket_provider.d.ts +2 -2
- package/build/providers/socket_provider.js +6 -0
- package/build/providers/socket_provider.js.map +1 -1
- package/build/services/socket.d.ts +2 -2
- package/build/{socket_service-mybqv1hj.d.ts → socket_service-D3jKrleE.d.ts} +1 -1
- package/build/src/assembler_hook.d.ts +6 -4
- package/build/src/assembler_hook.js +16 -4
- package/build/src/assembler_hook.js.map +1 -1
- package/build/src/client/index.d.ts +1 -1
- package/build/src/client/react.d.ts +2 -2
- package/build/src/client/react.js +1 -1
- package/build/src/client/svelte.d.ts +5 -4
- package/build/src/client/svelte.js +1 -1
- package/build/src/client/svelte.js.map +1 -1
- package/build/src/client/types.d.ts +4 -3
- package/build/src/client/vue.d.ts +5 -4
- package/build/src/client/vue.js +1 -1
- package/build/src/client/vue.js.map +1 -1
- package/build/src/decorators.d.ts +1 -1
- package/build/src/health_check.d.ts +2 -2
- package/build/src/types.d.ts +1 -1
- package/build/{types-C7Q36ryo.d.ts → types-DiYaFvgi.d.ts} +4 -0
- package/package.json +1 -1
- package/build/chunk-ANT2E3LT.js.map +0 -1
package/README.md
CHANGED
|
@@ -435,19 +435,19 @@ uncertain; runtime channel inheritance remains valid.
|
|
|
435
435
|
The default Assembler hook discovers `app/channels/**/*_channel.{ts,js}` and generates both
|
|
436
436
|
`.adonisjs/client/socket.ts` and `.adonisjs/server/socket_channels.ts`. Configure the frontend
|
|
437
437
|
project to resolve an alias such as `#generated/socket` to the client file; this frontend mapping is
|
|
438
|
-
separate from the AdonisJS server `#generated/*` mapping.
|
|
439
|
-
default
|
|
440
|
-
`
|
|
438
|
+
separate from the AdonisJS server `#generated/*` mapping. Channels are discovered in `app/channels`
|
|
439
|
+
by default. Any source inside `app` is supported, and generated imports use the corresponding
|
|
440
|
+
AdonisJS `#app` alias without TypeScript extensions. To customize discovery or client output, replace
|
|
441
|
+
the package hook in `adonisrc.ts` with a local hook:
|
|
441
442
|
|
|
442
443
|
```ts
|
|
443
444
|
// hooks/socket.ts
|
|
444
445
|
import { generateSocketRegistry } from '@rlanz/socket/assembler_hook'
|
|
445
446
|
|
|
446
447
|
export default generateSocketRegistry({
|
|
447
|
-
source: 'realtime',
|
|
448
|
+
source: './app/realtime',
|
|
448
449
|
glob: ['**/*.ts'],
|
|
449
450
|
output: '.adonisjs/client/socket.d.ts',
|
|
450
|
-
importAlias: '#realtime',
|
|
451
451
|
})
|
|
452
452
|
```
|
|
453
453
|
|
|
@@ -501,17 +501,14 @@ export default class ChatChannel extends BaseChannel<User> {
|
|
|
501
501
|
Middlewares run before subscription. They may be functions or objects with a `handle` method.
|
|
502
502
|
|
|
503
503
|
```ts
|
|
504
|
-
import { BaseChannel
|
|
504
|
+
import { BaseChannel } from '@rlanz/socket'
|
|
505
505
|
import type { MiddlewareContext } from '@rlanz/socket/types'
|
|
506
506
|
|
|
507
507
|
type User = { id: string; name: string }
|
|
508
508
|
|
|
509
509
|
async function auth(ctx: MiddlewareContext<User>, next: () => Promise<void>) {
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
await ctx.socket.joinUserRoom(ctx.socket.user.id)
|
|
510
|
+
const user = ctx.socket.getUserOrFail()
|
|
511
|
+
await ctx.socket.joinUserRoom(user.id)
|
|
515
512
|
await next()
|
|
516
513
|
}
|
|
517
514
|
|
|
@@ -541,10 +538,12 @@ export default class RoomChannel extends BaseChannel<User> {
|
|
|
541
538
|
static options = { presence: true }
|
|
542
539
|
|
|
543
540
|
getPresenceInfo(socket: AuthenticatedSocket<User>): PresenceInfo {
|
|
541
|
+
const user = socket.getUserOrFail()
|
|
542
|
+
|
|
544
543
|
return {
|
|
545
|
-
id:
|
|
544
|
+
id: user.id,
|
|
546
545
|
data: {
|
|
547
|
-
name:
|
|
546
|
+
name: user.name,
|
|
548
547
|
},
|
|
549
548
|
}
|
|
550
549
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client/framework.ts"],"sourcesContent":["import type { Channel } from './channel.js'\nimport type { Socket } from './socket.js'\nimport type { ChannelContract, ChannelContractFor, EventHandler } from './types.js'\nimport { callClientHandler } from './callback.js'\n\ntype AnySocket = Socket<any>\ntype UnknownContract = ChannelContract<unknown, unknown>\ntype ServerEvents<Contract> =\n Contract extends ChannelContract<unknown, infer Events> ? Events : unknown\ntype IsUnknown<Value> = unknown extends Value ? true : false\n\ntype FrameworkChannelMember<Registry, Name extends string> = string extends Name\n ? Channel<UnknownContract>\n : [Registry] extends [never]\n ? Channel<UnknownContract>\n : ChannelContractFor<Registry, Name> extends infer Contract\n ? [Contract] extends [never]\n ? never\n : Channel<Contract>\n : never\n\nexport type FrameworkChannel<Registry, Name extends string> = Name extends unknown\n ? FrameworkChannelMember<Registry, Name>\n : never\n\ntype FrameworkChannelNameValidity<Registry, Name extends string> = Name extends unknown\n ? FrameworkChannelMember<Registry, Name> extends never\n ? false\n : true\n : never\n\nexport type FrameworkChannelName<Registry, Name extends string> = Name &\n ([FrameworkChannelNameValidity<Registry, Name>] extends [true] ? unknown : never)\n\nexport type FrameworkChannelEvent<Registry, Name extends string> =\n FrameworkChannel<Registry, Name> extends Channel<infer Contract>\n ? IsUnknown<ServerEvents<Contract>> extends true\n ? string\n : Extract<keyof ServerEvents<Contract>, string>\n : never\n\nexport type FrameworkChannelEventPayload<\n Registry,\n Name extends string,\n Event extends FrameworkChannelEvent<Registry, Name>,\n> =\n FrameworkChannel<Registry, Name> extends Channel<infer Contract>\n ? IsUnknown<ServerEvents<Contract>> extends true\n ? unknown\n : Event extends keyof ServerEvents<Contract>\n ? ServerEvents<Contract>[Event]\n : never\n : never\n\ninterface ManagedEvent {\n handlers: Set<EventHandler<any>>\n dispatch: EventHandler<any>\n}\n\ninterface ManagedEntry {\n channel: Channel<any>\n socket: AnySocket\n leases: Set<ChannelLease>\n events: Map<string, ManagedEvent>\n lifecycle: { ready: Promise<Channel<any>>; release: () => Promise<void> } | undefined\n}\n\nconst socketEntries = new WeakMap<AnySocket, Map<string, ManagedEntry>>()\nconst socketOwners = new WeakMap<AnySocket, { count: number; generation: number }>()\n\nfunction reportSubscriptionError(error: unknown): void {\n queueMicrotask(() => {\n console.error(error)\n })\n}\n\nfunction attachEvents(entry: ManagedEntry): void {\n for (const [event, managed] of entry.events) {\n entry.channel.$listen(event, managed.dispatch)\n }\n}\n\nfunction getEntry(socket: AnySocket, name: string): ManagedEntry {\n let entries = socketEntries.get(socket)\n if (!entries) {\n entries = new Map()\n socketEntries.set(socket, entries)\n }\n\n const channel = socket.channel(name)\n let entry = entries.get(name)\n if (!entry || entry.channel !== channel) {\n entry = {\n channel,\n socket,\n leases: new Set(),\n events: new Map(),\n lifecycle: undefined,\n }\n entries.set(name, entry)\n }\n\n return entry\n}\n\nexport class ChannelLease {\n readonly entry: ManagedEntry\n #released = false\n #listeners: Array<{ event: string; handler: EventHandler<any> }> = []\n\n constructor(entry: ManagedEntry) {\n this.entry = entry\n }\n\n listen(event: string, handler: EventHandler<any>): void {\n if (this.#released) return\n\n let managed = this.entry.events.get(event)\n if (!managed) {\n const handlers = new Set<EventHandler<any>>()\n managed = {\n handlers,\n dispatch: (data) => {\n for (const listener of handlers) callClientHandler(listener, data)\n },\n }\n this.entry.events.set(event, managed)\n this.entry.channel.$listen(event, managed.dispatch)\n }\n const registration: EventHandler<any> = (data) => handler(data)\n managed.handlers.add(registration)\n this.#listeners.push({ event, handler: registration })\n }\n\n release(): void {\n if (this.#released) return\n this.#released = true\n\n for (const { event, handler } of this.#listeners) {\n const managed = this.entry.events.get(event)\n managed?.handlers.delete(handler)\n if (managed?.handlers.size === 0) {\n this.entry.channel.$stopListening(event, managed.dispatch)\n this.entry.events.delete(event)\n }\n }\n this.#listeners = []\n this.entry.leases.delete(this)\n\n queueMicrotask(() => {\n if (this.entry.leases.size > 0) return\n const lifecycle = this.entry.lifecycle\n this.entry.lifecycle = undefined\n void lifecycle?.release().then(() => {\n if (this.entry.leases.size > 0 || this.entry.lifecycle) return\n const entries = socketEntries.get(this.entry.socket)\n if (entries?.get(this.entry.channel.name) === this.entry) {\n entries.delete(this.entry.channel.name)\n }\n })\n })\n }\n}\n\nexport function acquireChannel<Registry, const Name extends string>(\n socket: Socket<Registry>,\n name: FrameworkChannelName<Registry, Name>\n): { channel: FrameworkChannel<Registry, Name>; lease: ChannelLease } {\n const entry = getEntry(socket, name)\n const lease = new ChannelLease(entry)\n entry.leases.add(lease)\n\n if (!entry.lifecycle) {\n const lifecycle = entry.channel.$acquire()\n entry.lifecycle = lifecycle\n attachEvents(entry)\n void lifecycle.ready\n .then(() => {\n if (entry.lifecycle === lifecycle) attachEvents(entry)\n })\n .catch((error) => {\n if (entry.lifecycle === lifecycle && entry.leases.size > 0 && entry.socket.connected) {\n reportSubscriptionError(error)\n }\n })\n }\n\n return { channel: entry.channel as FrameworkChannel<Registry, Name>, lease }\n}\n\n/** Connects an exclusively owned socket and coalesces development-mode remounts. */\nexport function acquireSocketOwnership(socket: AnySocket): () => void {\n let owner = socketOwners.get(socket)\n if (!owner) {\n owner = { count: 0, generation: 0 }\n socketOwners.set(socket, owner)\n socket.connect().catch(reportSubscriptionError)\n }\n owner.count++\n owner.generation++\n\n let released = false\n return () => {\n if (released) return\n released = true\n owner.count--\n const generation = ++owner.generation\n queueMicrotask(() => {\n if (owner.count === 0 && owner.generation === generation) {\n socket.disconnect()\n socketOwners.delete(socket)\n }\n })\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -4,8 +4,10 @@ import { ChannelContract, ChannelContractFor } from './src/client/types.js';
|
|
|
4
4
|
type UnknownContract = ChannelContract<unknown, unknown>;
|
|
5
5
|
type ServerEvents<Contract> = Contract extends ChannelContract<unknown, infer Events> ? Events : unknown;
|
|
6
6
|
type IsUnknown<Value> = unknown extends Value ? true : false;
|
|
7
|
-
type
|
|
8
|
-
type
|
|
7
|
+
type FrameworkChannelMember<Registry, Name extends string> = string extends Name ? Channel<UnknownContract> : [Registry] extends [never] ? Channel<UnknownContract> : ChannelContractFor<Registry, Name> extends infer Contract ? [Contract] extends [never] ? never : Channel<Contract> : never;
|
|
8
|
+
type FrameworkChannel<Registry, Name extends string> = Name extends unknown ? FrameworkChannelMember<Registry, Name> : never;
|
|
9
|
+
type FrameworkChannelNameValidity<Registry, Name extends string> = Name extends unknown ? FrameworkChannelMember<Registry, Name> extends never ? false : true : never;
|
|
10
|
+
type FrameworkChannelName<Registry, Name extends string> = Name & ([FrameworkChannelNameValidity<Registry, Name>] extends [true] ? unknown : never);
|
|
9
11
|
type FrameworkChannelEvent<Registry, Name extends string> = FrameworkChannel<Registry, Name> extends Channel<infer Contract> ? IsUnknown<ServerEvents<Contract>> extends true ? string : Extract<keyof ServerEvents<Contract>, string> : never;
|
|
10
12
|
type FrameworkChannelEventPayload<Registry, Name extends string, Event extends FrameworkChannelEvent<Registry, Name>> = FrameworkChannel<Registry, Name> extends Channel<infer Contract> ? IsUnknown<ServerEvents<Contract>> extends true ? unknown : Event extends keyof ServerEvents<Contract> ? ServerEvents<Contract>[Event] : never : never;
|
|
11
13
|
|
package/build/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { C as ChannelRouter } from './socket_service-
|
|
2
|
-
import { S as SocketConfig, d as SocketAuthenticationHandler } from './types-
|
|
3
|
-
export { A as AuthenticatedSocket, B as BaseChannel, e as BaseChannelConstructor, b as ChannelAck, f as ChannelHandlerFn, C as ChannelHandlerMap, g as ChannelMatch, c as ChannelMessage, h as ChannelOptions, a as ChannelServerEventsOf, D as Duration, M as Middleware, i as MiddlewareClass, j as MiddlewareContext, k as MiddlewareFn, l as PresenceInfo, P as PresenceManager, m as PresenceMember, R as RawSocket, n as SocketAuthenticationResult, o as SocketEvents, p as SocketHealthSnapshot, q as SocketHttpMiddleware, r as SocketResponseError, s as SocketServiceStatus, t as SocketUpgradeContext } from './types-
|
|
1
|
+
export { C as ChannelRouter } from './socket_service-D3jKrleE.js';
|
|
2
|
+
import { S as SocketConfig, d as SocketAuthenticationHandler } from './types-DiYaFvgi.js';
|
|
3
|
+
export { A as AuthenticatedSocket, B as BaseChannel, e as BaseChannelConstructor, b as ChannelAck, f as ChannelHandlerFn, C as ChannelHandlerMap, g as ChannelMatch, c as ChannelMessage, h as ChannelOptions, a as ChannelServerEventsOf, D as Duration, M as Middleware, i as MiddlewareClass, j as MiddlewareContext, k as MiddlewareFn, l as PresenceInfo, P as PresenceManager, m as PresenceMember, R as RawSocket, n as SocketAuthenticationResult, o as SocketEvents, p as SocketHealthSnapshot, q as SocketHttpMiddleware, r as SocketResponseError, s as SocketServiceStatus, t as SocketUpgradeContext } from './types-DiYaFvgi.js';
|
|
4
4
|
export { SocketHealthCheck } from './src/health_check.js';
|
|
5
5
|
export { SocketFake, SocketFakeCountQuery, SocketFakeEmission, SocketFakeEmissionQuery, SocketFakeTarget } from './src/testing.js';
|
|
6
6
|
import 'node:http';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ApplicationService } from '@adonisjs/core/types';
|
|
2
|
-
import { S as SocketService, C as ChannelRouter } from '../socket_service-
|
|
3
|
-
import { P as PresenceManager } from '../types-
|
|
2
|
+
import { S as SocketService, C as ChannelRouter } from '../socket_service-D3jKrleE.js';
|
|
3
|
+
import { P as PresenceManager } from '../types-DiYaFvgi.js';
|
|
4
4
|
import 'node:http';
|
|
5
5
|
import '@adonisjs/logger';
|
|
6
6
|
import 'emittery';
|
|
@@ -1338,6 +1338,12 @@ var SocketService = class extends Emittery {
|
|
|
1338
1338
|
return {
|
|
1339
1339
|
id: raw.id,
|
|
1340
1340
|
user: upgrade.user,
|
|
1341
|
+
getUserOrFail() {
|
|
1342
|
+
if (this.user === void 0) {
|
|
1343
|
+
throw new SocketResponseError("Unauthorized");
|
|
1344
|
+
}
|
|
1345
|
+
return this.user;
|
|
1346
|
+
},
|
|
1341
1347
|
emit: (event, data) => {
|
|
1342
1348
|
this.#sendSerializedEventFrame(connection, serializeFrame({ type: "event", event, data }));
|
|
1343
1349
|
},
|