Skip to content
This repository was archived by the owner on Jul 10, 2025. It is now read-only.

Commit f9abc64

Browse files
author
Akim
authored
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
1 parent 1266a90 commit f9abc64

File tree

24 files changed

+568
-270
lines changed

24 files changed

+568
-270
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ node_modules/
88
# Build directory
99
**/dist
1010
**/public
11+
.DS_Store

.prettierignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ pnpm-lock.yaml
77
**/build
88
**/public
99

10-
**/CHANGELOG.md
10+
**/CHANGELOG.md
11+
12+
packages/core/js-client/src/versions.ts

README.md

Lines changed: 44 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,72 @@
11
# Fluence JS Client
22

3-
[![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)
4-
[![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)
3+
[![npm](https://img.shields.io/npm/v/@fluencelabs/js-client?label=@fluencelabs/js-client)](https://www.npmjs.com/package/@fluencelabs/js-client)
54

65
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.
76

87
## Installation
98

10-
Adding the Fluence JS client for your web application is very easy.
9+
> JS Client only supports the ESM format that means not every Node.js project can install it.
10+
> You can read more [here](https://nodejs.org/api/esm.html)
1111
12-
### Browser-based Apps
12+
1. Install the client:
1313

14-
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.
15-
16-
Here is an example using the JSDELIVR CDN:
17-
18-
```html
19-
<head>
20-
<title>Cool App</title>
21-
<script
22-
src="https://cdn.jsdelivr.net/npm/@fluencelabs/[email protected]/dist/js-client.min.js"
23-
async
24-
></script>
25-
</head>
26-
```
27-
28-
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.)
29-
30-
2. Install the following packages:
31-
32-
```
33-
npm i @fluencelabs/js-client.api @fluencelabs/fluence-network-environment
14+
```bash
15+
npm i @fluencelabs/js-client
3416
```
3517

36-
3. Add the following lines at the beginning of your code:
18+
2. Add the following lines at the beginning of your code:
3719

38-
```
39-
import { Fluence } from "@fluencelabs/js-client.api";
40-
import { randomKras } from '@fluencelabs/fluence-network-environment';
20+
```javascript
21+
import { Fluence, randomKras } from "@fluencelabs/js-client";
4122

4223
Fluence.connect(randomKras());
4324
```
4425

45-
### Node.js Apps
46-
47-
**Prerequisites:**
26+
### HTML page
4827

49-
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:
28+
Add a script tag with the JS Client bundle to your `index.html`. The easiest way to do this is using a CDN (
29+
like [JSDELIVR](https://www.jsdelivr.com/) or [UNPKG](https://unpkg.com/)).
5030

51-
- Add `"type": "module"` to your package.json.
52-
- Replace `"main": "index.js"` with `"exports": "./index.js"` in your package.json.
53-
- Remove `'use strict';` from all JavaScript files.
54-
- Replace all `require()`/`module.export` with `import`/`export`.
55-
- Use only full relative file paths for imports: `import x from '.';``import x from './index.js';`.
31+
Here is an example using the JSDELIVR CDN:
5632

57-
If you are using TypeScript:
58-
59-
- Make sure you are using TypeScript 4.7 or later.
60-
- Add [`"module": "ESNext", "target": "ESNext", "moduleResolution": "nodenext"`](https://www.typescriptlang.org/tsconfig#module) to your tsconfig.json.
61-
- Use only full relative file paths for imports: `import x from '.';``import x from './index.js';`.
62-
- Remove `namespace` usage and use `export` instead.
63-
- You must use a `.js` extension in relative imports even though you're importing `.ts` files.
33+
```html
34+
<head>
35+
<title>Cool App</title>
36+
<script src="https://cdn.jsdelivr.net/npm/@fluencelabs/js-client/dist/browser/index.min.js"></script>
37+
</head>
38+
```
6439

65-
**Installation:**
40+
If you cannot or don't want to use a CDN, feel free to get the script directly from
41+
the [npm package](https://www.npmjs.com/package/@fluencelabs/js-client) and host it yourself. You can find the script in
42+
the `/dist` directory of the package. (Note: this option means that developers understand what they are doing and know
43+
how to serve this file from their own web server.)
6644

67-
1. Install the following packages:
45+
After importing JS-client to HTML page the client is available as `window.Fluence` variable.
46+
To get a specific network you can peek at
6847

69-
```
70-
npm i @fluencelabs/js-client.api"@fluencelabs/js-client.node @fluencelabs/fluence-network-environment
71-
```
72-
73-
2. Add the following lines at the beginning of your code:
48+
```
49+
https://cdn.jsdelivr.net/npm/@fluencelabs/js-client/dist/network.js
50+
```
7451

75-
```
76-
import '@fluencelabs/js-client.node';
77-
import { Fluence } from "@fluencelabs/js-client.api";
78-
import { randomKras } from '@fluencelabs/fluence-network-environment';
52+
and hardcode selected network. So initialization would look like this
7953

80-
Fluence.connect(randomKras());
81-
```
54+
```javascript
55+
// Passing 1 kras network config from ./dist/network.js above
56+
window.Fluence.connect({
57+
multiaddr:
58+
"/dns4/0-kras.fluence.dev/tcp/9000/wss/p2p/12D3KooWSD5PToNiLQwKDXsu8JSysCwUt8BVUJEqCHcDe7P5h45e",
59+
peerId: "12D3KooWSD5PToNiLQwKDXsu8JSysCwUt8BVUJEqCHcDe7P5h45e",
60+
});
61+
```
8262

8363
## Usage in an Application
8464

8565
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).
8666

8767
1. Install the package:
8868

89-
```
69+
```bash
9070
npm i -D @fluencelabs/cli
9171
```
9272

@@ -130,7 +110,7 @@ Once you've added the client, you can compile [Aqua](https://github.com/fluencel
130110
6. Now you can import and call Aqua code from your application like
131111
this:
132112

133-
```
113+
```javascript
134114
import { getRelayTime } from "./_aqua/demo";
135115

136116
async function buttonClick() {
@@ -172,7 +152,7 @@ Star (`*`) character can be used as a wildcard to enable logs for multiple compo
172152

173153
### Enabling logs in Node.js
174154

175-
enable logs, pass the environment variable `DEBUG` with the corresponding log level. For example:
155+
Enable logs by passing the environment variable `DEBUG` with the corresponding log level. For example:
176156

177157
```sh
178158
DEBUG=fluence:* node --loader ts-node/esm ./src/index.ts
@@ -182,13 +162,14 @@ DEBUG=fluence:* node --loader ts-node/esm ./src/index.ts
182162

183163
To enable logs, set the `localStorage.debug` variable. For example:
184164

185-
```
186-
localStorage.debug = 'fluence:*'
165+
```javascript
166+
localStorage.debug = "fluence:*";
187167
```
188168

189169
**NOTE**
190170

191-
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.
171+
In Chromium-based web browsers (e.g. Brave, Chrome, and Electron), the JavaScript console will be default—only to show
172+
messages logged by debug if the "Verbose" log level is enabled.
192173

193174
## Development
194175

packages/@tests/test-utils/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export const startContentServer = (
5959
rewrites: [
6060
{
6161
source: "/js-client.min.js",
62-
destination: "/source/index.umd.cjs",
62+
destination: "/source/index.min.js",
6363
},
6464
// TODO:
6565
// something like this

packages/core/aqua-to-js/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
"@fluencelabs/aqua-api": "0.12.0",
2222
"@fluencelabs/aqua-lib": "0.7.3",
2323
"@fluencelabs/interfaces": "workspace:*",
24-
"@fluencelabs/js-client": "workspace:*",
2524
"@fluencelabs/registry": "0.8.7",
2625
"@fluencelabs/spell": "0.5.20",
2726
"@fluencelabs/trust-graph": "0.4.7",

packages/core/aqua-to-js/src/generate/__test__/generate.spec.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,18 @@ describe("Aqua to js/ts compiler", () => {
4040
},
4141
};
4242

43+
// TODO: see https://github.com/fluencelabs/js-client/pull/366#discussion_r1370567711
44+
// @ts-expect-error don't use compileFromPath directly here
4345
const jsResult = generateSources(res, "js", pkg);
46+
// TODO: see https://github.com/fluencelabs/js-client/pull/366#discussion_r1370567711
47+
// @ts-expect-error don't use compileFromPath directly here
4448
const jsTypes = generateTypes(res, pkg);
4549

4650
expect(jsResult).toMatchSnapshot();
4751
expect(jsTypes).toMatchSnapshot();
4852

53+
// TODO: see https://github.com/fluencelabs/js-client/pull/366#discussion_r1370567711
54+
// @ts-expect-error don't use compileFromPath directly here
4955
const tsResult = generateSources(res, "ts", pkg);
5056

5157
expect(tsResult).toMatchSnapshot();
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"type": "module",
3+
"name": "@fluencelabs/js-client-isomorphic",
4+
"version": "1.0.0",
5+
"description": "Isomorphic entities for js-client",
6+
"files": [
7+
"dist"
8+
],
9+
"main": "index.js",
10+
"scripts": {
11+
"build": "tsc"
12+
},
13+
"exports": {
14+
".": "./dist/types.js",
15+
"./fetcher": {
16+
"node": "./dist/fetchers/node.js",
17+
"default": "./dist/fetchers/browser.js"
18+
},
19+
"./worker-resolver": {
20+
"node": "./dist/worker-resolvers/node.js",
21+
"default": "./dist/worker-resolvers/browser.js"
22+
}
23+
},
24+
"dependencies": {
25+
"@fluencelabs/avm": "0.52.0",
26+
"@fluencelabs/marine-js": "0.7.2",
27+
"@fluencelabs/marine-worker": "workspace:*",
28+
"threads": "fluencelabs/threads.js#b00a5342380b0278d3ae56dcfb170effb3cad7cd"
29+
},
30+
"keywords": [],
31+
"author": "Fluence Labs",
32+
"license": "Apache-2.0"
33+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* Copyright 2023 Fluence Labs Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import type { VersionedPackage } from "../types.js";
18+
19+
/**
20+
* @param pkg name of package with version
21+
* @param assetPath path of required asset in given package
22+
* @param root CDN domain in browser or file system root in node
23+
*/
24+
export async function fetchResource(
25+
pkg: VersionedPackage,
26+
assetPath: string,
27+
root: string,
28+
) {
29+
const refinedAssetPath = assetPath.startsWith("/")
30+
? assetPath.slice(1)
31+
: assetPath;
32+
33+
const url = new URL(`${pkg.name}@${pkg.version}/` + refinedAssetPath, root);
34+
35+
return fetch(url).catch(() => {
36+
throw new Error(`Cannot fetch from ${url.toString()}`);
37+
});
38+
}

packages/core/js-client/src/fetchers/node.ts renamed to packages/core/js-client-isomorphic/src/fetchers/node.ts

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,49 +14,41 @@
1414
* limitations under the License.
1515
*/
1616

17-
import fs from "fs";
18-
import module from "module";
19-
import path from "path";
17+
import { readFile } from "fs/promises";
18+
import { createRequire } from "module";
19+
import { sep, posix, join } from "path";
20+
21+
import type { VersionedPackage } from "../types.js";
2022

2123
/**
22-
* @param pkg name of package
24+
* @param pkg name of package with version
2325
* @param assetPath path of required asset in given package
24-
* @param root CDN domain in browser or file system root in node
26+
* @param root CDN domain in browser or js-client itself in node
2527
*/
2628
export async function fetchResource(
27-
pkg: string,
29+
pkg: VersionedPackage,
2830
assetPath: string,
2931
root: string,
3032
) {
3133
// TODO: `root` will be handled somehow in the future. For now, we use filesystem root where js-client is running;
3234
root = "/";
33-
const require = module.createRequire(import.meta.url);
34-
const packagePathIndex = require.resolve(pkg);
35+
const require = createRequire(import.meta.url);
36+
const packagePathIndex = require.resolve(pkg.name);
3537

3638
// Ensure that windows path is converted to posix path. So we can find a package
37-
const posixPath = packagePathIndex.split(path.sep).join(path.posix.sep);
39+
const posixPath = packagePathIndex.split(sep).join(posix.sep);
3840

39-
const matches = new RegExp(`(.+${pkg})`).exec(posixPath);
41+
const matches = new RegExp(`(.+${pkg.name})`).exec(posixPath);
4042

4143
const packagePath = matches?.[0];
4244

4345
if (packagePath == null) {
44-
throw new Error(`Cannot find dependency ${pkg} in path ${posixPath}`);
46+
throw new Error(`Cannot find dependency ${pkg.name} in path ${posixPath}`);
4547
}
4648

47-
const pathToResource = path.join(root, packagePath, assetPath);
48-
49-
const file = await new Promise<ArrayBuffer>((resolve, reject) => {
50-
// Cannot use 'fs/promises' with current vite config. This module is not polyfilled by default.
51-
fs.readFile(pathToResource, (err, data) => {
52-
if (err != null) {
53-
reject(err);
54-
return;
55-
}
49+
const pathToResource = join(root, packagePath, assetPath);
5650

57-
resolve(data);
58-
});
59-
});
51+
const file = await readFile(pathToResource);
6052

6153
return new Response(file, {
6254
headers: {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Copyright 2023 Fluence Labs Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { Worker } from "threads/master";
18+
19+
export type VersionedPackage = { name: string; version: string };
20+
export type GetWorker = (
21+
pkg: VersionedPackage,
22+
CDNUrl: string,
23+
) => Promise<Worker>;

0 commit comments

Comments
 (0)