@wixc3/patterns
Advanced tools
Comparing version 11.1.1 to 11.2.0
@@ -9,4 +9,4 @@ /** | ||
dispose(): Promise<void>; | ||
add(disposable: Disposable, timeout: number, name: string): void; | ||
remove(disposable: Disposable): void; | ||
add(disposable: Disposable, timeout: number, name: string): () => boolean; | ||
remove(target: Disposable): void; | ||
list(): { | ||
@@ -24,4 +24,3 @@ name: string; | ||
name: string; | ||
dispose: Disposable; | ||
}; | ||
//# sourceMappingURL=disposable.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Disposables = exports.createSimpleDisposable = void 0; | ||
const common_1 = require("@wixc3/common"); | ||
const promise_assist_1 = require("promise-assist"); | ||
@@ -16,20 +15,20 @@ /** | ||
constructor() { | ||
this.disposables = new Set(); | ||
this.disposables = new Map(); | ||
} | ||
async dispose() { | ||
const _disposables = Array.from(this.disposables.values()).reverse(); | ||
const _disposables = Array.from(this.disposables).reverse(); | ||
this.disposables.clear(); | ||
for (const disposable of _disposables) { | ||
await (0, promise_assist_1.timeout)(disposeOf(disposable), disposable.timeout, `Disposal timed out: "${disposable.name}" after ${disposable.timeout}ms`); | ||
for (const [disposable, details] of _disposables) { | ||
await (0, promise_assist_1.timeout)(disposeOf(disposable), details.timeout, `Disposal timed out: "${details.name}" after ${details.timeout}ms`); | ||
} | ||
} | ||
add(disposable, timeout, name) { | ||
this.disposables.add({ dispose: disposable, timeout, name }); | ||
if (this.disposables.has(disposable)) { | ||
throw new Error(`Disposable already added`); | ||
} | ||
this.disposables.set(disposable, { timeout, name }); | ||
return () => this.disposables.delete(disposable); | ||
} | ||
remove(target) { | ||
const oldSize = this.disposables.size; | ||
this.disposables = new Set((0, common_1.filter)(this.disposables, (d) => d.dispose !== target)); | ||
if (oldSize === this.disposables.size) { | ||
throw new Error(`Disposable not found`); | ||
} | ||
this.disposables.delete(target); | ||
} | ||
@@ -41,3 +40,3 @@ list() { | ||
exports.Disposables = Disposables; | ||
async function disposeOf({ dispose }) { | ||
async function disposeOf(dispose) { | ||
if (typeof dispose === 'function') { | ||
@@ -44,0 +43,0 @@ await dispose(); |
@@ -65,4 +65,5 @@ import { GroupConstraints } from './constraints'; | ||
* @param options if string, will be used as group name | ||
* @returns a function to remove the disposable | ||
*/ | ||
add: (disposable: Disposable, options?: DisposableOptions | string) => void; | ||
add: (disposable: Disposable, options?: DisposableOptions | string) => () => void; | ||
/** | ||
@@ -72,3 +73,11 @@ * removes a disposable from all disposal group | ||
remove: (disposable: Disposable) => void; | ||
/** | ||
* Disposes all disposables in all groups one at the time, | ||
* order based on constraints | ||
*/ | ||
dispose: () => Promise<void>; | ||
/** | ||
* | ||
* @returns a serialized list of groups and their disposables and constraints | ||
*/ | ||
list: () => { | ||
@@ -75,0 +84,0 @@ constrains: GroupConstraints[]; |
@@ -77,2 +77,3 @@ "use strict"; | ||
* @param options if string, will be used as group name | ||
* @returns a function to remove the disposable | ||
*/ | ||
@@ -89,2 +90,3 @@ add: (disposable, options) => { | ||
group.disposables.add(disposable, timeout, name); | ||
return () => group.disposables.remove(disposable); | ||
}, | ||
@@ -95,4 +97,17 @@ /** | ||
remove: (disposable) => { | ||
groups.forEach((g) => g.disposables.remove(disposable)); | ||
groups.forEach((g) => { | ||
try { | ||
g.disposables.remove(disposable); | ||
} | ||
catch (e) { | ||
if ((e === null || e === void 0 ? void 0 : e.message) !== 'Disposable not found') { | ||
throw e; | ||
} | ||
} | ||
}); | ||
}, | ||
/** | ||
* Disposes all disposables in all groups one at the time, | ||
* order based on constraints | ||
*/ | ||
dispose: async () => { | ||
@@ -103,2 +118,6 @@ for (const { disposables } of groups) { | ||
}, | ||
/** | ||
* | ||
* @returns a serialized list of groups and their disposables and constraints | ||
*/ | ||
list: () => { | ||
@@ -105,0 +124,0 @@ const g = groups.map((g) => { |
@@ -15,12 +15,14 @@ import { Signal } from './signal'; | ||
* Subscribe a handler for event | ||
* @returns unsubscribe fn | ||
*/ | ||
subscribe: <Event_1 extends EventId>(event: Event_1, handler: (data: Events[Event_1]) => void) => void; | ||
subscribe: <Event_1 extends EventId>(event: Event_1, handler: (data: Events[Event_1]) => void) => () => void; | ||
/** | ||
* {@inheritDoc EventEmitter.subscribe} | ||
*/ | ||
on: <Event_1 extends EventId>(event: Event_1, handler: (data: Events[Event_1]) => void) => void; | ||
on: <Event_1 extends EventId>(event: Event_1, handler: (data: Events[Event_1]) => void) => () => void; | ||
/** | ||
* Adds a handler that will be called at most once | ||
* @returns unsubscribe fn | ||
*/ | ||
once: <Event_1 extends EventId>(event: Event_1, handler: (data: Events[Event_1]) => void) => void; | ||
once: <Event_1 extends EventId>(event: Event_1, handler: (data: Events[Event_1]) => void) => () => void; | ||
/** | ||
@@ -27,0 +29,0 @@ * Unsubscribe a handler from event |
@@ -19,2 +19,3 @@ "use strict"; | ||
* Subscribe a handler for event | ||
* @returns unsubscribe fn | ||
*/ | ||
@@ -24,2 +25,3 @@ this.subscribe = (event, handler) => { | ||
bucket ? bucket.add(handler) : this.events.set(event, new signal_1.Signal([handler])); | ||
return () => this.unsubscribe(event, handler); | ||
}; | ||
@@ -32,2 +34,3 @@ /** | ||
* Adds a handler that will be called at most once | ||
* @returns unsubscribe fn | ||
*/ | ||
@@ -38,2 +41,3 @@ this.once = (event, handler) => { | ||
bucket ? bucket.add(handler) : this.emitOnce.set(event, new signal_1.Signal([handler])); | ||
return () => this.unsubscribe(event, handler); | ||
}; | ||
@@ -40,0 +44,0 @@ /** |
@@ -38,3 +38,3 @@ export type Listener<T> = (data: T) => void; | ||
*/ | ||
subscribe: (handler: Listener<T>) => void; | ||
subscribe: (handler: Listener<T>) => () => void; | ||
/** | ||
@@ -41,0 +41,0 @@ * Unsubscribe an existing callback |
@@ -44,2 +44,3 @@ "use strict"; | ||
this.add(handler); | ||
return () => this.unsubscribe(handler); | ||
}; | ||
@@ -46,0 +47,0 @@ /** |
@@ -9,4 +9,4 @@ /** | ||
dispose(): Promise<void>; | ||
add(disposable: Disposable, timeout: number, name: string): void; | ||
remove(disposable: Disposable): void; | ||
add(disposable: Disposable, timeout: number, name: string): () => boolean; | ||
remove(target: Disposable): void; | ||
list(): { | ||
@@ -24,4 +24,3 @@ name: string; | ||
name: string; | ||
dispose: Disposable; | ||
}; | ||
//# sourceMappingURL=disposable.d.ts.map |
@@ -1,2 +0,1 @@ | ||
import { filter } from '@wixc3/common'; | ||
import { timeout } from 'promise-assist'; | ||
@@ -12,20 +11,20 @@ /** | ||
constructor() { | ||
this.disposables = new Set(); | ||
this.disposables = new Map(); | ||
} | ||
async dispose() { | ||
const _disposables = Array.from(this.disposables.values()).reverse(); | ||
const _disposables = Array.from(this.disposables).reverse(); | ||
this.disposables.clear(); | ||
for (const disposable of _disposables) { | ||
await timeout(disposeOf(disposable), disposable.timeout, `Disposal timed out: "${disposable.name}" after ${disposable.timeout}ms`); | ||
for (const [disposable, details] of _disposables) { | ||
await timeout(disposeOf(disposable), details.timeout, `Disposal timed out: "${details.name}" after ${details.timeout}ms`); | ||
} | ||
} | ||
add(disposable, timeout, name) { | ||
this.disposables.add({ dispose: disposable, timeout, name }); | ||
if (this.disposables.has(disposable)) { | ||
throw new Error(`Disposable already added`); | ||
} | ||
this.disposables.set(disposable, { timeout, name }); | ||
return () => this.disposables.delete(disposable); | ||
} | ||
remove(target) { | ||
const oldSize = this.disposables.size; | ||
this.disposables = new Set(filter(this.disposables, (d) => d.dispose !== target)); | ||
if (oldSize === this.disposables.size) { | ||
throw new Error(`Disposable not found`); | ||
} | ||
this.disposables.delete(target); | ||
} | ||
@@ -36,3 +35,3 @@ list() { | ||
} | ||
async function disposeOf({ dispose }) { | ||
async function disposeOf(dispose) { | ||
if (typeof dispose === 'function') { | ||
@@ -39,0 +38,0 @@ await dispose(); |
@@ -65,4 +65,5 @@ import { GroupConstraints } from './constraints'; | ||
* @param options if string, will be used as group name | ||
* @returns a function to remove the disposable | ||
*/ | ||
add: (disposable: Disposable, options?: DisposableOptions | string) => void; | ||
add: (disposable: Disposable, options?: DisposableOptions | string) => () => void; | ||
/** | ||
@@ -72,3 +73,11 @@ * removes a disposable from all disposal group | ||
remove: (disposable: Disposable) => void; | ||
/** | ||
* Disposes all disposables in all groups one at the time, | ||
* order based on constraints | ||
*/ | ||
dispose: () => Promise<void>; | ||
/** | ||
* | ||
* @returns a serialized list of groups and their disposables and constraints | ||
*/ | ||
list: () => { | ||
@@ -75,0 +84,0 @@ constrains: GroupConstraints[]; |
@@ -74,2 +74,3 @@ import { getValidatedConstantsGroups, normalizeConstraints } from './constraints'; | ||
* @param options if string, will be used as group name | ||
* @returns a function to remove the disposable | ||
*/ | ||
@@ -86,2 +87,3 @@ add: (disposable, options) => { | ||
group.disposables.add(disposable, timeout, name); | ||
return () => group.disposables.remove(disposable); | ||
}, | ||
@@ -92,4 +94,17 @@ /** | ||
remove: (disposable) => { | ||
groups.forEach((g) => g.disposables.remove(disposable)); | ||
groups.forEach((g) => { | ||
try { | ||
g.disposables.remove(disposable); | ||
} | ||
catch (e) { | ||
if ((e === null || e === void 0 ? void 0 : e.message) !== 'Disposable not found') { | ||
throw e; | ||
} | ||
} | ||
}); | ||
}, | ||
/** | ||
* Disposes all disposables in all groups one at the time, | ||
* order based on constraints | ||
*/ | ||
dispose: async () => { | ||
@@ -100,2 +115,6 @@ for (const { disposables } of groups) { | ||
}, | ||
/** | ||
* | ||
* @returns a serialized list of groups and their disposables and constraints | ||
*/ | ||
list: () => { | ||
@@ -102,0 +121,0 @@ const g = groups.map((g) => { |
@@ -15,12 +15,14 @@ import { Signal } from './signal'; | ||
* Subscribe a handler for event | ||
* @returns unsubscribe fn | ||
*/ | ||
subscribe: <Event_1 extends EventId>(event: Event_1, handler: (data: Events[Event_1]) => void) => void; | ||
subscribe: <Event_1 extends EventId>(event: Event_1, handler: (data: Events[Event_1]) => void) => () => void; | ||
/** | ||
* {@inheritDoc EventEmitter.subscribe} | ||
*/ | ||
on: <Event_1 extends EventId>(event: Event_1, handler: (data: Events[Event_1]) => void) => void; | ||
on: <Event_1 extends EventId>(event: Event_1, handler: (data: Events[Event_1]) => void) => () => void; | ||
/** | ||
* Adds a handler that will be called at most once | ||
* @returns unsubscribe fn | ||
*/ | ||
once: <Event_1 extends EventId>(event: Event_1, handler: (data: Events[Event_1]) => void) => void; | ||
once: <Event_1 extends EventId>(event: Event_1, handler: (data: Events[Event_1]) => void) => () => void; | ||
/** | ||
@@ -27,0 +29,0 @@ * Unsubscribe a handler from event |
@@ -16,2 +16,3 @@ import { Signal } from './signal'; | ||
* Subscribe a handler for event | ||
* @returns unsubscribe fn | ||
*/ | ||
@@ -21,2 +22,3 @@ this.subscribe = (event, handler) => { | ||
bucket ? bucket.add(handler) : this.events.set(event, new Signal([handler])); | ||
return () => this.unsubscribe(event, handler); | ||
}; | ||
@@ -29,2 +31,3 @@ /** | ||
* Adds a handler that will be called at most once | ||
* @returns unsubscribe fn | ||
*/ | ||
@@ -35,2 +38,3 @@ this.once = (event, handler) => { | ||
bucket ? bucket.add(handler) : this.emitOnce.set(event, new Signal([handler])); | ||
return () => this.unsubscribe(event, handler); | ||
}; | ||
@@ -37,0 +41,0 @@ /** |
@@ -38,3 +38,3 @@ export type Listener<T> = (data: T) => void; | ||
*/ | ||
subscribe: (handler: Listener<T>) => void; | ||
subscribe: (handler: Listener<T>) => () => void; | ||
/** | ||
@@ -41,0 +41,0 @@ * Unsubscribe an existing callback |
@@ -41,2 +41,3 @@ /** | ||
this.add(handler); | ||
return () => this.unsubscribe(handler); | ||
}; | ||
@@ -43,0 +44,0 @@ /** |
{ | ||
"name": "@wixc3/patterns", | ||
"version": "11.1.1", | ||
"version": "11.2.0", | ||
"description": "A utility for saving objects to be disposed", | ||
@@ -5,0 +5,0 @@ "main": "dist/cjs/index.js", |
@@ -1,2 +0,1 @@ | ||
import { filter } from '@wixc3/common'; | ||
import { timeout } from 'promise-assist'; | ||
@@ -13,11 +12,11 @@ | ||
export class Disposables { | ||
private disposables = new Set<NamedDisposable>(); | ||
private disposables = new Map<Disposable, NamedDisposable>(); | ||
async dispose() { | ||
const _disposables = Array.from(this.disposables.values()).reverse(); | ||
const _disposables = Array.from(this.disposables).reverse(); | ||
this.disposables.clear(); | ||
for (const disposable of _disposables) { | ||
for (const [disposable, details] of _disposables) { | ||
await timeout( | ||
disposeOf(disposable), | ||
disposable.timeout, | ||
`Disposal timed out: "${disposable.name}" after ${disposable.timeout}ms` | ||
details.timeout, | ||
`Disposal timed out: "${details.name}" after ${details.timeout}ms` | ||
); | ||
@@ -28,12 +27,11 @@ } | ||
add(disposable: Disposable, timeout: number, name: string) { | ||
this.disposables.add({ dispose: disposable, timeout, name }); | ||
if (this.disposables.has(disposable)) { | ||
throw new Error(`Disposable already added`); | ||
} | ||
this.disposables.set(disposable, { timeout, name }); | ||
return () => this.disposables.delete(disposable); | ||
} | ||
remove(disposable: Disposable): void; | ||
remove(target: Disposable): void { | ||
const oldSize = this.disposables.size; | ||
this.disposables = new Set(filter(this.disposables, (d) => d.dispose !== target)); | ||
if (oldSize === this.disposables.size) { | ||
throw new Error(`Disposable not found`); | ||
} | ||
this.disposables.delete(target); | ||
} | ||
@@ -52,6 +50,5 @@ | ||
name: string; | ||
dispose: Disposable; | ||
}; | ||
async function disposeOf({ dispose }: NamedDisposable) { | ||
async function disposeOf(dispose: Disposable) { | ||
if (typeof dispose === 'function') { | ||
@@ -58,0 +55,0 @@ await dispose(); |
@@ -96,2 +96,3 @@ import { DisposalGroup, getValidatedConstantsGroups, GroupConstraints, normalizeConstraints } from './constraints'; | ||
* @param options if string, will be used as group name | ||
* @returns a function to remove the disposable | ||
*/ | ||
@@ -108,2 +109,3 @@ add: (disposable: Disposable, options?: DisposableOptions | string) => { | ||
group.disposables.add(disposable, timeout, name); | ||
return () => group.disposables.remove(disposable); | ||
}, | ||
@@ -115,5 +117,17 @@ | ||
remove: (disposable: Disposable) => { | ||
groups.forEach((g) => g.disposables.remove(disposable)); | ||
groups.forEach((g) => { | ||
try { | ||
g.disposables.remove(disposable); | ||
} catch (e) { | ||
if ((e as Error)?.message !== 'Disposable not found') { | ||
throw e; | ||
} | ||
} | ||
}); | ||
}, | ||
/** | ||
* Disposes all disposables in all groups one at the time, | ||
* order based on constraints | ||
*/ | ||
dispose: async () => { | ||
@@ -125,2 +139,6 @@ for (const { disposables } of groups) { | ||
/** | ||
* | ||
* @returns a serialized list of groups and their disposables and constraints | ||
*/ | ||
list: () => { | ||
@@ -127,0 +145,0 @@ const g = groups.map((g) => { |
@@ -18,2 +18,3 @@ import { Signal } from './signal'; | ||
* Subscribe a handler for event | ||
* @returns unsubscribe fn | ||
*/ | ||
@@ -23,2 +24,3 @@ subscribe = <Event extends EventId>(event: Event, handler: (data: Events[Event]) => void) => { | ||
bucket ? bucket.add(handler) : this.events.set(event, new Signal([handler])); | ||
return () => this.unsubscribe(event, handler); | ||
}; | ||
@@ -33,2 +35,3 @@ | ||
* Adds a handler that will be called at most once | ||
* @returns unsubscribe fn | ||
*/ | ||
@@ -39,2 +42,3 @@ once = <Event extends EventId>(event: Event, handler: (data: Events[Event]) => void) => { | ||
bucket ? bucket.add(handler) : this.emitOnce.set(event, new Signal([handler])); | ||
return () => this.unsubscribe(event, handler); | ||
}; | ||
@@ -41,0 +45,0 @@ |
@@ -41,2 +41,3 @@ export type Listener<T> = (data: T) => void; | ||
this.add(handler); | ||
return () => this.unsubscribe(handler); | ||
}; | ||
@@ -43,0 +44,0 @@ /** |
@@ -74,4 +74,4 @@ import { expect, use } from 'chai'; | ||
}); | ||
describe('add', () => { | ||
describe('with a string as options', () => { | ||
describe('add and remove', () => { | ||
it('add (with a string as options)', () => { | ||
const groups = createDisposables(); | ||
@@ -82,2 +82,46 @@ groups.registerGroup('first', { before: 'default' }); | ||
}); | ||
it('add (with options obj)', () => { | ||
const groups = createDisposables(); | ||
groups.registerGroup('first', { before: 'default' }); | ||
groups.add(() => void 0, { | ||
group: 'first', | ||
name: 'lucky', | ||
timeout: 1, | ||
}); | ||
expect(groups.list().groups[0]?.disposables).to.eql([ | ||
{ | ||
name: 'lucky', | ||
timeout: 1, | ||
}, | ||
]); | ||
}); | ||
it('add returns a remove func', () => { | ||
const disposables = createDisposables(); | ||
const remove = disposables.add(() => void 0); | ||
expect(disposables.list().groups[0]?.disposables).to.have.length(1); | ||
remove(); | ||
expect(disposables.list().groups[0]?.disposables).to.have.length(0); | ||
}); | ||
it('added disposables can be removed by reference', () => { | ||
const disposables = createDisposables(); | ||
const disposable = () => void 0; | ||
disposables.add(disposable); | ||
expect(disposables.list().groups[0]?.disposables).to.have.length(1); | ||
disposables.remove(disposable); | ||
expect(disposables.list().groups[0]?.disposables).to.have.length(0); | ||
}); | ||
it('removing missing disposables have no effect', () => { | ||
const disposables = createDisposables(); | ||
const disposable = () => void 0; | ||
disposables.add(disposable); | ||
expect(disposables.list().groups[0]?.disposables).to.have.length(1); | ||
disposables.remove(() => void 0); | ||
expect(disposables.list().groups[0]?.disposables).to.have.length(1); | ||
}); | ||
}); | ||
@@ -84,0 +128,0 @@ describe('list', () => { |
@@ -20,3 +20,3 @@ import chai, { expect } from 'chai'; | ||
describe('off', () => { | ||
it('handler is not called', () => { | ||
it('after off handler is not called', () => { | ||
const handler1 = spy(); | ||
@@ -32,2 +32,13 @@ const handler2 = spy(); | ||
}); | ||
it('returned fn from on is same as off', () => { | ||
const handler1 = spy(); | ||
const handler2 = spy(); | ||
const off1 = emitter.on('a', handler1); | ||
off1(); | ||
const off2 = emitter.once('a', handler2); | ||
off2(); | ||
emitter.emit('a', { data: 0 }); | ||
expect(handler1).to.have.callCount(0); | ||
expect(handler1).to.have.callCount(0); | ||
}); | ||
}); | ||
@@ -34,0 +45,0 @@ describe('once', () => { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
165329
3052