@maybe-remote/core
Advanced tools
Comparing version 0.0.2 to 0.0.3
@@ -0,1 +1,5 @@ | ||
## 0.0.3 (2024-10-14) | ||
This was a version bump only for core to align it with other projects, there were no code changes. | ||
## 0.0.2 (2024-10-14) | ||
@@ -2,0 +6,0 @@ |
{ | ||
"name": "@maybe-remote/core", | ||
"version": "0.0.2", | ||
"version": "0.0.3", | ||
"dependencies": { | ||
@@ -5,0 +5,0 @@ "tslib": "^2.3.0" |
@@ -1,2 +0,7 @@ | ||
import { ServiceConnection, ServiceDefinition } from './types'; | ||
import type { | ||
ServiceConnection, | ||
ServiceDefinition, | ||
ServicePlugin, | ||
ClientPlugin, | ||
} from './types'; | ||
@@ -60,6 +65,6 @@ export interface AsyncIteratorRequest { | ||
export function asyncIterationServicePlugin() { | ||
const iterators = new Map<string, AsyncIterator<any>>(); | ||
export class AsyncIterationServicePlugin implements ServicePlugin { | ||
private iterators = new Map<string, AsyncIterator<any>>(); | ||
return ( | ||
handleMessage( | ||
message: | ||
@@ -70,6 +75,7 @@ | AsyncIteratorRequest | ||
| AsyncIteratorReturn | ||
| AsyncIteratorGC, | ||
| AsyncIteratorGC | ||
| { type: ''; payload: any }, | ||
connection: ServiceConnection, | ||
serviceDefinition: ServiceDefinition | ||
) => { | ||
): boolean { | ||
switch (message.type) { | ||
@@ -91,3 +97,3 @@ case 'async-iterator-request': { | ||
const iterator = fn(...params); | ||
iterators.set(iteratorId, iterator); | ||
this.iterators.set(iteratorId, iterator); | ||
return true; | ||
@@ -97,3 +103,3 @@ } | ||
const { iteratorId, value } = message.payload; | ||
const iterator = iterators.get(iteratorId); | ||
const iterator = this.iterators.get(iteratorId); | ||
@@ -107,3 +113,3 @@ if (!iterator) { | ||
if (done) { | ||
iterators.delete(iteratorId); | ||
this.iterators.delete(iteratorId); | ||
} | ||
@@ -120,3 +126,3 @@ connection.send({ | ||
(error) => { | ||
iterators.delete(iteratorId); | ||
this.iterators.delete(iteratorId); | ||
connection.send({ | ||
@@ -135,3 +141,3 @@ type: 'async-iterator-error', | ||
const { iteratorId, reason } = message.payload; | ||
const iterator = iterators.get(iteratorId); | ||
const iterator = this.iterators.get(iteratorId); | ||
@@ -142,3 +148,3 @@ if (!iterator) { | ||
iterators.delete(iteratorId); | ||
this.iterators.delete(iteratorId); | ||
@@ -165,3 +171,3 @@ if (typeof iterator.throw !== 'function') { | ||
const iterator = iterators.get(iteratorId); | ||
const iterator = this.iterators.get(iteratorId); | ||
@@ -172,3 +178,3 @@ if (!iterator) { | ||
iterators.delete(iteratorId); | ||
this.iterators.delete(iteratorId); | ||
@@ -194,3 +200,3 @@ if (typeof iterator.return !== 'function') { | ||
const { iteratorId } = message.payload; | ||
iterators.delete(iteratorId); | ||
this.iterators.delete(iteratorId); | ||
return true; | ||
@@ -201,12 +207,14 @@ } | ||
return false; | ||
}; | ||
} | ||
} | ||
export function asyncIterationClientPlugin() { | ||
const refs = new Map<string, WeakRef<AsyncIterator<any>>>(); | ||
export const asyncIterationServicePlugin = new AsyncIterationServicePlugin(); | ||
const cleanRefs = (connection: ServiceConnection) => { | ||
for (const [iteratorId, ref] of refs) { | ||
export class AsyncIterationClientPlugin implements ClientPlugin { | ||
private refs = new Map<string, WeakRef<AsyncIterator<any>>>(); | ||
private cleanRefs(connection: ServiceConnection) { | ||
for (const [iteratorId, ref] of this.refs) { | ||
if (!ref.deref()) { | ||
refs.delete(iteratorId); | ||
this.refs.delete(iteratorId); | ||
connection.send({ | ||
@@ -220,16 +228,17 @@ type: 'async-iterator-gc', | ||
} | ||
}; | ||
} | ||
let scheduledCleanRefs = 0; | ||
const scheduleCleanRefs = (connection: ServiceConnection) => { | ||
if (scheduledCleanRefs !== 0 || refs.size === 0) return; | ||
private scheduledCleanRefs = 0; | ||
scheduledCleanRefs = requestIdleCallback(() => { | ||
scheduledCleanRefs = 0; | ||
cleanRefs(connection); | ||
private scheduleCleanRefs(connection: ServiceConnection) { | ||
if (this.scheduledCleanRefs !== 0 || this.refs.size === 0) return; | ||
this.scheduledCleanRefs = requestIdleCallback(() => { | ||
this.scheduledCleanRefs = 0; | ||
this.cleanRefs(connection); | ||
}); | ||
}; | ||
} | ||
return (method: string, connection: ServiceConnection) => { | ||
scheduleCleanRefs(connection); | ||
findHandler(method: string, connection: ServiceConnection) { | ||
this.scheduleCleanRefs(connection); | ||
@@ -345,9 +354,11 @@ if (!method.startsWith('iterate')) { | ||
refs.set(iteratorId, new WeakRef(iterator)); | ||
this.refs.set(iteratorId, new WeakRef(iterator)); | ||
return iterator; | ||
}; | ||
}; | ||
} | ||
} | ||
export const asyncIterationClientPlugin = new AsyncIterationClientPlugin(); | ||
class Deferred<T> { | ||
@@ -354,0 +365,0 @@ promise: Promise<T>; |
@@ -40,5 +40,5 @@ import { defaultClientPlugins } from './default-plugins'; | ||
for (const plugin of plugins) { | ||
const result = plugin(prop, connection); | ||
if (result !== undefined) { | ||
return result; | ||
const handler = plugin.findHandler(prop, connection); | ||
if (handler !== undefined) { | ||
return handler; | ||
} | ||
@@ -45,0 +45,0 @@ } |
@@ -9,9 +9,9 @@ import { | ||
export const defaultServicePlugins: ServicePlugin[] = [ | ||
promiseServicePlugin as ServicePlugin, | ||
asyncIterationServicePlugin() as ServicePlugin, | ||
promiseServicePlugin, | ||
asyncIterationServicePlugin, | ||
]; | ||
export const defaultClientPlugins: ClientPlugin[] = [ | ||
asyncIterationClientPlugin(), | ||
promiseClientPlugin, | ||
asyncIterationClientPlugin, | ||
]; |
@@ -1,2 +0,7 @@ | ||
import { ServiceConnection, ServiceDefinition } from './types'; | ||
import { | ||
ClientPlugin, | ||
ServiceConnection, | ||
ServiceDefinition, | ||
ServicePlugin, | ||
} from './types'; | ||
@@ -28,85 +33,90 @@ export interface PromiseRequest { | ||
export function promiseServicePlugin( | ||
message: PromiseRequest, | ||
connection: ServiceConnection, | ||
serviceDefintion: ServiceDefinition | ||
) { | ||
if (message.type === 'promise-request') { | ||
const { promiseId, method, params } = message.payload; | ||
const fn = serviceDefintion[method]; | ||
export class PromiseServicePlugin implements ServicePlugin { | ||
handleMessage( | ||
message: PromiseRequest, | ||
connection: ServiceConnection, | ||
serviceDefintion: ServiceDefinition | ||
): boolean { | ||
if (message.type === 'promise-request') { | ||
const { promiseId, method, params } = message.payload; | ||
const fn = serviceDefintion[method]; | ||
if (typeof fn !== 'function') { | ||
connection.send({ | ||
type: 'unknown-method-error', | ||
payload: { | ||
method, | ||
}, | ||
}); | ||
return true; | ||
} | ||
Promise.resolve(fn(...params)).then( | ||
(value) => { | ||
if (typeof fn !== 'function') { | ||
connection.send({ | ||
type: 'promise-resolved', | ||
type: 'unknown-method-error', | ||
payload: { | ||
promiseId, | ||
value, | ||
method, | ||
}, | ||
}); | ||
}, | ||
(reason) => { | ||
connection.send({ | ||
type: 'promise-rejected', | ||
payload: { | ||
promiseId, | ||
reason: reason instanceof Error ? reason.message : reason, | ||
}, | ||
}); | ||
return true; | ||
} | ||
); | ||
return true; | ||
Promise.resolve(fn(...params)).then( | ||
(value) => { | ||
connection.send({ | ||
type: 'promise-resolved', | ||
payload: { | ||
promiseId, | ||
value, | ||
}, | ||
}); | ||
}, | ||
(reason) => { | ||
connection.send({ | ||
type: 'promise-rejected', | ||
payload: { | ||
promiseId, | ||
reason: reason instanceof Error ? reason.message : reason, | ||
}, | ||
}); | ||
} | ||
); | ||
return true; | ||
} | ||
return false; | ||
} | ||
return false; | ||
} | ||
export function promiseClientPlugin( | ||
method: string, | ||
connection: ServiceConnection | ||
) { | ||
if (method.startsWith('get')) { | ||
return (...params: any[]) => | ||
new Promise((resolve, reject) => { | ||
const dispose = connection.onMessage( | ||
(message: PromiseResolved | PromiseRejected) => { | ||
if (message.type === 'promise-resolved') { | ||
if (message.payload.promiseId === promiseId) { | ||
resolve(message.payload.value); | ||
dispose(); | ||
export const promiseServicePlugin = new PromiseServicePlugin(); | ||
export class PromiseClientPlugin implements ClientPlugin { | ||
findHandler(method: string, connection: ServiceConnection) { | ||
if (method.startsWith('get')) { | ||
return (...params: any[]) => | ||
new Promise((resolve, reject) => { | ||
const dispose = connection.onMessage( | ||
(message: PromiseResolved | PromiseRejected) => { | ||
if (message.type === 'promise-resolved') { | ||
if (message.payload.promiseId === promiseId) { | ||
resolve(message.payload.value); | ||
dispose(); | ||
} | ||
} else if (message.type === 'promise-rejected') { | ||
if (message.payload.promiseId === promiseId) { | ||
reject(new Error(message.payload.reason)); | ||
dispose(); | ||
} | ||
} | ||
} else if (message.type === 'promise-rejected') { | ||
if (message.payload.promiseId === promiseId) { | ||
reject(new Error(message.payload.reason)); | ||
dispose(); | ||
} | ||
} | ||
} | ||
); | ||
); | ||
const promiseId = crypto.randomUUID(); | ||
const promiseId = crypto.randomUUID(); | ||
connection.send({ | ||
type: 'promise-request', | ||
payload: { | ||
promiseId, | ||
method, | ||
params, | ||
}, | ||
connection.send({ | ||
type: 'promise-request', | ||
payload: { | ||
promiseId, | ||
method, | ||
params, | ||
}, | ||
}); | ||
}); | ||
}); | ||
} | ||
return; | ||
} | ||
} | ||
return; | ||
} | ||
export const promiseClientPlugin = new PromiseClientPlugin(); |
@@ -29,3 +29,3 @@ import { defaultServicePlugins } from './default-plugins'; | ||
for (const plugin of this.plugins) { | ||
if (plugin(message, connection, serviceDefinition)) { | ||
if (plugin.handleMessage(message, connection, serviceDefinition)) { | ||
return; | ||
@@ -32,0 +32,0 @@ } |
@@ -18,7 +18,9 @@ type Teardown = () => void; | ||
export type ServicePlugin = ( | ||
message: TransportMessage, | ||
connection: ServiceConnection, | ||
serviceDefinition: ServiceDefinition | ||
) => boolean; | ||
export interface ServicePlugin { | ||
handleMessage( | ||
message: TransportMessage, | ||
connection: ServiceConnection, | ||
serviceDefinition: ServiceDefinition | ||
): boolean; | ||
} | ||
@@ -32,5 +34,4 @@ export interface UnknownMethodError { | ||
export type ClientPlugin = ( | ||
method: string, | ||
connection: ServiceConnection | ||
) => any; | ||
export interface ClientPlugin { | ||
findHandler(method: string, connection: ServiceConnection): any; | ||
} |
72319
1353