@matrixai/async-init
Advanced tools
Comparing version 2.0.0 to 2.1.0
@@ -1,23 +0,19 @@ | ||
import type { Status } from './types.js'; | ||
import type { Status, Class } from './types.js'; | ||
import { Evented } from '@matrixai/events'; | ||
import { RWLockWriter } from '@matrixai/async-locks'; | ||
import { _destroyed, destroyed, _status, status, initLock } from './utils.js'; | ||
interface CreateDestroy<DestroyReturn = unknown> { | ||
import { destroyed, status, statusP, initLock } from './utils.js'; | ||
interface CreateDestroy<DestroyReturn = unknown> extends Evented { | ||
get [destroyed](): boolean; | ||
get [status](): Status; | ||
get [statusP](): Promise<Status>; | ||
readonly [initLock]: RWLockWriter; | ||
destroy(...args: Array<any>): Promise<DestroyReturn | void>; | ||
} | ||
declare function CreateDestroy<DestroyReturn = unknown>(): <T extends new (...args: any[]) => { | ||
declare function CreateDestroy<DestroyReturn = unknown>({ eventDestroy, eventDestroyed, }?: { | ||
eventDestroy?: Class<Event>; | ||
eventDestroyed?: Class<Event>; | ||
}): <T extends new (...args: any[]) => { | ||
destroy?(...args: Array<any>): Promise<DestroyReturn | void>; | ||
}>(constructor: T) => { | ||
new (...args: any[]): { | ||
destroy(...args: Array<any>): Promise<DestroyReturn | void>; | ||
[_destroyed]: boolean; | ||
[_status]: Status; | ||
readonly [initLock]: RWLockWriter; | ||
readonly [destroyed]: boolean; | ||
readonly [status]: Status; | ||
}; | ||
} & T; | ||
}>(constructor: T) => (new (...args: Array<any>) => CreateDestroy<DestroyReturn>) & T; | ||
declare function ready(errorDestroyed?: Error, block?: boolean, allowedStatuses?: Array<Status>): (target: any, key: string, descriptor: PropertyDescriptor) => PropertyDescriptor; | ||
export { CreateDestroy, ready, destroyed, status, initLock }; | ||
export { CreateDestroy, ready, destroyed, status, statusP, initLock }; |
@@ -0,9 +1,14 @@ | ||
import { Evented } from '@matrixai/events'; | ||
import { RWLockWriter } from '@matrixai/async-locks'; | ||
import { _destroyed, destroyed, _status, status, initLock, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, resetStackTrace, } from './utils.js'; | ||
import { _destroyed, destroyed, _status, status, _statusP, statusP, resolveStatusP, initLock, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, promise, resetStackTrace, } from './utils.js'; | ||
import { EventAsyncInitDestroy, EventAsyncInitDestroyed } from './events.js'; | ||
import { ErrorAsyncInitDestroyed } from './errors.js'; | ||
function CreateDestroy() { | ||
function CreateDestroy({ eventDestroy = EventAsyncInitDestroy, eventDestroyed = EventAsyncInitDestroyed, } = {}) { | ||
return (constructor) => { | ||
const constructor_ = class extends constructor { | ||
const { p, resolveP } = promise(); | ||
const constructor_ = class extends Evented()(constructor) { | ||
[_destroyed] = false; | ||
[_status] = null; | ||
[_statusP] = p; | ||
[resolveStatusP] = resolveP; | ||
[initLock] = new RWLockWriter(); | ||
@@ -16,19 +21,31 @@ get [destroyed]() { | ||
} | ||
get [statusP]() { | ||
return this[_statusP]; | ||
} | ||
async destroy(...args) { | ||
return this[initLock].withWriteF(async () => { | ||
return this[initLock] | ||
.withWriteF(async () => { | ||
if (this[_destroyed]) { | ||
return; | ||
} | ||
this[_status] = 'destroying'; | ||
try { | ||
if (this[_destroyed]) { | ||
return; | ||
} | ||
let result; | ||
if (typeof super['destroy'] === 'function') { | ||
result = await super.destroy(...args); | ||
} | ||
this[_destroyed] = true; | ||
return result; | ||
this[resolveStatusP]('destroying'); | ||
const { p, resolveP } = promise(); | ||
this[_statusP] = p; | ||
this[resolveStatusP] = resolveP; | ||
this.dispatchEvent(new eventDestroy()); | ||
let result; | ||
if (typeof super['destroy'] === 'function') { | ||
result = await super.destroy(...args); | ||
} | ||
finally { | ||
this[_status] = null; | ||
} | ||
this[_destroyed] = true; | ||
this.dispatchEvent(new eventDestroyed()); | ||
return result; | ||
}) | ||
.finally(() => { | ||
this[_status] = null; | ||
this[resolveStatusP](null); | ||
const { p, resolveP } = promise(); | ||
this[_statusP] = p; | ||
this[resolveStatusP] = resolveP; | ||
}); | ||
@@ -60,2 +77,7 @@ } | ||
descriptor[kind] = async function (...args) { | ||
// If it is write locked, wait until the status has changed | ||
// This method may be called in between write locked and status change | ||
if (this[initLock].isLocked('write') && this[_status] === null) { | ||
await this[_statusP]; | ||
} | ||
if (allowedStatuses.includes(this[_status])) { | ||
@@ -87,3 +109,4 @@ return f.apply(this, args); | ||
} | ||
if (this[initLock].isLocked('write') || this[_destroyed]) { | ||
if ((this[initLock].isLocked('write') && this[status] !== null) || | ||
this[_destroyed]) { | ||
resetStackTrace(errorDestroyed, descriptor[kind]); | ||
@@ -97,2 +120,7 @@ throw errorDestroyed; | ||
descriptor[kind] = async function* (...args) { | ||
// If it is write locked, wait until the status has changed | ||
// This method may be called in between write locked and status change | ||
if (this[initLock].isLocked('write') && this[_status] === null) { | ||
await this[_statusP]; | ||
} | ||
if (allowedStatuses.includes(this[_status])) { | ||
@@ -124,3 +152,4 @@ return yield* f.apply(this, args); | ||
} | ||
if (this[initLock].isLocked('write') || this[_destroyed]) { | ||
if ((this[initLock].isLocked('write') && this[status] !== null) || | ||
this[_destroyed]) { | ||
resetStackTrace(errorDestroyed, descriptor[kind]); | ||
@@ -137,3 +166,3 @@ throw errorDestroyed; | ||
} | ||
export { CreateDestroy, ready, destroyed, status, initLock }; | ||
export { CreateDestroy, ready, destroyed, status, statusP, initLock }; | ||
//# sourceMappingURL=CreateDestroy.js.map |
@@ -1,8 +0,10 @@ | ||
import type { Status } from './types.js'; | ||
import type { Status, Class } from './types.js'; | ||
import { Evented } from '@matrixai/events'; | ||
import { RWLockWriter } from '@matrixai/async-locks'; | ||
import { _running, running, _destroyed, destroyed, _status, status, initLock } from './utils.js'; | ||
interface CreateDestroyStartStop<StartReturn = unknown, StopReturn = unknown, DestroyReturn = unknown> { | ||
import { running, destroyed, status, statusP, initLock } from './utils.js'; | ||
interface CreateDestroyStartStop<StartReturn = unknown, StopReturn = unknown, DestroyReturn = unknown> extends Evented { | ||
get [running](): boolean; | ||
get [destroyed](): boolean; | ||
get [status](): Status; | ||
get [statusP](): Promise<Status>; | ||
readonly [initLock]: RWLockWriter; | ||
@@ -13,21 +15,15 @@ start(...args: Array<any>): Promise<StartReturn | void>; | ||
} | ||
declare function CreateDestroyStartStop<StartReturn = unknown, StopReturn = unknown, DestroyReturn = unknown>(errorRunning?: Error, errorDestroyed?: Error): <T extends new (...args: any[]) => { | ||
declare function CreateDestroyStartStop<StartReturn = unknown, StopReturn = unknown, DestroyReturn = unknown>(errorRunning?: Error, errorDestroyed?: Error, { eventStart, eventStarted, eventStop, eventStopped, eventDestroy, eventDestroyed, }?: { | ||
eventStart?: Class<Event>; | ||
eventStarted?: Class<Event>; | ||
eventStop?: Class<Event>; | ||
eventStopped?: Class<Event>; | ||
eventDestroy?: Class<Event>; | ||
eventDestroyed?: Class<Event>; | ||
}): <T extends new (...args: any[]) => { | ||
start?(...args: Array<any>): Promise<StartReturn | void>; | ||
stop?(...args: Array<any>): Promise<StopReturn | void>; | ||
destroy?(...args: Array<any>): Promise<DestroyReturn | void>; | ||
}>(constructor: T) => { | ||
new (...args: any[]): { | ||
destroy(...args: Array<any>): Promise<DestroyReturn | void>; | ||
start(...args: Array<any>): Promise<StartReturn | void>; | ||
stop(...args: Array<any>): Promise<StopReturn | void>; | ||
[_running]: boolean; | ||
[_destroyed]: boolean; | ||
[_status]: Status; | ||
readonly [initLock]: RWLockWriter; | ||
readonly [running]: boolean; | ||
readonly [destroyed]: boolean; | ||
readonly [status]: Status; | ||
}; | ||
} & T; | ||
}>(constructor: T) => (new (...args: Array<any>) => CreateDestroyStartStop<StartReturn, StopReturn, DestroyReturn>) & T; | ||
declare function ready(errorNotRunning?: Error, block?: boolean, allowedStatuses?: Array<Status>): (target: any, key: string, descriptor: PropertyDescriptor) => PropertyDescriptor; | ||
export { CreateDestroyStartStop, ready, running, destroyed, status, initLock }; | ||
export { CreateDestroyStartStop, ready, running, destroyed, status, statusP, initLock, }; |
@@ -0,10 +1,15 @@ | ||
import { Evented } from '@matrixai/events'; | ||
import { RWLockWriter } from '@matrixai/async-locks'; | ||
import { _running, running, _destroyed, destroyed, _status, status, initLock, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, resetStackTrace, } from './utils.js'; | ||
import { _running, running, _destroyed, destroyed, _status, status, _statusP, statusP, resolveStatusP, initLock, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, promise, resetStackTrace, } from './utils.js'; | ||
import { EventAsyncInitStart, EventAsyncInitStarted, EventAsyncInitStop, EventAsyncInitStopped, EventAsyncInitDestroy, EventAsyncInitDestroyed, } from './events.js'; | ||
import { ErrorAsyncInitRunning, ErrorAsyncInitNotRunning, ErrorAsyncInitDestroyed, } from './errors.js'; | ||
function CreateDestroyStartStop(errorRunning = new ErrorAsyncInitRunning(), errorDestroyed = new ErrorAsyncInitDestroyed()) { | ||
function CreateDestroyStartStop(errorRunning = new ErrorAsyncInitRunning(), errorDestroyed = new ErrorAsyncInitDestroyed(), { eventStart = EventAsyncInitStart, eventStarted = EventAsyncInitStarted, eventStop = EventAsyncInitStop, eventStopped = EventAsyncInitStopped, eventDestroy = EventAsyncInitDestroy, eventDestroyed = EventAsyncInitDestroyed, } = {}) { | ||
return (constructor) => { | ||
const constructor_ = class extends constructor { | ||
const { p, resolveP } = promise(); | ||
const constructor_ = class extends Evented()(constructor) { | ||
[_running] = false; | ||
[_destroyed] = false; | ||
[_status] = null; | ||
[_statusP] = p; | ||
[resolveStatusP] = resolveP; | ||
[initLock] = new RWLockWriter(); | ||
@@ -20,74 +25,104 @@ get [running]() { | ||
} | ||
get [statusP]() { | ||
return this[_statusP]; | ||
} | ||
async destroy(...args) { | ||
return this[initLock].withWriteF(async () => { | ||
return this[initLock] | ||
.withWriteF(async () => { | ||
if (this[_destroyed]) { | ||
return; | ||
} | ||
if (this[_running]) { | ||
// Unfortunately `this.destroy` doesn't work as the decorated function | ||
resetStackTrace(errorRunning); | ||
throw errorRunning; | ||
} | ||
this[_status] = 'destroying'; | ||
try { | ||
if (this[_destroyed]) { | ||
return; | ||
} | ||
if (this[_running]) { | ||
// Unfortunately `this.destroy` doesn't work as the decorated function | ||
resetStackTrace(errorRunning); | ||
throw errorRunning; | ||
} | ||
let result; | ||
if (typeof super['destroy'] === 'function') { | ||
result = await super.destroy(...args); | ||
} | ||
this[_destroyed] = true; | ||
return result; | ||
this[resolveStatusP]('destroying'); | ||
const { p, resolveP } = promise(); | ||
this[_statusP] = p; | ||
this[resolveStatusP] = resolveP; | ||
this.dispatchEvent(new eventDestroy()); | ||
let result; | ||
if (typeof super['destroy'] === 'function') { | ||
result = await super.destroy(...args); | ||
} | ||
finally { | ||
this[_status] = null; | ||
} | ||
this[_destroyed] = true; | ||
this.dispatchEvent(new eventDestroyed()); | ||
return result; | ||
}) | ||
.finally(() => { | ||
this[_status] = null; | ||
this[resolveStatusP](null); | ||
const { p, resolveP } = promise(); | ||
this[_statusP] = p; | ||
this[resolveStatusP] = resolveP; | ||
}); | ||
} | ||
async start(...args) { | ||
return this[initLock].withWriteF(async () => { | ||
return this[initLock] | ||
.withWriteF(async () => { | ||
if (this[_running]) { | ||
return; | ||
} | ||
if (this[_destroyed]) { | ||
// Unfortunately `this.start` doesn't work as the decorated function | ||
resetStackTrace(errorDestroyed); | ||
throw errorDestroyed; | ||
} | ||
this[_status] = 'starting'; | ||
try { | ||
if (this[_running]) { | ||
return; | ||
} | ||
if (this[_destroyed]) { | ||
// Unfortunately `this.start` doesn't work as the decorated function | ||
resetStackTrace(errorDestroyed); | ||
throw errorDestroyed; | ||
} | ||
let result; | ||
if (typeof super['start'] === 'function') { | ||
result = await super.start(...args); | ||
} | ||
this[_running] = true; | ||
return result; | ||
this[resolveStatusP]('starting'); | ||
const { p, resolveP } = promise(); | ||
this[_statusP] = p; | ||
this[resolveStatusP] = resolveP; | ||
this.dispatchEvent(new eventStart()); | ||
let result; | ||
if (typeof super['start'] === 'function') { | ||
result = await super.start(...args); | ||
} | ||
finally { | ||
this[_status] = null; | ||
} | ||
this[_running] = true; | ||
this.dispatchEvent(new eventStarted()); | ||
return result; | ||
}) | ||
.finally(() => { | ||
this[_status] = null; | ||
this[resolveStatusP](null); | ||
const { p, resolveP } = promise(); | ||
this[_statusP] = p; | ||
this[resolveStatusP] = resolveP; | ||
}); | ||
} | ||
async stop(...args) { | ||
return this[initLock].withWriteF(async () => { | ||
return this[initLock] | ||
.withWriteF(async () => { | ||
if (!this[_running]) { | ||
return; | ||
} | ||
if (this[_destroyed]) { | ||
// It is not possible to be running and destroyed | ||
// however this line is here for completion | ||
// Unfortunately `this.stop` doesn't work as the decorated function | ||
resetStackTrace(errorDestroyed); | ||
throw errorDestroyed; | ||
} | ||
this[_status] = 'stopping'; | ||
try { | ||
if (!this[_running]) { | ||
return; | ||
} | ||
if (this[_destroyed]) { | ||
// It is not possible to be running and destroyed | ||
// however this line is here for completion | ||
// Unfortunately `this.stop` doesn't work as the decorated function | ||
resetStackTrace(errorDestroyed); | ||
throw errorDestroyed; | ||
} | ||
let result; | ||
if (typeof super['stop'] === 'function') { | ||
result = await super.stop(...args); | ||
} | ||
this[_running] = false; | ||
return result; | ||
this[resolveStatusP]('stopping'); | ||
const { p, resolveP } = promise(); | ||
this[_statusP] = p; | ||
this[resolveStatusP] = resolveP; | ||
this.dispatchEvent(new eventStop()); | ||
let result; | ||
if (typeof super['stop'] === 'function') { | ||
result = await super.stop(...args); | ||
} | ||
finally { | ||
this[_status] = null; | ||
} | ||
this[_running] = false; | ||
this.dispatchEvent(new eventStopped()); | ||
return result; | ||
}) | ||
.finally(() => { | ||
this[_status] = null; | ||
this[resolveStatusP](null); | ||
const { p, resolveP } = promise(); | ||
this[_statusP] = p; | ||
this[resolveStatusP] = resolveP; | ||
}); | ||
@@ -119,2 +154,7 @@ } | ||
descriptor[kind] = async function (...args) { | ||
// If it is write locked, wait until the status has changed | ||
// This method may be called in between write locked and status change | ||
if (this[initLock].isLocked('write') && this[_status] === null) { | ||
await this[_statusP]; | ||
} | ||
if (allowedStatuses.includes(this[_status])) { | ||
@@ -146,3 +186,4 @@ return f.apply(this, args); | ||
} | ||
if (this[initLock].isLocked('write') || !this[_running]) { | ||
if ((this[initLock].isLocked('write') && this[status] !== null) || | ||
!this[_running]) { | ||
resetStackTrace(errorNotRunning, descriptor[kind]); | ||
@@ -156,2 +197,7 @@ throw errorNotRunning; | ||
descriptor[kind] = async function* (...args) { | ||
// If it is write locked, wait until the status has changed | ||
// This method may be called in between write locked and status change | ||
if (this[initLock].isLocked('write') && this[_status] === null) { | ||
await this[_statusP]; | ||
} | ||
if (allowedStatuses.includes(this[_status])) { | ||
@@ -183,3 +229,4 @@ return yield* f.apply(this, args); | ||
} | ||
if (this[initLock].isLocked('write') || !this[_running]) { | ||
if ((this[initLock].isLocked('write') && this[status] !== null) || | ||
!this[_running]) { | ||
resetStackTrace(errorNotRunning, descriptor[kind]); | ||
@@ -196,3 +243,3 @@ throw errorNotRunning; | ||
} | ||
export { CreateDestroyStartStop, ready, running, destroyed, status, initLock }; | ||
export { CreateDestroyStartStop, ready, running, destroyed, status, statusP, initLock, }; | ||
//# sourceMappingURL=CreateDestroyStartStop.js.map |
@@ -5,3 +5,4 @@ export * as types from './types.js'; | ||
export * as startStop from './StartStop.js'; | ||
export * as events from './events.js'; | ||
export * as errors from './errors.js'; | ||
export { running, destroyed, status, initLock } from './utils.js'; | ||
export { running, destroyed, status, statusP, initLock } from './utils.js'; |
@@ -5,4 +5,5 @@ export * as types from './types.js'; | ||
export * as startStop from './StartStop.js'; | ||
export * as events from './events.js'; | ||
export * as errors from './errors.js'; | ||
export { running, destroyed, status, initLock } from './utils.js'; | ||
export { running, destroyed, status, statusP, initLock } from './utils.js'; | ||
//# sourceMappingURL=index.js.map |
@@ -1,7 +0,9 @@ | ||
import type { Status } from './types.js'; | ||
import type { Status, Class } from './types.js'; | ||
import { Evented } from '@matrixai/events'; | ||
import { RWLockWriter } from '@matrixai/async-locks'; | ||
import { _running, running, _status, status, initLock } from './utils.js'; | ||
interface StartStop<StartReturn = unknown, StopReturn = unknown> { | ||
import { running, status, statusP, initLock } from './utils.js'; | ||
interface StartStop<StartReturn = unknown, StopReturn = unknown> extends Evented { | ||
get [running](): boolean; | ||
get [status](): Status; | ||
get [statusP](): Promise<Status>; | ||
readonly [initLock]: RWLockWriter; | ||
@@ -11,17 +13,12 @@ start(...args: Array<any>): Promise<StartReturn | void>; | ||
} | ||
declare function StartStop<StartReturn = unknown, StopReturn = unknown>(): <T extends new (...args: any[]) => { | ||
declare function StartStop<StartReturn = unknown, StopReturn = unknown>({ eventStart, eventStarted, eventStop, eventStopped, }?: { | ||
eventStart?: Class<Event>; | ||
eventStarted?: Class<Event>; | ||
eventStop?: Class<Event>; | ||
eventStopped?: Class<Event>; | ||
}): <T extends new (...args: Array<any>) => { | ||
start?(...args: Array<any>): Promise<StartReturn | void>; | ||
stop?(...args: Array<any>): Promise<StopReturn | void>; | ||
}>(constructor: T) => { | ||
new (...args: any[]): { | ||
start(...args: Array<any>): Promise<StartReturn | void>; | ||
stop(...args: Array<any>): Promise<StopReturn | void>; | ||
[_running]: boolean; | ||
[_status]: Status; | ||
readonly [initLock]: RWLockWriter; | ||
readonly [running]: boolean; | ||
readonly [status]: Status; | ||
}; | ||
} & T; | ||
}>(constructor: T) => (new (...args: Array<any>) => StartStop<StartReturn, StopReturn>) & T; | ||
declare function ready(errorNotRunning?: Error, block?: boolean, allowedStatuses?: Array<Status>): (target: any, key: string, descriptor: PropertyDescriptor) => PropertyDescriptor; | ||
export { StartStop, ready, running, status, initLock }; | ||
export { StartStop, ready, running, status, statusP, initLock }; |
@@ -0,9 +1,14 @@ | ||
import { Evented } from '@matrixai/events'; | ||
import { RWLockWriter } from '@matrixai/async-locks'; | ||
import { _running, running, _status, status, initLock, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, resetStackTrace, } from './utils.js'; | ||
import { _running, running, _status, status, _statusP, statusP, resolveStatusP, initLock, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, promise, resetStackTrace, } from './utils.js'; | ||
import { EventAsyncInitStart, EventAsyncInitStarted, EventAsyncInitStop, EventAsyncInitStopped, } from './events.js'; | ||
import { ErrorAsyncInitNotRunning } from './errors.js'; | ||
function StartStop() { | ||
function StartStop({ eventStart = EventAsyncInitStart, eventStarted = EventAsyncInitStarted, eventStop = EventAsyncInitStop, eventStopped = EventAsyncInitStopped, } = {}) { | ||
return (constructor) => { | ||
const constructor_ = class extends constructor { | ||
const { p, resolveP } = promise(); | ||
const constructor_ = class extends Evented()(constructor) { | ||
[_running] = false; | ||
[_status] = null; | ||
[_statusP] = p; | ||
[resolveStatusP] = resolveP; | ||
[initLock] = new RWLockWriter(); | ||
@@ -16,38 +21,59 @@ get [running]() { | ||
} | ||
get [statusP]() { | ||
return this[_statusP]; | ||
} | ||
async start(...args) { | ||
return this[initLock].withWriteF(async () => { | ||
return this[initLock] | ||
.withWriteF(async () => { | ||
if (this[_running]) { | ||
return; | ||
} | ||
this[_status] = 'starting'; | ||
try { | ||
if (this[_running]) { | ||
return; | ||
} | ||
let result; | ||
if (typeof super['start'] === 'function') { | ||
result = await super.start(...args); | ||
} | ||
this[_running] = true; | ||
return result; | ||
this[resolveStatusP]('starting'); | ||
const { p, resolveP } = promise(); | ||
this[_statusP] = p; | ||
this[resolveStatusP] = resolveP; | ||
this.dispatchEvent(new eventStart()); | ||
let result; | ||
if (typeof super['start'] === 'function') { | ||
result = await super.start(...args); | ||
} | ||
finally { | ||
this[_status] = null; | ||
} | ||
this[_running] = true; | ||
this.dispatchEvent(new eventStarted()); | ||
return result; | ||
}) | ||
.finally(() => { | ||
this[_status] = null; | ||
this[resolveStatusP](null); | ||
const { p, resolveP } = promise(); | ||
this[_statusP] = p; | ||
this[resolveStatusP] = resolveP; | ||
}); | ||
} | ||
async stop(...args) { | ||
return this[initLock].withWriteF(async () => { | ||
return this[initLock] | ||
.withWriteF(async () => { | ||
if (!this[_running]) { | ||
return; | ||
} | ||
this[_status] = 'stopping'; | ||
try { | ||
if (!this[_running]) { | ||
return; | ||
} | ||
let result; | ||
if (typeof super['stop'] === 'function') { | ||
result = await super.stop(...args); | ||
} | ||
this[_running] = false; | ||
return result; | ||
this[resolveStatusP]('stopping'); | ||
const { p, resolveP } = promise(); | ||
this[_statusP] = p; | ||
this[resolveStatusP] = resolveP; | ||
this.dispatchEvent(new eventStop()); | ||
let result; | ||
if (typeof super['stop'] === 'function') { | ||
result = await super.stop(...args); | ||
} | ||
finally { | ||
this[_status] = null; | ||
} | ||
this[_running] = false; | ||
this.dispatchEvent(new eventStopped()); | ||
return result; | ||
}) | ||
.finally(() => { | ||
this[_status] = null; | ||
this[resolveStatusP](null); | ||
const { p, resolveP } = promise(); | ||
this[_statusP] = p; | ||
this[resolveStatusP] = resolveP; | ||
}); | ||
@@ -79,2 +105,7 @@ } | ||
descriptor[kind] = async function (...args) { | ||
// If it is write locked, wait until the status has changed | ||
// This method may be called in between write locked and status change | ||
if (this[initLock].isLocked('write') && this[_status] === null) { | ||
await this[_statusP]; | ||
} | ||
if (allowedStatuses.includes(this[_status])) { | ||
@@ -106,3 +137,4 @@ return f.apply(this, args); | ||
} | ||
if (this[initLock].isLocked('write') || !this[_running]) { | ||
if ((this[initLock].isLocked('write') && this[status] !== null) || | ||
!this[_running]) { | ||
resetStackTrace(errorNotRunning, descriptor[kind]); | ||
@@ -116,2 +148,7 @@ throw errorNotRunning; | ||
descriptor[kind] = async function* (...args) { | ||
// If it is write locked, wait until the status has changed | ||
// This method may be called in between write locked and status change | ||
if (this[initLock].isLocked('write') && this[_status] === null) { | ||
await this[_statusP]; | ||
} | ||
if (allowedStatuses.includes(this[_status])) { | ||
@@ -143,3 +180,4 @@ return yield* f.apply(this, args); | ||
} | ||
if (this[initLock].isLocked('write') || !this[_running]) { | ||
if ((this[initLock].isLocked('write') && this[status] !== null) || | ||
!this[_running]) { | ||
resetStackTrace(errorNotRunning, descriptor[kind]); | ||
@@ -156,3 +194,3 @@ throw errorNotRunning; | ||
} | ||
export { StartStop, ready, running, status, initLock }; | ||
export { StartStop, ready, running, status, statusP, initLock }; | ||
//# sourceMappingURL=StartStop.js.map |
@@ -0,2 +1,11 @@ | ||
/** | ||
* Deconstructed promise | ||
*/ | ||
type PromiseDeconstructed<T> = { | ||
p: Promise<T>; | ||
resolveP: (value: T | PromiseLike<T>) => void; | ||
rejectP: (reason?: any) => void; | ||
}; | ||
type Status = 'destroying' | 'starting' | 'stopping' | null; | ||
export type { Status }; | ||
type Class<T> = new (...args: any[]) => T; | ||
export type { PromiseDeconstructed, Status, Class }; |
@@ -0,1 +1,2 @@ | ||
import type { PromiseDeconstructed } from './types.js'; | ||
/** | ||
@@ -10,2 +11,5 @@ * Symbols prevents name clashes with decorated classes | ||
declare const status: unique symbol; | ||
declare const _statusP: unique symbol; | ||
declare const statusP: unique symbol; | ||
declare const resolveStatusP: unique symbol; | ||
declare const initLock: unique symbol; | ||
@@ -17,2 +21,6 @@ declare const AsyncFunction: Function; | ||
/** | ||
* Deconstructed promise | ||
*/ | ||
declare function promise<T = void>(): PromiseDeconstructed<T>; | ||
/** | ||
* Ready wrappers take exception objects | ||
@@ -24,2 +32,2 @@ * JS exception traces are created when the exception is instantiated | ||
declare function resetStackTrace(error: Error, decorated?: Function): void; | ||
export { _running, running, _destroyed, destroyed, _status, status, initLock, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, hasCaptureStackTrace, resetStackTrace, }; | ||
export { _running, running, _destroyed, destroyed, _status, status, _statusP, statusP, resolveStatusP, initLock, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, hasCaptureStackTrace, promise, resetStackTrace, }; |
@@ -10,2 +10,5 @@ /** | ||
const status = Symbol('status'); | ||
const _statusP = Symbol('_statusP'); | ||
const statusP = Symbol('statusP'); | ||
const resolveStatusP = Symbol('resolveStatusP'); | ||
const initLock = Symbol('initLock'); | ||
@@ -17,2 +20,17 @@ const AsyncFunction = (async () => { }).constructor; | ||
/** | ||
* Deconstructed promise | ||
*/ | ||
function promise() { | ||
let resolveP, rejectP; | ||
const p = new Promise((resolve, reject) => { | ||
resolveP = resolve; | ||
rejectP = reject; | ||
}); | ||
return { | ||
p, | ||
resolveP, | ||
rejectP, | ||
}; | ||
} | ||
/** | ||
* Ready wrappers take exception objects | ||
@@ -40,3 +58,3 @@ * JS exception traces are created when the exception is instantiated | ||
} | ||
export { _running, running, _destroyed, destroyed, _status, status, initLock, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, hasCaptureStackTrace, resetStackTrace, }; | ||
export { _running, running, _destroyed, destroyed, _status, status, _statusP, statusP, resolveStatusP, initLock, AsyncFunction, GeneratorFunction, AsyncGeneratorFunction, hasCaptureStackTrace, promise, resetStackTrace, }; | ||
//# sourceMappingURL=utils.js.map |
{ | ||
"name": "@matrixai/async-init", | ||
"version": "2.0.0", | ||
"version": "2.1.0", | ||
"author": "Roger Qiu", | ||
@@ -40,9 +40,10 @@ "description": "Asynchronous Initialisation and Deinitialisation Decorators", | ||
"@matrixai/async-locks": "^5.0.1", | ||
"@matrixai/errors": "^2.0.1" | ||
"@matrixai/errors": "^2.1.0", | ||
"@matrixai/events": "^4.0.0" | ||
}, | ||
"devDependencies": { | ||
"@swc/core": "^1.3.76", | ||
"@swc/core": "1.3.82", | ||
"@swc/jest": "^0.2.29", | ||
"@types/jest": "^29.5.2", | ||
"@types/node": "^18.15.0", | ||
"@types/node": "^20.5.7", | ||
"@typescript-eslint/eslint-plugin": "^5.61.0", | ||
@@ -49,0 +50,0 @@ "@typescript-eslint/parser": "^5.61.0", |
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
81912
28
910
3
+ Added@matrixai/events@^4.0.0
+ Added@matrixai/events@4.0.1(transitive)
Updated@matrixai/errors@^2.1.0