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:
Pavel
2023-02-13 17:41:35 +03:00
committed by GitHub
parent e02c506d7f
commit 9667c4fec6
212 changed files with 16522 additions and 7886 deletions

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 @@
/dist/

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,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));

View 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"
}
}

View 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();

View File

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