feat(js-client)!: Adding strictes eslint and ts config to all packages [fixes DXJ-464] (#355)

* introduce eslint

* Fix all eslint errors

* Eslint fix and some touches

* Fix tests

* Fix misc errors

* change semver

* change semver #2

* Fix path

* Fix path #2

* freeze lock file in CI

* fix package install

* Fix formatting of surrounding files

* Add empty prettier config

* Fix formatting

* Fix build errors

* Remove unused deps

* remove changelog from formatting

* deps cleanup

* make resource importers async

* Refactor

* Fix error message

* remove comment

* more refactoring

* Update packages/core/js-client/src/compilerSupport/registerService.ts

Co-authored-by: shamsartem <shamsartem@gmail.com>

* refactoring

* refactoring fix

* optimize import

* Update packages/@tests/smoke/node/src/index.ts

Co-authored-by: shamsartem <shamsartem@gmail.com>

* Revert package

* Fix pnpm lock

* Lint-fix

* Fix CI

* Update tests

* Fix build

* Fix import

* Use forked threads dep

* Use fixed version

* Update threads

* Fix lint

* Fix test

* Fix test

* Add polyfill for assert

* Add subpath import

* Fix tests

* Fix deps

---------

Co-authored-by: shamsartem <shamsartem@gmail.com>
This commit is contained in:
Akim
2023-10-17 22:14:08 +07:00
committed by GitHub
parent b46933252a
commit 919c7d6ea1
135 changed files with 10529 additions and 9167 deletions

View File

@ -1,4 +1,4 @@
/*
/**
* Copyright 2023 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -13,7 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import type { SecurityTetraplet } from '@fluencelabs/avm';
import type { SecurityTetraplet } from "@fluencelabs/avm";
import { InterfaceToType, MaybePromise } from "./utils.js";
/**
* Peer ID's id as a base58 string (multihash/CIDv0).
@ -24,42 +27,61 @@ export type PeerIdB58 = string;
* Node of the Fluence network specified as a pair of node's multiaddr and it's peer id
*/
export type Node = {
peerId: PeerIdB58;
multiaddr: string;
peerId: PeerIdB58;
multiaddr: string;
};
/**
* Additional information about a service call
* @typeparam ArgName
*/
export interface CallParams<ArgName extends string | null> {
/**
* The identifier of particle which triggered the call
*/
particleId: string;
export type CallParams<ArgName extends string | null> = {
/**
* The identifier of particle which triggered the call
*/
particleId: string;
/**
* The peer id which created the particle
*/
initPeerId: PeerIdB58;
/**
* The peer id which created the particle
*/
initPeerId: PeerIdB58;
/**
* Particle's timestamp when it was created
*/
timestamp: number;
/**
* Particle's timestamp when it was created
*/
timestamp: number;
/**
* Time to live in milliseconds. The time after the particle should be expired
*/
ttl: number;
/**
* Time to live in milliseconds. The time after the particle should be expired
*/
ttl: number;
/**
* Particle's signature
*/
signature?: string;
/**
* Particle's signature
*/
signature?: string;
/**
* Security tetraplets
*/
tetraplets: ArgName extends string ? Record<ArgName, SecurityTetraplet[]> : Record<string, never>;
}
/**
* Security tetraplets
*/
tetraplets: ArgName extends string
? Record<ArgName, InterfaceToType<SecurityTetraplet>[]>
: Record<string, never>;
};
export type ServiceImpl = Record<
string,
(
...args: [...JSONArray, CallParams<string>]
) => MaybePromise<JSONValue | undefined>
>;
export type JSONValue =
| string
| number
| boolean
| null
| { [x: string]: JSONValue }
| Array<JSONValue>;
export type JSONArray = Array<JSONValue>;
export type JSONObject = { [x: string]: JSONValue };

View File

@ -1,4 +1,4 @@
/*
/**
* Copyright 2023 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -13,257 +13,279 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
type SimpleTypes = ScalarType | OptionType | ArrayType | StructType | TopType | BottomType | NilType;
export type NonArrowType = SimpleTypes | ProductType<SimpleTypes>;
export type SimpleTypes =
| ScalarType
| OptionType
| ArrayType
| StructType
| TopType
| BottomType
| NilType;
export type NonArrowType = SimpleTypes | ProductType;
export type TopType = {
/**
* Type descriptor. Used for pattern-matching
*/
tag: 'topType';
/**
* Type descriptor. Used for pattern-matching
*/
tag: "topType";
};
export type BottomType = {
/**
* Type descriptor. Used for pattern-matching
*/
tag: 'bottomType';
/**
* Type descriptor. Used for pattern-matching
*/
tag: "bottomType";
};
export type OptionType = {
/**
* Type descriptor. Used for pattern-matching
*/
tag: 'option';
/**
* Type descriptor. Used for pattern-matching
*/
tag: "option";
/**
* Underlying type of the option
*/
type: NonArrowType;
/**
* Underlying type of the option
*/
type: SimpleTypes;
};
export type NilType = {
/**
* Type descriptor. Used for pattern-matching
*/
tag: 'nil';
/**
* Type descriptor. Used for pattern-matching
*/
tag: "nil";
};
export type ArrayType = {
/**
* Type descriptor. Used for pattern-matching
*/
tag: 'array';
/**
* Type descriptor. Used for pattern-matching
*/
tag: "array";
/**
* Type of array elements
*/
type: NonArrowType;
/**
* Type of array elements
*/
type: SimpleTypes;
};
/**
* All possible scalar type names
*/
export type ScalarNames =
| 'u8'
| 'u16'
| 'u32'
| 'u64'
| 'i8'
| 'i16'
| 'i32'
| 'i64'
| 'f32'
| 'f64'
| 'bool'
| 'string';
| "u8"
| "u16"
| "u32"
| "u64"
| "i8"
| "i16"
| "i32"
| "i64"
| "f32"
| "f64"
| "bool"
| "string";
export type ScalarType = {
/**
* Type descriptor. Used for pattern-matching
*/
tag: 'scalar';
/**
* Type descriptor. Used for pattern-matching
*/
tag: "scalar";
/**
* Name of the scalar type
*/
name: ScalarNames;
/**
* Name of the scalar type
*/
name: ScalarNames;
};
export type StructType = {
/**
* Type descriptor. Used for pattern-matching
*/
tag: 'struct';
/**
* Type descriptor. Used for pattern-matching
*/
tag: "struct";
/**
* Struct name
*/
name: string;
/**
* Struct name
*/
name: string;
/**
* Struct fields
*/
fields: { [key: string]: NonArrowType };
/**
* Struct fields
*/
fields: { [key: string]: SimpleTypes };
};
export type LabeledProductType<T> = {
/**
* Type descriptor. Used for pattern-matching
*/
tag: 'labeledProduct';
export type LabeledProductType<
T extends
| SimpleTypes
| ArrowType<LabeledProductType<SimpleTypes> | UnlabeledProductType> =
| SimpleTypes
| ArrowType<LabeledProductType<SimpleTypes> | UnlabeledProductType>,
K extends { [key: string]: T } = { [key: string]: T },
> = {
/**
* Type descriptor. Used for pattern-matching
*/
tag: "labeledProduct";
/**
* Labelled product fields
*/
fields: { [key: string]: T };
/**
* Labelled product fields
*/
fields: K;
};
export type UnlabeledProductType<T> = {
export type UnlabeledProductType<T extends Array<SimpleTypes> = SimpleTypes[]> =
{
/**
* Type descriptor. Used for pattern-matching
*/
tag: 'unlabeledProduct';
tag: "unlabeledProduct";
/**
* Items in unlabelled product
*/
items: Array<T>;
};
items: T;
};
export type ProductType<T> = UnlabeledProductType<T> | LabeledProductType<T> | NilType;
export type ProductType = UnlabeledProductType | LabeledProductType;
/**
* ArrowType is a profunctor pointing its domain to codomain.
* Profunctor means variance: Arrow is contravariant on domain, and variant on codomain.
*/
export type ArrowType<T> = {
/**
* Type descriptor. Used for pattern-matching
*/
tag: 'arrow';
export type ArrowType<T extends LabeledProductType | UnlabeledProductType> = {
/**
* Type descriptor. Used for pattern-matching
*/
tag: "arrow";
/**
* Where this Arrow is defined
*/
domain: ProductType<T>;
/**
* Where this Arrow is defined
*/
domain: T | NilType;
/**
* Where this Arrow points to
*/
codomain: UnlabeledProductType<NonArrowType> | NilType;
/**
* Where this Arrow points to
*/
codomain: UnlabeledProductType | NilType;
};
/**
* Arrow which domain contains only non-arrow types
*/
export type ArrowWithoutCallbacks = ArrowType<NonArrowType>;
export type ArrowWithoutCallbacks = ArrowType<
UnlabeledProductType | LabeledProductType<SimpleTypes>
>;
/**
* Arrow which domain does can contain both non-arrow types and arrows (which themselves cannot contain arrows)
*/
export type ArrowWithCallbacks = ArrowType<NonArrowType | ArrowWithoutCallbacks>;
export type ArrowWithCallbacks = ArrowType<LabeledProductType>;
export interface FunctionCallConstants {
/**
* The name of the relay variable
*/
relay: string;
/**
* The name of the relay variable
*/
relay: string;
/**
* The name of the serviceId used load variables at the beginning of the script
*/
getDataSrv: string;
/**
* The name of the serviceId used load variables at the beginning of the script
*/
getDataSrv: string;
/**
* The name of serviceId is used to execute callbacks for the current particle
*/
callbackSrv: string;
/**
* The name of serviceId is used to execute callbacks for the current particle
*/
callbackSrv: string;
/**
* The name of the serviceId which is called to propagate return value to the generated function caller
*/
responseSrv: string;
/**
* The name of the serviceId which is called to propagate return value to the generated function caller
*/
responseSrv: string;
/**
* The name of the functionName which is called to propagate return value to the generated function caller
*/
responseFnName: string;
/**
* The name of the functionName which is called to propagate return value to the generated function caller
*/
responseFnName: string;
/**
* The name of the serviceId which is called to report errors to the generated function caller
*/
errorHandlingSrv: string;
/**
* The name of the serviceId which is called to report errors to the generated function caller
*/
errorHandlingSrv: string;
/**
* The name of the functionName which is called to report errors to the generated function caller
*/
errorFnName: string;
/**
* The name of the functionName which is called to report errors to the generated function caller
*/
errorFnName: string;
}
/**
* Definition of function (`func` instruction) generated by the Aqua compiler
*/
export interface FunctionCallDef {
/**
* The name of the function in Aqua language
*/
functionName: string;
/**
* The name of the function in Aqua language
*/
functionName: string;
/**
* Underlying arrow which represents function in aqua
*/
arrow: ArrowWithCallbacks;
/**
* Underlying arrow which represents function in aqua
*/
arrow: ArrowType<
LabeledProductType<SimpleTypes | ArrowType<UnlabeledProductType>>
>;
/**
* Names of the different entities used in generated air script
*/
names: FunctionCallConstants;
/**
* Names of the different entities used in generated air script
*/
names: FunctionCallConstants;
}
/**
* Definition of service registration function (`service` instruction) generated by the Aqua compiler
*/
export interface ServiceDef {
/**
* Default service id. If the service has no default id the value should be undefined
*/
defaultServiceId?: string;
/**
* Default service id. If the service has no default id the value should be undefined
*/
defaultServiceId?: string;
/**
* List of functions which the service consists of
*/
functions: LabeledProductType<ArrowWithoutCallbacks> | NilType;
/**
* List of functions which the service consists of
*/
functions:
| LabeledProductType<ArrowType<LabeledProductType<SimpleTypes>>>
| NilType;
}
/**
* Options to configure Aqua function execution
*/
export interface FnConfig {
/**
* Sets the TTL (time to live) for particle responsible for the function execution
* If the option is not set the default TTL from FluencePeer config is used
*/
ttl?: number;
/**
* Sets the TTL (time to live) for particle responsible for the function execution
* If the option is not set the default TTL from FluencePeer config is used
*/
ttl?: number;
}
export const getArgumentTypes = (
def: FunctionCallDef,
def: FunctionCallDef,
): {
[key: string]: NonArrowType | ArrowWithoutCallbacks;
[key: string]: NonArrowType | ArrowWithoutCallbacks;
} => {
if (def.arrow.domain.tag !== 'labeledProduct') {
throw new Error('Should be impossible');
}
if (def.arrow.domain.tag !== "labeledProduct") {
throw new Error("Should be impossible");
}
return def.arrow.domain.fields;
return def.arrow.domain.fields;
};
export const isReturnTypeVoid = (def: FunctionCallDef): boolean => {
if (def.arrow.codomain.tag === 'nil') {
return true;
}
if (def.arrow.codomain.tag === "nil") {
return true;
}
return def.arrow.codomain.items.length == 0;
return def.arrow.codomain.items.length === 0;
};

View File

@ -1,4 +1,4 @@
/*
/**
* Copyright 2023 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -13,72 +13,88 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { IFluenceInternalApi } from '../fluenceClient.js';
import { FnConfig, FunctionCallDef, ServiceDef } from './aquaTypeDefinitions.js';
import { JSONValue } from "../commonTypes.js";
import { IFluenceInternalApi } from "../fluenceClient.js";
import {
FnConfig,
FunctionCallDef,
ServiceDef,
} from "./aquaTypeDefinitions.js";
/**
* Type for callback passed as aqua function argument
*/
export type ArgCallbackFunction = (
...args: JSONValue[]
) => JSONValue | Promise<JSONValue>;
/**
* Arguments passed to Aqua function
*/
export type PassedArgs = { [key: string]: any };
export type PassedArgs = { [key: string]: JSONValue | ArgCallbackFunction };
/**
* Arguments for callAquaFunction function
*/
export interface CallAquaFunctionArgs {
/**
* Peer to call the function on
*/
peer: IFluenceInternalApi;
/**
* Peer to call the function on
*/
peer: IFluenceInternalApi;
/**
* Function definition
*/
def: FunctionCallDef;
/**
* Function definition
*/
def: FunctionCallDef;
/**
* Air script used by the aqua function
*/
script: string;
/**
* Air script used by the aqua function
*/
script: string;
/**
* Function configuration
*/
config: FnConfig;
/**
* Function configuration
*/
config: FnConfig;
/**
* Arguments to pass to the function
*/
args: PassedArgs;
/**
* Arguments to pass to the function
*/
args: PassedArgs;
}
/**
* Call a function from Aqua script
*/
export type CallAquaFunctionType = (args: CallAquaFunctionArgs) => Promise<unknown>;
export type CallAquaFunctionType = (
args: CallAquaFunctionArgs,
) => Promise<unknown>;
/**
* Arguments for registerService function
*/
export interface RegisterServiceArgs {
/**
* Peer to register the service on
*/
peer: IFluenceInternalApi;
/**
* Peer to register the service on
*/
peer: IFluenceInternalApi;
/**
* Service definition
*/
def: ServiceDef;
/**
* Service definition
*/
def: ServiceDef;
/**
* Service id
*/
serviceId: string | undefined;
/**
* Service id
*/
serviceId: string | undefined;
/**
* Service implementation
*/
service: any;
/**
* Service implementation
*/
service: unknown;
}
/**

View File

@ -1,4 +1,4 @@
/*
/**
* Copyright 2023 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import type { Node } from './commonTypes.js';
import type { Node } from "./commonTypes.js";
/**
* A node in Fluence network a client can connect to.
@ -26,78 +27,83 @@ export type RelayOptions = string | Node;
/**
* Fluence Peer's key pair types
*/
export type KeyTypes = 'RSA' | 'Ed25519' | 'secp256k1';
export type KeyTypes = "RSA" | "Ed25519" | "secp256k1";
/**
* Options to specify key pair used in Fluence Peer
*/
export type KeyPairOptions = {
type: 'Ed25519';
source: 'random' | Uint8Array;
type: "Ed25519";
source: "random" | Uint8Array;
};
/**
* Configuration used when initiating Fluence Client
*/
export interface ClientConfig {
/**
* Specify the KeyPair to be used to identify the Fluence Peer.
* Will be generated randomly if not specified
*/
keyPair?: KeyPairOptions;
/**
* Options to configure the connection to the Fluence network
*/
connectionOptions?: {
/**
* Specify the KeyPair to be used to identify the Fluence Peer.
* Will be generated randomly if not specified
* When the peer established the connection to the network it sends a ping-like message to check if it works correctly.
* The options allows to specify the timeout for that message in milliseconds.
* If not specified the default timeout will be used
*/
keyPair?: KeyPairOptions;
skipCheckConnection?: boolean;
/**
* Options to configure the connection to the Fluence network
* The dialing timeout in milliseconds
*/
connectionOptions?: {
/**
* When the peer established the connection to the network it sends a ping-like message to check if it works correctly.
* The options allows to specify the timeout for that message in milliseconds.
* If not specified the default timeout will be used
*/
skipCheckConnection?: boolean;
/**
* The dialing timeout in milliseconds
*/
dialTimeoutMs?: number;
/**
* The maximum number of inbound streams for the libp2p node.
* Default: 1024
*/
maxInboundStreams?: number;
/**
* The maximum number of outbound streams for the libp2p node.
* Default: 1024
*/
maxOutboundStreams?: number;
};
dialTimeoutMs?: number;
/**
* Sets the default TTL for all particles originating from the peer with no TTL specified.
* If the originating particle's TTL is defined then that value will be used
* If the option is not set default TTL will be 7000
* The maximum number of inbound streams for the libp2p node.
* Default: 1024
*/
defaultTtlMs?: number;
maxInboundStreams?: number;
/**
* Enables\disabled various debugging features
* The maximum number of outbound streams for the libp2p node.
* Default: 1024
*/
debug?: {
/**
* If set to true, newly initiated particle ids will be printed to console.
* Useful to see what particle id is responsible for aqua function
*/
printParticleId?: boolean;
};
maxOutboundStreams?: number;
};
/**
* Sets the default TTL for all particles originating from the peer with no TTL specified.
* If the originating particle's TTL is defined then that value will be used
* If the option is not set default TTL will be 7000
*/
defaultTtlMs?: number;
/**
* Enables\disabled various debugging features
*/
debug?: {
/**
* If set to true, newly initiated particle ids will be printed to console.
* Useful to see what particle id is responsible for aqua function
*/
printParticleId?: boolean;
};
}
/**
* Fluence JS Client connection states as string literals
*/
export const ConnectionStates = ['disconnected', 'connecting', 'connected', 'disconnecting'] as const;
export const ConnectionStates = [
"disconnected",
"connecting",
"connected",
"disconnecting",
] as const;
/**
* Fluence JS Client connection states
@ -105,47 +111,45 @@ export const ConnectionStates = ['disconnected', 'connecting', 'connected', 'dis
export type ConnectionState = (typeof ConnectionStates)[number];
export interface IFluenceInternalApi {
/**
* Internal API
*/
internals: any;
/**
* Internal API
*/
internals: unknown;
}
/**
* Public API of Fluence JS Client
*/
export interface IFluenceClient extends IFluenceInternalApi {
/**
* Connect to the Fluence network
*/
connect: () => Promise<void>;
/**
* Connect to the Fluence network
*/
connect: () => Promise<void>;
/**
* Disconnect from the Fluence network
*/
disconnect(): Promise<void>;
/**
* Disconnect from the Fluence network
*/
disconnect(): Promise<void>;
/**
* Handle connection state changes. Immediately returns current connection state
*/
onConnectionStateChange(handler: (state: ConnectionState) => void): ConnectionState;
/**
* Handle connection state changes. Immediately returns current connection state
*/
onConnectionStateChange(
handler: (state: ConnectionState) => void,
): ConnectionState;
/**
* Return peer's secret key as byte array.
*/
getPeerSecretKey(): Uint8Array;
/**
* Return peer's secret key as byte array.
*/
getPeerSecretKey(): Uint8Array;
/**
* Return peer's public key as a base58 string (multihash/CIDv0).
*/
getPeerId(): string;
/**
* Return peer's public key as a base58 string (multihash/CIDv0).
*/
getPeerId(): string;
/**
* Return relay's public key as a base58 string (multihash/CIDv0).
*/
getRelayPeerId(): string;
/**
* Return relay's public key as a base58 string (multihash/CIDv0).
*/
getRelayPeerId(): string;
}

View File

@ -0,0 +1,90 @@
/**
* Copyright 2023 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
ArrayType,
ArrowType,
LabeledProductType,
NilType,
OptionType,
ScalarType,
SimpleTypes,
StructType,
TopType,
UnlabeledProductType,
} from "@fluencelabs/interfaces";
import { Call, Pipe, Objects, Tuples, Unions, Fn } from "hotscript";
// Type definitions for inferring ts types from air json definition
// In the future we may remove string type declaration and move to type inference.
type GetTsTypeFromScalar<T extends ScalarType> = [T["name"]] extends [
"u8" | "u16" | "u32" | "u64" | "i8" | "i16" | "i32" | "i64" | "f32" | "f64",
]
? number
: [T["name"]] extends ["bool"]
? boolean
: [T["name"]] extends ["string"]
? string
: never;
type MapTuple<T> = {
[K in keyof T]: [T[K]] extends [SimpleTypes] ? GetSimpleType<T[K]> : never;
};
type UnpackIfSingle<T> = [T] extends [[infer R]] ? R : T;
type GetSimpleType<T> = [T] extends [NilType]
? null
: [T] extends [ArrayType]
? GetSimpleType<T["type"]>[]
: [T] extends [StructType]
? { [K in keyof T["fields"]]: GetSimpleType<T["fields"][K]> }
: [T] extends [OptionType]
? GetSimpleType<T["type"]> | null
: [T] extends [ScalarType]
? GetTsTypeFromScalar<T>
: [T] extends [TopType]
? unknown
: never;
interface Access<T> extends Fn {
return: __GetTsType<Call<Objects.Get<this["arg0"]>, T>>;
}
type __GetTsType<T> = [T] extends [SimpleTypes]
? GetSimpleType<T>
: [T] extends [UnlabeledProductType]
? MapTuple<T["items"]>
: [T] extends [LabeledProductType]
? { [K in keyof T["fields"]]: __GetTsType<T["fields"][K]> }
: [T] extends [ArrowType<infer H>]
? (
...t: [H] extends [UnlabeledProductType<infer K>]
? MapTuple<K>
: [H] extends [LabeledProductType<infer _V, infer K>]
? Pipe<K, [Objects.Keys, Unions.ToTuple, Tuples.Map<Access<K>>]>
: []
) => [T["codomain"]] extends [UnlabeledProductType]
? UnpackIfSingle<MapTuple<T["codomain"]["items"]>>
: undefined
: never;
type DeepMutable<T> = {
-readonly [K in keyof T]: DeepMutable<T[K]>;
};
export type GetTsType<T> = __GetTsType<DeepMutable<T>>;

View File

@ -1,4 +1,4 @@
/*
/**
* Copyright 2023 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -13,7 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './compilerSupport/aquaTypeDefinitions.js';
export * from './compilerSupport/compilerSupportInterface.js';
export * from './commonTypes.js';
export * from './fluenceClient.js';
export * from "./compilerSupport/aquaTypeDefinitions.js";
export * from "./compilerSupport/compilerSupportInterface.js";
export * from "./commonTypes.js";
export * from "./fluenceClient.js";
export * from "./future.js";

View File

@ -0,0 +1,21 @@
/**
* Copyright 2023 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export type InterfaceToType<T extends object> = {
[K in keyof T]: T[K];
};
export type MaybePromise<T> = T | Promise<T>;