mirror of
https://github.com/fluencelabs/fluence-js.git
synced 2025-06-27 06:41:32 +00:00
feat!: Standalone web JS Client (#243)
- Move marine-related part into FJS repo (fixes DXJ-184) - Move towards component-oriented architecture (fixes DXJ-183) - Different JS Client distros for node.js and web (fixes DXJ-185) - Update libp2p to 0.42.2 (fixes DXJ-26) - Add JS Client API (fixes DXJ-196, fixes DXJ-177, fixes DXJ-60) - Add Smoke test for JS Client web (fixes DXJ-253) --------- Co-authored-by: Anatoly Laskaris <github_me@nahsi.dev>
This commit is contained in:
22
packages/client/api/.gitignore
vendored
Normal file
22
packages/client/api/.gitignore
vendored
Normal 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
|
11
packages/client/api/README.md
Normal file
11
packages/client/api/README.md
Normal 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)
|
42
packages/client/api/package.json
Normal file
42
packages/client/api/package.json
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
"_1": "This should actually be named @fluencelabs/js-client.api. Naming it fluence-js is needed for backward compat w/ aqua compiler",
|
||||
"name": "@fluencelabs/fluence",
|
||||
"version": "0.60.0",
|
||||
"description": "JS Client API",
|
||||
"main": "./dist/index.js",
|
||||
"typings": "./dist/index.d.ts",
|
||||
"engines": {
|
||||
"node": ">=10",
|
||||
"pnpm": ">=3"
|
||||
},
|
||||
"type": "module",
|
||||
"_2": "dist/internal/ export is needed for backward compat w/ aqua compiler",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
},
|
||||
"./compilerSupport/v5": {
|
||||
"import": "./dist/compilerSupport/v5.js",
|
||||
"types": "./dist/compilerSupport/v5.d.ts"
|
||||
},
|
||||
"./dist/compilerSupport/v5": {
|
||||
"import": "./dist/compilerSupport/v5.js",
|
||||
"types": "./dist/compilerSupport/v5.d.ts"
|
||||
},
|
||||
"./dist/internal/compilerSupport/v4": {
|
||||
"import": "./dist/compilerSupport/v5.js",
|
||||
"types": "./dist/compilerSupport/v5.d.ts"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc"
|
||||
},
|
||||
"repository": "https://github.com/fluencelabs/fluence-js",
|
||||
"author": "Fluence Labs",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@fluencelabs/interfaces": "0.5.0"
|
||||
},
|
||||
"devDependencies": {}
|
||||
}
|
181
packages/client/api/src/compilerSupport/implementation.ts
Normal file
181
packages/client/api/src/compilerSupport/implementation.ts
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* 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/compilerSupport';
|
||||
import type { IFluenceClient } from '@fluencelabs/interfaces/fluenceClient';
|
||||
import { getArgumentTypes } from '@fluencelabs/interfaces/compilerSupport';
|
||||
import { isFluencePeer } from '@fluencelabs/interfaces/fluenceClient';
|
||||
|
||||
import { getDefaultPeer } from '../index.js';
|
||||
|
||||
export type { IFluenceClient, CallParams } from '@fluencelabs/interfaces/fluenceClient';
|
||||
|
||||
export {
|
||||
ArrayType,
|
||||
ArrowType,
|
||||
ArrowWithCallbacks,
|
||||
ArrowWithoutCallbacks,
|
||||
BottomType,
|
||||
FnConfig,
|
||||
FunctionCallConstants,
|
||||
FunctionCallDef,
|
||||
LabeledProductType,
|
||||
NilType,
|
||||
NonArrowType,
|
||||
OptionType,
|
||||
ProductType,
|
||||
ScalarNames,
|
||||
ScalarType,
|
||||
ServiceDef,
|
||||
StructType,
|
||||
TopType,
|
||||
UnlabeledProductType,
|
||||
} from '@fluencelabs/interfaces/compilerSupport';
|
||||
|
||||
/**
|
||||
* 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 callFunction = async (rawFnArgs: Array<any>, def: FunctionCallDef, script: string): Promise<unknown> => {
|
||||
const { args, peer, config } = await extractFunctionArgs(rawFnArgs, def);
|
||||
return peer.compilerSupport.callFunction({
|
||||
args,
|
||||
def,
|
||||
script,
|
||||
config: config || {},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 registerService = async (args: any[], def: ServiceDef): Promise<unknown> => {
|
||||
const { peer, service, serviceId } = await extractServiceArgs(args, def.defaultServiceId);
|
||||
return peer.compilerSupport.registerService({
|
||||
def,
|
||||
service,
|
||||
serviceId,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 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<{
|
||||
peer: 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 {
|
||||
peer = await getDefaultPeer();
|
||||
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 {
|
||||
peer: 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 {
|
||||
peer = await getDefaultPeer();
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
};
|
41
packages/client/api/src/compilerSupport/v5.ts
Normal file
41
packages/client/api/src/compilerSupport/v5.ts
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { IFluenceClient } from './implementation.js';
|
||||
export { CallParams as CallParams$$ } from './implementation.js';
|
||||
export {
|
||||
ArrayType as ArrayType$$,
|
||||
ArrowType as ArrowType$$,
|
||||
ArrowWithCallbacks as ArrowWithCallbacks$$,
|
||||
ArrowWithoutCallbacks as ArrowWithoutCallbacks$$,
|
||||
BottomType as BottomType$$,
|
||||
FnConfig as FnConfig$$,
|
||||
FunctionCallConstants as FunctionCallConstants$$,
|
||||
FunctionCallDef as FunctionCallDef$$,
|
||||
LabeledProductType as LabeledProductType$$,
|
||||
NilType as NilType$$,
|
||||
NonArrowType as NonArrowType$$,
|
||||
OptionType as OptionType$$,
|
||||
ProductType as ProductType$$,
|
||||
ScalarNames as ScalarNames$$,
|
||||
ScalarType as ScalarType$$,
|
||||
ServiceDef as ServiceDef$$,
|
||||
StructType as StructType$$,
|
||||
TopType as TopType$$,
|
||||
UnlabeledProductType as UnlabeledProductType$$,
|
||||
callFunction as callFunction$$,
|
||||
registerService as registerService$$,
|
||||
} from './implementation.js';
|
69
packages/client/api/src/index.ts
Normal file
69
packages/client/api/src/index.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import type { IFluenceClient, ClientOptions } from '@fluencelabs/interfaces/fluenceClient';
|
||||
|
||||
export { IFluenceClient, ClientOptions, CallParams } from '@fluencelabs/interfaces/fluenceClient';
|
||||
|
||||
// TODO: hack needed to kinda have backward compat with compiler api
|
||||
export type FluencePeer = IFluenceClient;
|
||||
|
||||
const getPeerFromGlobalThis = (): IFluenceClient | undefined => {
|
||||
// @ts-ignore
|
||||
return globalThis.defaultPeer;
|
||||
};
|
||||
|
||||
// TODO: DXJ-271
|
||||
const REJECT_MESSAGE = 'You probably forgot to add script tag. Read about it here: ';
|
||||
|
||||
/**
|
||||
* Wait until the js client script it loaded and return the default peer from globalThis
|
||||
*/
|
||||
export const getDefaultPeer = (): Promise<IFluenceClient> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let interval: NodeJS.Timer | undefined;
|
||||
let hits = 50;
|
||||
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 options - object specifying peer configuration
|
||||
*/
|
||||
start: async (options?: ClientOptions): Promise<void> => {
|
||||
const peer = await getDefaultPeer();
|
||||
return peer.start(options);
|
||||
},
|
||||
|
||||
/**
|
||||
* 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 instance
|
||||
* @returns the default peer instance
|
||||
*/
|
||||
getPeer: async (): Promise<IFluenceClient> => {
|
||||
return getDefaultPeer();
|
||||
},
|
||||
};
|
7
packages/client/api/tsconfig.json
Normal file
7
packages/client/api/tsconfig.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
21
packages/client/js-client.node/.gitignore
vendored
Normal file
21
packages/client/js-client.node/.gitignore
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# 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/
|
||||
|
||||
dist
|
||||
esm
|
||||
types
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
.idea
|
11
packages/client/js-client.node/README.md
Normal file
11
packages/client/js-client.node/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# JS Client node
|
||||
|
||||
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)
|
33
packages/client/js-client.node/package.json
Normal file
33
packages/client/js-client.node/package.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "@fluencelabs/js-client.node",
|
||||
"version": "0.1.0",
|
||||
"description": "TypeScript implementation of Fluence Peer",
|
||||
"main": "./dist/index.js",
|
||||
"typings": "./dist/index.d.ts",
|
||||
"engines": {
|
||||
"node": ">=10",
|
||||
"pnpm": ">=3"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc"
|
||||
},
|
||||
"repository": "https://github.com/fluencelabs/fluence-js",
|
||||
"author": "Fluence Labs",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@fluencelabs/js-peer": "0.5.0",
|
||||
"@fluencelabs/avm": "0.35.3",
|
||||
"@fluencelabs/marine-js": "0.3.42",
|
||||
"platform": "1.3.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/platform": "1.3.4"
|
||||
}
|
||||
}
|
48
packages/client/js-client.node/src/index.ts
Normal file
48
packages/client/js-client.node/src/index.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import * as platform from 'platform';
|
||||
|
||||
import { FluencePeer } from '@fluencelabs/js-peer/dist/js-peer/FluencePeer.js';
|
||||
import { MarineBasedAvmRunner } from '@fluencelabs/js-peer/dist/js-peer/avm.js';
|
||||
import { MarineBackgroundRunner } from '@fluencelabs/js-peer/dist/marine/worker';
|
||||
import { marineLogFunction } from '@fluencelabs/js-peer/dist/js-peer/utils.js';
|
||||
import { WasmLoaderFromNpm } from '@fluencelabs/js-peer/dist/marine/deps-loader/node.js';
|
||||
import { WorkerLoader } from '@fluencelabs/js-peer/dist/marine/worker-script/workerLoader.js';
|
||||
|
||||
throwIfNotSupported();
|
||||
|
||||
export const defaultNames = {
|
||||
avm: {
|
||||
file: 'avm.wasm',
|
||||
package: '@fluencelabs/avm',
|
||||
},
|
||||
marine: {
|
||||
file: 'marine-js.wasm',
|
||||
package: '@fluencelabs/marine-js',
|
||||
},
|
||||
};
|
||||
|
||||
export const makeDefaultPeer = () => {
|
||||
const workerLoader = new WorkerLoader();
|
||||
const controlModuleLoader = new WasmLoaderFromNpm(defaultNames.marine.package, defaultNames.marine.file);
|
||||
const avmModuleLoader = new WasmLoaderFromNpm(defaultNames.avm.package, defaultNames.avm.file);
|
||||
|
||||
const marine = new MarineBackgroundRunner(workerLoader, controlModuleLoader, marineLogFunction);
|
||||
const avm = new MarineBasedAvmRunner(marine, avmModuleLoader, undefined);
|
||||
return new FluencePeer(marine, avm);
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
globalThis.defaultPeer = makeDefaultPeer();
|
||||
|
||||
function throwIfNotSupported() {
|
||||
if (platform.name === 'Node.js' && platform.version) {
|
||||
const version = platform.version.split('.').map(Number);
|
||||
const major = version[0];
|
||||
if (major < 16) {
|
||||
throw new Error(
|
||||
'FluenceJS requires node.js version >= "16.x"; Detected ' +
|
||||
platform.description +
|
||||
' Please update node.js to version 16 or higher.\nYou can use https://nvm.sh utility to update node.js version: "nvm install 17 && nvm use 17 && nvm alias default 17"',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
7
packages/client/js-client.node/tsconfig.json
Normal file
7
packages/client/js-client.node/tsconfig.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
22
packages/client/js-client.web.standalone/.gitignore
vendored
Normal file
22
packages/client/js-client.web.standalone/.gitignore
vendored
Normal 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
|
1
packages/client/js-client.web.standalone/.prettierignore
Normal file
1
packages/client/js-client.web.standalone/.prettierignore
Normal file
@ -0,0 +1 @@
|
||||
/dist/
|
11
packages/client/js-client.web.standalone/README.md
Normal file
11
packages/client/js-client.web.standalone/README.md
Normal 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)
|
126
packages/client/js-client.web.standalone/build.ts
Normal file
126
packages/client/js-client.web.standalone/build.ts
Normal file
@ -0,0 +1,126 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { fromUint8Array } from 'js-base64';
|
||||
import { build } from 'vite';
|
||||
import { createRequire } from 'module';
|
||||
import type { InlineConfig } from 'vite';
|
||||
import tsconfigPaths from 'vite-tsconfig-paths';
|
||||
import * as inject from '@rollup/plugin-inject';
|
||||
import { replaceCodePlugin } from 'vite-plugin-replace';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
const getWorkerScriptPathOrDie = () => {
|
||||
const scriptPath = path.resolve('../../core/js-peer/dist/marine/worker-script/index.js');
|
||||
if (!fs.existsSync(scriptPath)) {
|
||||
console.error('Worker script not found, looking at: ' + scriptPath);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
return scriptPath;
|
||||
};
|
||||
|
||||
const commonConfig = (opts: {
|
||||
outDir: string;
|
||||
name: string;
|
||||
entry: string;
|
||||
}): InlineConfig & Required<Pick<InlineConfig, 'build'>> => {
|
||||
return {
|
||||
mode: 'production',
|
||||
build: {
|
||||
minify: 'esbuild',
|
||||
lib: {
|
||||
entry: opts.entry,
|
||||
name: opts.name,
|
||||
fileName: opts.name,
|
||||
},
|
||||
outDir: opts.outDir,
|
||||
},
|
||||
base: '',
|
||||
plugins: [tsconfigPaths()],
|
||||
optimizeDeps: {
|
||||
esbuildOptions: {
|
||||
define: {
|
||||
global: 'globalThis',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const readAsBase64 = async (filePath: string): Promise<string> => {
|
||||
const scriptRaw = await fs.promises.readFile(filePath);
|
||||
const b64 = fromUint8Array(scriptRaw);
|
||||
return b64;
|
||||
};
|
||||
|
||||
const readWasmFromNpmAsBase64 = (pkg: string, wasmFileName: string): Promise<string> => {
|
||||
const pkgPath = require.resolve(pkg);
|
||||
const wasmFilePath = path.join(path.dirname(pkgPath), wasmFileName);
|
||||
return readAsBase64(wasmFilePath);
|
||||
};
|
||||
|
||||
const buildClient = async () => {
|
||||
await fs.promises.mkdir('tmp', { recursive: true });
|
||||
|
||||
// build worker script
|
||||
const workerConfig = commonConfig({
|
||||
outDir: './tmp',
|
||||
entry: getWorkerScriptPathOrDie(),
|
||||
name: 'worker-script',
|
||||
});
|
||||
workerConfig.build!.rollupOptions = {
|
||||
plugins: [
|
||||
inject.default({
|
||||
Buffer: ['buffer', 'Buffer'],
|
||||
process: 'process',
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
await build(workerConfig);
|
||||
|
||||
// build js-client
|
||||
const jsClientConfig = commonConfig({
|
||||
outDir: './dist',
|
||||
entry: './src/index.ts',
|
||||
name: 'js-client',
|
||||
});
|
||||
|
||||
const workerScriptB64 = await readAsBase64('./tmp/worker-script.umd.cjs');
|
||||
const avmBase64 = await readWasmFromNpmAsBase64('@fluencelabs/avm', 'avm.wasm');
|
||||
const marineBase64 = await readWasmFromNpmAsBase64('@fluencelabs/marine-js', 'marine-js.wasm');
|
||||
|
||||
jsClientConfig.plugins!.push(
|
||||
replaceCodePlugin({
|
||||
replacements: [
|
||||
{
|
||||
from: '___worker___',
|
||||
to: workerScriptB64,
|
||||
},
|
||||
{
|
||||
from: '___avm___',
|
||||
to: avmBase64,
|
||||
},
|
||||
{
|
||||
from: '___marine___',
|
||||
to: marineBase64,
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
|
||||
await build(jsClientConfig);
|
||||
|
||||
// We should exclude the script with type=module because
|
||||
// - it might be confusing (i.e won't work in browsers that do not support ESM, or if you miss the `type` attribute)
|
||||
// - there is a problem when using `self.crypto` in web workers
|
||||
await fs.promises.rm('./dist/js-client.js');
|
||||
|
||||
// browsers don't understand `.cjs` extensions, just use `.js`
|
||||
await fs.promises.rename('./dist/js-client.umd.cjs', './dist/js-client.min.js');
|
||||
};
|
||||
|
||||
buildClient()
|
||||
.then(() => console.log('Built successfully'))
|
||||
.catch((err) => console.error('failed', err));
|
36
packages/client/js-client.web.standalone/package.json
Normal file
36
packages/client/js-client.web.standalone/package.json
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"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": "0.5.0",
|
||||
"buffer": "6.0.3",
|
||||
"process": "0.11.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fluencelabs/avm": "0.35.3",
|
||||
"@fluencelabs/marine-js": "0.3.42",
|
||||
"@types/node": "16.11.59",
|
||||
"@types/jest": "28.1.0",
|
||||
"jest": "28.1.0",
|
||||
"ts-jest": "28.0.2",
|
||||
"js-base64": "3.7.2",
|
||||
"@rollup/plugin-inject": "5.0.3",
|
||||
"vite-plugin-replace": "0.1.1",
|
||||
"vite": "4.0.4",
|
||||
"vite-tsconfig-paths": "4.0.3"
|
||||
}
|
||||
}
|
18
packages/client/js-client.web.standalone/src/index.ts
Normal file
18
packages/client/js-client.web.standalone/src/index.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { FluencePeer } from '@fluencelabs/js-peer/dist/js-peer/FluencePeer.js';
|
||||
import { MarineBasedAvmRunner } from '@fluencelabs/js-peer/dist/js-peer/avm.js';
|
||||
import { MarineBackgroundRunner } from '@fluencelabs/js-peer/dist/marine/worker';
|
||||
import { checkConnection, marineLogFunction } from '@fluencelabs/js-peer/dist/js-peer/utils.js';
|
||||
import { InlinedWorkerLoader, InlinedWasmLoader } from '@fluencelabs/js-peer/dist/marine/deps-loader/common.js';
|
||||
|
||||
export const makeDefaultPeer = () => {
|
||||
const workerLoader = new InlinedWorkerLoader('___worker___');
|
||||
const controlModuleLoader = new InlinedWasmLoader('___marine___');
|
||||
const avmModuleLoader = new InlinedWasmLoader('___avm___');
|
||||
|
||||
const marine = new MarineBackgroundRunner(workerLoader, controlModuleLoader, marineLogFunction);
|
||||
const avm = new MarineBasedAvmRunner(marine, avmModuleLoader, undefined);
|
||||
return new FluencePeer(marine, avm);
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
globalThis.defaultPeer = makeDefaultPeer();
|
8
packages/client/js-client.web.standalone/tsconfig.json
Normal file
8
packages/client/js-client.web.standalone/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
21
packages/client/js-client.web/.gitignore
vendored
Normal file
21
packages/client/js-client.web/.gitignore
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# 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/
|
||||
|
||||
dist
|
||||
esm
|
||||
types
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
.idea
|
11
packages/client/js-client.web/README.md
Normal file
11
packages/client/js-client.web/README.md
Normal 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)
|
26
packages/client/js-client.web/package.json.skip
Normal file
26
packages/client/js-client.web/package.json.skip
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "@fluencelabs/js-client.web",
|
||||
"version": "0.1.0",
|
||||
"description": "TypeScript implementation of Fluence Peer",
|
||||
"main": "./dist/index.js",
|
||||
"typings": "./dist/index.d.ts",
|
||||
"engines": {
|
||||
"node": ">=10",
|
||||
"pnpm": ">=3"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc"
|
||||
},
|
||||
"repository": "https://github.com/fluencelabs/fluence-js",
|
||||
"author": "Fluence Labs",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@fluencelabs/js-peer": "workspace:0.60.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "16.11.59",
|
||||
"@types/jest": "28.1.0",
|
||||
"jest": "28.1.0",
|
||||
"ts-jest": "28.0.2"
|
||||
}
|
||||
}
|
23
packages/client/js-client.web/src/index.ts
Normal file
23
packages/client/js-client.web/src/index.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { MarineBackgroundRunner } from '@fluencelabs/marine.background-runner';
|
||||
import { MarineBasedAvmRunner } from '@fluencelabs/js-peer/dist/avm';
|
||||
import { marineLogFunction } from '@fluencelabs/js-peer/dist/utils';
|
||||
import { FluencePeer } from '@fluencelabs/js-peer/dist/FluencePeer';
|
||||
import { InlinedWorkerLoader, WasmWebLoader } from '@fluencelabs/marine.deps-loader.web';
|
||||
|
||||
export const defaultNames = {
|
||||
avm: 'avm.wasm',
|
||||
marine: 'marine-js.wasm',
|
||||
};
|
||||
|
||||
export const makeDefaultPeer = () => {
|
||||
const workerLoader = new InlinedWorkerLoader();
|
||||
const controlModuleLoader = new WasmWebLoader(defaultNames.marine);
|
||||
const avmModuleLoader = new WasmWebLoader(defaultNames.avm);
|
||||
|
||||
const marine = new MarineBackgroundRunner(workerLoader, controlModuleLoader, marineLogFunction);
|
||||
const avm = new MarineBasedAvmRunner(marine, avmModuleLoader, undefined);
|
||||
return new FluencePeer(marine, avm);
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
globalThis.defaultPeer = makeDefaultPeer();
|
7
packages/client/js-client.web/tsconfig.json
Normal file
7
packages/client/js-client.web/tsconfig.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
21
packages/client/tools/.gitignore
vendored
Normal file
21
packages/client/tools/.gitignore
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# 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/
|
||||
|
||||
dist
|
||||
esm
|
||||
types
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
.idea
|
12
packages/client/tools/.npmignore
Normal file
12
packages/client/tools/.npmignore
Normal file
@ -0,0 +1,12 @@
|
||||
.idea
|
||||
.gitignore
|
||||
node_modules
|
||||
types
|
||||
|
||||
src/
|
||||
|
||||
tsconfig.json
|
||||
webpack.config.js
|
||||
|
||||
bundle
|
||||
pkg
|
1
packages/client/tools/.prettierignore
Normal file
1
packages/client/tools/.prettierignore
Normal file
@ -0,0 +1 @@
|
||||
/dist/
|
13
packages/client/tools/CONTRIBUTING.md
Normal file
13
packages/client/tools/CONTRIBUTING.md
Normal file
@ -0,0 +1,13 @@
|
||||
## Contribute Code
|
||||
|
||||
You are welcome to contribute to Fluence.
|
||||
|
||||
Things you need to know:
|
||||
|
||||
1. You need to **agree to the Contributors License Agreement**. This is a common practice in all major Open Source projects. At the current moment we are unable to accept contributions made on behalf of a company. Only individual contributions will be accepted.
|
||||
2. **Not all proposed contributions can be accepted**. Some features may e.g. just fit a third-party add-on better. The contribution must fit the overall direction of Fluence and really improve it. The more effort you invest, the better you should clarify in advance whether the contribution fits: the best way would be to just open an issue to discuss the contribution you plan to make.
|
||||
|
||||
### Contributor License Agreement
|
||||
|
||||
When you contribute, you have to be aware that your contribution is covered by **Apache License 2.0**, but might relicensed under few other software licenses mentioned in the **Contributor License Agreement**.
|
||||
In particular you need to agree to the [Contributor License Agreement](https://gist.github.com/fluencelabs-org/3f4cbb3cc14c1c0fb9ad99d8f7316ed7). If you agree to its content, you simply have to click on the link posted by the CLA assistant as a comment to the pull request. Click it to check the CLA, then accept it on the following screen if you agree to it. CLA assistant will save this decision for upcoming contributions and will notify you if there is any change to the CLA in the meantime.
|
11
packages/client/tools/README.md
Normal file
11
packages/client/tools/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Fluence JS Client tools
|
||||
|
||||
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)
|
24
packages/client/tools/package.json
Normal file
24
packages/client/tools/package.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "@fluencelabs/tools",
|
||||
"version": "0.1.0",
|
||||
"description": "Fluence JS Client tools",
|
||||
"main": "./dist/index.js",
|
||||
"typings": "./dist/index.d.ts",
|
||||
"engines": {
|
||||
"node": ">=10",
|
||||
"pnpm": ">=3"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc"
|
||||
},
|
||||
"repository": "https://github.com/fluencelabs/fluence-js",
|
||||
"author": "Fluence Labs",
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"copy-marine": "dist/copyMarine.js"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@types/node": "16.11.59"
|
||||
}
|
||||
}
|
46
packages/client/tools/src/copyMarine.ts
Normal file
46
packages/client/tools/src/copyMarine.ts
Normal file
@ -0,0 +1,46 @@
|
||||
#! /usr/bin/env node
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
const firstArgument = process.argv[2];
|
||||
|
||||
if (!firstArgument) {
|
||||
console.log(`Expected exactly 1 argument, got 0. Usage: ${path.basename(process.argv[1])} <destination directory>`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let destPath = firstArgument;
|
||||
if (!path.isAbsolute(destPath)) {
|
||||
destPath = path.join(process.cwd(), destPath);
|
||||
}
|
||||
|
||||
async function copyFile(packageName: string, fileName: string) {
|
||||
const modulePath = require.resolve(packageName);
|
||||
const source = path.join(path.dirname(modulePath), fileName);
|
||||
const dest = path.join(destPath, fileName);
|
||||
|
||||
console.log(`copying ${fileName}`);
|
||||
console.log('from: ', source);
|
||||
console.log('to: ', dest);
|
||||
await fs.promises.copyFile(source, dest);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('ensure directory exists: ', destPath);
|
||||
await fs.promises.mkdir(destPath, { recursive: true });
|
||||
|
||||
await Promise.all([
|
||||
copyFile('@fluencelabs/marine.worker-script', 'marine-js.web.js'),
|
||||
copyFile('@fluencelabs/marine-js', 'marine-js.wasm'),
|
||||
copyFile('@fluencelabs/avm', 'avm.wasm'),
|
||||
]);
|
||||
}
|
||||
|
||||
main()
|
||||
.then(() => {
|
||||
console.log('done!');
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Something went wrong!', err);
|
||||
});
|
7
packages/client/tools/tsconfig.json
Normal file
7
packages/client/tools/tsconfig.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
Reference in New Issue
Block a user