@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 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. Generated channel imports are relative by
439
- default, so an `importAlias` is optional. To customize discovery, replace the package hook in
440
- `adonisrc.ts` with a local hook:
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, SocketResponseError } from '@rlanz/socket'
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
- if (!ctx.socket.user) {
511
- throw new SocketResponseError('Unauthorized')
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: socket.user!.id,
544
+ id: user.id,
546
545
  data: {
547
- name: socket.user!.name,
546
+ name: user.name,
548
547
  },
549
548
  }
550
549
  }
@@ -133,4 +133,4 @@ export {
133
133
  acquireChannel,
134
134
  acquireSocketOwnership
135
135
  };
136
- //# sourceMappingURL=chunk-ANT2E3LT.js.map
136
+ //# sourceMappingURL=chunk-FVPY6HZW.js.map
@@ -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 FrameworkChannel<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 FrameworkChannelName<Registry, Name extends string> = Name & (FrameworkChannel<Registry, Name> extends never ? never : unknown);
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-mybqv1hj.js';
2
- import { S as SocketConfig, d as SocketAuthenticationHandler } from './types-C7Q36ryo.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-C7Q36ryo.js';
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-mybqv1hj.js';
3
- import { P as PresenceManager } from '../types-C7Q36ryo.js';
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
  },