Added the js-client api package, WIP

This commit is contained in:
Pavel Murygin 2023-02-07 01:23:02 +04:00
parent a1265f4d7a
commit ae546ce328
24 changed files with 319 additions and 112 deletions

22
packages/client/api/.gitignore vendored Normal file
View File

@ -0,0 +1,22 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
bundle/
tmp/
dist
esm
types
# Dependency directories
node_modules/
jspm_packages/
.idea

View File

@ -0,0 +1,11 @@
# JS Client web
This package is a part of FluenceJS, the official implementation of the Fluence Peer in typescript. See the [FluenceJS repo](https://github.com/fluencelabs/fluence-js) for more info
## Contributing
While the project is still in the early stages of development, you are welcome to track progress and contribute. As the project is undergoing rapid changes, interested contributors should contact the team before embarking on larger pieces of work. All contributors should consult with and agree to our [basic contributing rules](CONTRIBUTING.md).
## License
[Apache 2.0](LICENSE)

View File

@ -0,0 +1,22 @@
{
"name": "@fluencelabs/js-client.web.standalone",
"version": "0.1.0",
"description": "TypeScript implementation of Fluence Peer",
"main": "./dist/index.js",
"typings": "./dist/index.d.ts",
"engines": {
"node": ">=10",
"pnpm": ">=3"
},
"type": "module",
"scripts": {
"build": "node --loader ts-node/esm ./build.ts"
},
"repository": "https://github.com/fluencelabs/fluence-js",
"author": "Fluence Labs",
"license": "Apache-2.0",
"dependencies": {
"@fluencelabs/js-peer": "workspace:*"
},
"devDependencies": {}
}

View File

@ -0,0 +1,75 @@
import type { IFluencePeer } from '@fluencelabs/js-peer/dist/interfaces/index.js';
import type { PeerConfig } from '@fluencelabs/js-peer/dist/interfaces/peerConfig';
const getPeerFromGlobalThis = (): IFluencePeer | undefined => {
// @ts-ignore
return globalThis.defaultPeer;
};
const REJECT_MESSAGE = "Couldn't load the peer. Please try this and this or refer to the docs bla bla";
/**
* Wait until the js client script it loaded and return the default peer from globalThis
* @returns
*/
const getDefaultPeer = (): Promise<IFluencePeer> => {
// @ts-ignore
return new Promise((resolve, reject) => {
let interval: any;
let hits = 20;
interval = setInterval(() => {
if (hits === 0) {
clearInterval(interval);
reject(REJECT_MESSAGE);
}
let res = getPeerFromGlobalThis();
if (res) {
clearInterval(interval);
resolve(res);
}
hits--;
}, 100);
});
};
/**
* Public interface to Fluence JS
*/
export const Fluence = {
/**
* Initializes the default peer: starts the Aqua VM, initializes the default call service handlers
* and (optionally) connect to the Fluence network
* @param config - object specifying peer configuration
*/
start: async (config?: PeerConfig): Promise<void> => {
const peer = await getDefaultPeer();
return peer.start(config);
},
/**
* Un-initializes the default peer: stops all the underlying workflows, stops the Aqua VM
* and disconnects from the Fluence network
*/
stop: async (): Promise<void> => {
const peer = await getDefaultPeer();
return peer.stop();
},
/**
* Get the default peer's status
* @returns Default peer's status
*/
// getStatus: async () => {
// const peer = await getDefaultPeer();
// return peer.getStatus();
// },
/**
* Get the default peer instance
* @returns the default peer instance
*/
getPeer: async (): Promise<IFluencePeer> => {
return getDefaultPeer();
},
};

View File

@ -0,0 +1,8 @@
{
"extends": "../../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"moduleResolution": "node"
},
"exclude": ["node_modules", "dist"]
}

View File

@ -17,10 +17,17 @@
import type { JSONArray, JSONObject, LogLevel } from '@fluencelabs/marine-js/dist/types';
import type { RunParameters, CallResultsArray, InterpreterResult } from '@fluencelabs/avm';
import type { WorkerImplementation } from 'threads/dist/types/master';
import { PeerConfig } from './peerConfig';
export type PeerIdB58 = string;
export type ParticleHandler = (particle: string) => void;
export interface IFluencePeer {
start(config?: PeerConfig): Promise<void>;
stop(): Promise<void>;
}
/**
* Base class for connectivity layer to Fluence Network
*/

View File

@ -0,0 +1,106 @@
import type { MultiaddrInput } from '@multiformats/multiaddr';
import type { PeerIdB58 } from './commonTypes';
// import { KeyPair } from '../keypair';
/**
* Node of the Fluence network specified as a pair of node's multiaddr and it's peer id
*/
type Node = {
peerId: PeerIdB58;
multiaddr: string;
};
export type ConnectionOption = string | MultiaddrInput | Node;
/**
* Configuration used when initiating Fluence Peer
*/
export interface PeerConfig {
/**
* Node in Fluence network to connect to.
* Can be in the form of:
* - string: multiaddr in string format
* - Multiaddr: multiaddr object, @see https://github.com/multiformats/js-multiaddr
* - Node: node structure, @see Node
* - Implementation of FluenceConnection class, @see FluenceConnection
* If not specified the will work locally and would not be able to send or receive particles.
*/
connectTo?: ConnectionOption;
/**
* @deprecated. AVM run through marine-js infrastructure.
* @see debug.marineLogLevel option to configure logging level of AVM
*/
// avmLogLevel?: LogLevel | 'off';
/**
* Specify the KeyPair to be used to identify the Fluence Peer.
* Will be generated randomly if not specified
*/
//KeyPair?: KeyPair;
/**
* 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
*/
checkConnectionTimeoutMs?: number;
/**
* When the peer established the connection to the network it sends a ping-like message to check if it works correctly.
* If set to true, the ping-like message will be skipped
* Default: false
*/
skipCheckConnection?: boolean;
/**
* The dialing timeout in milliseconds
*/
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
*/
defaultTtlMs?: number;
/**
* This option allows to specify the location of various dependencies needed for marine-js.
* Each key specifies the location of the corresponding dependency.
* If Fluence peer is started inside browser the location is treated as the path to the file relative to origin.
* IF Fluence peer is started in nodejs the location is treated as the full path to file on the file system.
*/
// marineJS?: {
// /**
// * Configures path to the marine-js worker script.
// */
// workerScriptPath: string;
// /**
// * Configures the path to marine-js control wasm module
// */
// marineWasmPath: string;
// /**
// * Configures the path to AVM wasm module
// */
// avmWasmPath: string;
// };
/**
* 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;
// /**
// * Log level for marine services. By default logging is turned off.
// */
// marineLogLevel?: LogLevel;
// };
}

View File

@ -16,11 +16,15 @@
import 'buffer';
import { RelayConnection } from '../connection/index.js';
import { FluenceConnection, IAvmRunner, IMarine } from '../interfaces/index.js';
import { FluenceConnection, IAvmRunner, IFluencePeer, IMarine } from '../interfaces/index.js';
import { KeyPair } from '../keypair/index.js';
import type { MultiaddrInput } from '@multiformats/multiaddr';
import { CallServiceData, CallServiceResult, GenericCallServiceHandler, ResultCodes } from './commonTypes.js';
import { PeerIdB58 } from './commonTypes.js';
import {
CallServiceData,
CallServiceResult,
GenericCallServiceHandler,
ResultCodes,
} from '../interfaces/commonTypes.js';
import { PeerIdB58 } from '../interfaces/commonTypes.js';
import { Particle, ParticleExecutionStage, ParticleQueueItem } from './Particle.js';
import { throwIfNotSupported, dataToString, jsonify, isString, ServiceError } from './utils.js';
import { concatMap, filter, pipe, Subject, tap } from 'rxjs';
@ -32,75 +36,57 @@ import { registerSrv } from './_aqua/single-module-srv.js';
import { Buffer } from 'buffer';
import { JSONValue } from '@fluencelabs/avm';
import { LogLevel } from '@fluencelabs/marine-js/dist/types';
import { NodeUtils, Srv } from './builtins/SingleModuleSrv.js';
import { registerNodeUtils } from './_aqua/node-utils.js';
import { LogLevel } from '@fluencelabs/marine-js/dist/types';
import { ConnectionOption, PeerConfig } from '../interfaces/peerConfig.js';
import type { MultiaddrInput } from '@multiformats/multiaddr';
/**
* Node of the Fluence network specified as a pair of node's multiaddr and it's peer id
* Information about Fluence Peer connection.
* Represented as object with the following keys:
* - `isInitialized`: Is the peer initialized or not.
* - `peerId`: Peer Id of the peer. Null if the peer is not initialized
* - `isConnected`: Is the peer connected to network or not
* - `relayPeerId`: Peer Id of the relay the peer is connected to. If the connection is direct relayPeerId is null
* - `isDirect`: True if the peer is connected to the network directly (not through relay)
*/
type Node = {
peerId: PeerIdB58;
multiaddr: string;
};
export type PeerStatus =
| {
isInitialized: false;
peerId: null;
isConnected: false;
relayPeerId: null;
}
| {
isInitialized: true;
peerId: PeerIdB58;
isConnected: false;
relayPeerId: null;
}
| {
isInitialized: true;
peerId: PeerIdB58;
isConnected: true;
relayPeerId: PeerIdB58;
}
| {
isInitialized: true;
peerId: PeerIdB58;
isConnected: true;
isDirect: true;
relayPeerId: null;
};
const DEFAULT_TTL = 7000;
export type ConnectionOption = string | MultiaddrInput | Node;
/**
* Configuration used when initiating Fluence Peer
*/
export interface PeerConfig {
/**
* Node in Fluence network to connect to.
* Can be in the form of:
* - string: multiaddr in string format
* - Multiaddr: multiaddr object, @see https://github.com/multiformats/js-multiaddr
* - Node: node structure, @see Node
* - Implementation of FluenceConnection class, @see FluenceConnection
* If not specified the will work locally and would not be able to send or receive particles.
*/
connectTo?: ConnectionOption;
/**
* @deprecated. AVM run through marine-js infrastructure.
* @see debug.marineLogLevel option to configure logging level of AVM
*/
avmLogLevel?: LogLevel | 'off';
export interface PeerConfig2 extends PeerConfig {
/**
* Specify the KeyPair to be used to identify the Fluence Peer.
* Will be generated randomly if not specified
*/
KeyPair?: KeyPair;
/**
* 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
*/
checkConnectionTimeoutMs?: number;
/**
* When the peer established the connection to the network it sends a ping-like message to check if it works correctly.
* If set to true, the ping-like message will be skipped
* Default: false
*/
skipCheckConnection?: boolean;
/**
* The dialing timeout in milliseconds
*/
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
*/
defaultTtlMs?: number;
/**
* This option allows to specify the location of various dependencies needed for marine-js.
* Each key specifies the location of the corresponding dependency.
@ -141,47 +127,11 @@ export interface PeerConfig {
};
}
/**
* Information about Fluence Peer connection.
* Represented as object with the following keys:
* - `isInitialized`: Is the peer initialized or not.
* - `peerId`: Peer Id of the peer. Null if the peer is not initialized
* - `isConnected`: Is the peer connected to network or not
* - `relayPeerId`: Peer Id of the relay the peer is connected to. If the connection is direct relayPeerId is null
* - `isDirect`: True if the peer is connected to the network directly (not through relay)
*/
export type PeerStatus =
| {
isInitialized: false;
peerId: null;
isConnected: false;
relayPeerId: null;
}
| {
isInitialized: true;
peerId: PeerIdB58;
isConnected: false;
relayPeerId: null;
}
| {
isInitialized: true;
peerId: PeerIdB58;
isConnected: true;
relayPeerId: PeerIdB58;
}
| {
isInitialized: true;
peerId: PeerIdB58;
isConnected: true;
isDirect: true;
relayPeerId: null;
};
/**
* This class implements the Fluence protocol for javascript-based environments.
* It provides all the necessary features to communicate with Fluence network
*/
export class FluencePeer {
export class FluencePeer implements IFluencePeer {
constructor(private marine: IMarine, private avmRunner: IAvmRunner) {}
/**
@ -239,7 +189,7 @@ export class FluencePeer {
* and (optionally) connect to the Fluence network
* @param config - object specifying peer configuration
*/
async start(config: PeerConfig = {}): Promise<void> {
async start(config: PeerConfig2 = {}): Promise<void> {
throwIfNotSupported();
const keyPair = config.KeyPair ?? (await KeyPair.randomEd25519());
const newConfig = { ...config, KeyPair: keyPair };
@ -419,7 +369,7 @@ export class FluencePeer {
/**
* @private Subject to change. Do not use this method directly
*/
async init(config: PeerConfig & Required<Pick<PeerConfig, 'KeyPair'>>) {
async init(config: PeerConfig2 & Required<Pick<PeerConfig2, 'KeyPair'>>) {
this._keyPair = config.KeyPair;
const peerId = this._keyPair.getPeerId();

View File

@ -18,7 +18,7 @@ import { fromUint8Array, toUint8Array } from 'js-base64';
import { CallResultsArray, LogLevel } from '@fluencelabs/avm';
import { v4 as uuidv4 } from 'uuid';
import log from 'loglevel';
import { ParticleContext } from './commonTypes.js';
import { ParticleContext } from '../interfaces/commonTypes.js';
import { dataToString, jsonify } from './utils.js';
import { Buffer } from 'buffer';

View File

@ -1,5 +1,5 @@
import { toUint8Array } from 'js-base64';
import { CallParams, CallServiceData } from '../../commonTypes.js';
import { CallParams, CallServiceData } from '../../../interfaces/commonTypes.js';
import { builtInServices } from '../../builtins/common.js';
import { KeyPair } from '../../../keypair/index.js';
import { Sig, defaultSigGuard } from '../../builtins/Sig.js';

View File

@ -1,7 +1,7 @@
import * as api from '@fluencelabs/aqua-api/aqua-api.js';
import { promises as fs } from 'fs';
import { FluencePeer, PeerConfig } from '../FluencePeer.js';
import { FluencePeer, PeerConfig2 as PeerConfig } from '../FluencePeer.js';
import { Particle } from '../Particle.js';
import { MakeServiceCall } from '../utils.js';
import { avmModuleLoader, controlModuleLoader } from '../utilsForNode.js';

View File

@ -6,7 +6,7 @@
* Aqua version: 0.7.7-362
*
*/
import { CallParams } from '../commonTypes.js';
import { CallParams } from '../../interfaces/commonTypes.js';
import { registerServiceImpl } from '../compilerSupport/registerService.js';
import { FluencePeer } from '../FluencePeer.js';

View File

@ -6,7 +6,7 @@
* Aqua version: 0.7.7-362
*
*/
import { CallParams } from '../commonTypes.js';
import { CallParams } from '../../interfaces/commonTypes.js';
import { registerServiceImpl } from '../compilerSupport/registerService.js';
import { FluencePeer } from '../FluencePeer.js';

View File

@ -6,7 +6,7 @@
* Aqua version: 0.7.7-362
*
*/
import { CallParams } from '../commonTypes.js';
import { CallParams } from '../../interfaces/commonTypes.js';
import { registerServiceImpl } from '../compilerSupport/registerService.js';
import { FluencePeer } from '../FluencePeer.js';

View File

@ -1,4 +1,4 @@
import { CallParams, PeerIdB58 } from '../commonTypes.js';
import { CallParams, PeerIdB58 } from '../../interfaces/commonTypes.js';
import { KeyPair } from '../../keypair/index.js';
import { SigDef } from '../_aqua/services.js';
import { allowOnlyParticleOriginatedAt, allowServiceFn, and, or, SecurityGuard } from './securityGuard.js';

View File

@ -2,7 +2,7 @@ import { v4 as uuidv4 } from 'uuid';
import { SrvDef } from '../_aqua/single-module-srv.js';
import { NodeUtilsDef } from '../_aqua/node-utils.js';
import { FluencePeer } from '../FluencePeer.js';
import { CallParams } from '../commonTypes.js';
import { CallParams } from '../../interfaces/commonTypes.js';
import { Buffer } from 'buffer';
import { allowOnlyParticleOriginatedAt, SecurityGuard } from './securityGuard.js';

View File

@ -19,7 +19,7 @@ import * as bs58 from 'bs58';
import { sha256 } from 'multiformats/hashes/sha2';
import { CallServiceResult } from '@fluencelabs/avm';
import { GenericCallServiceHandler, ResultCodes } from '../commonTypes.js';
import { GenericCallServiceHandler, ResultCodes } from '../../interfaces/commonTypes.js';
import { jsonify } from '../utils.js';
import { Buffer } from 'buffer';

View File

@ -1,5 +1,5 @@
import { SecurityTetraplet } from '@fluencelabs/avm';
import { CallParams, PeerIdB58 } from '../commonTypes.js';
import { CallParams, PeerIdB58 } from '../../interfaces/commonTypes.js';
type ArgName = string | null;

View File

@ -1,7 +1,7 @@
import { jsonify } from '../utils.js';
import { match } from 'ts-pattern';
import { ArrowType, ArrowWithoutCallbacks, NonArrowType } from './interface.js';
import { CallServiceData } from '../commonTypes.js';
import { CallServiceData } from '../../interfaces/commonTypes.js';
/**
* Convert value from its representation in aqua language to representation in typescript

View File

@ -2,7 +2,7 @@ import { SecurityTetraplet } from '@fluencelabs/avm';
import { match } from 'ts-pattern';
import { Particle } from '../Particle.js';
import { CallParams, CallServiceData, GenericCallServiceHandler, ResultCodes } from '../commonTypes.js';
import { CallParams, CallServiceData, GenericCallServiceHandler, ResultCodes } from '../../interfaces/commonTypes.js';
import { FluencePeer } from '../FluencePeer.js';
import { aquaArgs2Ts, responseServiceValue2ts, returnType2Aqua, ts2aqua } from './conversions.js';

View File

@ -1,6 +1,6 @@
import { FluenceConnection, ParticleHandler } from '../interfaces/index.js';
import { keyPairFromBase64Sk } from '../keypair/index.js';
import { PeerIdB58 } from './commonTypes.js';
import { PeerIdB58 } from '../interfaces/commonTypes.js';
import { FluencePeer } from './FluencePeer.js';
import { MarineBackgroundRunner } from '../marine/worker/index.js';
import { avmModuleLoader, controlModuleLoader } from './utilsForNode';

View File

@ -18,7 +18,7 @@ import log from 'loglevel';
import * as platform from 'platform';
import { Buffer } from 'buffer';
import { CallServiceData, CallServiceResult, CallServiceResultType, ResultCodes } from './commonTypes.js';
import { CallServiceData, CallServiceResult, CallServiceResultType, ResultCodes } from '../interfaces/commonTypes.js';
import { FluencePeer } from './FluencePeer.js';
import { ParticleExecutionStage } from './Particle.js';
import { LogFunction } from '@fluencelabs/marine-js/dist/types';

6
pnpm-lock.yaml generated
View File

@ -10,6 +10,12 @@ importers:
ts-node: 10.9.1_nv75g3i7xuh23du6z7qul3uiqi
typescript: 4.7.4
packages/client/api:
specifiers:
'@fluencelabs/js-peer': workspace:*
dependencies:
'@fluencelabs/js-peer': link:../../core
packages/client/js-client.web.standalone:
specifiers:
'@fluencelabs/avm': 0.35.3