@agoric/eventual-send
Advanced tools
Comparing version 0.14.2-dev-28c48e4.0 to 0.14.2-dev-290b19c.0
{ | ||
"name": "@agoric/eventual-send", | ||
"version": "0.14.2-dev-28c48e4.0+28c48e4", | ||
"version": "0.14.2-dev-290b19c.0+290b19c", | ||
"description": "Extend a Promise class to implement the eventual-send API", | ||
@@ -29,4 +29,4 @@ "type": "module", | ||
"devDependencies": { | ||
"@endo/lockdown": "^0.1.8", | ||
"@endo/ses-ava": "^0.2.20", | ||
"@endo/lockdown": "^0.1.9", | ||
"@endo/ses-ava": "^0.2.21", | ||
"ava": "^3.12.1", | ||
@@ -58,3 +58,3 @@ "c8": "^7.7.2" | ||
}, | ||
"gitHead": "28c48e4e2aa0833cc85ac360cd4f34132b17894a" | ||
"gitHead": "290b19c66dbec9119409d075875599ee9e2db962" | ||
} |
@@ -1,9 +0,45 @@ | ||
/* eslint-disable no-shadow,no-unused-vars,no-use-before-define,no-var,vars-on-top */ | ||
/* eslint-disable no-shadow,no-use-before-define,no-var,vars-on-top */ | ||
// Type definitions for eventual-send | ||
// TODO: Add jsdocs. | ||
// *Eventually* to be moved to @endo/eventual-send | ||
type Property = string | number | symbol; | ||
/** | ||
* @file Type definitions for @agoric/eventual-send | ||
* | ||
* Some useful background knowledge: | ||
* | ||
* `Omit<T, U>` means to return a record type `T2` which has none of the properties whose keys are part of `U`. | ||
* `Omit<{a: 1, b: 2, c: 3}, 'b'>` is the type `{a: 1, c: 3}`. | ||
* | ||
* `Pick<T, U>` means to return a record type `T2` which has only the properties whose keys are part of `U`. | ||
* `Pick<{a: 1, b: 2, c: 3}, 'b'>` is the type `{b: 2}`. | ||
* | ||
* `PromiseLike<T>` is a thenable which resolves to `T`. | ||
* | ||
* `Promise<PromiseLike<T>>` doesn't handle recursion and is distinct from `T`. | ||
* | ||
* `Unpromise<PromiseLike<T>>` strips off just one layer and is just `T`. `Unpromise<PromiseLike<PromiseLIke<T>>` is `PromiseLike<T>`. | ||
* | ||
* `Awaited<PromiseLike<T>>` recurses, and is just `T`. | ||
* `Awaited<PromiseLike<PromiseLike<T>>>` is just `T` as well. | ||
* | ||
* @see {@link https://www.typescriptlang.org/docs/handbook/2/generics.html#handbook-content} | ||
* @see {@link https://www.typescriptlang.org/docs/handbook/2/conditional-types.html} | ||
*/ | ||
type ERef<T> = PromiseLike<T> | T; | ||
// TODO adopt symbol after https://github.com/endojs/endo/issues/1035 and eventual-send lives in Endo only | ||
// declare const RemoteTag: unique symbol; | ||
// For now maintain compatibility with @endo/marshal that is using '__Remote__' literal | ||
declare const RemoteTag: '__Remote__'; | ||
/** | ||
* The remote interface of T | ||
*/ | ||
export interface Remotable<T> { | ||
[RemoteTag]: T; | ||
} | ||
export type Callable = (...args: any[]) => any; | ||
// Same as https://github.com/microsoft/TypeScript/issues/31394 | ||
export type ERef<T> = PromiseLike<T> | T; | ||
// Type for an object that must only be invoked with E. It supports a given | ||
@@ -13,3 +49,3 @@ // interface but declares all the functions as asyncable. | ||
? (...args: P) => ERef<R> | EOnly<R> | ||
: T extends Record<string | number | symbol, Function> | ||
: T extends Record<PropertyKey, Callable> | ||
? ERef<{ | ||
@@ -20,30 +56,67 @@ [K in keyof T]: EOnly<T[K]>; | ||
type FilteredKeys<T, U> = { | ||
/** | ||
* Return a union of property names/symbols/numbers P for which the record element T[P]'s type extends U. | ||
* | ||
* Given const x = { a: 123, b: 'hello', c: 42, 49: () => {}, 53: 67 }, | ||
* | ||
* FilteredKeys<typeof x, number> is the type 'a' | 'c' | 53. | ||
* FilteredKeys<typeof x, string> is the type 'b'. | ||
* FilteredKeys<typeof x, 42 | 67> is the type 'c' | 53. | ||
* FilteredKeys<typeof x, boolean> is the type never. | ||
*/ | ||
export type FilteredKeys<T, U> = { | ||
[P in keyof T]: T[P] extends U ? P : never; | ||
}[keyof T]; | ||
type DataOnly<T> = Omit<T, FilteredKeys<T, Function>>; | ||
type FunctionOnly<T> = Pick<T, FilteredKeys<T, Function>> & | ||
(T extends Function ? (...args: Parameters<T>) => ReturnType<T> : {}); | ||
/** | ||
* `DataOnly<T>` means to return a record type `T2` consisting only of properties that are *not* functions. | ||
*/ | ||
export type DataOnly<T> = Omit<T, FilteredKeys<T, Callable>>; | ||
/** | ||
* `FunctionOnly<T>` means to return a record type `T2` consisting only of properties that are functions. | ||
*/ | ||
export type FunctionOnly<T> = Pick<T, FilteredKeys<T, Callable>> & | ||
(T extends Callable ? (...args: Parameters<T>) => ReturnType<T> : {}); | ||
interface Remotable<T> { | ||
__Remote__: T; | ||
} | ||
type Remote<Primary, Local = DataOnly<Primary>> = ERef< | ||
/** | ||
* Creates a type that accepts both near and marshalled references that were returned from `Remotable` or `Far`. | ||
*/ | ||
export type Remote<Primary, Local = DataOnly<Primary>> = ERef< | ||
Local & Remotable<Primary> | ||
>; | ||
interface EHandler<T> { | ||
get?: (p: T, name: Property, returnedP?: Promise<unknown>) => any; | ||
getSendOnly?: (p: T, name: Property) => void; | ||
applyFunction?: (p: T, args: unknown[], returnedP?: Promise<unknown>) => any; | ||
export type RemoteFunctions<T> = T extends Remotable<infer U> // if a given T is the remote interface of some U | ||
? // then, | ||
FunctionOnly<U> // use all the function properties of that U | ||
: // otherwise, | ||
Awaited<T> extends Remotable<infer U> // if the final resolution of T is the remote interface of some U | ||
? // then, | ||
FunctionOnly<U> // use the function properties of that U | ||
: // otherwise, | ||
Awaited<T>; // use the final resolution of that T | ||
export type PromisedData<T> = T extends Remotable<infer U> | ||
? DataOnly<U> | ||
: Awaited<T> extends Remotable<infer U> | ||
? DataOnly<U> | ||
: Awaited<T>; | ||
export interface EHandler<T> { | ||
get?: (p: T, name: PropertyKey, returnedP?: Promise<unknown>) => unknown; | ||
getSendOnly?: (p: T, name: PropertyKey) => void; | ||
applyFunction?: ( | ||
p: T, | ||
args: unknown[], | ||
returnedP?: Promise<unknown>, | ||
) => unknown; | ||
applyFunctionSendOnly?: (p: T, args: unknown[]) => void; | ||
applyMethod?: ( | ||
p: T, | ||
name: Property | undefined, | ||
name: PropertyKey | undefined, | ||
args: unknown[], | ||
returnedP?: Promise<unknown>, | ||
) => any; | ||
) => unknown; | ||
applyMethodSendOnly?: ( | ||
p: T, | ||
name: Property | undefined, | ||
name: PropertyKey | undefined, | ||
args: unknown[], | ||
@@ -53,3 +126,3 @@ ) => void; | ||
type HandledExecutor<R> = ( | ||
export type HandledExecutor<R> = ( | ||
resolveHandled: (value?: R) => void, | ||
@@ -63,3 +136,3 @@ rejectHandled: (reason?: unknown) => void, | ||
type ResolveWithPresenceOptionsBag<T extends Object> = { | ||
export type ResolveWithPresenceOptionsBag<T extends Object> = { | ||
proxy?: { | ||
@@ -72,5 +145,5 @@ handler: ProxyHandler<T>; | ||
declare interface HandledPromiseStaticMethods { | ||
resolve<T>(x: T): Promise<Awaited<T>>; | ||
resolve(): Promise<undefined>; | ||
export interface HandledPromiseStaticMethods { | ||
resolve(): Promise<void>; | ||
resolve<T>(value: T | PromiseLike<T>): Promise<T>; | ||
applyFunction(target: unknown, args: unknown[]): Promise<unknown>; | ||
@@ -80,11 +153,15 @@ applyFunctionSendOnly(target: unknown, args: unknown[]): void; | ||
target: unknown, | ||
prop: Property | undefined, | ||
prop: PropertyKey | undefined, | ||
args: unknown[], | ||
): Promise<unknown>; | ||
applyMethodSendOnly(target: unknown, prop: Property, args: unknown[]): void; | ||
get(target: unknown, prop: Property): Promise<unknown>; | ||
getSendOnly(target: unknown, prop: Property): void; | ||
applyMethodSendOnly( | ||
target: unknown, | ||
prop: PropertyKey, | ||
args: unknown[], | ||
): void; | ||
get(target: unknown, prop: PropertyKey): Promise<unknown>; | ||
getSendOnly(target: unknown, prop: PropertyKey): void; | ||
} | ||
declare interface HandledPromiseConstructor | ||
export interface HandledPromiseConstructor | ||
extends PromiseConstructor, | ||
@@ -99,3 +176,3 @@ HandledPromiseStaticMethods { | ||
declare var HandledPromise: HandledPromiseConstructor; | ||
export declare const HandledPromise: HandledPromiseConstructor; | ||
@@ -106,15 +183,21 @@ declare namespace global { | ||
declare function makeHandledPromise(): HandledPromiseConstructor; | ||
/** | ||
* "E" short for "Eventual", what we call something that has to return a promise. | ||
*/ | ||
type ECallable<T extends Callable> = ReturnType<T> extends Promise<infer U> | ||
? // function already returns a promise | ||
T | ||
: // make it return a promise | ||
(...args: Parameters<T>) => Promise<ReturnType<T>>; | ||
/* Types for E proxy calls. */ | ||
type ESingleMethod<T> = { | ||
readonly [P in keyof T]: ( | ||
...args: Parameters<T[P]> | ||
) => Promise<Awaited<ReturnType<T[P]>>>; | ||
/** | ||
* Ensure each function in T returns a promise | ||
*/ | ||
type EMethods<T> = { | ||
readonly [P in keyof T]: ECallable<T[P]>; | ||
}; | ||
type ESingleCall<T> = T extends Function | ||
? ((...args: Parameters<T>) => Promise<Awaited<ReturnType<T>>>) & | ||
ESingleMethod<Required<T>> | ||
: ESingleMethod<Required<T>>; | ||
type ESingleGet<T> = { | ||
type EGetters<T> = { | ||
readonly [P in keyof T]: Promise<Awaited<T[P]>>; | ||
@@ -125,5 +208,7 @@ }; | ||
type ESingleMethodOnly<T> = { | ||
readonly [P in keyof T]: (...args: Parameters<T[P]>) => void; | ||
readonly [P in keyof T]: T[P] extends Callable | ||
? (...args: Parameters<T[P]>) => void | ||
: never; | ||
}; | ||
type ESingleCallOnly<T> = T extends Function | ||
type ESingleCallOnly<T> = T extends Callable | ||
? ((...args: Parameters<T>) => void) & ESingleMethodOnly<T> | ||
@@ -139,2 +224,3 @@ : ESingleMethodOnly<T>; | ||
// Generic on the proxy target {T} | ||
interface EProxy { | ||
@@ -147,12 +233,12 @@ /** | ||
* | ||
* @param {*} x target for method/function call | ||
* @returns {ESingleCall} method/function call proxy | ||
* @param x target for method/function call | ||
* @returns method/function call proxy | ||
*/ | ||
<T>(x: T): ESingleCall< | ||
T extends Remotable<infer U> | ||
? FunctionOnly<U> | ||
: Awaited<T> extends Remotable<infer U> | ||
? FunctionOnly<U> | ||
: Awaited<T> | ||
>; | ||
// T is callable, but may still contain methods. E.g., | ||
// const a = () => 'primary'; | ||
// a.foo = () => 'nested'; | ||
<T extends Callable>(x: T): ECallable<T> & EMethods<Required<T>>; | ||
// T is an object of methods. | ||
// Must be defined after the `T extends Callable` overload so it doesn't consume that case. | ||
<T>(x: T): EMethods<Required<RemoteFunctions<T>>>; | ||
@@ -165,14 +251,6 @@ /** | ||
* | ||
* @param {*} x target for property get | ||
* @returns {ESingleGet} property get proxy | ||
* @param x target for property get | ||
* @returns property get proxy | ||
*/ | ||
readonly get: <T>( | ||
x: T, | ||
) => ESingleGet< | ||
T extends Remotable<infer U> | ||
? DataOnly<U> | ||
: Awaited<T> extends Remotable<infer U> | ||
? DataOnly<U> | ||
: Awaited<T> | ||
>; | ||
readonly get: <T>(x: T) => EGetters<PromisedData<T>>; | ||
@@ -179,0 +257,0 @@ /** |
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
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
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
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
72867
1120