Skip to content

Commit

Permalink
Update ts config to be strict
Browse files Browse the repository at this point in the history
  • Loading branch information
Dominik Piatek committed Aug 7, 2023
1 parent 3ca8a83 commit 785089c
Show file tree
Hide file tree
Showing 11 changed files with 110 additions and 93 deletions.
4 changes: 2 additions & 2 deletions src/CursorBatching.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@ export default class CursorBatching {
this.outgoingBuffers.push(value);
}

private async publishFromBuffer(channel, eventName: string) {
private async publishFromBuffer(channel: Types.RealtimeChannelPromise, eventName: string) {
if (!this.isRunning) {
this.isRunning = true;
await this.batchToChannel(channel, eventName);
}
}

private async batchToChannel(channel, eventName: string) {
private async batchToChannel(channel: Types.RealtimeChannelPromise, eventName: string) {
if (!this.hasMovement) {
this.isRunning = false;
return;
Expand Down
9 changes: 2 additions & 7 deletions src/CursorDispensing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,8 @@ export default class CursorDispensing {
private buffer: Record<string, CursorUpdate[]> = {};
private handlerRunning: boolean = false;
private timerIds: ReturnType<typeof setTimeout>[] = [];
private emitCursorUpdate: (update: CursorUpdate) => void;
private getCurrentBatchTime: () => number;

constructor(emitCursorUpdate, getCurrentBatchTime) {
this.emitCursorUpdate = emitCursorUpdate;
this.getCurrentBatchTime = getCurrentBatchTime;
}
constructor(private emitCursorUpdate: (update: CursorUpdate) => void, private getCurrentBatchTime: () => number) {}

emitFromBatch(batchDispenseInterval: number) {
if (!this.bufferHaveData()) {
Expand Down Expand Up @@ -66,7 +61,7 @@ export default class CursorDispensing {
}

processBatch(message: RealtimeMessage) {
const updates = message.data || [];
const updates: CursorUpdate[] = message.data || [];

updates.forEach((update) => {
const enhancedMsg = {
Expand Down
38 changes: 22 additions & 16 deletions src/Cursors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,6 @@ type CursorsEventMap = {

export const CURSOR_UPDATE = 'cursorUpdate';

const emitterHasListeners = (emitter) => {
const flattenEvents = (obj) =>
Object.entries(obj)
.map((_, v) => v)
.flat();

return (
emitter.any.length > 0 ||
emitter.anyOnce.length > 0 ||
flattenEvents(emitter.events).length > 0 ||
flattenEvents(emitter.eventsOnce).length > 0
);
};

export default class Cursors extends EventEmitter<CursorsEventMap> {
private readonly cursorBatching: CursorBatching;
private readonly cursorDispensing: CursorDispensing;
Expand Down Expand Up @@ -92,9 +78,29 @@ export default class Cursors extends EventEmitter<CursorsEventMap> {

private isUnsubscribed() {
const channel = this.getChannel();
return !emitterHasListeners(channel['subscriptions']);

interface ChannelWithSubscriptions extends Types.RealtimeChannelPromise {
subscriptions: EventEmitter<{}>;
}

const subscriptions = (channel as ChannelWithSubscriptions).subscriptions;
return !this.emitterHasListeners(subscriptions);
}

private emitterHasListeners = (emitter: EventEmitter<{}>) => {
const flattenEvents = (obj: Record<string, Function[]>) =>
Object.entries(obj)
.map((_, v) => v)
.flat();

return (
emitter.any.length > 0 ||
emitter.anyOnce.length > 0 ||
flattenEvents(emitter.events).length > 0 ||
flattenEvents(emitter.eventsOnce).length > 0
);
};

subscribe<K extends EventKey<CursorsEventMap>>(
listenerOrEvents?: K | K[] | EventListener<CursorsEventMap[K]>,
listener?: EventListener<CursorsEventMap[K]>,
Expand Down Expand Up @@ -136,7 +142,7 @@ export default class Cursors extends EventEmitter<CursorsEventMap> {
}
}

const hasListeners = emitterHasListeners(this);
const hasListeners = this.emitterHasListeners(this);

if (!hasListeners) {
const channel = this.getChannel();
Expand Down
4 changes: 2 additions & 2 deletions src/Locations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,14 @@ export default class Locations extends EventEmitter<LocationsEventMap> {
return this.space.members
.getAll()
.filter((member) => member.connectionId !== self?.connectionId)
.reduce((acc, member) => {
.reduce((acc: Record<string, unknown>, member: SpaceMember) => {
acc[member.connectionId] = member.location;
return acc;
}, {});
}

getAll(): Record<string, unknown> {
return this.space.members.getAll().reduce((acc, member) => {
return this.space.members.getAll().reduce((acc: Record<string, unknown>, member: SpaceMember) => {
acc[member.connectionId] = member.location;
return acc;
}, {});
Expand Down
6 changes: 5 additions & 1 deletion src/Space.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,11 @@ class Space extends EventEmitter<SpaceEventsMap> {
return new Promise((resolve) => {
const presence = this.channel.presence;

presence['subscriptions'].once('enter', async () => {
interface PresenceWithSubscriptions extends Types.RealtimePresencePromise {
subscriptions: EventEmitter<{ enter: [unknown] }>;
}

(presence as PresenceWithSubscriptions).subscriptions.once('enter', async () => {
const presenceMessages = await presence.get();
const members = this.members.mapPresenceMembersToSpaceMembers(presenceMessages);

Expand Down
16 changes: 10 additions & 6 deletions src/Spaces.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { it, describe, expect, expectTypeOf, vi, beforeEach } from 'vitest';
import { Realtime, Types } from 'ably/promises';

import Spaces from './Spaces.js';
import Spaces, { type ClientWithOptions } from './Spaces.js';

interface SpacesTestContext {
client: Types.RealtimePromise;
client: ClientWithOptions;
}

vi.mock('ably/promises');

describe('Spaces', () => {
beforeEach<SpacesTestContext>((context) => {
context.client = new Realtime({ key: 'asd' });
context.client = new Realtime({ key: 'asd' }) as ClientWithOptions;
});

it<SpacesTestContext>('expects the injected client to be of the type RealtimePromise', ({ client }) => {
Expand All @@ -32,14 +32,18 @@ describe('Spaces', () => {

it<SpacesTestContext>('applies the agent header to an existing SDK instance', ({ client }) => {
const spaces = new Spaces(client);
expect(client['options'].agents).toEqual({ 'ably-spaces': spaces.version, 'space-custom-client': true });
expect(client.options.agents).toEqual({
'ably-spaces': spaces.version,
'space-custom-client': true,
});
});

it<SpacesTestContext>('extend the agents array when it already exists', ({ client }) => {
client['options']['agents'] = { 'some-client': '1.2.3' };
(client as ClientWithOptions).options.agents = { 'some-client': '1.2.3' };
const spaces = new Spaces(client);
const ablyClient = spaces.ably as ClientWithOptions;

expect(spaces.ably['options'].agents).toEqual({
expect(ablyClient.options.agents).toEqual({
'some-client': '1.2.3',
'ably-spaces': spaces.version,
'space-custom-client': true,
Expand Down
8 changes: 7 additions & 1 deletion src/Spaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ import Space from './Space.js';
import type { SpaceOptions } from './types.js';
import type { Subset } from './utilities/types.js';

export interface ClientWithOptions extends Types.RealtimePromise {
options: {
agents?: Record<string, string | boolean>;
};
}

class Spaces {
private spaces: Record<string, Space> = {};
ably: Types.RealtimePromise;
Expand All @@ -13,7 +19,7 @@ class Spaces {

constructor(client: Types.RealtimePromise) {
this.ably = client;
this.addAgent(this.ably['options']);
this.addAgent((this.ably as ClientWithOptions)['options']);
this.ably.time();
}

Expand Down
40 changes: 20 additions & 20 deletions src/utilities/EventEmitter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,14 @@ describe('EventEmitter', () => {
it('adds a listener to the "any" set of event listeners', (context) => {
context.eventEmitter['on'](context.spy);
expect(context.eventEmitter['any']).toStrictEqual([context.spy]);
context.eventEmitter['emit']('myEvent');
context.eventEmitter['emit']('myEvent', '');
expect(context.spy).toHaveBeenCalledOnce();
});

it('adds a listener to a provided field of an event listener', (context) => {
context.eventEmitter['on']('myEvent', context.spy);
expect(context.eventEmitter['events']['myEvent']).toStrictEqual([context.spy]);
context.eventEmitter['emit']('myEvent');
context.eventEmitter['emit']('myEvent', '');
expect(context.spy).toHaveBeenCalledOnce();
});

Expand All @@ -114,11 +114,11 @@ describe('EventEmitter', () => {
expect(context.eventEmitter['events']['myEvent']).toStrictEqual([context.spy]);
expect(context.eventEmitter['events']['myOtherEvent']).toStrictEqual([context.spy]);
expect(context.eventEmitter['events']['myThirdEvent']).toStrictEqual([context.spy]);
context.eventEmitter['emit']('myEvent');
context.eventEmitter['emit']('myEvent', '');
expect(context.spy).toHaveBeenCalledTimes(1);
context.eventEmitter['emit']('myOtherEvent');
context.eventEmitter['emit']('myOtherEvent', '');
expect(context.spy).toHaveBeenCalledTimes(2);
context.eventEmitter['emit']('myThirdEvent');
context.eventEmitter['emit']('myThirdEvent', '');
expect(context.spy).toHaveBeenCalledTimes(3);
});
});
Expand Down Expand Up @@ -148,7 +148,7 @@ describe('EventEmitter', () => {
expect(context.eventEmitter['anyOnce']).toStrictEqual([]);
expect(context.eventEmitter['events']).toStrictEqual(Object.create(null));
expect(context.eventEmitter['eventsOnce']).toStrictEqual(Object.create(null));
context.eventEmitter['emit']('myEvent');
context.eventEmitter['emit']('myEvent', '');
expect(context.spy).not.toHaveBeenCalled();
});

Expand All @@ -158,7 +158,7 @@ describe('EventEmitter', () => {
expect(context.eventEmitter['anyOnce']).toStrictEqual([altListener]);
expect(context.eventEmitter['events']['myEvent']).not.toContain(context.spy);
expect(context.eventEmitter['eventsOnce']['myEvent']).not.toContain(context.spy);
context.eventEmitter['emit']('myEvent');
context.eventEmitter['emit']('myEvent', '');
expect(context.spy).not.toHaveBeenCalled();
});

Expand All @@ -168,9 +168,9 @@ describe('EventEmitter', () => {
expect(context.eventEmitter['anyOnce']).toStrictEqual([context.spy, altListener]);
expect(context.eventEmitter['events']['myEvent']).not.toContain(context.spy);
expect(context.eventEmitter['events']['myOtherEvent']).toContain(context.spy);
context.eventEmitter['emit']('myEvent');
context.eventEmitter['emit']('myEvent', '');
expect(context.spy).toHaveBeenCalledTimes(2);
context.eventEmitter['emit']('myOtherEvent');
context.eventEmitter['emit']('myOtherEvent', '');
expect(context.spy).toHaveBeenCalledTimes(3);
});

Expand All @@ -182,11 +182,11 @@ describe('EventEmitter', () => {
expect(eventEmitter['events']['myEvent']).toBe(undefined);
expect(eventEmitter['events']['myOtherEvent']).toBe(undefined);
expect(eventEmitter['events']['myThirdEvent']).toContain(specificListener);
eventEmitter['emit']('myEvent');
eventEmitter['emit']('myOtherEvent');
eventEmitter['emit']('myEvent', '');
eventEmitter['emit']('myOtherEvent', '');
expect(specificListener).not.toHaveBeenCalled();
expect(eventEmitter['events']['myThirdEvent']).toContain(specificListener);
eventEmitter['emit']('myThirdEvent');
eventEmitter['emit']('myThirdEvent', '');
expect(specificListener).toHaveBeenCalledOnce();
});

Expand Down Expand Up @@ -241,17 +241,17 @@ describe('EventEmitter', () => {
it('adds a listener to anyOnce on calling `once` with a listener', (context) => {
context.eventEmitter['once'](context.spy);
expect(context.eventEmitter['anyOnce']).toHaveLength(1);
context.eventEmitter['emit']('myEvent');
context.eventEmitter['emit']('myEvent', '');
expect(context.spy).toHaveBeenCalledOnce();
context.eventEmitter['emit']('myOtherEvent');
context.eventEmitter['emit']('myOtherEvent', '');
});

it('adds a listener to an eventOnce on calling `once` with a listener and event name', (context) => {
context.eventEmitter['once']('myEvent', context.spy);
expect(context.eventEmitter['eventsOnce']['myEvent']).toHaveLength(1);
context.eventEmitter['emit']('myEvent');
context.eventEmitter['emit']('myEvent', '');
expect(context.spy).toHaveBeenCalledOnce();
context.eventEmitter['emit']('myEvent');
context.eventEmitter['emit']('myEvent', '');
expect(context.spy).toHaveBeenCalledOnce();
});

Expand All @@ -260,7 +260,7 @@ describe('EventEmitter', () => {
expect(context.eventEmitter['eventsOnce']['myEvent']).toHaveLength(1);
expect(context.eventEmitter['eventsOnce']['myOtherEvent']).toHaveLength(1);
expect(context.eventEmitter['eventsOnce']['myThirdEvent']).toHaveLength(1);
expect(context.eventEmitter['emit']('myEvent'));
expect(context.eventEmitter['emit']('myEvent', ''));
expect(context.eventEmitter['eventsOnce']['myEvent']).toBe(undefined);
expect(context.eventEmitter['eventsOnce']['myOtherEvent']).toBe(undefined);
expect(context.eventEmitter['eventsOnce']['myThirdEvent']).toBe(undefined);
Expand All @@ -279,23 +279,23 @@ describe('EventEmitter', () => {
context.eventEmitter['on']('myEvent', context.spy);
expect(context.eventEmitter['listeners']('myEvent')).toContain(context.spy);
expect(context.spy).not.toHaveBeenCalled();
context.eventEmitter['emit']('myEvent');
context.eventEmitter['emit']('myEvent', '');
expect(context.spy).toHaveBeenCalledOnce();
// anyOnce must also be emptied
expect(context.eventEmitter['anyOnce']).toStrictEqual([]);
});

it('emits any events in anyOnce on emitting specific events', (context) => {
context.eventEmitter['on']('myEvent', context.spy);
context.eventEmitter['emit']('myEvent');
context.eventEmitter['emit']('myEvent', '');
expect(context.eventEmitter['anyOnce']).toStrictEqual([]);
expect(context.spy).toHaveBeenCalledOnce();
});

it('emits an event and removes it on being called for a once operation', (context) => {
context.eventEmitter['once']('myEvent', context.spy);
expect(context.eventEmitter['listeners']('myEvent')).toContain(context.spy);
context.eventEmitter['emit']('myEvent');
context.eventEmitter['emit']('myEvent', '');
expect(context.eventEmitter['listeners']('myEvent')).toBe(null);
expect(context.eventEmitter['anyOnce']).toStrictEqual([]);
expect(context.spy).toHaveBeenCalledOnce();
Expand Down
Loading

0 comments on commit 785089c

Please sign in to comment.