chore(js-client)!: Simplify/optimize js-client and update README [fixes DXJ-490] (#366)

* Update README

* Improve build experience

* Fix eslint

* Fix eslint

* Fix eslint

* Fix tooling

* Fix formatting

* Fix formatting

* Fix test resource name

* Remove async

* Fix comments

* Add ts-check

* Add new line

* Fix arg

* add todo's

* Fix lint

* Fix typo

* Type module

* Add deps to isomorphic package

* Extract function type

* Fix newline

* Remove private

* Use prepare hook instead of postinstall
This commit is contained in:
Akim 2023-10-25 19:02:42 +07:00 committed by GitHub
parent 1266a90737
commit f9abc6419c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 576 additions and 278 deletions

1
.gitignore vendored
View File

@ -8,3 +8,4 @@ node_modules/
# Build directory
**/dist
**/public
.DS_Store

View File

@ -7,4 +7,6 @@ pnpm-lock.yaml
**/build
**/public
**/CHANGELOG.md
**/CHANGELOG.md
packages/core/js-client/src/versions.ts

123
README.md
View File

@ -1,92 +1,72 @@
# Fluence JS Client
[![npm](https://img.shields.io/npm/v/@fluencelabs/js-client.api?label=@fluencelabs/js-client.api)](https://www.npmjs.com/package/@fluencelabs/js-client.api)
[![npm](https://img.shields.io/npm/v/@fluencelabs/js-client.web.standalone?label=@fluencelabs/js-client.web.standalone)](https://www.npmjs.com/package/@fluencelabs/js-client.web.standalone)
[![npm](https://img.shields.io/npm/v/@fluencelabs/js-client?label=@fluencelabs/js-client)](https://www.npmjs.com/package/@fluencelabs/js-client)
This is the Javascript client for the [Fluence](https://fluence.network) network. The main role of the JS client is to connect to the Fluence Network and allow you to integrate Aqua code into your application.
## Installation
Adding the Fluence JS client for your web application is very easy.
> JS Client only supports the ESM format that means not every Node.js project can install it.
> You can read more [here](https://nodejs.org/api/esm.html)
### Browser-based Apps
1. Install the client:
1. Add a script tag with the JS Client bundle to your `index.html`. The easiest way to do this is using a CDN (like [JSDELIVR](https://www.jsdelivr.com/) or [UNPKG](https://unpkg.com/)). The script is large, thus we highly recommend to use the `async` attribute.
Here is an example using the JSDELIVR CDN:
```html
<head>
<title>Cool App</title>
<script
src="https://cdn.jsdelivr.net/npm/@fluencelabs/js-client.web.standalone@0.13.3/dist/js-client.min.js"
async
></script>
</head>
```
If you cannot or don't want to use a CDN, feel free to get the script directly from the [npm package](https://www.npmjs.com/package/@fluencelabs/js-client.web.standalone) and host it yourself. You can find the script in the `/dist` directory of the package. (Note: this option means that developers understand what they are doing and know how to serve this file from their own web server.)
2. Install the following packages:
```
npm i @fluencelabs/js-client.api @fluencelabs/fluence-network-environment
```
3. Add the following lines at the beginning of your code:
```
import { Fluence } from "@fluencelabs/js-client.api";
import { randomKras } from '@fluencelabs/fluence-network-environment';
Fluence.connect(randomKras());
```
### Node.js Apps
**Prerequisites:**
The Fluence JS Client only supports the ESM format. This implies that a few preliminary steps are required if your project is not already using ESM:
- Add `"type": "module"` to your package.json.
- Replace `"main": "index.js"` with `"exports": "./index.js"` in your package.json.
- Remove `'use strict';` from all JavaScript files.
- Replace all `require()`/`module.export` with `import`/`export`.
- Use only full relative file paths for imports: `import x from '.';``import x from './index.js';`.
If you are using TypeScript:
- Make sure you are using TypeScript 4.7 or later.
- Add [`"module": "ESNext", "target": "ESNext", "moduleResolution": "nodenext"`](https://www.typescriptlang.org/tsconfig#module) to your tsconfig.json.
- Use only full relative file paths for imports: `import x from '.';``import x from './index.js';`.
- Remove `namespace` usage and use `export` instead.
- You must use a `.js` extension in relative imports even though you're importing `.ts` files.
**Installation:**
1. Install the following packages:
```
npm i @fluencelabs/js-client.api"@fluencelabs/js-client.node @fluencelabs/fluence-network-environment
```bash
npm i @fluencelabs/js-client
```
2. Add the following lines at the beginning of your code:
```
import '@fluencelabs/js-client.node';
import { Fluence } from "@fluencelabs/js-client.api";
import { randomKras } from '@fluencelabs/fluence-network-environment';
```javascript
import { Fluence, randomKras } from "@fluencelabs/js-client";
Fluence.connect(randomKras());
```
### HTML page
Add a script tag with the JS Client bundle to your `index.html`. The easiest way to do this is using a CDN (
like [JSDELIVR](https://www.jsdelivr.com/) or [UNPKG](https://unpkg.com/)).
Here is an example using the JSDELIVR CDN:
```html
<head>
<title>Cool App</title>
<script src="https://cdn.jsdelivr.net/npm/@fluencelabs/js-client/dist/browser/index.min.js"></script>
</head>
```
If you cannot or don't want to use a CDN, feel free to get the script directly from
the [npm package](https://www.npmjs.com/package/@fluencelabs/js-client) and host it yourself. You can find the script in
the `/dist` directory of the package. (Note: this option means that developers understand what they are doing and know
how to serve this file from their own web server.)
After importing JS-client to HTML page the client is available as `window.Fluence` variable.
To get a specific network you can peek at
```
https://cdn.jsdelivr.net/npm/@fluencelabs/js-client/dist/network.js
```
and hardcode selected network. So initialization would look like this
```javascript
// Passing 1 kras network config from ./dist/network.js above
window.Fluence.connect({
multiaddr:
"/dns4/0-kras.fluence.dev/tcp/9000/wss/p2p/12D3KooWSD5PToNiLQwKDXsu8JSysCwUt8BVUJEqCHcDe7P5h45e",
peerId: "12D3KooWSD5PToNiLQwKDXsu8JSysCwUt8BVUJEqCHcDe7P5h45e",
});
```
## Usage in an Application
Once you've added the client, you can compile [Aqua](https://github.com/fluencelabs/aqua) and run it in your application. To compile Aqua, use [Fluence CLI](https://github.com/fluencelabs/cli).
1. Install the package:
```
```bash
npm i -D @fluencelabs/cli
```
@ -130,7 +110,7 @@ Once you've added the client, you can compile [Aqua](https://github.com/fluencel
6. Now you can import and call Aqua code from your application like
this:
```
```javascript
import { getRelayTime } from "./_aqua/demo";
async function buttonClick() {
@ -172,7 +152,7 @@ Star (`*`) character can be used as a wildcard to enable logs for multiple compo
### Enabling logs in Node.js
enable logs, pass the environment variable `DEBUG` with the corresponding log level. For example:
Enable logs by passing the environment variable `DEBUG` with the corresponding log level. For example:
```sh
DEBUG=fluence:* node --loader ts-node/esm ./src/index.ts
@ -182,13 +162,14 @@ DEBUG=fluence:* node --loader ts-node/esm ./src/index.ts
To enable logs, set the `localStorage.debug` variable. For example:
```
localStorage.debug = 'fluence:*'
```javascript
localStorage.debug = "fluence:*";
```
**NOTE**
In Chromium-based web browsers (e.g. Brave, Chrome, and Electron), the JavaScript console will—by default—only show messages logged by debug if the "Verbose" log level is enabled.
In Chromium-based web browsers (e.g. Brave, Chrome, and Electron), the JavaScript console will be default—only to show
messages logged by debug if the "Verbose" log level is enabled.
## Development

View File

@ -59,7 +59,7 @@ export const startContentServer = (
rewrites: [
{
source: "/js-client.min.js",
destination: "/source/index.umd.cjs",
destination: "/source/index.min.js",
},
// TODO:
// something like this

View File

@ -21,7 +21,6 @@
"@fluencelabs/aqua-api": "0.12.0",
"@fluencelabs/aqua-lib": "0.7.3",
"@fluencelabs/interfaces": "workspace:*",
"@fluencelabs/js-client": "workspace:*",
"@fluencelabs/registry": "0.8.7",
"@fluencelabs/spell": "0.5.20",
"@fluencelabs/trust-graph": "0.4.7",

View File

@ -40,12 +40,18 @@ describe("Aqua to js/ts compiler", () => {
},
};
// TODO: see https://github.com/fluencelabs/js-client/pull/366#discussion_r1370567711
// @ts-expect-error don't use compileFromPath directly here
const jsResult = generateSources(res, "js", pkg);
// TODO: see https://github.com/fluencelabs/js-client/pull/366#discussion_r1370567711
// @ts-expect-error don't use compileFromPath directly here
const jsTypes = generateTypes(res, pkg);
expect(jsResult).toMatchSnapshot();
expect(jsTypes).toMatchSnapshot();
// TODO: see https://github.com/fluencelabs/js-client/pull/366#discussion_r1370567711
// @ts-expect-error don't use compileFromPath directly here
const tsResult = generateSources(res, "ts", pkg);
expect(tsResult).toMatchSnapshot();

View File

@ -0,0 +1,33 @@
{
"type": "module",
"name": "@fluencelabs/js-client-isomorphic",
"version": "1.0.0",
"description": "Isomorphic entities for js-client",
"files": [
"dist"
],
"main": "index.js",
"scripts": {
"build": "tsc"
},
"exports": {
".": "./dist/types.js",
"./fetcher": {
"node": "./dist/fetchers/node.js",
"default": "./dist/fetchers/browser.js"
},
"./worker-resolver": {
"node": "./dist/worker-resolvers/node.js",
"default": "./dist/worker-resolvers/browser.js"
}
},
"dependencies": {
"@fluencelabs/avm": "0.52.0",
"@fluencelabs/marine-js": "0.7.2",
"@fluencelabs/marine-worker": "workspace:*",
"threads": "fluencelabs/threads.js#b00a5342380b0278d3ae56dcfb170effb3cad7cd"
},
"keywords": [],
"author": "Fluence Labs",
"license": "Apache-2.0"
}

View File

@ -0,0 +1,38 @@
/**
* 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 { VersionedPackage } from "../types.js";
/**
* @param pkg name of package with version
* @param assetPath path of required asset in given package
* @param root CDN domain in browser or file system root in node
*/
export async function fetchResource(
pkg: VersionedPackage,
assetPath: string,
root: string,
) {
const refinedAssetPath = assetPath.startsWith("/")
? assetPath.slice(1)
: assetPath;
const url = new URL(`${pkg.name}@${pkg.version}/` + refinedAssetPath, root);
return fetch(url).catch(() => {
throw new Error(`Cannot fetch from ${url.toString()}`);
});
}

View File

@ -14,49 +14,41 @@
* limitations under the License.
*/
import fs from "fs";
import module from "module";
import path from "path";
import { readFile } from "fs/promises";
import { createRequire } from "module";
import { sep, posix, join } from "path";
import type { VersionedPackage } from "../types.js";
/**
* @param pkg name of package
* @param pkg name of package with version
* @param assetPath path of required asset in given package
* @param root CDN domain in browser or file system root in node
* @param root CDN domain in browser or js-client itself in node
*/
export async function fetchResource(
pkg: string,
pkg: VersionedPackage,
assetPath: string,
root: string,
) {
// TODO: `root` will be handled somehow in the future. For now, we use filesystem root where js-client is running;
root = "/";
const require = module.createRequire(import.meta.url);
const packagePathIndex = require.resolve(pkg);
const require = createRequire(import.meta.url);
const packagePathIndex = require.resolve(pkg.name);
// Ensure that windows path is converted to posix path. So we can find a package
const posixPath = packagePathIndex.split(path.sep).join(path.posix.sep);
const posixPath = packagePathIndex.split(sep).join(posix.sep);
const matches = new RegExp(`(.+${pkg})`).exec(posixPath);
const matches = new RegExp(`(.+${pkg.name})`).exec(posixPath);
const packagePath = matches?.[0];
if (packagePath == null) {
throw new Error(`Cannot find dependency ${pkg} in path ${posixPath}`);
throw new Error(`Cannot find dependency ${pkg.name} in path ${posixPath}`);
}
const pathToResource = path.join(root, packagePath, assetPath);
const pathToResource = join(root, packagePath, assetPath);
const file = await new Promise<ArrayBuffer>((resolve, reject) => {
// Cannot use 'fs/promises' with current vite config. This module is not polyfilled by default.
fs.readFile(pathToResource, (err, data) => {
if (err != null) {
reject(err);
return;
}
resolve(data);
});
});
const file = await readFile(pathToResource);
return new Response(file, {
headers: {

View File

@ -0,0 +1,23 @@
/**
* 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 { Worker } from "threads/master";
export type VersionedPackage = { name: string; version: string };
export type GetWorker = (
pkg: VersionedPackage,
CDNUrl: string,
) => Promise<Worker>;

View File

@ -0,0 +1,38 @@
/**
* 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 { BlobWorker } from "threads/master";
import { fetchResource } from "../fetchers/browser.js";
import type { GetWorker, VersionedPackage } from "../types.js";
export const getWorker: GetWorker = async (
pkg: VersionedPackage,
CDNUrl: string,
) => {
const fetchWorkerCode = async () => {
const resource = await fetchResource(
pkg,
"/dist/browser/marine-worker.umd.cjs",
CDNUrl,
);
return resource.text();
};
const workerCode = await fetchWorkerCode();
return BlobWorker.fromText(workerCode);
};

View File

@ -0,0 +1,35 @@
/**
* 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 { createRequire } from "module";
import { dirname, relative } from "path";
import { fileURLToPath } from "url";
import { Worker } from "threads/master";
import type { GetWorker, VersionedPackage } from "../types.js";
export const getWorker: GetWorker = (pkg: VersionedPackage) => {
const require = createRequire(import.meta.url);
const pathToThisFile = dirname(fileURLToPath(import.meta.url));
const pathToWorker = require.resolve(pkg.name);
const relativePathToWorker = relative(pathToThisFile, pathToWorker);
return Promise.resolve(new Worker(relativePathToWorker));
};

View File

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

View File

@ -22,3 +22,5 @@ jspm_packages/
# workaround to make integration tests work
src/marine/worker-script/index.js
src/versions.ts

View File

@ -1 +0,0 @@
/dist/

View File

@ -1,11 +0,0 @@
# JS Peer
TDB
## 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,41 @@
/*
* 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.
*/
// @ts-check
import pkg from "./package.json" assert { type: "json" };
import { writeFile } from "fs/promises";
import { join, dirname } from "path";
import { fileURLToPath } from "url";
const names = [
"@fluencelabs/avm",
"@fluencelabs/marine-js",
"@fluencelabs/marine-worker",
];
const entries = Object.entries({
...pkg.dependencies,
...pkg.devDependencies,
}).filter(([name]) => names.includes(name));
const output = Object.fromEntries(entries);
await writeFile(
join(dirname(fileURLToPath(import.meta.url)), "src", "versions.ts"),
`/* eslint-disable */
export default ${JSON.stringify(output, null, 2)} as const`,
);

View File

@ -9,24 +9,23 @@
"files": [
"dist"
],
"main": "./dist/index.js",
"unpkg": "./dist/browser/index.umd.js",
"main": "./dist/browser/index.min.js",
"types": "./dist/index.d.ts",
"exports": {
"types": "./dist/index.d.ts",
"node": "./dist/index.js",
"default": "./dist/browser/index.js"
},
"imports": {
"#fetcher": {
"node": "./dist/fetchers/node.js",
"default": "./dist/fetchers/browser.js"
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
},
"./keypair": {
"types": "./dist/keypair/index.d.ts",
"import": "./dist/keypair/index.js"
}
},
"type": "module",
"scripts": {
"build": "tsc && vite build",
"test": "vitest --threads false run"
"test": "vitest --threads false run",
"prepare": "node createVersionFile.js"
},
"repository": "https://github.com/fluencelabs/fluence-js",
"author": "Fluence Labs",
@ -36,6 +35,7 @@
"@chainsafe/libp2p-yamux": "5.0.0",
"@fluencelabs/avm": "0.52.0",
"@fluencelabs/interfaces": "workspace:*",
"@fluencelabs/js-client-isomorphic": "workspace:*",
"@fluencelabs/marine-worker": "0.4.0",
"@libp2p/crypto": "2.0.3",
"@libp2p/interface": "0.1.2",

View File

@ -1,69 +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.
*/
interface PackageJsonContent {
dependencies: Record<string, string | undefined>;
devDependencies: Record<string, string | undefined>;
}
// This will be substituted in build phase
const packageJsonContentString = `__PACKAGE_JSON_CONTENT__`;
let parsedPackageJsonContent: PackageJsonContent | undefined;
/**
* @param pkg name of package
* @param assetPath path of required asset in given package
* @param root CDN domain in browser or file system root in node
*/
export async function fetchResource(
pkg: string,
assetPath: string,
root: string,
) {
const packageJsonContent =
parsedPackageJsonContent ??
// TODO: Should be validated
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
(parsedPackageJsonContent = JSON.parse(
packageJsonContentString,
) as PackageJsonContent);
const version =
packageJsonContent.dependencies[pkg] ??
packageJsonContent.devDependencies[pkg];
if (version === undefined) {
const availableDeps = [
...Object.keys(packageJsonContent.dependencies),
...Object.keys(packageJsonContent.devDependencies),
];
throw new Error(
`Cannot find version of ${pkg} in package.json. Available versions: ${availableDeps.join(
",",
)}`,
);
}
const refinedAssetPath = assetPath.startsWith("/")
? assetPath.slice(1)
: assetPath;
const url = new globalThis.URL(`${pkg}@${version}/` + refinedAssetPath, root);
return fetch(url).catch(() => {
throw new Error(`Cannot fetch from ${url.toString()}`);
});
}

View File

@ -14,12 +14,9 @@
* limitations under the License.
*/
import module from "module";
import path from "path";
import process from "process";
import url from "url";
import { BlobWorker, Worker } from "threads/master";
import type { VersionedPackage } from "@fluencelabs/js-client-isomorphic";
import { fetchResource } from "@fluencelabs/js-client-isomorphic/fetcher";
import { getWorker } from "@fluencelabs/js-client-isomorphic/worker-resolver";
import { ClientPeer, makeClientPeerConfig } from "./clientPeer/ClientPeer.js";
import {
@ -30,36 +27,26 @@ import {
import { callAquaFunction } from "./compilerSupport/callFunction.js";
import { registerService } from "./compilerSupport/registerService.js";
import { MarineBackgroundRunner } from "./marine/worker/index.js";
import { doRegisterNodeUtils } from "./services/NodeUtils.js";
import { fetchResource } from "#fetcher";
import versions from "./versions.js";
const DEFAULT_CDN_URL = "https://unpkg.com";
const isNode =
// process.release is undefined in browser env
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
typeof process !== "undefined" && process.release?.name === "node";
const getVersionedPackage = (pkg: keyof typeof versions): VersionedPackage => {
return {
name: pkg,
version: versions[pkg],
};
};
const createClient = async (
relay: RelayOptions,
config: ClientConfig,
config: ClientConfig = {},
): Promise<ClientPeer> => {
const CDNUrl = config.CDNUrl ?? DEFAULT_CDN_URL;
const fetchWorkerCode = async () => {
const resource = await fetchResource(
"@fluencelabs/marine-worker",
"/dist/browser/marine-worker.umd.cjs",
CDNUrl,
);
return resource.text();
};
const fetchMarineJsWasm = async () => {
const resource = await fetchResource(
"@fluencelabs/marine-js",
getVersionedPackage("@fluencelabs/marine-js"),
"/dist/marine-js.wasm",
CDNUrl,
);
@ -69,7 +56,7 @@ const createClient = async (
const fetchAvmWasm = async () => {
const resource = await fetchResource(
"@fluencelabs/avm",
getVersionedPackage("@fluencelabs/avm"),
"/dist/avm.wasm",
CDNUrl,
);
@ -83,25 +70,10 @@ const createClient = async (
const marine = new MarineBackgroundRunner(
{
async getValue() {
if (isNode) {
const require = module.createRequire(import.meta.url);
const pathToThisFile = path.dirname(
url.fileURLToPath(import.meta.url),
);
const pathToWorker = require.resolve("@fluencelabs/marine-worker");
const relativePathToWorker = path.relative(
pathToThisFile,
pathToWorker,
);
return new Worker(relativePathToWorker);
} else {
const workerCode = await fetchWorkerCode();
return BlobWorker.fromText(workerCode);
}
return getWorker(
getVersionedPackage("@fluencelabs/marine-worker"),
CDNUrl,
);
},
start() {
return Promise.resolve(undefined);
@ -141,9 +113,10 @@ const createClient = async (
const client = new ClientPeer(peerConfig, relayConfig, keyPair, marine);
if (isNode) {
doRegisterNodeUtils(client);
}
// TODO: Support node specific utils
// if (isNode) {
// doRegisterNodeUtils(client);
// }
await client.connect();
return client;
@ -154,7 +127,7 @@ const createClient = async (
*/
interface FluencePublicApi {
defaultClient: ClientPeer | undefined;
connect: (relay: RelayOptions, config: ClientConfig) => Promise<void>;
connect: (relay: RelayOptions, config?: ClientConfig) => Promise<void>;
disconnect: () => Promise<void>;
onConnectionStateChange: (
handler: (state: ConnectionState) => void,
@ -205,37 +178,8 @@ export const Fluence: FluencePublicApi = {
},
};
export type { CallParams } from "@fluencelabs/interfaces";
export type { ClientConfig, IFluenceClient } from "./clientPeer/types.js";
export type {
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 "./api.js";
// @ts-expect-error Writing to global object like this prohibited by ts
@ -249,9 +193,13 @@ globalThis.fluence = {
};
export { createClient, callAquaFunction, registerService };
// Deprecated exports. Later they will be exposed only under js-client/keypair path
export {
KeyPair,
fromBase64Sk,
fromBase58Sk,
fromOpts,
} from "./keypair/index.js";
export * from "./network.js";

View File

@ -0,0 +1,187 @@
/**
* 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 Relay = { peerId: string; multiaddr: string };
export const stage: Relay[] = [
{
multiaddr:
"/dns4/0-stage.fluence.dev/tcp/9000/wss/p2p/12D3KooWDcpWuyrMTDinqNgmXAuRdfd2mTdY9VoXZSAet2pDzh6r",
peerId: "12D3KooWDcpWuyrMTDinqNgmXAuRdfd2mTdY9VoXZSAet2pDzh6r",
},
{
multiaddr:
"/dns4/1-stage.fluence.dev/tcp/9000/wss/p2p/12D3KooWHCJbJKGDfCgHSoCuK9q4STyRnVveqLoXAPBbXHTZx9Cv",
peerId: "12D3KooWHCJbJKGDfCgHSoCuK9q4STyRnVveqLoXAPBbXHTZx9Cv",
},
{
multiaddr:
"/dns4/2-stage.fluence.dev/tcp/9000/wss/p2p/12D3KooWMigkP4jkVyufq5JnDJL6nXvyjeaDNpRfEZqQhsG3sYCU",
peerId: "12D3KooWMigkP4jkVyufq5JnDJL6nXvyjeaDNpRfEZqQhsG3sYCU",
},
{
multiaddr:
"/dns4/3-stage.fluence.dev/tcp/9000/wss/p2p/12D3KooWMMGdfVEJ1rWe1nH1nehYDzNEHhg5ogdfiGk88AupCMnf",
peerId: "12D3KooWMMGdfVEJ1rWe1nH1nehYDzNEHhg5ogdfiGk88AupCMnf",
},
{
multiaddr:
"/dns4/4-stage.fluence.dev/tcp/9000/wss/p2p/12D3KooWJ4bTHirdTFNZpCS72TAzwtdmavTBkkEXtzo6wHL25CtE",
peerId: "12D3KooWJ4bTHirdTFNZpCS72TAzwtdmavTBkkEXtzo6wHL25CtE",
},
{
multiaddr:
"/dns4/5-stage.fluence.dev/tcp/9000/wss/p2p/12D3KooWAKNos2KogexTXhrkMZzFYpLHuWJ4PgoAhurSAv7o5CWA",
peerId: "12D3KooWAKNos2KogexTXhrkMZzFYpLHuWJ4PgoAhurSAv7o5CWA",
},
];
export const testNet: Relay[] = [
{
multiaddr:
"/dns4/0-testnet.fluence.dev/tcp/9000/wss/p2p/12D3KooWMhVpgfQxBLkQkJed8VFNvgN4iE6MD7xCybb1ZYWW2Gtz",
peerId: "12D3KooWMhVpgfQxBLkQkJed8VFNvgN4iE6MD7xCybb1ZYWW2Gtz",
},
{
multiaddr:
"/dns4/1-testnet.fluence.dev/tcp/9000/wss/p2p/12D3KooWEXNUbCXooUwHrHBbrmjsrpHXoEphPwbjQXEGyzbqKnE9",
peerId: "12D3KooWEXNUbCXooUwHrHBbrmjsrpHXoEphPwbjQXEGyzbqKnE9",
},
{
multiaddr:
"/dns4/2-testnet.fluence.dev/tcp/9000/wss/p2p/12D3KooWHk9BjDQBUqnavciRPhAYFvqKBe4ZiPPvde7vDaqgn5er",
peerId: "12D3KooWHk9BjDQBUqnavciRPhAYFvqKBe4ZiPPvde7vDaqgn5er",
},
{
multiaddr:
"/dns4/3-testnet.fluence.dev/tcp/9000/wss/p2p/12D3KooWBUJifCTgaxAUrcM9JysqCcS4CS8tiYH5hExbdWCAoNwb",
peerId: "12D3KooWBUJifCTgaxAUrcM9JysqCcS4CS8tiYH5hExbdWCAoNwb",
},
{
multiaddr:
"/dns4/4-testnet.fluence.dev/tcp/9000/wss/p2p/12D3KooWJbJFaZ3k5sNd8DjQgg3aERoKtBAnirEvPV8yp76kEXHB",
peerId: "12D3KooWJbJFaZ3k5sNd8DjQgg3aERoKtBAnirEvPV8yp76kEXHB",
},
{
multiaddr:
"/dns4/5-testnet.fluence.dev/tcp/9000/wss/p2p/12D3KooWCKCeqLPSgMnDjyFsJuWqREDtKNHx1JEBiwaMXhCLNTRb",
peerId: "12D3KooWCKCeqLPSgMnDjyFsJuWqREDtKNHx1JEBiwaMXhCLNTRb",
},
{
multiaddr:
"/dns4/6-testnet.fluence.dev/tcp/9000/wss/p2p/12D3KooWKnRcsTpYx9axkJ6d69LPfpPXrkVLe96skuPTAo76LLVH",
peerId: "12D3KooWKnRcsTpYx9axkJ6d69LPfpPXrkVLe96skuPTAo76LLVH",
},
{
multiaddr:
"/dns4/7-testnet.fluence.dev/tcp/9000/wss/p2p/12D3KooWBSdm6TkqnEFrgBuSkpVE3dR1kr6952DsWQRNwJZjFZBv",
peerId: "12D3KooWBSdm6TkqnEFrgBuSkpVE3dR1kr6952DsWQRNwJZjFZBv",
},
{
multiaddr:
"/dns4/8-testnet.fluence.dev/tcp/9000/wss/p2p/12D3KooWGzNvhSDsgFoHwpWHAyPf1kcTYCGeRBPfznL8J6qdyu2H",
peerId: "12D3KooWGzNvhSDsgFoHwpWHAyPf1kcTYCGeRBPfznL8J6qdyu2H",
},
{
multiaddr:
"/dns4/9-testnet.fluence.dev/tcp/9000/wss/p2p/12D3KooWF7gjXhQ4LaKj6j7ntxsPpGk34psdQicN2KNfBi9bFKXg",
peerId: "12D3KooWF7gjXhQ4LaKj6j7ntxsPpGk34psdQicN2KNfBi9bFKXg",
},
{
multiaddr:
"/dns4/10-testnet.fluence.dev/tcp/9000/wss/p2p/12D3KooWB9P1xmV3c7ZPpBemovbwCiRRTKd3Kq2jsVPQN4ZukDfy",
peerId: "12D3KooWB9P1xmV3c7ZPpBemovbwCiRRTKd3Kq2jsVPQN4ZukDfy",
},
];
export const kras: Relay[] = [
{
multiaddr:
"/dns4/0-kras.fluence.dev/tcp/9000/wss/p2p/12D3KooWSD5PToNiLQwKDXsu8JSysCwUt8BVUJEqCHcDe7P5h45e",
peerId: "12D3KooWSD5PToNiLQwKDXsu8JSysCwUt8BVUJEqCHcDe7P5h45e",
},
{
multiaddr:
"/dns4/1-kras.fluence.dev/tcp/9000/wss/p2p/12D3KooWR4cv1a8tv7pps4HH6wePNaK6gf1Hww5wcCMzeWxyNw51",
peerId: "12D3KooWR4cv1a8tv7pps4HH6wePNaK6gf1Hww5wcCMzeWxyNw51",
},
{
multiaddr:
"/dns4/2-kras.fluence.dev/tcp/9000/wss/p2p/12D3KooWKnEqMfYo9zvfHmqTLpLdiHXPe4SVqUWcWHDJdFGrSmcA",
peerId: "12D3KooWKnEqMfYo9zvfHmqTLpLdiHXPe4SVqUWcWHDJdFGrSmcA",
},
{
multiaddr:
"/dns4/3-kras.fluence.dev/tcp/9000/wss/p2p/12D3KooWHLxVhUQyAuZe6AHMB29P7wkvTNMn7eDMcsqimJYLKREf",
peerId: "12D3KooWHLxVhUQyAuZe6AHMB29P7wkvTNMn7eDMcsqimJYLKREf",
},
{
multiaddr:
"/dns4/4-kras.fluence.dev/tcp/9000/wss/p2p/12D3KooWJd3HaMJ1rpLY1kQvcjRPEvnDwcXrH8mJvk7ypcZXqXGE",
peerId: "12D3KooWJd3HaMJ1rpLY1kQvcjRPEvnDwcXrH8mJvk7ypcZXqXGE",
},
{
multiaddr:
"/dns4/5-kras.fluence.dev/tcp/9000/wss/p2p/12D3KooWFEwNWcHqi9rtsmDhsYcDbRUCDXH84RC4FW6UfsFWaoHi",
peerId: "12D3KooWFEwNWcHqi9rtsmDhsYcDbRUCDXH84RC4FW6UfsFWaoHi",
},
{
multiaddr:
"/dns4/6-kras.fluence.dev/tcp/9000/wss/p2p/12D3KooWCMr9mU894i8JXAFqpgoFtx6qnV1LFPSfVc3Y34N4h4LS",
peerId: "12D3KooWCMr9mU894i8JXAFqpgoFtx6qnV1LFPSfVc3Y34N4h4LS",
},
{
multiaddr:
"/dns4/7-kras.fluence.dev/tcp/9000/wss/p2p/12D3KooWDUszU2NeWyUVjCXhGEt1MoZrhvdmaQQwtZUriuGN1jTr",
peerId: "12D3KooWDUszU2NeWyUVjCXhGEt1MoZrhvdmaQQwtZUriuGN1jTr",
},
{
multiaddr:
"/dns4/8-kras.fluence.dev/tcp/9000/wss/p2p/12D3KooWEFFCZnar1cUJQ3rMWjvPQg6yMV2aXWs2DkJNSRbduBWn",
peerId: "12D3KooWEFFCZnar1cUJQ3rMWjvPQg6yMV2aXWs2DkJNSRbduBWn",
},
{
multiaddr:
"/dns4/9-kras.fluence.dev/tcp/9000/wss/p2p/12D3KooWFtf3rfCDAfWwt6oLZYZbDfn9Vn7bv7g6QjjQxUUEFVBt",
peerId: "12D3KooWFtf3rfCDAfWwt6oLZYZbDfn9Vn7bv7g6QjjQxUUEFVBt",
},
{
multiaddr:
"/dns4/10-kras.fluence.dev/tcp/9000/wss/p2p/12D3KooWD7CvsYcpF9HE9CCV9aY3SJ317tkXVykjtZnht2EbzDPm",
peerId: "12D3KooWD7CvsYcpF9HE9CCV9aY3SJ317tkXVykjtZnht2EbzDPm",
},
];
export const randomKras = () => {
return randomItem(kras);
};
export const randomTestNet = () => {
return randomItem(testNet);
};
export const randomStage = () => {
return randomItem(stage);
};
function randomItem(arr: Relay[]) {
const index = randomInt(0, arr.length);
return arr[index];
}
function randomInt(min: number, max: number) {
return Math.floor(Math.random() * (max - min)) + min;
}

View File

@ -3,7 +3,6 @@
"compilerOptions": {
"types": ["vite/client"],
"outDir": "./dist",
"esModuleInterop": true,
"resolveJsonModule": true,
"rootDir": "src"
},

View File

@ -17,7 +17,6 @@
import inject from "@rollup/plugin-inject";
import tsconfigPaths from "vite-tsconfig-paths";
import { createRequire } from "module";
import { readFileSync } from "fs";
import { UserConfig } from "vite";
const require = createRequire(import.meta.url);
@ -30,7 +29,8 @@ const config: UserConfig = {
lib: {
entry: "./src/index.ts",
name: "js-client",
fileName: "index",
fileName: () => "index.min.js",
formats: ["umd"],
},
outDir: "./dist/browser",
rollupOptions: {
@ -55,9 +55,6 @@ const config: UserConfig = {
},
},
},
define: {
__PACKAGE_JSON_CONTENT__: readFileSync("./package.json", "utf-8"),
},
};
export default config;

59
pnpm-lock.yaml generated
View File

@ -169,9 +169,6 @@ importers:
'@fluencelabs/interfaces':
specifier: workspace:*
version: link:../interfaces
'@fluencelabs/js-client':
specifier: workspace:*
version: link:../js-client
'@fluencelabs/registry':
specifier: 0.8.7
version: 0.8.7
@ -211,6 +208,9 @@ importers:
'@fluencelabs/interfaces':
specifier: workspace:*
version: link:../interfaces
'@fluencelabs/js-client-isomorphic':
specifier: workspace:*
version: link:../js-client-isomorphic
'@fluencelabs/marine-worker':
specifier: 0.4.0
version: link:../marine-worker
@ -318,6 +318,21 @@ importers:
specifier: 0.34.6
version: 0.34.6
packages/core/js-client-isomorphic:
dependencies:
'@fluencelabs/avm':
specifier: 0.52.0
version: 0.52.0
'@fluencelabs/marine-js':
specifier: 0.7.2
version: 0.7.2
'@fluencelabs/marine-worker':
specifier: workspace:*
version: link:../marine-worker
threads:
specifier: fluencelabs/threads.js#b00a5342380b0278d3ae56dcfb170effb3cad7cd
version: github.com/fluencelabs/threads.js/b00a5342380b0278d3ae56dcfb170effb3cad7cd
packages/core/marine-worker:
dependencies:
'@fluencelabs/marine-js':
@ -1166,6 +1181,16 @@ packages:
'@babel/helper-plugin-utils': 7.22.5
dev: false
/@babel/plugin-syntax-flow@7.22.5(@babel/core@7.22.10):
resolution: {integrity: sha512-9RdCl0i+q0QExayk2nOS7853w08yLucnnPML6EN9S8fgMPVtdLDCdx/cOQ/i44Lb9UeQX9A35yaqBBOMMZxPxQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.22.10
'@babel/helper-plugin-utils': 7.22.5
dev: false
/@babel/plugin-syntax-flow@7.22.5(@babel/core@7.22.5):
resolution: {integrity: sha512-9RdCl0i+q0QExayk2nOS7853w08yLucnnPML6EN9S8fgMPVtdLDCdx/cOQ/i44Lb9UeQX9A35yaqBBOMMZxPxQ==}
engines: {node: '>=6.9.0'}
@ -1252,6 +1277,16 @@ packages:
'@babel/helper-plugin-utils': 7.22.5
dev: false
/@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.22.10):
resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.22.10
'@babel/helper-plugin-utils': 7.22.5
dev: false
/@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.22.5):
resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==}
engines: {node: '>=6.9.0'}
@ -2375,6 +2410,20 @@ packages:
'@babel/plugin-transform-react-jsx': 7.22.5(@babel/core@7.22.5)
dev: false
/@babel/plugin-transform-react-jsx@7.22.5(@babel/core@7.22.10):
resolution: {integrity: sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.22.10
'@babel/helper-annotate-as-pure': 7.22.5
'@babel/helper-module-imports': 7.22.5
'@babel/helper-plugin-utils': 7.22.5
'@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.10)
'@babel/types': 7.22.5
dev: false
/@babel/plugin-transform-react-jsx@7.22.5(@babel/core@7.22.5):
resolution: {integrity: sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==}
engines: {node: '>=6.9.0'}
@ -10373,8 +10422,8 @@ packages:
'@babel/plugin-transform-react-jsx': ^7.14.9
eslint: ^8.1.0
dependencies:
'@babel/plugin-syntax-flow': 7.22.5(@babel/core@7.22.5)
'@babel/plugin-transform-react-jsx': 7.22.5(@babel/core@7.22.5)
'@babel/plugin-syntax-flow': 7.22.5(@babel/core@7.22.10)
'@babel/plugin-transform-react-jsx': 7.22.5(@babel/core@7.22.10)
eslint: 8.50.0
lodash: 4.17.21
string-natural-compare: 3.0.1