feat!: Unify all packages (#327)

* * Separate marine worker as a package
* Trying to fix tests

* Finalizing test fixes

* fix: rename back to Fluence CLI (#320)

chore: rename back to Fluence CLI

* fix(deps): update dependency @fluencelabs/avm to v0.43.1 (#322)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore: release master (#324)

* chore: release master

* chore: Regenerate pnpm lock file

* feat: use marine-js 0.7.2 (#321)

* use marine-js 0.5.0

* increace some timeouts

* increace some timeouts

* use latest marine + remove larger timeouts

* propagate CallParameters type

* use marine 0.7.2

* Temp use node 18 and 20

* Comment out node 20.x

---------

Co-authored-by: Anatoly Laskaris <github_me@nahsi.dev>

* chore: Fix test with node 18/20 error message (#323)

* Fix test with node 18/20 error message

* Run tests on node 18 and 20

* Enhance description

* Fix type and obj property

---------

Co-authored-by: Anatoly Laskaris <github_me@nahsi.dev>

* * Separate marine worker as a package
* Trying to fix tests

* Finalizing test fixes

* * Refactoring packages.
* Using CDN to load .wasm deps.
* Setting up tests for new architecture

* Fix almost all tests

* Fix last strange test

* Remove package specific packages

* Remove avm class as it looks excessive

* marine worker new version

* misc refactoring/remove console.log's

* Rename package js-peer to js-client

* Move service info to marine worker

* Change CDN path

* Fix worker race confition

* Remove buffer type

* Remove turned off headless mode in platform tests

* Remove async keyword to make tests pass

* Remove util package

* Make js-client.api package just reexport interface from js-client main package

* Update package info in CI

* Fix review comments

* Remove test entry from marine-worker package

* Misc fixes

* Fix worker type

* Add fetchers

* Specify correct versions for js-client package

* Set first ver for js-client

* Update libp2p and related dep versions to the latest

* Build all deps into package itself

* Fix review

* Refine package

* Fix comment

* Update packages/core/js-client/src/fetchers/browser.ts

* Update packages/core/js-client/src/fetchers/index.ts

* Update packages/core/js-client/src/fetchers/node.ts

* Update packages/core/js-client/src/jsPeer/FluencePeer.ts

* Update packages/core/js-client/src/keypair/__test__/KeyPair.spec.ts

* Update packages/core/js-client/src/jsPeer/FluencePeer.ts

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

* Delete outdated file

* Need types for build to work

* Inline func call

* Add comments to replacement lines.
P.S. we can remove some of them after update libp2p

---------

Co-authored-by: shamsartem <shamsartem@gmail.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: fluencebot <116741523+fluencebot@users.noreply.github.com>
Co-authored-by: Valery Antopol <valery.antopol@gmail.com>
Co-authored-by: Anatoly Laskaris <github_me@nahsi.dev>
This commit is contained in:
Akim
2023-08-25 00:15:49 +07:00
committed by GitHub
parent 2d2f5591cf
commit 97c24918d8
130 changed files with 3350 additions and 3119 deletions

View File

@ -2,6 +2,11 @@
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
## Notes
This package just reexports everything from main library for backward compatibility
`export * from '@fluencelabs/js-client';`
## 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).

View File

@ -24,13 +24,14 @@
"repository": "https://github.com/fluencelabs/fluence-js",
"author": "Fluence Labs",
"license": "Apache-2.0",
"dependencies": {
"@fluencelabs/interfaces": "0.8.1"
},
"devDependencies": {
"@fluencelabs/avm": "0.43.1",
"@fluencelabs/interfaces": "workspace:*",
"@fluencelabs/marine-js": "0.7.2",
"microbundle": "0.15.1",
"dts-bundle-generator": "7.2.0"
"dts-bundle-generator": "7.2.0",
"microbundle": "0.15.1"
},
"dependencies": {
"@fluencelabs/js-client": "0.0.10"
}
}

View File

@ -1,178 +0,0 @@
/*
* Copyright 2022 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 type { FnConfig, FunctionCallDef, ServiceDef } from '@fluencelabs/interfaces';
import type { IFluenceClient } from '@fluencelabs/interfaces';
import { getArgumentTypes } from '@fluencelabs/interfaces';
import { isFluencePeer } from '@fluencelabs/interfaces';
import { getFluenceInterface } from '../util.js';
/**
* Convenience function to support Aqua `func` generation backend
* The compiler only need to generate a call the function and provide the corresponding definitions and the air script
*
* @param rawFnArgs - raw arguments passed by user to the generated function
* @param def - function definition generated by the Aqua compiler
* @param script - air script with function execution logic generated by the Aqua compiler
*/
export const v5_callFunction = async (
rawFnArgs: Array<any>,
def: FunctionCallDef,
script: string,
): Promise<unknown> => {
const { args, client: peer, config } = await extractFunctionArgs(rawFnArgs, def);
const fluence = await getFluenceInterface();
return fluence.callAquaFunction({
args,
def,
script,
config: config || {},
peer: peer,
});
};
/**
* Convenience function to support Aqua `service` generation backend
* The compiler only need to generate a call the function and provide the corresponding definitions and the air script
* @param args - raw arguments passed by user to the generated function
* @param def - service definition generated by the Aqua compiler
*/
export const v5_registerService = async (args: any[], def: ServiceDef): Promise<unknown> => {
const { peer, service, serviceId } = await extractServiceArgs(args, def.defaultServiceId);
const fluence = await getFluenceInterface();
return fluence.registerService({
def,
service,
serviceId,
peer,
});
};
/**
* Arguments could be passed in one these configurations:
* [...actualArgs]
* [peer, ...actualArgs]
* [...actualArgs, config]
* [peer, ...actualArgs, config]
*
* This function select the appropriate configuration and returns
* arguments in a structured way of: { peer, config, args }
*/
const extractFunctionArgs = async (
args: any[],
def: FunctionCallDef,
): Promise<{
client: IFluenceClient;
config?: FnConfig;
args: { [key: string]: any };
}> => {
const argumentTypes = getArgumentTypes(def);
const argumentNames = Object.keys(argumentTypes);
const numberOfExpectedArgs = argumentNames.length;
let peer: IFluenceClient;
let structuredArgs: any[];
let config: FnConfig;
if (isFluencePeer(args[0])) {
peer = args[0];
structuredArgs = args.slice(1, numberOfExpectedArgs + 1);
config = args[numberOfExpectedArgs + 1];
} else {
const fluence = await getFluenceInterface();
if (!fluence.defaultClient) {
throw new Error(
'Could not register Aqua service because the client is not initialized. Did you forget to call Fluence.connect()?',
);
}
peer = fluence.defaultClient;
structuredArgs = args.slice(0, numberOfExpectedArgs);
config = args[numberOfExpectedArgs];
}
if (structuredArgs.length !== numberOfExpectedArgs) {
throw new Error(`Incorrect number of arguments. Expecting ${numberOfExpectedArgs}`);
}
const argsRes = argumentNames.reduce((acc, name, index) => ({ ...acc, [name]: structuredArgs[index] }), {});
return {
client: peer,
config: config,
args: argsRes,
};
};
/**
* Arguments could be passed in one these configurations:
* [serviceObject]
* [peer, serviceObject]
* [defaultId, serviceObject]
* [peer, defaultId, serviceObject]
*
* Where serviceObject is the raw object with function definitions passed by user
*
* This function select the appropriate configuration and returns
* arguments in a structured way of: { peer, serviceId, service }
*/
const extractServiceArgs = async (
args: any[],
defaultServiceId?: string,
): Promise<{ peer: IFluenceClient; serviceId: string; service: any }> => {
let peer: IFluenceClient;
let serviceId: any;
let service: any;
if (isFluencePeer(args[0])) {
peer = args[0];
} else {
const fluence = await getFluenceInterface();
if (!fluence.defaultClient) {
throw new Error(
'Could not register Aqua service because the client is not initialized. Did you forget to call Fluence.connect()?',
);
}
peer = fluence.defaultClient;
}
if (typeof args[0] === 'string') {
serviceId = args[0];
} else if (typeof args[1] === 'string') {
serviceId = args[1];
} else {
serviceId = defaultServiceId;
}
// Figuring out which overload is the service.
// If the first argument is not Fluence Peer and it is an object, then it can only be the service def
// If the first argument is peer, we are checking further. The second argument might either be
// an object, that it must be the service object
// or a string, which is the service id. In that case the service is the third argument
if (!isFluencePeer(args[0]) && typeof args[0] === 'object') {
service = args[0];
} else if (typeof args[1] === 'object') {
service = args[1];
} else {
service = args[2];
}
return {
peer: peer,
serviceId: serviceId,
service: service,
};
};

View File

@ -13,120 +13,5 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { getFluenceInterface, getFluenceInterfaceFromGlobalThis } from './util.js';
import {
IFluenceClient,
ClientConfig,
RelayOptions,
ConnectionState,
CallAquaFunctionType,
RegisterServiceType,
} from '@fluencelabs/interfaces';
export type { IFluenceClient, ClientConfig, CallParams } from '@fluencelabs/interfaces';
export {
ArrayType,
ArrowType,
ArrowWithCallbacks,
ArrowWithoutCallbacks,
BottomType,
FunctionCallConstants,
FunctionCallDef,
LabeledProductType,
NilType,
NonArrowType,
OptionType,
ProductType,
ScalarNames,
ScalarType,
ServiceDef,
StructType,
TopType,
UnlabeledProductType,
CallAquaFunctionType,
CallAquaFunctionArgs,
PassedArgs,
FnConfig,
RegisterServiceType,
RegisterServiceArgs,
} from '@fluencelabs/interfaces';
export { v5_callFunction, v5_registerService } from './compilerSupport/implementation.js';
/**
* Public interface to Fluence Network
*/
export const Fluence = {
/**
* Connect to the Fluence network
* @param relay - relay node to connect to
* @param config - client configuration
*/
connect: async (relay: RelayOptions, config?: ClientConfig): Promise<void> => {
const fluence = await getFluenceInterface();
const client = await fluence.clientFactory(relay, config);
fluence.defaultClient = client;
},
/**
* Disconnect from the Fluence network
*/
disconnect: async (): Promise<void> => {
const fluence = await getFluenceInterface();
await fluence.defaultClient?.disconnect();
fluence.defaultClient = undefined;
},
/**
* Handle connection state changes. Immediately returns the current connection state
*/
onConnectionStateChange(handler: (state: ConnectionState) => void): ConnectionState {
const optimisticResult = getFluenceInterfaceFromGlobalThis();
if (optimisticResult && optimisticResult.defaultClient) {
return optimisticResult.defaultClient.onConnectionStateChange(handler);
}
getFluenceInterface().then((fluence) => {
fluence.defaultClient?.onConnectionStateChange(handler);
});
return 'disconnected';
},
/**
* Low level API. Get the underlying client instance which holds the connection to the network
* @returns IFluenceClient instance
*/
getClient: async (): Promise<IFluenceClient> => {
const fluence = await getFluenceInterface();
if (!fluence.defaultClient) {
throw new Error('Fluence client is not initialized. Call Fluence.connect() first');
}
return fluence.defaultClient;
},
};
/**
* Low level API. Generally you need Fluence.connect() instead.
* @returns IFluenceClient instance
*/
export const createClient = async (relay: RelayOptions, config?: ClientConfig): Promise<IFluenceClient> => {
const fluence = await getFluenceInterface();
return await fluence.clientFactory(relay, config);
};
/**
* Low level API. Generally you should use code generated by the Aqua compiler.
*/
export const callAquaFunction: CallAquaFunctionType = async (args) => {
const fluence = await getFluenceInterface();
return await fluence.callAquaFunction(args);
};
/**
* Low level API. Generally you should use code generated by the Aqua compiler.
*/
export const registerService: RegisterServiceType = async (args) => {
const fluence = await getFluenceInterface();
return await fluence.registerService(args);
};
export * from '@fluencelabs/js-client';

View File

@ -1,79 +0,0 @@
/*
* 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 type {
CallAquaFunctionType,
ClientConfig,
IFluenceClient,
RegisterServiceType,
RelayOptions,
} from '@fluencelabs/interfaces';
type PublicFluenceInterface = {
defaultClient: IFluenceClient | undefined;
clientFactory: (relay: RelayOptions, config?: ClientConfig) => Promise<IFluenceClient>;
callAquaFunction: CallAquaFunctionType;
registerService: RegisterServiceType;
};
export const getFluenceInterfaceFromGlobalThis = (): PublicFluenceInterface | undefined => {
// @ts-ignore
return globalThis.fluence;
};
// TODO: fix link DXJ-271
const REJECT_MESSAGE = `Could not load Fluence JS Client library.
If you are using Node.js that probably means that you forgot in install or import the @fluencelabs/js-client.node package.
If you are using a browser, then you probably forgot to add the <script> tag to your HTML.
Please refer to the documentation page for more details: https://fluence.dev/docs/build/js-client/installation
`;
// Let's assume that if the library has not been loaded in 5 seconds, then the user has forgotten to add the script tag
const POLL_PEER_TIMEOUT = 5000;
// The script might be cached so need to try loading it ASAP, thus short interval
const POLL_PEER_INTERVAL = 100;
/**
* Wait until the js client script it loaded and return the default peer from globalThis
*/
export const getFluenceInterface = (): Promise<PublicFluenceInterface> => {
// If the script is already loaded, then return the value immediately
const optimisticResult = getFluenceInterfaceFromGlobalThis();
if (optimisticResult) {
return Promise.resolve(optimisticResult);
}
return new Promise((resolve, reject) => {
// This function is internal
// Make it sure that would be zero way for unnecessary types
// to break out into the public API
let interval: any;
let hits = POLL_PEER_TIMEOUT / POLL_PEER_INTERVAL;
interval = setInterval(() => {
if (hits === 0) {
clearInterval(interval);
reject(REJECT_MESSAGE);
}
let res = getFluenceInterfaceFromGlobalThis();
if (res) {
clearInterval(interval);
resolve(res);
}
hits--;
}, POLL_PEER_INTERVAL);
});
};